K最临近(K-Nearest Neighbors,KNN)方法是一种简单且直观的分类和回归算法,主要用于分类任务。其基本原理是用到表决的方法,找到距离其最近的K个样本,然后通过K个样本的标签进行表决,预测结果给出的标签是表决多的一方。
在使用K最临近方法的时候,有两个方面可调:
一是K值的大小,K一般选用单数,这样不会导致在进行表决时出现概率相等的情况。
二是样本之间的距离,由于样本特征的分布不同,因此在描述两样本之间的距离时有多种方式可以描述,例如:欧氏距离(Euclidean Distance)、曼哈顿距离(Manhattan Distance)和闵可夫斯基距离(Minkowski Distance)等。而且往往由于选择的距离不同,对应的K值也不一样,大家可以根据自己的数据特点尝试用不用的距离构建分类模型。本文提供了这些方法供大家选择。
在matlab中实现K最临近方法构建分类模型的代码如下:
labels = res(:, 1); % 第一列是标签 features = res(:, 2:end); % 后面的列是特征 features = zscore(features); %归一化处理 % %% 欧式距离 % % % % 设置 K 值 % K = 7; % % % 初始化分类准确度 % accuracy = 0; % % % 留一交叉验证 % for i = 1:size(features, 1) % % 从样本中选择一个作为验证样本,其余作为训练样本 % validation_sample = features(i, :); % validation_label = labels(i); % % train_samples = features([1:i-1, i+1:end], :); % train_labels = labels([1:i-1, i+1:end]); % % % 计算验证样本与训练样本的距离 % distances = sqrt(sum((train_samples - validation_sample).^2, 2)); % % % 寻找最近的 K 个邻居 % [~, idx] = mink(distances, K); % % % 投票确定验证样本的类别 % predicted_label = mode(train_labels(idx)); % % % 检查预测结果是否正确 % if predicted_label == validation_label % accuracy = accuracy + 1; % end % end % % % 计算分类准确度 % accuracy = accuracy / size(features, 1); % disp(['分类准确度:', num2str(accuracy)]); % % % % 曼哈顿距离 % % % % 设置 K 值 % K = 9; % % % 初始化分类准确度 % accuracy = 0; % % % 留一交叉验证 % for i = 1:size(features, 1) % % 从样本中选择一个作为验证样本,其余作为训练样本 % validation_sample = features(i, :); % validation_label = labels(i); % % train_samples = features([1:i-1, i+1:end], :); % train_labels = labels([1:i-1, i+1:end]); % % % 计算曼哈顿距离 % distances = sum(abs(train_samples - validation_sample), 2); % % % 寻找最近的 K 个邻居 % [~, idx] = mink(distances, K); % % % 投票确定验证样本的类别 % predicted_label = mode(train_labels(idx)); % % % 检查预测结果是否正确 % if predicted_label == validation_label % accuracy = accuracy + 1; % end % end % % % 计算分类准确度 % accuracy = accuracy / size(features, 1); % disp(['分类准确度:', num2str(accuracy)]); % %% 闵可夫斯基距离 % % % 设置 K 值 % K = 5; % % % 初始化分类准确度 % accuracy = 0; % % % 留一交叉验证 % for i = 1:size(features, 1) % % 从样本中选择一个作为验证样本,其余作为训练样本 % validation_sample = features(i, :); % validation_label = labels(i); % % train_samples = features([1:i-1, i+1:end], :); % train_labels = labels([1:i-1, i+1:end]); % % % 计算闵可夫斯基距离 % distances = pdist2(train_samples, validation_sample, 'minkowski', 1); % p=1, 曼哈顿距离 % % % 寻找最近的 K 个邻居 % [~, idx] = mink(distances, K); % % % 投票确定验证样本的类别 % predicted_label = mode(train_labels(idx)); % % % 检查预测结果是否正确 % if predicted_label == validation_label % accuracy = accuracy + 1; % end % end % % % 计算分类准确度 % accuracy = accuracy / size(features, 1); % disp(['分类准确度:', num2str(accuracy)]); % %% KD树搜索方法 % 设置 K 值 K = 5; % 初始化分类准确度 accuracy = 0; predictedScores=zeros(56,2); % 留一交叉验证 for i = 1:size(features, 1) % 从样本中选择一个作为验证样本,其余作为训练样本 validation_sample = features(i, :); validation_label = labels(i); train_samples = features([1:i-1, i+1:end], :); train_labels = labels([1:i-1, i+1:end]); % 创建KD树 mdl = fitcknn(train_samples, train_labels, 'NumNeighbors', K, 'Distance', 'euclidean', 'NSMethod', 'kdtree'); % 预测验证样本的类别 %predicted_label = predict(mdl, validation_sample); [predicted_label,predictedScore] = predict(mdl, validation_sample); predictedScores(i,:)=predictedScore; % 检查预测结果是否正确 if predicted_label == validation_label accuracy = accuracy + 1; end end % 计算分类准确度 accuracy = accuracy / size(features, 1); disp(['分类准确度:', num2str(accuracy)]);