kNN-Iris分类器(一)

“著名的鸢尾花(Iris)数据集(由Ronald Fisher于1936年发表)是一种展示机器学习框架API的好方法。从某种程度上说,Iris数据集是机器学习界的”Hello world“。数据集链接:https://archive.ics.uci.edu/ml/datasets/Iris

我叫了一学期的兰花分类器。。。竟然是鸢尾花。。。

我要去跟着小甲鱼学英语了

“人们对外界事物的识别,很大部分是把事物按分类来进行的。”比如,依靠分类我们可以区别图像上的景物、声音中的内容、医学上的疾病诊断。在我们的心目中,“房子”、“树木”都是类别概念,而不是具体的某一座房子才是房子、某一棵树才是树。人认知的过程就是对类别的认识,所以学习分类器就是机器学习的基础。

训练Learning Machine的过程:将预测结果与实际结果比较来优化Machine,使结果更逼近于实际结果。

Iris dataset是Fisher先生多年前采集的样本数据,包含了3种鸢尾花、150个样本集,每个样本集包含鸢尾花的四个特征值,分别是:花瓣长度、花瓣宽度、花蕊长度、花蕊宽度。(看到有些地方说是萼片的长宽,我也不知道萼片是什么。。。)我们将它分为两个样本集,前75个dataset(样本集)作为Train_set(训练样本),后75个dataset作为Test_set(测试样本),用来测试我通过训练样本训练得到的分类器好不好用。

01

kNN算法原理

(1)我已知三个类别的样本,分别是:小红、小蓝、小绿,现在我有个新样本,想知道它是属于哪一类。(已知:Train_set,Train_label)

(2)将测试样本点与已知的所有样本点求欧式距离。

欧式距离:

马氏距离:

S:样本协方差矩阵

欧氏距离( Euclidean distance)是一个通常采用的距离定义,它是在m维空间中两个点之间的真实距离。 它将样品的不同属性(即各指标或各变量)之间的差别等同看待,这一点有时不能满足实际要求。

马氏距离是由印度统计学家马哈拉诺比斯(P. C. Mahalanobis)提出的,表示数据的协方差距离。马氏距离不受量纲的影响,两点之间的马氏距离与原始数据的测量单位无关;由标准化数据和中心化数据(即原始数据与均值之差)计算出的二点之间的马氏距离相同。马氏距离还可以排除变量之间的相关性的干扰。

这里由于四个特征的单位都是cm,用欧式距离即可。

(3)将距离从小到大排序,记录下距离测试样本最近的k个训练样本的类别。其中在类别个数比较中占优的类别=测试样本的类别。

k的取值:取奇数,避免两个类别“平票”的情况。

02

Matlab实现

Matlab Code:

clear all;

close all;

clc

%载入数据

TrainData=load('iris_train.data');

TrainLabel=load('iris_train.labels');

TestData=load('iris_valid.data');

TestLabel=load('iris_valid.labels');

%设定k个最近邻点

k=3;

%计算TestData与TrainData间的欧式距离

fori=1:75

for j=1:75

distance(j,i)=sqrt((TestData(i,1)-TrainData(j,1))^2+(TestData(i,2)-TrainData(j,2))^2+(TestData(i,3)-TrainData(j,3))^2+(TestData(i,4)-TrainData(j,4))^2);

end

end

%将距离按升序排列,order1为原序号

[distance_ascent,order1]=sort(distance);

%选取欧式距离最小的前k个训练样本,统计其在各类别中的频率

num1=0;

num2=0;

num3=0;

error_num=0;

fori=1:75

num1=0;

num2=0;

num3=0;

for m=1:k

if TrainLabel(order1(m,i),1)==1;

num1=num1+1;

elseif TrainLabel(order1(m,i),1)==2;

num2=num2+1;

elseif TrainLabel(order1(m,i),1)==3;

num3=num3+1;

end

end

class=[num1 num2 num3];

classname=find(class(1,:)==max(class));

fprintf('测试点%d属于第%d类',i,classname);

%结果分行

if mod(i,3)==0

fprintf('\n');

end

%计算误判率

if classname~=TestLabel(i)

error_num=error_num+1;

end

end

%输出正确率

accuracy=1-(error_num/75);

fprintf('\n判断分类正确率为:%d',accuracy);

而实际上matlab里有k近邻算法的包,可以直接调用

(图片转自:csdn:Liu_LongPo)

03

结果分析

结果:

测试点1属于第1类测试点2属于第1类测试点3属于第1类

测试点4属于第1类测试点5属于第1类测试点6属于第1类

。。。。。

测试点70属于第3类测试点71属于第3类测试点72属于第3类

测试点73属于第3类测试点74属于第3类测试点75属于第3类

判断分类正确率为:9.600000e-01>>

评价:

(1)之前就k值选取的讨论并不完全,当取奇数时,投票结果可能也会出现平票。比如,选择距离测试样本最近的9个样本,其中属于3个不同类别的样本数各为3。其次,由于样本容量不均,比如某一类别样本个数远远大于另两个类别,那么测试样本更可能被分入样本容量大的类别,这样也容易形成误判。

针对这个问题我们用加权平均求距离的方法:

加权平均:w=1/s

将距离的倒数作为权值加入类别投票的考虑中,距离近的权值大,距离远的权值小。

(2)需要始终存储所有的已知样本,并将每一个新样本和所有已知样本比较、排序,计算和存储成本过大。当样本集较大,比如上万个样本点,求距离就要做10的8次方计算,计算量过大。针对这个问题我们可以建立k维树,原理及实现方法见下一篇推送!

04

参考文献

1.《模式识别》 清华大学出版社

2. csdn的大神们

今天208喝酒去!

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20171226G0JUV000?refer=cp_1026

扫码关注云+社区