2017-09-22 120 views
0

我試圖用非數字數據訓練KNeighborClassifier,但我提供的自定義度量允許計算樣本之間的相似度分數。帶有非數字數據的KNeighborClassifier失敗

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) 

我得到以下錯誤:

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' 

我想我可以很輕鬆地實現算法,但沒有sklearn分類的所有功能。我錯過了一些選擇?或者,如果在我不將樣本翻譯成浮標之前,我無法訓練模型?

N.B.我知道這個問題可以通過把數字而不是字符來解決。但是我需要解決另一個處理非數字數據的問題,並且我無法找到一個簡單的浮點映射,如前所述。

回答

1

您的代碼中存在一些錯誤。首先,你必須以某種方式將分類數據轉換爲數字數據。 Sklearn中的KNN分類器尚不支持分類數據。其次,您需要使用sklearn中的make_Scorer()函數才能使用您的自定義指標。 KNN中的默認score函數將返回平均精度而不是您指定的度量。你可以閱讀更多關於它here。您需要更改數據集才能使用KNN分類器的sklearn實現。

2

除了穆罕默德已經提到的東西:你的方法在數學上有缺陷和sklearn可能不會保證會發生什麼。

KNN分類器對於核心數據結構如KD-treesBall-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)

公平。 That's just what a metric is

這樣表示,您的公制不是真正的公制! (即使最明顯的規則:沒有給出非負性

現在在上面的文字中,只給出了關於球樹(而不是KD樹)的警告,並且KNN選擇了底層樹結構所以這裏可能會出現一個不好的情況,你應該避免這種情況,

雖然我不確定,如果這些假設對於KD樹也是需要的,我會期待yes和just指向kd-trees docs哪個還在使用這個詞指標和可用kd_tree.valid_metrics(雖然這個名單只是其附帶sklearn的通用指標的一個子集)。

+0

我知道我要離開一個重要的一點是!感謝這個信息。在度量屬性上。 :) –