机器学习笔记-KNN分类

系列文章目录

一、KNN算法介绍

  本章将学习KNN算法,KNN又称K近邻(k-nearest neighbor,k-NN)。该算法即可以解决分类问题,又可以解决回归问题,只不过解决回归问题是在分类问题基础上提出的,所以本文只讨论分类算法。
  KNN算法的核心就是近朱者赤近墨者黑。对于给定的数据训练集,其中类别已经分好,对于一个新的数据样本点,根据其最近的 k k k个最近邻来决定新样本点的类别,决定方法就是进行投票,通过多数表决的方式进行预测。
如果结合图形看起来会更清晰:
在这里插入图片描述
  像这个图一样,我们需要通过已有的三种样本点的数据来判断空心圆所属的种类,在KNN算法中,我们需要对紫色圆内的点的种类进行一个投票表决,显然在空心圆周围,有红色样本点4个,绿色样本点3个,黑色样本点2个,红色样本点出现的次数最多,于是将空心圆归为红色样本点。
  KNN的分类原理就是上述这样,我们可以发现,KNN算法是不具有显式的学习过程,是一种惰性算法,即我们不需要先通过训练集数据学习一个模型,而是直接计算待测样本点与训练集的距离,从而直接预测。

二、KNN算法实现

  其实在初步了解KNN算法之后,我们就能知道,KNN算法是没有太多数学模型的,其主要的思想就在于K值的选取和计算距离的方式。

2.1.K值的确定

  在KNN分类算法中,K值的选取可以说是最重要的,合适的K值可以使得模型更优秀。
当K值较小时,就相当于使用较小的领域来对样本点进行预测,也就说只有与预测实例相近的点才起到作用,如果该点是噪声点,那么很容易导致模型预测错误。这也说明K值小,模型容易过拟合。
  当K值较大时,相当于搜索的领域较大,距离预测点很远的样本都会起作用,这样也可能导致预测错误,就相当于欠拟合。
  所以K值的选取非常重要,一般在确定K值时使用的方法就是交叉验证。遍历可能取值的K值,计算当K取不同值时的误差大小,取最小误差时的K值作为最优K值。

2.2.距离计算方式

  除了确定K值这一重要工作以外,计算距离的方式也是非常重要的。何为计算距离的方式,我们前面说了,要根据预测点最近的K个样本点来进行投票表决,但是如何知道哪K个点距离预测点最近呢?我在举例中是通过画图,在图上观察得到的。但是在真实计算过程中,可不能通过观察得到,我们需要找到一个能够反映距离远近的度量,也就是距离计算方式。
假设给定两个样本点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1) ( x 2 , y 2 ) (x_2,y_2) (x2,y2),那么如何计算这两个样本点之间的距离呢?
最常用的计算距离方式就是欧式距离:
D = ∑ l = 1 N ( x 1 ( l ) − x 2 ( l ) ) 2 D=\sqrt {\sum\limits_{l=1}^N({x^{(l)}_1-x^{(l)}_2})^2} D=l=1N(x1(l)x2(l))2
  其中 N N N表示特征的维数,除了欧式距离以外,还有其他的距离公式例如曼哈顿距离和切比雪夫距离等等,一般来说,我们最常用的距离公式就是欧式距离。在确定好距离的计算公式之后,我们就可以试着编写KNN算法的程序了。

2.3.KNN算法实例实现

  知道了如何选取K值和如何计算样本之间的距离后,我们就可以编写代码,这次使用的任然是Matlab,使用什么语言不重要,主要是能够理解算法的本质,Matlab相比于Python有很多便捷的函数可以使用。
  在分类前,我们需要对数据进行归一化处理,因为不同特征之间的度量肯定是不一样的,就比如一个人的身高和体重,身高可以达到180cm,体重60kg,如果只看数值的话180>60,但是体重和身高之间是没法进行比较的,所以我们不能直接带入欧式距离计算公式,需要对不同量纲的数据进行归一化,将数据都缩放在0-1之间,这样后续计算欧式距离时就可以进行比较了。
  处理完数据之后,我们需要了解KNN算法的结构,对于一个新的输入样本点,我们需要计算已知所有的样本点与新的样本点之间距离,然后取距离最近的K个样本点为”邻居“,再从邻居中进行投票决定,将新样本点归为票数最多的类别,输出该类别,即KNN算法结束。
下面来看代码:

主函数

clc,clear
tic
% 读取数据
XlRange = 'A2:D68';
data_old = xlsread('多分类水果数据',XlRange);
labels = xlsread('多分类水果数据','E2:E60');
% 数据预处理
data_new = zeros(size(data_old));
for i=1:size(data_old,2) % 遍历每一行
    value_max = max(data_old(:,i));
    value_min = min(data_old(:,i));
    for j =1:size(data_old,1)
        data_new(j,i) = (data_old(j,i) - value_min)/(value_max - value_min);
    end
end
% 划分测试集与训练集
data_train = data_new(1:59,:);
data_test = data_new(60:67,:);
K = 7;
% 这里的model等于2表示计算KNN算法的方式不同,最后结果都是一样的
model = 2;
% 主函数部分
for i =1:size(data_test,1)% 遍历测试集所有数据
    label = KNN(data_test(i,:),data_train,labels,K,model);
    disp(['第',num2str(i),'个测试集数据的类别为:',num2str(label)])
end
toc

KNN分类函数

function [label] = KNN(test,train,labels,K,model)
% KNN函数部分
% 计算输入数据距离与样本点的距离
[n,~] = size(train);
dist =  zeros(n,1);
for i =1:n
    dist(i,:) = norm(train(i,:)-test);
end
% 对距离进行排序
[y,I] = sort(dist,1);
K = min(K,length(y));
class_sort = labels(I); % 得到对应排序的标签
% 1
if model == 1
    class = class_sort(1:K); % 获取前K个的标签
%     class_num = length(unique(class)); % 获得前K个标签种类的个数
    class_ma = zeros(max(class),1); % 提前创造一个矩阵存储后续标签出现的个数
    for i =1:length(class) % 遍历前K个标签
        temp = class(i);
        class_ma(temp) = class_ma(temp) + 1;
    end
    % 找到出现次数最多的标签
    [~,label] = max(class_ma);
else % 直接用众数计算函数
    label=mode(class_sort(1:K));
end
end

三、kNN算法总结

  KNN算法与常规的机器学习算法相比非常特殊,由于其没有显式的学习过程,所以就不存在过多的参数,影响结果的只有一个参数 k k k,而且算法的思想非常简单易懂。
KNN算法的优点

  1. 简单易用,相比其他算法,KNN算法非常易懂,即使没有高数知识也能搞懂其原理;
  2. 模型训练时间较快;
  3. 对异常值不是很敏感;
  4. 由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合

KNN算法的缺点

  1. 每一次对预测点都需要计算所有样本点与预测点的距离,对内存要求较高;
  2. 对于预测样本点的可解释性不强;
  3. KNN算法在处理样本不平衡的情况下效果不好。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值