【发布时间】:2014-12-11 12:59:15
【问题描述】:
在MATLAB 遇到问题后,我决定尝试 Python:
我编写了一个函数,当样本属于我自己的类时,我使用我自己的距离函数计算 kNN:
def closestK(sample, otherSamples, distFunc, k):
"Returns the closest k samples to sample based on distFunc"
n = len(otherSamples)
d = [distFunc(sample, otherSamples[i]) for i in range(0,n)]
idx = sorted(range(0,len(d)), key=lambda k: d[k])
return idx[1:(k+1)]
def kNN(samples, distFunc, k):
return [[closestK(samples[i], samples, distFunc, k)] for i in range(len(samples))]
这是距离函数:
@staticmethod def distanceRepr(c1, c2): r1 = c1.repr r2 = c2.repr # because cdist needs 2D array if r1.ndim == 1: r1 = np.vstack([r1,r1]) if r2.ndim == 1: r2 = np.vstack([r2,r2]) return scipy.spatial.distance.cdist(r1, r2, 'euclidean').min()
但与“正常”kNN 函数相比,它的运行速度仍然慢得惊人,即使使用“蛮力”算法也是如此。我做错了吗?
更新
我正在添加类的构造函数。 repr 属性包含一组向量(从 1 到任意值),并且距离被计算为两组 repr 之间的最小欧几里得距离。
class myCluster:
def __init__(self, index = -1, P = np.array([])):
if index ==-1 :
self.repr = np.array([])
self.IDs = np.array([])
self.n = 0
self.center = np.array([])
else:
self.repr = np.array(P)
self.IDs = np.array(index)
self.n = 1
self.center = np.array(P)
以及其余相关代码(X 是一个矩阵,其行是样本,列是变量):
level = [myCluster(i, X[i,:]) for i in range(0,n)]
kNN(level, myCluster.distanceRepr, 3)
更新 2
我做了一些测量,花费大部分时间的线路是
d = [distFunc(sample, otherSamples[i]) for i in range(0,n)]
所以distFunc 有一些东西。当我将其更改为返回时
np.linalg.norm(c1.repr-c2.repr)
即“正常”向量计算,no排序,运行时间保持不变。所以问题出在这个函数的调用上。使用类将运行时间更改为 60 倍是否有意义?
【问题讨论】:
-
你指的这个“正常”kNN函数究竟是什么?
-
@moarningsun:scikit 中的 NearestNeighbors 函数。在我测试的设置中,他们做的完全一样:为 n 个欧几里得向量计算 kNN,只是我的向量被一个类“包装”了。
-
使用 Numpy 函数代替
d = [dist...和idx = sorted(....之类的列表解析是解决方案 转换为 Numpy 取决于distFunc是什么。如果您提供完整的来源,您可以获得更好的答案。 -
@mskimm:我已经添加了相关代码。谢谢。
-
只是好奇,当您使用
sklearn.NearestNeighbors类时,您是否也在使用algorithm='ball_tree'或algorithm='kd_tree'选项?这些将大大加快算法速度,但前提是您进行重复查询。我也不确定这是否是您问题的重点,所以想先发表评论。
标签: python numpy machine-learning distance knn