【问题标题】:k-nearest neighbour classifier using numpy使用 numpy 的 k 最近邻分类器
【发布时间】:2017-03-17 02:23:19
【问题描述】:

我正在尝试实现我自己的 kNN 分类器。我已经设法实现了一些东西,但是速度非常慢......

def euclidean_distance(X_train, X_test):
    """
    Create list of all euclidean distances between the given
    feature vector and all other feature vectors in the training set
    """
    return [np.linalg.norm(X - X_test) for X in X_train]

def k_nearest(X, Y, k):
    """
    Get the indices of the nearest feature vectors and return a
    list of their classes
    """
    idx = np.argpartition(X, k)
    return np.take(Y, idx[:k])

def predict(X_test):
    """
    For each feature vector get its predicted class
    """
    distance_list = [euclidean_distance(X_train, X) for X in X_test]
    return np.array([Counter(k_nearest(distances, Y_train, k)).most_common()[0][0] for distances in distance_list])

在哪里(例如)

X = [[  1.96701284   6.05526865]
     [  1.43021202   9.17058291]]

Y = [ 1.  0.]

显然,如果我不使用任何 for 循环,它会快得多,但我不知道如何让它在没有它们的情况下工作。有没有办法在不使用 for 循环/列表推导的情况下做到这一点?

【问题讨论】:

  • X_train 是什么?
  • @Divakar 您将X 拆分为训练集和测试集。想象一下 X 实际上是 200 行 x, y 值而不是只有 2 行。然后将其拆分为 X_trainX_test

标签: python numpy knn


【解决方案1】:

这是一种矢量化方法 -

from scipy.spatial.distance import cdist
from scipy.stats import mode

dists = cdist(X_train, X)
idx = np.argpartition(dists, k, axis=0)[:k]
nearest_dists = np.take(Y_train, idx)
out = mode(nearest_dists,axis=0)[0]

【讨论】:

  • 我也设法使用spatial.KDTree 来实现它,而且它肯定更快,但是在尝试这个example 时仍然需要40 秒(之前是240 秒)。我无法理解sklearn 怎么能在 0.7 秒内做到这一点?!
  • @user5368737 我不知道它的内部结构。但如果我不得不猜测,我会说它可能不会计算所有距离,然后抛出除最近的k 之外的所有距离,就像我们在这里所做的那样。但是,是的,我已经看到 kDtree 与任何 Python/Numpy 实现相比非常快。
  • @user5368737 只是好奇 - 您是否通过任何更改配置文件建议的代码并查看哪个步骤在更大的数据集上花费的时间最多?
  • 我没有使用您的代码,而是我自己的代码与spatial.KDTree,这是我做的查询(X = Y_train[tree.query(X_test, k=k)[1]]),自X_train.shape = (268288, 2) 以来需要很长时间。不幸的是,我不知道如何让它更快......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 2011-06-23
  • 2019-01-03
  • 1970-01-01
  • 1970-01-01
  • 2011-12-06
  • 2015-01-21
相关资源
最近更新 更多