我目前正在阅读Ethem Alpaydin的《机器学习导论》,在书中遇到了最近邻质心分类器并尝试实现它。我认为我已经正确实现了这个分类器,但我的准确率只有68%。那么,是最近邻质心分类器本身效率低,还是我的实现(如下)有错误?
数据集包含1372个数据点,每个数据点有4个特征,并且有2个输出类别。我的MATLAB实现如下:
DATA = load("-ascii", "data.txt");#DATA是1372x5的矩阵,其中762个数据点属于类别0,610个数据点属于类别1#每个数据点有4个特征X = DATA(:,1:4); #存储所有特征的矩阵X0 = DATA(1:762,1:4); #存储类别0特征的矩阵X1 = DATA(763:1372,1:4); #存储类别1特征的矩阵X0 = X0(1:610,:); #确保两个数据集大小相同,以便先验概率相等Y = DATA(:,5); #存储输出mean0 = sum(X0)/610; #类别0特征的均值mean1 = sum(X1)/610; #类别1特征的均值count = 0;for i = 1:1372 pre = 0; cost1 = X(i,:)*(mean0'); #计算数据集与两个类别特征均值的点积 cost2 = X(i,:)*(mean1'); if (cost1<cost2) pre = 1; end if pre == Y(i) count = count+1; #计算正确预测值的数量 endenddisp("accuracy"); #计算准确率disp((count/1372)*100);
回答:
这里至少有几点需要注意:
-
你使用点积来分配输入空间的相似性,这几乎永远是不合理的。使用点积的唯一理由是假设所有数据点的范数相同,或者范数无关紧要(几乎从不成立)。尝试使用欧几里得距离代替,虽然它非常简单,但应该会显著改善效果。
-
它是一个效率低的分类器吗?这取决于对效率的定义。它是一个极其简单且快速的分类器,但在预测能力方面是极其差的。实际上,它比已经视为“玩具模型”的朴素贝叶斯还要差。
-
代码中也有一些问题
X0 = DATA(1:762,1:4); #存储类别0特征的矩阵X1 = DATA(763:1372,1:4); #存储类别1特征的矩阵X0 = X0(1:610,:); #确保两个数据集大小相同,以便先验概率相等
一旦你对X0进行子采样,你就有1220个训练样本,但在“测试”过程中,你同时在训练集和“X0缺失的元素”上进行测试,这从概率的角度来看并不合理。首先,你永远不应该在训练集上测试准确率(因为这会高估真实准确率),其次,通过子采样你的训练数据,你没有平衡先验概率。在这种方法中,你只是降低了质心估计的质量,仅此而已。这类技术(子/过采样)对于确实建模先验概率的模型来说可以平衡先验概率。你的方法没有(因为它基本上是假设先验概率为1/2的生成模型),所以不会有好的结果。