【问题标题】:Using k-nearest neighbour without splitting into training and test sets使用 k 近邻而不拆分为训练集和测试集
【发布时间】:2017-06-04 15:32:36
【问题描述】:

我有以下数据集,超过 20,000 行:

我想使用列 A 到 E 使用 k 近邻算法预测列 X。我曾尝试使用 sklearn 中的KNeighborsRegressor,如下:

import pandas as pd
import random
from numpy.random import permutation
import math
from sklearn.neighbors import KNeighborsRegressor

df = pd.read_csv("data.csv")

random_indices = permutation(df.index)
test_cutoff = int(math.floor(len(df)/5))
test = df.loc[random_indices[1:test_cutoff]]
train = df.loc[random_indices[test_cutoff:]]

x_columns = ['A', 'B', 'C', D', E']
y_column = ['X']

knn = KNeighborsRegressor(n_neighbors=100, weights='distance')
knn.fit(train[x_columns], train[y_column])
predictions = knn.predict(test[x_columns])

这仅对原始数据集的五分之一的测试数据进行预测。我还想要训练数据的预测值。

为此,我尝试通过计算每行与其他行的欧几里得距离、找到 k 个最短距离并从这 k 行中取 X 值的平均值来实现我自己的 k-最近算法。这个过程只用了 30 多秒,我有超过 20,000 行。有没有更快的方法来做到这一点?

【问题讨论】:

  • 因此您将KNeighorsRegressor 拟合到训练数据上并预测到测试中。你已经有了一个训练有素的模型,那么为什么不直接做knn.predict(train[x_columns]) 呢?或者也许你应该做 k-fold 交叉验证,所以不会有任何行被排除在“测试”之外。您基本上会从 CV 构建一个平均模型并预测所有内容。或者只是在整个数据集上拟合一个模型并预测整个数据集:knn.fit(df[x_columns], df[y_column])
  • 我尝试了您的第一个建议,但它只是准确地预测了 X 列的值。对整个数据集进行建模也是如此。正如我在问题末尾提到的,我基本上实现了 k 折交叉验证,但每一行只需要很长时间。

标签: python numpy machine-learning scikit-learn nearest-neighbor


【解决方案1】:

如果您只需要对训练数据进行预测,则无需将数据拆分为训练和测试。

您可以只拟合原始数据,然后对其进行预测。

model.fit(original data, target)
model.predict(original data)

【讨论】:

    【解决方案2】:

    试试这个代码:

    import numpy as np
    import pandas as pd
    from sklearn.model_selection import ShuffleSplit
    from sklearn.neighbors import KNeighborsRegressor
    
    df = pd.read_csv("data.csv")
    X = np.asarray(df.loc[:, ['A', 'B', 'C', 'D', 'E']])
    y = np.asarray(df['X'])
    
    rs = ShuffleSplit(n_splits=1, test_size=1./5, random_state=0)
    train_indices, test_indices = rs.split(X).next()
    
    knn = KNeighborsRegressor(n_neighbors=100, weights='distance')
    knn.fit(X[train_indices], y[train_indices])
    
    predictions = knn.predict(X)
    

    您的解决方案的主要区别在于使用ShuffleSplit

    注意事项:

    • predictions 包含所有数据(测试和训练)的预测值。
    • 可以通过参数test_size调整测试数据的比例(我用的是你的设置,即五分之一)。
    • 需要为迭代器调用方法next() 以产生训练和测试数据的索引。

    【讨论】:

      【解决方案3】:

      为此,我尝试通过计算每行与其他行的欧几里得距离、找到 k 个最短距离并从这 k 行中取 X 值的平均值来实现我自己的 k-最近算法。这个过程只用了 30 多秒,我有超过 20,000 行。有没有更快的方法来做到这一点?

      是的,问题在于 python 中的循环非常慢。您可以做的是矢量化您的计算。因此,假设您的数据在矩阵 X (n x d) 中,然后是距离矩阵 D_ij = || X_i - X_j ||^2 是

      D = X^2 + X'^2 -  2 X X'
      

      在 Python 中是这样

      D = (X ** 2).sum(1).reshape(-1, 1) + (X ** 2).sum(1).reshape(1, -1) - 2*X.dot(X.T)
      

      【讨论】:

      • 那么每行数据的距离是矩阵D的行还是列?
      • D_ij 元素将是 X_i 和 X_j 之间的平方距离。由于距离矩阵是对称的,您可以按行或按列解释(但在数学上 - 第 i 行表示 X_i 与所有剩余行的距离)。
      猜你喜欢
      • 2017-11-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-11
      • 1970-01-01
      • 1970-01-01
      • 2018-04-22
      • 2017-07-17
      • 1970-01-01
      相关资源
      最近更新 更多