上一篇文章总结了k-近邻算法的基本思想和伪代码、Matlab代码实现,本文使用Matlab对书中2.2节所提到的约会网站配对效果问题进行实现。
问题抽象与描述
海伦同学想要自动寻找适合自己的约会对象,那么她所描述的三种类型的人,即不喜欢的人、魅力一般的人和极具魅力的人(三种标签)。对于这些人,可以通过他们每年获得的飞行常客里程数、玩视频游戏所耗时间百分比以及每周消费的冰激凌公升数(三种特征)进行判别。问题简化为:手上有带标签的一组数据,判断新输入的数据(对应于一个人)属于哪个分类。
我们首先来看一下数据的分布情况,图中显示的是采用两个维度的特征进行绘制的样本
对于样本所提供的数据,如果直接采用原始数据进行距离测算,那距离将直接受到数字差值最大的特征的影响,为了保证每种特征对结果的影响程度一致,需对数据进行归一化处理。 归一化特征值代码如下:
function [normDataSet,range,minVals] = autoNorm(dataSet)
for i =1:size(dataSet,2)
minVals(i) = min(dataSet(:,i));
maxVals(i) = max(dataSet(:,i));
range(i) = maxVals(i) - minVals(i);
normDataSet(1:length(dataSet),i) = minVals(i);
normDataSet(:,i) = (dataSet(:,i) - normDataSet(:,i))/range(i);
end
分类器测试代码如下:
clc;
clear;
%导入数据并归一化数据
[returnMat,classLabelVector] = file2matric('datingTestSet2');
[returnMat,range,minVals] = autoNorm(returnMat);
%设定测试集大小
hoRatio = 0.1;
numTestVecs = length(returnMat) * hoRatio;
errorCount = 0;
%测试分类器
for i = 1 : numTestVecs
classifierResult(i,1) = classify0(returnMat(i,:),returnMat(numTestVecs+1:length(returnMat),:),classLabelVector(numTestVecs+1:length(returnMat)),3);
% fprintf('Output:%c,Original:%c\n',classifierResult(i,1),classLabelVector{i});
if ~strcmp(classifierResult(i),classLabelVector(i))
errorCount = errorCount + 1;
end
end
errorRate = errorCount/numTestVecs;
%% 画图
figure;
for i = 1:length(classLabelVector)
switch classLabelVector(i)
case '1'
scatter(returnMat(i,1),returnMat(i,2),'r.');
% text(returnMat(i,1),returnMat(i,2),classLabelVector{i},'Color','red');
hold on;
case '2'
scatter(returnMat(i,1),returnMat(i,2),'g.');
% text(returnMat(i,1),returnMat(i,2),classLabelVector{i},'Color','green');
hold on;
case '3'
scatter(returnMat(i,1),returnMat(i,2),'b.');
% text(returnMat(i,1),returnMat(i,2),classLabelVector{i},'Color','black');
hold on;
end
end
for i=1:numTestVecs
switch classifierResult(i)
case '1'
text(returnMat(i,1),returnMat(i,2),classLabelVector(i),'Color','red');
hold on;
case '2'
text(returnMat(i,1),returnMat(i,2),classLabelVector(i),'Color','green');
hold on;
case '3'
text(returnMat(i,1),returnMat(i,2),classLabelVector(i),'Color','black');
hold on;
end
end
axis([-0.1 1.1 -0.1 1.1]);
其中,file2matric函数提供从txt文本中导入数据的功能,代码如下:
function [returnMat,classLabelVector] = file2matric(filename)
dataWithLabels = importdata(strcat(filename,'.txt'));
returnMat = dataWithLabels(:,1:size(dataWithLabels,2)-1);
classLabelVector = num2str(dataWithLabels(:,size(dataWithLabels,2)));
最后的分类结果可以在图形中展示:
算法最后计算的errorRate=8%。
另外,上一篇文章及本文的k-近邻算法实现源码(Matlab)及数据均可在本人github(https://github.com/guankaer/kNN)上查看。源码中还提供了一个使用此数据集进行用户交互判别的简单程序classifyperson.m。