【发布时间】:2016-06-27 23:34:25
【问题描述】:
所以我正在为一些更大的数据集构建一个 KNN,并且我需要运行 Leave-one-out 交叉验证以选择正确的 K,因此速度很重要。
我正在尝试通过广播进行距离计算。
情况是:X 是我的训练矩阵,一个二维矩阵,行上有样本。 Q 是我的查询矩阵或测试数据,行上也有样本。
我需要运行类似于矩阵乘法的东西,其中我将 Q 的每一行与 X.T 的每一列(x 转置)匹配,并构建一个 sample x sample 矩阵,其中每个条目 [i,j] 是查询样本 i 与训练样本 j 的距离。然后我会从前 k 个样本中排序并选择类的模式。
无论如何,在矩阵乘法中,numpy 正是这样做的……但它不是进行距离计算,而是进行分段乘法和求和(点积)。如果我可以将距离函数插入到那个位置,我想我的 KNN 距离计算将与 numpy 矩阵乘法一样快。
有没有办法使用广播或其他一些 numpy 技术来做到这一点?
也许是一种并行化的方法?
示例代码:
import numpy as np
x1 = np.asarray([1.0,10.0,100.0])
x2 = np.asarray([40.0,60.0,80.0])
x3 = np.asarray([20.,30.,40.])
x = np.concatenate((x1.reshape(3,1),x2.reshape(3,1),x3.reshape(3,1)),axis=1)
y1 = np.asarray([4.0,88.0,35.0])
y2 = np.asarray([7.0,65.0,99.0])
y3 = np.asarray([40.0,13.0,27.0])
y = np.concatenate((y1.reshape(3,1),y2.reshape(3,1),y3.reshape(3,1)),axis=1)
def euclidean_distance(p1,p2):
return np.sqrt(np.sum((p1-p2)**2.0))
所以,我可以写:
distances = np.zeros((y.shape[0],x.shape[0]))
for i in range(y.shape[0]):
for j in range(x.shape[0]):
distances[i,j] = euclidean_distance(y[i,:],x[j,:])
这就是我接下来要排序的内容。在上面的当前 for 循环中,我将只选择我的 k 个最近邻居并在该内部循环中找到类......但它比在矢量化计算中计算所有距离要慢得多。
【问题讨论】:
-
好吧,您可以使用 cdist 获取距离:
from scipy.spatial.distance import cdist; distances = cdist(y,x)。不确定这是否能回答您的问题。 -
您上面的代码生成
(9, 1)向量作为x和y- 这是您的意图吗?也许您的意思是连接第二个轴而不是第一个? -
它让我更接近一点。谢啦。我还要做一个马氏距离版本,这需要我在距离计算中进行矩阵乘法...
-
@ali_m 成功了。
-
看起来
mahalanobis也支持 dist 计算 - docs.scipy.org/doc/scipy/reference/generated/…