KNN分类器

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

KNN 分类器
KNN 学习(K-Nearest Neighbor algorithm ,K 最邻近⽅法 )是⼀种统计分类器,对数据的特征变量的筛选尤其有效。

基本原理
KNN 的基本思想是:输⼊没有标签(标注数据的类别),即没有经过分类的新数据,⾸先提取新数据的特征并与測试集中的每⼀个数据特征进⾏⽐較;然后从測试集中提取K 个最邻近(最类似)的数据特征标签,统计这K 个最邻近数据中出现次数最多的分类,将其作为新的数据类别。

KNN 的这样的基本思想有点类似于⽣活中的“物以类聚。

⼈以群分”。

在KNN 学习中,⾸先计算待分类数据特征与训练数据特征之间的距离并排序。

取出距离近期的K 个训练数据特征。

然后根据这K 个相近训练数据特征所属类别来判定新样本类别:假设它们都属于⼀类,那么新的样本也属于这个类;否则,对每⼀个候选类别进⾏评分,依照某种规则确定新的样本的类别。

笔者借⽤以下这个图来做更形象的解释:
如上图,图中最⼩的那个圆圈代表新的待分类数据。

三⾓形和矩形分别代表已知的类型,如今须要推断圆圈属于菱形那⼀类还是矩形那⼀类。

可是我该以什么样的根据来推断呢?
1. 看离圆形近期(K=1)的那个类型是什么,由图可知,离圆形近期的是三⾓形,故将新数据判定为属于三⾓形这个类别。

2. 看离圆形近期的3个数据(K=3)的类型是什么,由图可知离圆形近期的三个中间有两个是矩形,⼀个是三⾓形,故将新数据判定为属于矩形这个类别。

3. 看离圆形近期的9个数据(K=9)的类型是什么,由图可知离圆形近期的9个数据中间,有五个是三⾓形。

四个是矩形。

故新数据判定为属于三⾓形这个类别。

上⾯所说的三种情况也能够说成是1-近邻⽅法、3-近邻⽅法、9-近邻⽅法。

当然,K 还能够取更⼤的值,当样本⾜够多,且样本类别的分布⾜够好的话,那么K 值越⼤,划分的类别就越正确。

⽽KNN 中的K 表⽰的就是划分数据时。

所取类似样本的个数。

我们都知道,当K=1时,其抗⼲扰能⼒就较差。

由于假如样本中出现了某种偶然的类别,那么新的数据⾮常有可能被分错。

为了添加分类的可靠性,能够考察待測数据的K 个近期邻样本 。

统计这K 个近邻样本中属于哪⼀类别的样本最多,就将样本X 判属于该类。

当然。

假设在样本有限的情况下,KNN 算法的误判概率和距离的详细測度⽅法就有了直接关系。

即⽤何种⽅式判定哪些数据与新数据近邻。

不同的样本选择不同的距离測量函数,这能够提⾼分类的正确率。

通常情况下,KNN 能够採⽤Euclidean (欧⼏⾥得)、Manhattan (曼哈顿)、Mahalanobis (马⽒距离)等距离⽤于计算。

Euclidean 距离为:
Manhattan 距离为:
Mahalanobis 距离为:当中n 为特征的维数,为和所在的数据集的协⽅差函数。

以下给出KNN 学习的伪代码:
Algorithm KNN(A[n],k,x)
Input:
A[n]为N 个训练样本的特征,K 为近邻数,x 为新的样本;
Initialize:
取A[1]~A[k]作为x 的初始近邻。

计算測试样本与x 间的欧式距离d(x,A[i]),i=1,2...,k;
按d(x,A[i])升序排序。

计算最远样本与x 间距离D 。

即max{d(x,A[i])};
for(i=k+1;i<=n;i++)
计算A[i]与x 之间的距离d(x,A[i]);
if (d(x,A[i]))<D then ⽤A[i]取代最远样本。

依照d(x,A[i])升序排序;
计算最远样本与x 间的距离D ,即max{d(x,A[i])};
End for
计算前K 个样本A[i],i=1,2...,k 所属类别的概率。

具有最⼤概率的类别即为样本x 的类;
Output:x 所属的类别。

d (,)=[]
x y ∑i =1n (−)x i y i 2=(,,...,)x x 1x 2x n =(,,...,)
y y 1y 2y n d (,)=|−|
x y ∑i =1n x i y i d (,)=(−(−)x y x y )′V −1x y
V x y
KNN 的不⾜
1、添加某些类别的样本容量⾮常⼤,⽽其它类样本容量⾮常⼩,即已知的样本数量不均衡。

有可能当输⼊⼀个和⼩容量类同样的的新样本时,该样本的K 个近邻中,⼤容量类的样本占多数,从⽽导致误分类。

针对此种情况能够採⽤加权的⽅法,即和该样本距离⼩的近邻所相应的权值越⼤,将权值纳⼊分类的參考根据。

2、分类时须要先计算待分类样本和全体已知样本的距离。

才⼲求得所需的K 近邻点,计算量较⼤,尤其是样本数量较多时。

针对这样的情况能够事先对已知样本点进⾏剪辑。

去除对分类作⽤不⼤的样本,这⼀处理步骤仅适⽤于样本容量较⼤的情况,假设在原始样本数量较少时採⽤这样的处理。

反⽽会添加误分类的概率。

改进的KNN 算法
KNN 学习easy 受噪声影响,尤其是样本中的孤⽴点对分类或回归处理有⾮常⼤的影响。

因此通常也对已知样本进⾏滤波和筛选,去除对分类有⼲扰的样本。

K 值得选取也会影响分类结果。

因此需根据每类样本的数⽬和分散程度选取合理的K 值,⽽且对不同的应⽤也要考虑K 值得选择。

基于组合分类器的KNN 改进算法
经常使⽤的组合分类器⽅法有投票法、⾮投票法、动态法和静态法等,⽐⽅简单的投票法中全部的基分类器对分类採取同样的权值;权值投票法中每⼀个基分类器具有相关的动态权重,该权重能够随时间变化。

⾸先随机选择属性⼦集。

构建多个K 近邻分类器;然后对未分类元组进⾏分类。

最后把分类器的分类结果依照投票法进⾏组合,将得票最多的分类器作为终于组合近邻分类器的输出。

基于核映射的KNN 改进算法
将原空间中的样本映射到⼀个⾼维的核空间F 中,突出不同类别样本之间的特征差异出。

使得样本在核空间中变得线性可分或者近似线性可分,其流程例如以下所看到的:
⾸先进⾏⾮线性映射:
然后在⾼维的核空间。

待分类的样本变为。

随意两个样本。

之间的距离为:
当中为核函数,在此基础上进⾏KNN 分类。

实践代码
以下给出⼀个简单的KNN 分类的MATLAB 实践代码:
main.m ⽂件
function main
trainData = [
0.6213 0.5226 0.9797 0.9568 0.8801 0.8757 0.1730 0.2714 0.2523
0.7373 0.8939 0.6614 0.0118 0.1991 0.0648 0.2987 0.2844 0.4692
];
trainClass = [
1 1 1
2 2 2
3 3 3
];
testData = [
0.9883 0.5828 0.4235 0.5155 0.3340
0.4329 0.2259 0.5798 0.7604 0.5298
];
% main
testClass = cvKnn(testData, trainData, trainClass);
% plot prototype vectors
classLabel = unique(trainClass);
nClass = length(classLabel);
plotLabel = {'r*', 'g*', 'b*'};
figure;
for i=1:nClass
A = trainData(:, trainClass == classLabel(i));
plot(A(1,:), A(2,:), plotLabel{i});
hold on;
end
% plot classifiee vectors
plotLabel = {'ro', 'go', 'bo'};
for i=1:nClass
R n x Φ:→F ,x →Φ(x )
R n (Φ(),...,Φ())x 1x n Φ()x i Φ()x j ∥Φ()−Φ()=K (,)+K (,)
x i x j ∥2x i x i x j x j K (∗,∗)
A = testData(:, testClass == classLabel(i));
plot(A(1,:), A(2,:), plotLabel{i});
hold on;
end
legend('1: prototype','2: prototype', '3: prototype', '1: classifiee', '2: classifiee', '3: classifiee', 'Location', 'NorthWest'); title('K nearest neighbor');
hold off;
KNN.m⽂件
function [Class, Rank] = cvKnn(X, Proto, ProtoClass, K, distFunc)
if ~exist('K', 'var') || isempty(K)
K = 1;%默觉得K = 1
end
if ~exist('distFunc', 'var') || isempty(distFunc)
distFunc = @cvEucdist;
end
if size(X, 1) ~= size(Proto, 1)
error('Dimensions of classifiee vectors and prototype vectors do not match.');
end
[D, N] = size(X);
% Calculate euclidean distances between classifiees and prototypes
d = distFunc(X, Proto);
if K == 1, % sort distances only if K>1
[mini, IndexProto] = min(d, [], 2); % 2 == row%每列的最⼩元素
Class = ProtoClass(IndexProto);
if nargout == 2, % instance indices in similarity descending order
[sorted, ind] = sort(d'); % PxN
RankIndex = ProtoClass(ind); %,e.g., [2 1 2 3 1 5 4 1 2]'
% conv into, e.g., [2 1 3 5 4]'
for n = 1:N
[ClassLabel, ind] = unique(RankIndex(:,n),'first');
[sorted, ind] = sort(ind);
Rank(:,n) = ClassLabel(ind);
end
end
else
[sorted, IndexProto] = sort(d'); % PxN
clear d。

% K closest
IndexProto = IndexProto(1:K,:);
KnnClass = ProtoClass(IndexProto);
% Find all class labels
ClassLabel = unique(ProtoClass);
nClass = length(ClassLabel);
for i = 1:nClass
ClassCounter(i,:) = sum(KnnClass == ClassLabel(i));
end
[maxi, winnerLabelIndex] = max(ClassCounter, [], 1); % 1 == col
% Future Work: Handle ties somehow
Class = ClassLabel(winnerLabelIndex);
end
Eucdist.m⽂件
function d = cvEucdist(X, Y)
if ~exist('Y', 'var') || isempty(Y)
%% Y = zeros(size(X, 1), 1);
U = ones(size(X, 1), 1);
d = abs(X'.^2*U).'; return;
end
V = ~isnan(X); X(~V) = 0; % V = ones(D, N);
%clear V;
U = ~isnan(Y); Y(~U) = 0; % U = ones(D, P);
%clear U;
%d = abs(X'.^2*U - 2*X'*Y + V'*Y.^2);
d1 = X'.^2*U;
d3 = V'*Y.^2;
d2 = X'*Y;
d = abs(d1-2*d2+d3);
代码效果例如以下:。

相关文档
最新文档