【发布时间】:2021-03-12 02:27:23
【问题描述】:
我想在限制训练样本数量的同时构建一个 KNN 分类器。
例如,我有一个总共有 60K 训练样本的 MNIST 数据集,我正在寻找一种方法来选择该数据集的大小为n 的子集,以提供最佳分类器(就准确性而言)。
这相当于寻找最能“代表”数据(或数据分布)的n 样本。
下面是一些示例代码来澄清这个问题:
from sklearn.neighbors import KNeighborsClassifier
from keras.datasets import mnist
from sklearn.model_selection import train_test_split
import numpy as np
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0], -1)
x_test = x_test.reshape(x_test.shape[0], -1)
n_digits = 10
ims_per_class = list(range(1, 11)) + [12, 15, 20]
scores = []
for i in ims_per_class :
x_train_k, _, y_train_k, _ = train_test_split(x_train, y_train, train_size=n_digits * i, stratify=y_train, random_state=42)
neigh = KNeighborsClassifier(n_neighbors=1)
neigh.fit(x_train_k, y_train_k)
scores.append(neigh.score(x_test, y_test))
结果如预期所示,在随机选择样本时,随着训练样本数量的增加,模型变得更好。
但是,如果我选择在每个类由单个样本(即平均像素值)表示时训练模型,我会得到更好的结果:
x_train_mean, y_train_mean = zip(*[(x_train[y_train == i].mean(axis=0), i) for i in range(n_digits)])
x_train_mean = np.stack(x_train_mean, axis=0)
neigh.fit(x_train_mean, y_train_mean)
print(neigh.score(x_test, y_test))
0.8203
n=#classes 时,按类别平均样本比随机抽取样本产生更好的结果,我想知道 n>#classes 时如何扩展选择过程?
- 目前,问题的范围是
K=1的情况(KNN 图中的邻居数),但是,也欢迎对不同 K 值进行良好泛化的解决方案!
【问题讨论】:
-
这里的
n不清楚你的意思。在循环中,您使用n来表示每个类的图像数量。n = 11, 12, 15, 20已经是>#classes(假设 MNIST 有 10 个类)。那么你到底是什么意思呢? -
n是训练样本的总数,如果我为每个班级拍摄一张图片,最好的方法是取班级图片的平均值(即在n=10选择一个每个类的随机图像将产生acc~=0.38,而取平均值则产生acc=0.82)。我已经编辑了代码 sn-p 以使其更清晰。 -
我不明白为什么有人要选择最好的 N 张图片来训练他们的模型。如果你在测试中挑选你的数据集,它们可能会出现巨大的性能错误。我错过了什么吗?
-
@itamarkanter 要很好地代表您的图像分布,只需确保在您的 y 标签上对数据进行分层。因此,您将拥有一个均匀分布在所有不同类别之间的训练集。就是这样。
-
@ombk 我想选择最好的 n 以减小 KNN 模型的大小。请注意,在我提供的示例中,我使用分层数据训练模型。但是您可以看到,当随机抽取 10 个分层数据点(即每个类别的单个图像)时,结果比获取每个类别的平均像素强度的 10 个伪图像要差得多。我想知道是否可以找到一种类似的方法,它比随机选择图像(在 y 上分层)更好,以防我可以为每个类选择多个样本
标签: python machine-learning knn