0

Ich versuche, ein KNeighborClassifier mit nicht-numerischen Daten zu trainieren, aber ich liefere eine benutzerdefinierte Metrik, die es ermöglicht, einen Ähnlichkeits-Score zwischen Stichproben zu berechnen.KNeighborClassifier mit nicht numerischen Daten schlägt fehl

from sklearn.neighbors import KNeighborsClassifier 

#Compute the "ASCII" distance: 
def my_metric(a,b): 
    return ord(a)-ord(b) 

#Samples and labels 
X = [["a"],["b"], ["c"],["m"], ["z"]] 

#S=Start of the alphabet, M=Middle, E=end 
y = ["S", "S", "S", "M", "E"] 

model = KNeighborsClassifier(metric=my_metric) 
model.fit(X,y) 

X_test = [["e"],["f"],["w"]] 
y_test = [["S"],["M"],["E"]] 
model.score(X_test, y_test) 

bekomme ich folgende Fehlermeldung:

Traceback (most recent call last): 
File "/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site-packages/IPython/core/interactiveshell.py", line 2862, in run_code 
    exec(code_obj, self.user_global_ns, self.user_ns) 
File "<ipython-input-20-e339c96eea22>", line 1, in <module> 
    model.score(X_test, y_test) 
File "/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site-packages/sklearn/base.py", line 350, in score 
    return accuracy_score(y, self.predict(X), sample_weight=sample_weight) 
File "/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site-packages/sklearn/neighbors/classification.py", line 145, in predict 
    neigh_dist, neigh_ind = self.kneighbors(X) 
File "/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site-packages/sklearn/neighbors/base.py", line 361, in kneighbors 
    **self.effective_metric_params_) 
File "/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site-packages/sklearn/metrics/pairwise.py", line 1247, in pairwise_distances 
    return _parallel_pairwise(X, Y, func, n_jobs, **kwds) 
File "/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site-packages/sklearn/metrics/pairwise.py", line 1090, in _parallel_pairwise 
    return func(X, Y, **kwds) 
File "/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site-packages/sklearn/metrics/pairwise.py", line 1104, in _pairwise_callable 
    X, Y = check_pairwise_arrays(X, Y) 
File "/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site-packages/sklearn/metrics/pairwise.py", line 110, in check_pairwise_arrays 
    warn_on_dtype=warn_on_dtype, estimator=estimator) 
File "/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site-packages/sklearn/utils/validation.py", line 402, in check_array 
    array = np.array(array, dtype=dtype, order=order, copy=copy) 
ValueError: could not convert string to float: 'e' 

ich ich denke, sehr leicht, den Algorithmus implementieren können, aber ohne all die Funktion des sklearn Klassifikator. Ich vermisse eine Option? Oder kann ich das Modell einfach nicht trainieren, wenn ich vorher keine Proben in Floats übersetze?

N.B. Ich weiß, dass das Problem leicht gelöst werden kann, indem man Zahlen anstelle von Zeichen setzt. Aber ich muss ein anderes Problem lösen, das sich mit nicht-numerischen Daten beschäftigt und wo ich kein einfaches Mapping auf Floats finden kann, wie schon gesagt.

Antwort

1

Es gibt ein paar Fehler in Ihrem Code. Erstens müssen Sie die kategorischen Daten irgendwie in numerische konvertieren. Der KNN-Klassifikator in Sklearn unterstützt noch keine kategorischen Daten. Zweitens müssen Sie die Funktion make_Scorer() in sklearn verwenden, um Ihre benutzerdefinierten Messwerte zu verwenden. Die Standardfunktion score in einem KNN gibt die mittlere Genauigkeit und nicht die von Ihnen angegebene Metrik zurück. Sie können mehr darüber lesen here. Sie müssen Ihre Datenmenge ändern, um diese sklearn-Implementierung von KNN Classifier verwenden zu können.

2

Abgesehen von den Sachen, die Mohammed bereits erwähnte: ist Ihr Ansatz mathematisch fehlerhaft und Sklearn gibt wahrscheinlich keine Garantien, was passieren wird.

KNN-Klassifikator ist nur ein netter Wrapper für die Kerndatenstrukturen wie KD-trees und Ball-trees. Here you can see what kind of assumptions those need.

Here func is a function which takes two one-dimensional numpy arrays, and returns a distance. Note that in order to be used within the BallTree, the distance must be a true metric: i.e. it must satisfy the following properties

Non-negativity: d(x, y) >= 0

Identity: d(x, y) = 0 if and only if x == y

Symmetry: d(x, y) = d(y, x)

Triangle Inequality: d(x, y) + d(y, z) >= d(x, z)

Um fair zu sein. That's just what a metric is.

Wie gesagt, Ihre Metrik ist keine echte Metrik! (Selbst die offensichtlichste Regel: Nicht-Negativität ist nicht gegeben.

Jetzt im obigen Text wird nur eine Warnung in Bezug auf Ball-Baum (nicht KD-Baum) gegeben, und KNN wählt die zugrunde liegende Baumstruktur Es kann also einen schlimmen Fall geben, den Sie vermeiden sollten.

Ich bin mir nicht sicher, ob diese Annahmen auch für den KD-Baum benötigt werden! Ich hätte ein Ja erwartet und zeige einfach auf kd-trees docs verwenden immer noch das Wort metrisch und die verfügbaren kd_tree.valid_metrics (obwohl diese Liste nur eine Teilmenge der allgemeinen Metriken ist, die mit sklearn kommen).

+0

Ich wusste, dass ich eine verließ wichtig hinweisen! Danke für diese Info. auf metrische Eigenschaften. :) –

Verwandte Themen