模式识别实验三:k-NN算法实验

一、实验目的

1、掌握k-NN最近邻算法的基本思想;

2、认识影响算法性能的因素;

3、编写对实际模式正确分类的算法程序。

二、实验原理

(一)k-NN算法

k近邻法(k-NN)是一种基本的分类和回归方法,设有N个待分类样本为X1, X2, ..., XNM个已分类样本为Y1, Y2, ..., YM,选择k个与Xi距离最近的已分类样本,要将这N个样本分到以Z1, Z2, ...ZT 为聚类中心的T个类中,实现原理图如图3-1所示,具体的实现步骤如下:

1、计算距离。对于任一待分类样本Xi,求出其与Y1, Y2, ..., YM的距离,一般选择欧式距离作为相似性度量标准;

2、选出k个已分类样本。将各个距离排序后,选出前k个距离最小的已分类样本,$sort\left\{ ||{​{X}_{i}}-{​{Y}_{1}}||,\text{ }||{​{X}_{i}}-{​{Y}_{2}}||,\text{ }\cdots ,\text{ }||{​{X}_{i}}-{​{Y}_{M}}|| \right\}$

3、统计众数。在所选的k个样本中,分别各个样本所在的类,所在类出现次数最多的类号作为Xi的类号。

图3-1 k-NN算法原理图

(二)N折交叉验证

N折交叉验证常用来测试算法准确性,是常用的测试方法,具体的实现如图3-2所示。以N=10为例实现步骤如下:

1、将数据集分成十份,轮流将其中9份作为训练数据,1份作为测试数据,进行试验。每次试验都会得出相应的正确率;

2、10次的结果的正确率的平均值作为对算法精度的估计,一般还需要进行多次10折交叉验证,再求其均值,作为对算法准确性的估计。

图3-2 十折交叉验证原理图

三、实验内容

1、根据已有的数据,将模式集划分为训练集和测试集,并对测试集分类;

2、统计错分概率,分析产生错分的原因;

四、实验结果与分析

(一)实验结果

表3-1 k-NN算法不同分类的准确率统计数据(计算次数M=10)

数据序号datai

拆分折数N

近邻数k

平均准确率A%

1

7

10

99.09

7

20

98.67

10

10

99.40

2

5

10

99.05

5

20

98.85

9

10

99.46

3

3

10

99.28

3

20

99.22

8

10

99.20

(二)实验图像

图1 原始数据类数为2

图2 原始数据类数为3

图3 测试集类数为2

 图4 测试集类数为3

图5 输出结果类数为2

图6 输出结果类数为3

(三)实验代码

数据集及代码可于文章顶部进行资源下载

1、k-NN算法:KNN.m

function class = KNN(T, k, trainset, sample)
%% 函数功能:利用k近邻分析法实现分类
% 参数说明:
% T:取前T个距离最小的数
% k:分类数
% trainset:训练集
% sample:待分类数据

%% 变量初始化
[trainM, trainN] = size(trainset);
[M, N] = size(sample);
class = zeros(M, 1);

%% 主函数
for i=1:M
    for j=1:trainM
        D(j,:) = dist(sample(i, :), trainset(j, 1:trainN-1)');
    end
    [~, idx_sort] = sort(D);
    idx_sort = idx_sort(1: T);
    classlab = trainset(idx_sort, trainN);
    count= zeros(k, 1);
    for j=1:T
        count(classlab(j)) = count(classlab(j))+1;
    end
    [~, class(i)] = max(count);
end

2、准确率计算:Calcu_Accuracy.m

function accuracy = Calcu_Accuracy(textset, class)
%% 功能:计算准确率
% textset:验证集
% class:分类结果

[textM, textN] = size(textset);
wrong = 0;

for i=1:textM
    if textset(i, textN) ~= class(i)
        wrong = wrong+1;
    end
end

accuracy = (textM - wrong)/(textM);

3、主程序:main.m

clear; clc; 
load('Data03_knn_nclassesoriginal.mat');

res = zeros(10, 1);

for i=1:10
%%  数据集预处理
    [M, N] = size(X);
    k = 2; % 将初始数据分为三类
    idx = kmeans(X, k);
    X(:, N) = idx;
    str = {'rx', 'go', 'b*', 'y<'};

%     figure(1);
%     hold on;
%     for i=1:M
%         plot(X(i, 1), X(i, 2), str{X(i, 3)});
%     end
%     hold off

%% 训练集与测试集划分
    indices=crossvalind('Kfold', X(1:M, N), 8);
    textIdx = (indices == 3);
    trainIdx = ~textIdx;
    textset = X(textIdx, :);
    trainset = X(trainIdx, :);
    sample = textset(:, 1:N-1);

%% 使用KNN算法分类
    T = 10;
    class = KNN(T, k, trainset, sample);

%% 可视化
% figure(2);  %% 输出测试集
% hold on
% for i=1:size(textset, 1)
%     plot(textset(i, 1), textset(i, 2), str{textset(i, 3)});
% end
% hold off
% 
% figure(3)   %% 输出测试结果
% hold on
% for i=1:size(textset, 1)
%     plot(textset(i, 1), textset(i, 2), str{class(i)});
% end
% hold off

%% 返回最后的准确率
    accuracy = Calcu_Accuracy(textset, class);
    res(i) = accuracy;
end
sum(res)
mean(res)

(四)实验分析

1、总体来说,k-NN算法对此次使用的三组数据的分类准确率比较高,保持在98%以上;

2、就近邻数k而言,此次实验只选取了k=10和k=20两种情况,根据实验结果前者的准确率大于后者,这也表示k的选取并不是越大越好,随着k的增大,可能会受到其他异常值或者数据分布的干扰;

3、就拆分折数N而言,前两组的拆分折数较大的一方都取得了更高的准确率,但是第三组可能由于样本数据有些许混杂导致N越大准确率并没有明显的提升。

五、思考与提高

1、k-NN算法中,k值对判决结果有什么影响?如何比较并选取合适的k值;

答:(1)k值对噪声和异常值的影响:

a、当k值较小,更容易受到噪声和异常值的影响。因为异常值可能会对最近的k个邻居的平均值产生较大影响,导致不准确的分类结果。

b、当k值较大,异常值对结果的影响会相对较小,因为它们在计算平均值时的权重会降低。但这也可能导致另一个问题,即“投票疲劳”。当k值过大时,即使某个类别有很多样本,其最近邻居可能仍然会比其他类别的样本少,这可能导致类别不平衡问题。

(2)如何比较并选取合适的k值:

a、使用交叉验证:通过交叉验证,我们可以评估不同k值下的模型性能。对于分类问题,可以使用混淆矩阵或准确率来评估;对于回归问题,可以使用均方误差等指标来评估。通过交叉验证,我们可以找到在特定数据集上表现最好的k值。

b、考虑数据集的规模:如果数据集很大,可以考虑使用较大的k值;如果数据集较小,可以考虑使用较小的k值。这是因为在大数据集上,最近邻居可能更具有代表性。

2、有哪些方法可以将模式集划分为训练集、测试集等?

答:(1)留出法:将数据集直接划分为两个互斥的集合,其中一个作为训练集,另一个作为测试集。这种方法的重点是确保训练/测试集的划分要尽可能保持数据分布的一致性,以避免因数据划分过程引入额外的偏差而对最终结果产生影响。

(2)随机划分:这是最常用的划分方法之一。它通过随机地将数据集中的样本划分为训练集和测试集。通常情况下,会将大部分样本划分为训练集,剩余样本划分为测试集。这种方法简单快捷,适用于各种数据集。

(3)时间序列划分:这是针对时间序列数据的一种特殊划分方法。在时间序列问题中,数据样本的观测值是按照时间顺序排列的。由于时间的因素,将数据集随机划分为训练集和测试集会导致训练集和测试集之间存在时间上的断裂,从而影响模型的泛化能力。

3、要实现重复剪辑k-NN,需要哪些关键步骤?

答:(1)将数据集D分为多个样本集。

(2)互相作为新的训练集和测试集。

(3)按照剪辑法的步骤进行训练和测试。

(4)根据性能评估结果调整参数或更换算法进行优化。

(5)重复以上步骤直至达到预设的迭代次数或性能要求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值