Python 带有非数字数据的KNeighborClassifier失败

Python 带有非数字数据的KNeighborClassifier失败,python,machine-learning,scikit-learn,knn,nearest-neighbor,Python,Machine Learning,Scikit Learn,Knn,Nearest Neighbor,我试图用非数字数据训练一个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"]]

我试图用非数字数据训练一个
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'
回溯(最近一次呼叫最后一次):
文件“/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site packages/IPython/core/interactiveshell.py”,第2862行,运行代码
exec(代码对象、self.user\u全局、self.user\n)
文件“”,第1行,在
模型分数(X_检验、y_检验)
文件“/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site packages/sklearn/base.py”,第350行,在分数中
返回准确度得分(y,自我预测(X),样本权重=样本权重)
文件“/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site-packages/sklearn/neights/classification.py”,第145行,在predict中
neigh_dist,neigh_ind=self.kneighbors(X)
文件“/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site packages/sklearn/neighbors/base.py”,第361行,在kneighbors中
**自有效(度量参数)
文件“/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site packages/sklearn/metrics/pairwise.py”,第1247行,成对距离
返回平行成对(X、Y、func、n个作业,**KWD)
文件“/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site packages/sklearn/metrics/pairwise.py”,第1090行,平行排列
返回函数(X,Y,**kwds)
文件“/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site packages/sklearn/metrics/pairwise.py”,第1104行,成对调用
十、 Y=检查成对数组(X,Y)
文件“/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site packages/sklearn/metrics/pairwise.py”,第110行,在check\u pairwise\u数组中
警告类型=警告类型,估计员=估计员)
文件“/home/marcofavorito/virtualenvs/nlp/lib/python3.5/site packages/sklearn/utils/validation.py”,第402行,在check_数组中
array=np.array(array,dtype=dtype,order=order,copy=copy)
ValueError:无法将字符串转换为浮点:“e”
我想我可以很容易地实现该算法,但是没有
sklearn
分类器的所有功能。我错过了一些选择?或者,如果之前我没有将样本转换为浮点数,我就无法训练模型


N.B.我知道这个问题可以很容易地用数字而不是字符来解决。但我需要解决另一个问题,即处理非数字数据,并且找不到浮点数的简单映射,如前所述。

您的代码中有一些错误。首先,您必须以某种方式将分类数据转换为数字数据。Sklearn中的KNN分类器还不支持分类数据。其次,您需要在sklearn中使用函数,以便使用自定义度量。KNN中的默认
score
函数返回平均精度,而不是您指定的度量。你可以阅读更多关于它的内容。为了使用KNN分类器的sklearn实现,您需要更改数据集。

除了Mohammed已经提到的内容:您的方法在数学上有缺陷,sklearn可能无法保证会发生什么

KNN分类器只是一个很好的包装器,用于和等核心数据结构

这里func是一个函数,它接受两个一维numpy数组,并返回一个距离。请注意,为了在BallTree中使用,距离必须是真实的度量:即,它必须满足以下属性

非负性:d(x,y)>=0

恒等式:d(x,y)=0当且仅当x==y

对称性:d(x,y)=d(y,x)

三角形不等式:d(x,y)+d(y,z)>=d(x,z)

说句公道话

这样说,你的度量不是真正的度量!(即使是最明显的规则:非否定性也没有给出

现在在上面的文本中,只给出了一个关于Ball树(不是KD树)的警告,KNN自动选择基础树结构。因此,这里可能有一个坏情况,您应该避免

但是我不确定KD树是否也需要这些假设!我希望得到一个“是”和“正”的点,该点仍然使用单词metric和可用的
KD_树。有效的_指标
(尽管此列表只是sklearn附带的常用指标的子集)