基于KLPP与PCA的数据降维方法

概述

本文将介绍两种重要的数据降维技术:主成分分析(PCA)和核局部保持投影(KLPP),并提供完整的MATLAB实现代码。这两种方法在机器学习、模式识别和计算机视觉领域有广泛应用。

核心原理

PCA (主成分分析)

  • 目标:寻找数据最大方差方向,保留全局结构
  • 数学原理
    • 计算协方差矩阵:\(C = \frac{1}{n} \sum_{i=1}^{n} (x_i - \mu)(x_i - \mu)^T\)
    • 特征值分解:\(C = V\Lambda V^T\)
    • 选择前k个最大特征值对应的特征向量作为投影矩阵

KLPP (核局部保持投影)

  • 目标:保持数据局部结构,处理非线性数据
  • 数学原理
    • 使用核函数将数据映射到高维空间:\(\phi: x \rightarrow \phi(x)\)
    • 构建邻接图并计算权重矩阵W
    • 求解广义特征值问题:\(XLX^T a = \lambda XDX^T a\)
    • 选择前k个最小非零特征值对应的特征向量

MATLAB

%% PCA与KLPP降维算法实现
clear; clc; close all;

%% 加载数据
% 使用MATLAB内置鸢尾花数据集
load fisheriris;
X = meas;           % 150x4数据矩阵
labels = species;   % 类别标签

% 数据标准化
X = zscore(X);

fprintf('数据集信息:\n');
fprintf('样本数: %d, 特征数: %d\n', size(X,1), size(X,2));
fprintf('类别: %s, %s, %s\n\n', unique(labels));

%% PCA降维实现
function [Y, V] = my_pca(X, k)
    % 输入: 
    %   X - m x n 数据矩阵 (m样本数, n特征数)
    %   k - 目标维度
    % 输出:
    %   Y - 降维后的数据 (m x k)
    %   V - 投影矩阵 (n x k)
    
    % 计算均值
    mu = mean(X, 1);
    
    % 中心化数据
    X_centered = X - mu;
    
    % 计算协方差矩阵
    cov_matrix = cov(X_centered);
    
    % 特征值分解
    [V, D] = eig(cov_matrix);
    
    % 特征值排序(降序)
    [~, idx] = sort(diag(D), 'descend');
    V = V(:, idx);
    
    % 选择前k个主成分
    V = V(:, 1:k);
    
    % 数据投影
    Y = X_centered * V;
end

%% KLPP降维实现
function [Y, A] = my_klpp(X, k, kernel_type, sigma, neighbor_num)
    % 输入:
    %   X - m x n 数据矩阵
    %   k - 目标维度
    %   kernel_type - 核函数类型 ('gaussian', 'linear', 'poly')
    %   sigma - 高斯核参数
    %   neighbor_num - 近邻数
    % 输出:
    %   Y - 降维后的数据 (m x k)
    %   A - 投影矩阵
    
    [m, n] = size(X);
    
    % 1. 计算核矩阵
    K = compute_kernel_matrix(X, kernel_type, sigma);
    
    % 2. 构建邻接图
    W = build_adjacency_matrix(X, neighbor_num);
    
    % 3. 计算度矩阵D和拉普拉斯矩阵L
    D = diag(sum(W, 2));
    L = D - W;
    
    % 4. 求解广义特征值问题 K*L*K'*a = λ*K*D*K'*a
    A = K * L * K';
    B = K * D * K';
    
    % 处理奇异矩阵问题
    B = B + 1e-6 * eye(size(B)); 
    
    % 求解广义特征值问题
    [eig_vecs, eig_vals] = eig(A, B);
    
    % 特征值排序(升序)
    eig_vals = diag(eig_vals);
    [~, idx] = sort(eig_vals, 'ascend');
    eig_vecs = eig_vecs(:, idx);
    
    % 选择前k个特征向量(忽略零特征值)
    A = eig_vecs(:, 2:k+1);  % 跳过第一个特征向量
    
    % 5. 数据投影
    Y = K * A;
end

%% 核矩阵计算函数
function K = compute_kernel_matrix(X, kernel_type, sigma)
    m = size(X, 1);
    K = zeros(m, m);
    
    switch kernel_type
        case 'gaussian'
            for i = 1:m
                for j = 1:m
                    K(i,j) = exp(-norm(X(i,:)-X(j,:))^2/(2*sigma^2));
                end
            end
            
        case 'linear'
            K = X * X';
            
        case 'poly'
            % 使用二次多项式核
            K = (X * X' + 1).^2;
            
        otherwise
            error('未知的核函数类型');
    end
end

%% 邻接矩阵构建函数
function W = build_adjacency_matrix(X, neighbor_num)
    m = size(X, 1);
    W = zeros(m, m);
    
    % 计算距离矩阵
    dist_matrix = pdist2(X, X);
    
    % 构建邻接图(无向图)
    for i = 1:m
        % 找到最近的k个邻居
        [~, idx] = sort(dist_matrix(i,:), 'ascend');
        neighbors = idx(2:neighbor_num+1); % 排除自身
        
        % 设置权重(热核权重)
        for j = neighbors
            dist = dist_matrix(i,j);
            W(i,j) = exp(-dist^2 / (2 * mean(dist_matrix(:))^2));
            W(j,i) = W(i,j); % 对称权重
        end
    end
end

%% 参数设置
k = 2;              % 目标维度
kernel_type = 'gaussian';
sigma = 1.5;        % 高斯核参数
neighbor_num = 7;   % 邻接图近邻数

%% 执行降维
% PCA降维
[Y_pca, V_pca] = my_pca(X, k);

% KLPP降维
[Y_klpp, A_klpp] = my_klpp(X, k, kernel_type, sigma, neighbor_num);

fprintf('降维完成:\n');
fprintf('PCA投影矩阵大小: %dx%d\n', size(V_pca));
fprintf('KLPP投影矩阵大小: %dx%d\n\n', size(A_klpp));

%% 结果可视化
figure('Position', [100, 100, 1200, 500]);

% 原始数据可视化
subplot(1, 3, 1);
gscatter(X(:,1), X(:,2), labels, 'rgb', 'os^', [], 'off');
title('原始数据 (前两个特征)');
xlabel('花萼长度');
ylabel('花萼宽度');
grid on;

% PCA降维结果
subplot(1, 3, 2);
gscatter(Y_pca(:,1), Y_pca(:,2), labels, 'rgb', 'os^', [], 'off');
title('PCA降维结果 (k=2)');
xlabel('主成分1');
ylabel('主成分2');
grid on;

% KLPP降维结果
subplot(1, 3, 3);
gscatter(Y_klpp(:,1), Y_klpp(:,2), labels, 'rgb', 'os^', [], 'off');
title(['KLPP降维结果 (\sigma=', num2str(sigma), ', k=', num2str(neighbor_num), ')']);
xlabel('KLPP分量1');
ylabel('KLPP分量2');
grid on;

%% 性能评估 - 降维后数据分类精度
% 使用kNN分类器评估降维效果
rng(42); % 设置随机种子

% 创建kNN分类器
knn_model = fitcknn(X, labels, 'NumNeighbors', 5);
cv_model = crossval(knn_model, 'KFold', 5);
acc_orig = 1 - kfoldLoss(cv_model);

% PCA降维数据
knn_model_pca = fitcknn(Y_pca, labels, 'NumNeighbors', 5);
cv_model_pca = crossval(knn_model_pca, 'KFold', 5);
acc_pca = 1 - kfoldLoss(cv_model_pca);

% KLPP降维数据
knn_model_klpp = fitcknn(Y_klpp, labels, 'NumNeighbors', 5);
cv_model_klpp = crossval(knn_model_klpp, 'KFold', 5);
acc_klpp = 1 - kfoldLoss(cv_model_klpp);

fprintf('分类性能评估 (5折交叉验证):\n');
fprintf('原始数据分类精度: %.4f\n', acc_orig);
fprintf('PCA降维后分类精度: %.4f\n', acc_pca);
fprintf('KLPP降维后分类精度: %.4f\n\n', acc_klpp);

%% 参数敏感性分析
% 分析不同参数对KLPP性能的影响
sigma_values = 0.5:0.5:3;
neighbor_values = 3:2:15;
acc_matrix = zeros(length(sigma_values), length(neighbor_values));

fprintf('KLPP参数敏感性分析...\n');
for i = 1:length(sigma_values)
    for j = 1:length(neighbor_values)
        [Y_temp, ~] = my_klpp(X, k, 'gaussian', sigma_values(i), neighbor_values(j));
        
        knn_model = fitcknn(Y_temp, labels, 'NumNeighbors', 5);
        cv_model = crossval(knn_model, 'KFold', 5);
        acc_matrix(i,j) = 1 - kfoldLoss(cv_model);
    end
end

% 可视化参数敏感性
figure('Name', 'KLPP参数敏感性分析');
imagesc(neighbor_values, sigma_values, acc_matrix);
colorbar;
xlabel('近邻数');
ylabel('高斯核参数 \sigma');
title('KLPP降维后分类精度');
set(gca, 'YDir', 'normal');

% 标记最佳参数
[max_acc, max_idx] = max(acc_matrix(:));
[row, col] = ind2sub(size(acc_matrix), max_idx);
hold on;
plot(neighbor_values(col), sigma_values(row), 'ro', 'MarkerSize', 10, 'LineWidth', 2);
text(neighbor_values(col)+0.5, sigma_values(row), ...
    sprintf('最佳: \\sigma=%.1f, k=%d\n精度: %.4f', ...
    sigma_values(row), neighbor_values(col), max_acc), ...
    'VerticalAlignment', 'bottom');

代码说明

1. 核心函数实现

  1. PCA函数 (my_pca)

    • 数据标准化
    • 计算协方差矩阵
    • 特征值分解
    • 选择主成分
    • 数据投影
  2. KLPP函数 (my_klpp)

    • 核矩阵计算
    • 邻接图构建
    • 图拉普拉斯矩阵计算
    • 广义特征值求解
    • 数据投影

2. 辅助函数

  • compute_kernel_matrix:支持高斯核、线性核、多项式核
  • build_adjacency_matrix:基于k近邻构建邻接图,使用热核权重

3. 实验分析

  1. 可视化

    • 原始数据分布
    • PCA降维结果
    • KLPP降维结果
  2. 性能评估

    • 使用kNN分类器评估降维后数据质量
    • 5折交叉验证计算分类精度
  3. 参数敏感性分析

    • 分析不同核参数和近邻数对KLPP性能的影响
    • 可视化参数组合与分类精度的关系

算法比较

特性 PCA KLPP
结构保持 全局结构 局部结构
数据假设 线性 非线性
计算复杂度 中高
参数敏感度 中高
适用场景 高斯分布数据 流形结构数据
主要优势 计算简单,去相关 保持局部结构,处理非线性

参考代码 此算法是 基于KLPP与PCA的数据的降维的方法 www.youwenfan.com/contentcnl/81760.html,可用于图像处理和故障诊断等需要降维的应用中。

结果分析

  1. 可视化分析

    • PCA倾向于最大化全局方差,可能忽略局部结构
    • KLPP能更好地保持数据的局部邻域关系
    • 在鸢尾花数据集上,KLPP通常能实现更好的类别分离
  2. 性能评估

    • KLPP降维后数据通常获得更高分类精度
    • PCA在计算效率上优于KLPP
    • 对于线性可分数据,PCA可能足够有效
  3. 参数敏感性

    • KLPP性能受核参数σ和近邻数k影响显著
    • 高斯核参数σ过小导致过拟合,过大导致欠拟合
    • 近邻数k需要平衡局部与全局信息
posted @ 2025-11-18 09:48  u95900090  阅读(12)  评论(0)    收藏  举报