Python 如何为KNeighboursRegressor使用自定义距离度量?

Python 如何为KNeighboursRegressor使用自定义距离度量?,python,scikit-learn,Python,Scikit Learn,在使用knn回归模型时,我尝试应用我自己的自定义距离度量函数。 我的数据集混合了标称、顺序、数字和二进制类型的字段 代码: def cus_距离(阵列1、阵列2、**kwargs): #计算距离,返回一个浮点值 通过 knn=近邻。KNEIGHBORSREgressionor(权重=距离),公制=cus_距离) #列车_数据是一个数据帧obj knn.fit(序列数据.ix[:,字段列表],序列数据['时间成本]) 最后一行将导致异常: ----------------------------

在使用knn回归模型时,我尝试应用我自己的自定义距离度量函数。 我的数据集混合了标称、顺序、数字和二进制类型的字段

代码:

def cus_距离(阵列1、阵列2、**kwargs):
#计算距离,返回一个浮点值
通过
knn=近邻。KNEIGHBORSREgressionor(权重=距离),公制=cus_距离)
#列车_数据是一个数据帧obj
knn.fit(序列数据.ix[:,字段列表],序列数据['时间成本])
最后一行将导致异常:

---------------------------------------------------------------------------
ValueError回溯(最近一次调用上次)
在()
---->1 knn.fit(序列数据.ix[:,字段列表],序列数据['时间成本])
/usr/local/lib/python2.7/dist-packages/sklearn/neights/base.pyc-in-fit(self,X,y)
587 X,y=检查数组(X,y,稀疏格式=“csr”)
588自身_y=y
-->589回位自适配(X)
590
591
/usr/local/lib/python2.7/dist-packages/sklearn/neights/base.pyc in_-fit(self,X)
214 self.\u tree=BallTree(X,self.leaf\u size,
215公制=自生效公制,
-->216**self.effective\u metric\u kwds\u
217 elif self._fit_method=='kd_tree':
218 self._tree=KDTree(X,self.leaf_size,
/usr/local/lib/python2.7/dist-packages/sklearn/neights/ball_tree.so中的sklearn.neights.ball_tree.BinaryTree.uu init_u(sklearn/neights/ball_tree.c:7983)()
/asarray中的usr/local/lib/python2.7/dist-packages/numpy/core/numeric.pyc(a,数据类型,顺序)
318
319     """
-->320返回数组(a,数据类型,副本=False,顺序=order)
321
322 def asanyarray(a,数据类型=无,订单=无):
ValueError:无法将字符串转换为浮点:未知
我知道这个错误是由数据集中的字符串值(其中一个是“未知”值)引起的。
这让我感到困惑,在我的理解中,函数cus_distance应该考虑这些str值,而kneighbors回归器只使用函数的返回值

问:
*这是在KNN回归中使用自定义距离度量的正确方法吗?
*如果是,我为什么会遇到这种例外情况?

*如果不是,正确的方法是什么?

无论使用何种度量,Ball树和KD树都需要浮点数据。如果您的数据无法转换为浮点,则会出现此类错误

>>> import numpy as np
>>> data = [1, "Unknown", 2]
>>> np.asarray(data, dtype=float)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
----> 1 np.asarray(data, dtype=float)

ValueError: could not convert string to float: Unknown
谢谢@jakevdp.
scikit学习支持暴力、球树和KD树,根据@jakevdp的回答,我只能使用暴力算法,因此我的代码更改为:

knn=neighborsressegator(权重='distance',度量=cus_距离,算法='brute')
knn.fit(序列数据.ix[:,字段列表],序列数据['时间成本])
这一次它将不再引发错误,谢谢你的VDP!

但当我尝试使用这个knn对象时,新的问题出现了:

这将在我的问题中导致相同的错误。因此,我查看了scikit learn的源代码,发现导致此错误:

elif可调用(度量):
#首先检查矩阵(这通常由度量完成)。
十、 Y=检查成对数组(X,Y)
n_x,n_y=x.shape[0],y.shape[0]
函数check_pairwise_array将尝试将所有值转换为float,“Unknown”再次导致错误

我认为这是一种错误,因为scikit的内置度量不支持混合类型的数据集,所以我编写了一个客户度量函数,但这一行仍然强制数据集为纯浮点类型。
正如这一行上面的评论所说,检查工作应该由客户指标来完成,因此我刚刚评论了这一行,,重新加载此模块,我的knn对象现在可以完美工作:)


ps:我正在努力将这一变化推广到scikit learn官方github回购协议。

那么,如果你点击了一个“未知”按钮,它会返回什么?@IvoFlipse会这样做吗“是指函数cus_distance吗?是的,我指的就是这个。但似乎@jakevdp已经提供了一个answer@IvoFlipse在函数cus_distance中,我处理str值(被视为标称类型)、int值(被视为数字类型)以及其他不同方式的值,以计算两个记录之间的差异。这不是一个bug。这确保了在许多设置中的正确行为。sklearn不支持使用熊猫数据帧。我认为为您的设置编写自己的KNN应该相当简单。
knn.predict(check_data.ix[:, fields_list])