matlab实现多标签K近邻(ML-KNN)算法

多标签K近邻(ML-KNN)是经典KNN算法在多标签学习场景下的直接扩展,也是非常有效和常用的基准方法。


一、 算法核心思想

传统的KNN用于多分类问题时,会找出K个最近邻,然后通过"投票法"决定样本的单一类别。而多标签KNN(ML-KNN)的核心思想是:

对于每一个标签(Label),独立地判断样本属于该标签的概率。这个判断依据是其K个最近邻样本在该标签上的表现(即哪些邻居有这个标签)。

它本质上为每个标签都训练了一个独立的分类器(基于邻居信息),因此可以输出样本的多个标签。


二、 算法步骤详解

假设我们有训练集 Train_X (特征), Train_Y (标签,0/1矩阵),要预测测试样本 Test_X 的标签 Test_Y

  1. Step 1: 计算最近邻

    • 对于每一个测试样本 Test_X(i),计算它与所有训练样本 Train_X 的距离(如欧氏距离)。
    • 找出与 Test_X(i) 距离最近的 K 个训练样本,记其索引为 N_i (大小为 K 的集合)。
  2. Step 2: 统计邻居的标签信息(核心)

    • 对于每一个标签 l (即标签矩阵的每一列):
      • 统计这 K 个邻居中,拥有该标签 l 的邻居个数。记作 C_l
        C_l = sum(Train_Y(N_i, l) == 1)
  3. Step 3: 应用贝叶斯规则进行预测

    • 这是ML-KNN区别于简单投票法的关键。它使用先验概率来做出更稳健的决策。
    • 先验概率 (Prior) : 从整个训练集中计算。
      • P1_prior(l) = (s + sum(Train_Y(:, l) == 1)) / (s*2 + n_train)
      • P0_prior(l) = 1 - P1_prior(l) (通常用拉普拉斯平滑,s=1 防止概率为0)
    • 后验概率 (Posterior) :基于当前样本的邻居信息计算。
      • P1 = P(H_l^1) * P(E_l^c | H_l^1)
      • P0 = P(H_l^0) * P(E_l^c | H_l^0)
      • 其中:
        • H_l^1: 事件"测试样本有标签l"
        • H_l^0: 事件"测试样本没有标签l"
        • E_l^c: 事件"测试样本的K个邻居中,恰好有c个拥有标签l"(这里 c = C_l
    • 决策 :如果 P1 > P0,则预测该测试样本拥有标签 l,否则没有。

    在实际代码实现中,我们通常预先计算整个训练集每个标签的邻居数量分布(似然概率),然后查表。


三、 MATLAB

matlab 复制代码
function Predicted_Labels = ML_KNN(Train_X, Train_Y, Test_X, K, Smooth)
    % ML-KNN 多标签K近邻算法
    % 输入:
    %   Train_X, Train_Y - 训练数据和标签 (多标签,0/1矩阵)
    %   Test_X          - 测试数据
    %   K               - 近邻数
    %   Smooth          - 拉普拉斯平滑参数 (通常为1)
    % 输出:
    %   Predicted_Labels - 测试集的预测标签 (0/1矩阵)

    [n_train, n_label] = size(Train_Y);
    n_test = size(Test_X, 1);
    
    % 初始化预测结果矩阵
    Predicted_Labels = zeros(n_test, n_label);
    
    % 1. 计算所有测试样本与所有训练样本的距离
    % 注意:对于大数据集,此处需要优化以防止内存溢出 (例如使用循环或pdist2)
    Dist = pdist2(Test_X, Train_X); % 需要 Statistics and Machine Learning Toolbox
    % 或者自己实现欧氏距离: 
    % for i=1:n_test
    %     Dist(i,:) = sqrt(sum((Train_X - Test_X(i,:)).^2, 2));
    % end
    
    % 2. 对每个标签,预先计算先验概率
    P1_prior = zeros(1, n_label);
    for l = 1:n_label
        P1_prior(l) = (Smooth + sum(Train_Y(:, l) == 1)) / (Smooth * 2 + n_train);
    end
    P0_prior = 1 - P1_prior;
    
    % 3. 对每个测试样本进行预测
    for i = 1:n_test
        % a. 获取当前测试样本的K个最近邻的索引
        [~, sorted_idx] = sort(Dist(i, :));
        neighbor_idx = sorted_idx(1:K);
        
        % b. 获取这些邻居的标签子集
        Neighbor_Labels = Train_Y(neighbor_idx, :);
        
        % c. 对于每一个标签l,进行贝叶斯推断
        for l = 1:n_label
            % 统计K个邻居中拥有标签l的个数 (c)
            c = sum(Neighbor_Labels(:, l));
            
            % --- 此处应使用预计算的似然概率 P(c | H_l^1) 和 P(c | H_l^0) ---
            % 为了简化示例,我们做一个近似估计:
            % 假设似然概率正比于二项分布,并从训练集中估计其参数
            
            % 计算整个训练集中,每个样本的K近邻拥有标签l的个数的分布
            % (在实际完整实现中,这里需要预先用交叉验证等方法计算一个概率表)
            % 本例简化: 使用邻居中标签l的频率作为概率的估计
            % 注意:这是一个简化,完整的ML-KNN需要预先计算整个训练集的这个分布。
            
            % 简单频率估计 (带平滑)
            prob_c_given_H1 = (Smooth + c) / (Smooth * 2 + K);
            prob_c_given_H0 = (Smooth + (K - c)) / (Smooth * 2 + K); 
            
            % 计算后验概率
            P1 = P1_prior(l) * prob_c_given_H1;
            P0 = P0_prior(l) * prob_c_given_H0;
            
            % 决策
            if P1 > P0
                Predicted_Labels(i, l) = 1;
            else
                Predicted_Labels(i, l) = 0;
            end
        end
    end
end

如何使用:

matlab 复制代码
% 假设您已有数据
% Train_X: n_train x d_features 矩阵
% Train_Y: n_train x n_labels 矩阵 (元素为0或1)
% Test_X: n_test x d_features 矩阵

K = 10; % 选择近邻数
Smooth = 1; % 拉普拉斯平滑参数

Predicted_Y = ML_KNN(Train_X, Train_Y, Test_X, K, Smooth);

% 评估性能 (例如计算Hamming Loss)
% True_Y 是测试集真实的标签
hamming_loss = sum(sum(Predicted_Y ~= True_Y)) / (size(True_Y, 1) * size(True_Y, 2));
fprintf('Hamming Loss: %.4f\n', hamming_loss);

参考代码 多标签K近邻方法实现对多标签数据进行分类 www.3dddown.com/csa/53349.html

四、 事项与优化

  1. 距离度量 : 欧氏距离是默认选择,但对于高维或特定类型数据(如文本),余弦距离可能更合适。务必对特征数据进行标准化(Z-score或Min-Max),防止某些特征主导距离计算。

  2. 参数选择:

    • K(近邻数):是最关键的参数。太小容易过拟合,太大会平滑过度,导致性能下降。需要通过交叉验证在验证集上选择最佳K值。
    • Smooth(平滑参数):通常设为1(拉普拉斯平滑)即可,用于处理概率为0的情况。
  3. 计算效率:

    • ML-KNN的预测阶段很慢,因为需要为每个测试样本 计算与所有训练样本的距离。对于大规模数据集,这是主要瓶颈。
    • 优化方法 :使用KD树、Ball Tree等数据结构进行近邻搜索(MATLAB中可使用knnsearchfitcknn);或采用近似最近邻算法(ANN)。
  4. 完整实现:

    • 上面的代码是简化版 。完整的ML-KNN实现需要在训练阶段预先为每个标签 l 计算一个概率分布表,即 P(c | H_l^1)P(c | H_l^0)(c从0到K)。这个表是通过对训练集本身进行K近邻统计得到的。上述示例中用简单频率估计代替了这一步。
  5. 评估指标:

    • 多标签学习的评估指标与单标签不同,常用:
      • Hamming Loss(汉明损失):被错误预测的标签比例(越小越好)。
      • F1-Score(宏平均/微平均):精确率和召回率的调和平均。
      • Subset Accuracy(子集准确率):预测的标签集合与真实集合完全一致的样本比例(非常严格)。
相关推荐
一招定胜负3 小时前
逻辑回归调优三板斧:参数调整、阈值设定、数据集平衡
算法·机器学习·逻辑回归
豆约翰4 小时前
Z字形扫描ccf
java·开发语言·算法
Salt_07284 小时前
DAY 35 文件的规范拆分和写法
python·算法·机器学习
Coding茶水间4 小时前
基于深度学习的肾结石检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
图像处理·人工智能·深度学习·yolo·目标检测·机器学习·计算机视觉
风筝在晴天搁浅4 小时前
代码随想录 109.冗余连接Ⅱ
算法
业精于勤的牙4 小时前
浅谈:算法中的斐波那契数(三)
算法·职场和发展
ss2734 小时前
阻塞队列:三组核心方法全对比
java·数据结构·算法
小O的算法实验室4 小时前
2026年SEVC SCI2区,面向空地跨域无人集群的目标引导自适应路径规划方法,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
Blossom.1184 小时前
基于多模态大模型的工业质检系统:从AOI到“零样本“缺陷识别的产线实践
运维·人工智能·python·机器学习·自动化·测试用例·知识图谱