Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 近邻权衡-运行速度更快,结果更不准确_Python_Scikit Learn_Smooth_Nearest Neighbor - Fatal编程技术网

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
    情况)
  • 拟合(“训练”)需要18秒,但平滑~1000个样本需要20分钟以上。如果平滑过程更短,我愿意得到精度更低的结果。可能吗?为了实现它,我应该改变哪些

  • 如果没有数据集和完整的代码,很难说清楚。以下是我的想法

    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)