Python 近邻权衡-运行速度更快,结果更不准确
我正在处理一个中等大小的数据集(Python 近邻权衡-运行速度更快,结果更不准确,python,scikit-learn,smooth,nearest-neighbor,Python,Scikit Learn,Smooth,Nearest Neighbor,我正在处理一个中等大小的数据集(shape=(14013L,46L))。 我想用它的平滑度来平滑每个样品。 我正在用以下方法训练我的模特: NearestNeighbors(n_neighbors, algorithm='ball_tree', metric=sklearn.metrics.pairwise.cosine_distances) 其平滑度如下所示: def smooth(x,nbrs,data,alpha): """ input:
shape=(14013L,46L)
)。
我想用它的平滑度来平滑每个样品。
我正在用以下方法训练我的模特:
NearestNeighbors(n_neighbors, algorithm='ball_tree',
metric=sklearn.metrics.pairwise.cosine_distances)
其平滑度如下所示:
def smooth(x,nbrs,data,alpha):
"""
input:
alpha: the smoothing factor
nbrs: trained NearestNeighbors from sklearn
data: the original data
(since NearestNeighbors returns only the index and not the samples)
x: what we want to smooth
output:
smoothed x with its nearest neighbours
"""
distances, indices = nbrs.kneighbors(x)
distances = map(lambda z:abs(-z+1),distances)[0]
norm = sum(distances)
if norm == 0:
"No neighbours were found."
return x
distances = map(lambda z: (1-alpha)*z/norm ,distances)
indices = map(lambda z: data[z],indices)[0]
other = np.array([indices[i] * distances[i] for i in range(len(distances))])
z = x * alpha
z = z.reshape((1,z.shape[0]))
smoothed = sum(np.concatenate((other,z),axis=0))
return smoothed
我的问题是:
if
情况)如果没有数据集和完整的代码,很难说清楚。以下是我的想法
distances = map(lambda z:abs(-z+1),distances)[0]
norm = sum(distances)
因为你索引了地图的结果,你应该只得到第一个邻居。如果x
实际上是您用来训练的点之一,那么第一个最近的邻居将是…x
。因为使用的是余弦距离,所以该距离正好为:1<代码>abs(1-1)=0。在我建议更正之前,让我们先谈谈性能
关于性能:到处都在使用map
函数,这是Python内置的。Scikit learn构建在numpy
的基础上,它的数学运算速度比本地Python代码快得多。这就是为什么培训比代码快得多。您应该使用numpy算法,而不是map
。一个例子:这一行
distances = map(lambda z: (1-alpha)*z/norm ,distances)
应该是这个吗
distances *= ((1-alpha)/norm)
如果norm
是一个数组,那么它应该具有正确的维度,以便numpy广播规则能够生效,并且完全用C语言完成“正确的事情”
好的,既然我建议使用numpy数组(而不是map
和Python列表),我认为if
语句前面两行的正确做法是删除索引。(其余代码可能也会被索引破坏;在函数的第二行之后,distance
不是数组或列表,而是标量。)
此外,您不应该多次调用
smooth()
函数,每次调用一次。您应该通过N\u dimensions==46
numpy数组在N\u samples
上调用它,并适当地调整smooth()
代码。(例如,最近的邻居将通过N\u邻居
数组返回N\u样本
,比返回N\u样本
长度N\u样本
的单个数组要快得多)首先,为什么要使用球树?也许你的度量确实暗示了这一点,但如果不是这样,你也可以使用kd树
我将从理论的角度来探讨你的问题。默认情况下,
半径
参数设置为1.0。这对于您的数据集来说可能太小,因为如果我理解正确,这将指定查询中要查看的半径。所以,我建议在得到一些结果之前,增加这个值来运行代码。然后减少它,直到没有结果为止。再增加一点,就有了数据集的最佳参数
一个重要参数是leaf\u size
,它实际上会影响查询到达时要检查的点数。此参数的值越小,执行速度越快,精度越低
您可能还想检查我的答案,这解释了速度和准确性之间的权衡,在进行最近邻搜索时,这一权衡非常重要。我不知道在Python中如何使用knn,但您在哪里传递参数?还是您允许他们获取默认值?@gsamaras看到了第一个代码块-
nearestneights
的启动,我已经看到了。但是,从这一点上,我可以假设您使用的是默认参数,对吗?@gsamaras是的,任何未说明的参数都会给出其默认值,您可以在“是的,我看到了链接”中看到这些。谢谢,好问题,顺便说一句,+1。谢谢您的提示<代码>距离*=((1-alpha)/norm)是有问题的,因为每个的norm
都是距离的l1和。您的意思可能是距离*=((1-alpha)/sum(距离))。除此之外,我为每个示例调用了一次smooth()
,调用次数不多。至于调用smooth()
:对不起,不清楚。您希望为所有示例调用一次smooth()
,而不是为每个示例调用一次。
distances = np.abs( distances-1 )
norm = np.sum(distances)