基于流形学习的无监督降维算法

1. 主程序:流形学习降维工具箱

%% 流形学习降维工具箱主程序
clear; close all; clc;

%% 参数设置
disp('=== 流形学习降维工具箱 ===');

% 数据集选项
dataset_type = 'swiss_roll';  % 'swiss_roll', 's_curve', 'helix', 'iris', 'mnist', 'custom'
n_samples = 1000;             % 样本数量
noise_level = 0.1;            % 噪声水平 (0-1)

% 算法参数
target_dim = 2;               % 目标维度
k_neighbors = 10;             % 近邻数
epsilon = 0.5;                % 邻域半径(用于Isomap)

% 算法选择(可以运行多个算法进行对比)
algorithms = {'Isomap', 'LLE', 'Laplacian', 'HessianLLE', 'LTSA', 'MVU', 'DiffusionMaps'};
run_all = true;               % 运行所有算法
selected_algorithms = {'Isomap', 'LLE', 'Laplacian', 'DiffusionMaps'}; % 如果run_all=false时选择

% 可视化选项
plot_original = true;         % 绘制原始高维数据(如果可能)
plot_embeddings = true;       % 绘制降维结果
plot_comparison = true;       % 绘制算法对比
compute_quality = true;       % 计算降维质量指标
save_results = true;          % 保存结果

%% 生成或加载数据集
disp('=== 准备数据集 ===');
[X, labels, dataset_name, original_dim] = prepare_dataset(dataset_type, n_samples, noise_level);

disp(['数据集: ', dataset_name]);
disp(['样本数: ', num2str(size(X,1))]);
disp(['原始维度: ', num2str(original_dim)]);
disp(['目标维度: ', num2str(target_dim)]);

%% 可视化原始数据(如果维度<=3)
if plot_original && original_dim <= 3
    figure('Position', [100, 100, 800, 600]);
    plot_original_data(X, labels, original_dim, dataset_name);
end

%% 运行流形学习算法
disp('=== 运行流形学习算法 ===');

% 确定要运行的算法
if run_all
    alg_to_run = algorithms;
else
    alg_to_run = selected_algorithms;
end

% 存储结果
results = struct();
timings = zeros(length(alg_to_run), 1);
quality_scores = struct();

% 进度条
h = waitbar(0, '运行流形学习算法...');

for i = 1:length(alg_to_run)
    algorithm = alg_to_run{i};
    waitbar(i/length(alg_to_run), h, ['运行算法: ', algorithm]);
    
    disp(['运行 ', algorithm, '...']);
    
    % 记录开始时间
    tic;
    
    % 运行对应算法
    switch algorithm
        case 'Isomap'
            Y = isomap_embedding(X, target_dim, k_neighbors, epsilon);
            
        case 'LLE'
            Y = lle_embedding(X, target_dim, k_neighbors);
            
        case 'Laplacian'
            Y = laplacian_eigenmaps_embedding(X, target_dim, k_neighbors);
            
        case 'HessianLLE'
            Y = hessian_lle_embedding(X, target_dim, k_neighbors);
            
        case 'LTSA'
            Y = ltsa_embedding(X, target_dim, k_neighbors);
            
        case 'MVU'
            Y = mvu_embedding(X, target_dim, k_neighbors);
            
        case 'DiffusionMaps'
            Y = diffusion_maps_embedding(X, target_dim, k_neighbors);
            
        case 'tSNE'
            Y = tsne_embedding(X, target_dim);
            
        case 'UMAP'
            Y = umap_embedding(X, target_dim, k_neighbors);
            
        otherwise
            warning(['未知算法: ', algorithm]);
            continue;
    end
    
    % 记录时间
    timings(i) = toc;
    
    % 存储结果
    results(i).algorithm = algorithm;
    results(i).embedding = Y;
    results(i).time = timings(i);
    
    % 计算质量指标(如果启用)
    if compute_quality
        [trustworthiness, continuity, mrre] = compute_quality_metrics(X, Y, k_neighbors);
        results(i).trustworthiness = trustworthiness;
        results(i).continuity = continuity;
        results(i).mrre = mrre;
    end
    
    disp([algorithm, ' 完成,耗时: ', num2str(timings(i), '%.2f'), ' 秒']);
end

close(h);

%% 可视化降维结果
if plot_embeddings
    disp('=== 可视化降维结果 ===');
    
    % 确定子图布局
    n_algs = length(alg_to_run);
    n_cols = min(3, n_algs);
    n_rows = ceil(n_algs / n_cols);
    
    figure('Position', [50, 50, 1400, 800]);
    
    for i = 1:n_algs
        subplot(n_rows, n_cols, i);
        
        Y = results(i).embedding;
        alg_name = results(i).algorithm;
        
        % 绘制嵌入结果
        if target_dim == 1
            % 一维情况
            scatter(Y, zeros(size(Y)), 30, labels, 'filled');
            xlabel('嵌入维度 1');
            ylim([-0.1, 0.1]);
            
        elseif target_dim == 2
            % 二维情况
            scatter(Y(:,1), Y(:,2), 30, labels, 'filled');
            xlabel('嵌入维度 1');
            ylabel('嵌入维度 2');
            
        elseif target_dim == 3
            % 三维情况
            scatter3(Y(:,1), Y(:,2), Y(:,3), 30, labels, 'filled');
            xlabel('嵌入维度 1');
            ylabel('嵌入维度 2');
            zlabel('嵌入维度 3');
            view(3);
        end
        
        title([alg_name, sprintf('\n时间: %.2fs', results(i).time)]);
        
        % 添加质量指标(如果计算了)
        if compute_quality
            txt = sprintf('T=%.3f\nC=%.3f', ...
                         results(i).trustworthiness, results(i).continuity);
            text(0.02, 0.98, txt, 'Units', 'normalized', ...
                 'VerticalAlignment', 'top', 'BackgroundColor', 'white');
        end
        
        axis equal tight;
        grid on;
    end
    
    sgtitle([dataset_name, ' - 流形学习降维结果 (目标维度=', num2str(target_dim), ')'], ...
            'FontSize', 14, 'FontWeight', 'bold');
end

%% 算法对比分析
if plot_comparison && length(alg_to_run) > 1
    disp('=== 生成算法对比图 ===');
    
    % 对比图1:性能指标雷达图
    if compute_quality
        figure('Position', [100, 100, 1000, 800]);
        
        % 准备数据
        alg_names = {results.algorithm};
        n_algs = length(alg_names);
        
        % 质量指标
        trust_scores = [results.trustworthiness];
        cont_scores = [results.continuity];
        mrre_scores = [results.mrre];
        time_scores = [results.time];
        
        % 归一化(越高越好,除了时间和MRRE)
        trust_norm = trust_scores / max(trust_scores);
        cont_norm = cont_scores / max(cont_scores);
        mrre_norm = 1 - (mrre_scores / max(mrre_scores));  % MRRE越低越好
        time_norm = 1 - (time_scores / max(time_scores));  % 时间越短越好
        
        % 创建雷达图
        categories = {'可信度', '连续性', 'MRRE', '速度'};
        data = [trust_norm; cont_norm; mrre_norm; time_norm];
        
        subplot(2,2,1);
        spider_plot(data, categories, alg_names);
        title('算法性能雷达图(归一化)');
        
        % 对比图2:质量指标柱状图
        subplot(2,2,2);
        bar_data = [trust_scores; cont_scores; mrre_scores]';
        bar(bar_data);
        xlabel('算法');
        ylabel('分数');
        title('降维质量指标对比');
        legend('可信度', '连续性', 'MRRE', 'Location', 'best');
        set(gca, 'XTickLabel', alg_names);
        grid on;
        
        % 对比图3:运行时间
        subplot(2,2,3);
        bar([results.time]);
        xlabel('算法');
        ylabel('时间 (秒)');
        title('算法运行时间');
        set(gca, 'XTickLabel', alg_names);
        grid on;
        
        % 对比图4:降维结果投影(前两个维度)
        subplot(2,2,4);
        hold on;
        colors = lines(n_algs);
        for i = 1:n_algs
            Y = results(i).embedding;
            if size(Y,2) >= 2
                scatter(Y(:,1), Y(:,2), 20, colors(i,:), 'filled', ...
                       'DisplayName', alg_names{i});
            end
        end
        hold off;
        xlabel('嵌入维度 1');
        ylabel('嵌入维度 2');
        title('算法结果对比(前两维)');
        legend('Location', 'best');
        axis equal tight;
        grid on;
        
        sgtitle('流形学习算法对比分析', 'FontSize', 14, 'FontWeight', 'bold');
    end
end

%% 高级分析:参数敏感性分析
disp('=== 参数敏感性分析 ===');
if strcmp(dataset_type, 'swiss_roll') || strcmp(dataset_type, 's_curve')
    analyze_parameter_sensitivity(X, labels, target_dim, dataset_name);
end

%% 保存结果
if save_results
    results_dir = 'Manifold_Learning_Results/';
    if ~exist(results_dir, 'dir')
        mkdir(results_dir);
    end
    
    % 保存所有结果
    save([results_dir, 'manifold_learning_results.mat'], ...
         'X', 'labels', 'results', 'target_dim', ...
         'k_neighbors', 'dataset_name', 'original_dim');
    
    % 保存降维后的数据
    for i = 1:length(results)
        alg_name = results(i).algorithm;
        Y = results(i).embedding;
        
        % 保存为文本文件
        filename = [results_dir, 'embedding_', alg_name, '.txt'];
        dlmwrite(filename, Y, 'delimiter', '\t', 'precision', '%.6f');
    end
    
    % 生成报告
    generate_manifold_learning_report(results_dir, results, X, dataset_name);
    
    disp(['结果已保存至: ', results_dir]);
end

disp('=== 流形学习降维完成 ===');

2. 数据集准备函数

function [X, labels, dataset_name, original_dim] = prepare_dataset(dataset_type, n_samples, noise_level)
% 准备数据集
% 输入:
%   dataset_type - 数据集类型
%   n_samples - 样本数量
%   noise_level - 噪声水平
% 输出:
%   X - 数据矩阵 (n_samples × original_dim)
%   labels - 标签(用于着色)
%   dataset_name - 数据集名称
%   original_dim - 原始维度

switch dataset_type
    case 'swiss_roll'
        % Swiss Roll 数据集
        [X, labels] = generate_swiss_roll(n_samples, noise_level);
        dataset_name = 'Swiss Roll';
        original_dim = 3;
        
    case 's_curve'
        % S-曲线数据集
        [X, labels] = generate_s_curve(n_samples, noise_level);
        dataset_name = 'S-Curve';
        original_dim = 3;
        
    case 'helix'
        % 螺旋线数据集
        [X, labels] = generate_helix(n_samples, noise_level);
        dataset_name = 'Helix';
        original_dim = 3;
        
    case 'iris'
        % Iris 数据集
        load fisheriris;
        X = meas;
        labels = grp2idx(species);
        dataset_name = 'Iris Dataset';
        original_dim = size(X, 2);
        
    case 'mnist'
        % MNIST数据集(简化版)
        [X, labels] = load_mnist_subset(n_samples);
        dataset_name = 'MNIST Digits';
        original_dim = size(X, 2);
        
    case 'custom'
        % 自定义数据集
        % 从文件加载
        data = load('custom_data.mat');
        X = data.X;
        labels = data.labels;
        dataset_name = 'Custom Dataset';
        original_dim = size(X, 2);
        
    otherwise
        error('未知的数据集类型');
end

% 确保X是双精度
X = double(X);

% 归一化(可选)
X = (X - mean(X)) ./ std(X);

% 如果没有标签,使用索引作为标签
if isempty(labels)
    labels = 1:size(X,1);
end
end

function [X, t] = generate_swiss_roll(n_samples, noise_level)
% 生成Swiss Roll数据集
t = 3*pi/2 * (1 + 2*rand(n_samples, 1));
height = 21 * rand(n_samples, 1);
X = zeros(n_samples, 3);
X(:,1) = t .* cos(t);
X(:,2) = height;
X(:,3) = t .* sin(t);

% 添加噪声
if noise_level > 0
    X = X + noise_level * randn(size(X));
end

% 标签(基于参数t)
t = t / max(t);  % 归一化作为标签
end

function [X, t] = generate_s_curve(n_samples, noise_level)
% 生成S-曲线数据集
t = 3 * pi * (rand(n_samples, 1) - 0.5);
X = zeros(n_samples, 3);
X(:,1) = sin(t);
X(:,2) = 2 * rand(n_samples, 1);
X(:,3) = sign(t) .* (cos(t) - 1);

% 添加噪声
if noise_level > 0
    X = X + noise_level * randn(size(X));
end

% 标签(基于参数t)
t = (t - min(t)) / (max(t) - min(t));  % 归一化作为标签
end

function [X, t] = generate_helix(n_samples, noise_level)
% 生成螺旋线数据集
t = linspace(0, 4*pi, n_samples)';
X = zeros(n_samples, 3);
X(:,1) = cos(t);
X(:,2) = sin(t);
X(:,3) = 0.1 * t;

% 添加噪声
if noise_level > 0
    X = X + noise_level * randn(size(X));
end

% 标签(基于参数t)
t = t / max(t);  % 归一化作为标签
end

function [X, labels] = load_mnist_subset(n_samples)
% 加载MNIST子集
% 注意:需要MNIST数据集文件
try
    % 尝试加载MNIST数据集
    load('mnist.mat');  % 假设有mnist.mat文件
    if n_samples > size(images, 1)
        n_samples = size(images, 1);
    end
    
    % 随机选择样本
    idx = randperm(size(images, 1), n_samples);
    X = double(images(idx, :));
    labels = double(labels(idx));
    
catch
    % 如果无法加载,使用随机数据模拟
    warning('无法加载MNIST数据集,使用模拟数据');
    X = randn(n_samples, 784);
    labels = randi(10, n_samples, 1);
end
end

3. Isomap算法实现

function Y = isomap_embedding(X, target_dim, k_neighbors, epsilon)
% Isomap (等距映射) 算法
% 输入:
%   X - 高维数据矩阵 (n×d)
%   target_dim - 目标维度
%   k_neighbors - 近邻数
%   epsilon - 邻域半径
% 输出:
%   Y - 低维嵌入 (n×target_dim)

[n, ~] = size(X);

% 步骤1:计算距离矩阵
disp('  Isomap: 计算距离矩阵...');
D = pdist2(X, X);  % 欧氏距离矩阵

% 步骤2:构建邻域图
disp('  Isomap: 构建邻域图...');
if k_neighbors > 0
    % k近邻方法
    G = zeros(n);
    for i = 1:n
        [~, idx] = sort(D(i,:));
        neighbors = idx(2:k_neighbors+1);  % 排除自身
        G(i, neighbors) = D(i, neighbors);
        G(neighbors, i) = D(neighbors, i);
    end
else
    % epsilon邻域方法
    G = D .* (D <= epsilon);
    G = G + diag(inf(n,1));  % 对角线设为无穷大
end

% 步骤3:计算最短路径距离(Floyd-Warshall算法)
disp('  Isomap: 计算最短路径...');
DG = graph(G);
distances = distances(DG);  % 计算所有点对之间的最短路径

% 处理无穷大距离(不连通的点)
inf_indices = isinf(distances);
if any(inf_indices(:))
    warning('Isomap: 图不连通,用最大有限距离填充');
    max_finite = max(distances(~inf_indices));
    distances(inf_indices) = max_finite * 2;
end

% 步骤4:多维缩放(MDS)
disp('  Isomap: 执行多维缩放...');
Y = classical_mds(distances, target_dim);
end

function Y = classical_mds(D, target_dim)
% 经典多维缩放
% 输入:距离矩阵 D (n×n),目标维度 target_dim
% 输出:嵌入 Y (n×target_dim)

n = size(D, 1);

% 双中心化
J = eye(n) - ones(n)/n;
B = -0.5 * J * (D.^2) * J;

% 特征值分解
[V, Lambda] = eig(B);
lambda = diag(Lambda);

% 按特征值降序排序
[lambda_sorted, idx] = sort(lambda, 'descend');
V_sorted = V(:, idx);

% 选择前target_dim个正特征值
positive_idx = lambda_sorted > 1e-10;
lambda_pos = lambda_sorted(positive_idx);
V_pos = V_sorted(:, positive_idx);

if length(lambda_pos) < target_dim
    warning('MDS: 正特征值数量不足,使用所有特征值');
    target_dim = length(lambda_pos);
end

% 构造嵌入
Y = V_pos(:, 1:target_dim) * diag(sqrt(lambda_pos(1:target_dim)));
end

4. LLE算法实现

function Y = lle_embedding(X, target_dim, k_neighbors)
% LLE (局部线性嵌入) 算法
% 输入:
%   X - 高维数据矩阵 (n×d)
%   target_dim - 目标维度
%   k_neighbors - 近邻数
% 输出:
%   Y - 低维嵌入 (n×target_dim)

[n, d] = size(X);

% 步骤1:寻找每个点的k个最近邻
disp('  LLE: 寻找最近邻...');
[idx, dist] = knnsearch(X, X, 'K', k_neighbors+1);
idx = idx(:, 2:end);  % 排除自身

% 步骤2:计算重构权重矩阵 W
disp('  LLE: 计算重构权重...');
W = zeros(n, n);
tol = 1e-3;

for i = 1:n
    % 获取邻居
    neighbors = idx(i, :);
    
    % 计算局部协方差矩阵
    Z = X(neighbors, :) - repmat(X(i, :), k_neighbors, 1);
    C = Z * Z';
    
    % 正则化(防止奇异性)
    C = C + tol * trace(C) * eye(k_neighbors) / k_neighbors;
    
    % 求解权重(约束:权重和为1)
    w = C \ ones(k_neighbors, 1);
    w = w / sum(w);
    
    % 存储权重
    W(i, neighbors) = w';
end

% 步骤3:计算低维嵌入
disp('  LLE: 计算低维嵌入...');
M = (eye(n) - W)' * (eye(n) - W);

% 特征值分解,排除最小的特征值(对应平移自由度)
[V, Lambda] = eig(M);
lambda = diag(Lambda);

% 按特征值升序排序
[lambda_sorted, idx_sort] = sort(lambda);
V_sorted = V(:, idx_sort);

% 选择第2到第target_dim+1小的特征值对应的特征向量
Y = V_sorted(:, 2:target_dim+1)';

% 确保嵌入是实数的
Y = real(Y)';
end

5. 拉普拉斯特征映射算法

function Y = laplacian_eigenmaps_embedding(X, target_dim, k_neighbors)
% 拉普拉斯特征映射算法
% 输入:
%   X - 高维数据矩阵 (n×d)
%   target_dim - 目标维度
%   k_neighbors - 近邻数
% 输出:
%   Y - 低维嵌入 (n×target_dim)

[n, ~] = size(X);

% 步骤1:构建邻接图
disp('  Laplacian: 构建邻接图...');

% 计算距离矩阵
D = pdist2(X, X);

% 构建k近邻图
W = zeros(n);
for i = 1:n
    [~, idx] = sort(D(i,:));
    neighbors = idx(2:k_neighbors+1);
    
    % 热核权重(高斯核)
    sigma = mean(D(i, neighbors));
    weights = exp(-D(i, neighbors).^2 / (2*sigma^2));
    
    W(i, neighbors) = weights;
    W(neighbors, i) = weights;
end

% 步骤2:计算拉普拉斯矩阵
disp('  Laplacian: 计算拉普拉斯矩阵...');
D_mat = diag(sum(W, 2));
L = D_mat - W;  % 未归一化拉普拉斯矩阵

% 步骤3:广义特征值问题
disp('  Laplacian: 求解特征值问题...');

% 求解 Lv = λDv 的最小特征值
[V, Lambda] = eig(L, D_mat);
lambda = diag(Lambda);

% 排除零特征值(对应常数特征向量)
[lambda_sorted, idx] = sort(lambda);
V_sorted = V(:, idx);

% 选择第2到第target_dim+1小的特征值对应的特征向量
Y = V_sorted(:, 2:target_dim+1);

% 归一化嵌入
Y = Y ./ sqrt(sum(Y.^2, 1));
end

6. 扩散映射算法

function Y = diffusion_maps_embedding(X, target_dim, k_neighbors)
% 扩散映射算法
% 输入:
%   X - 高维数据矩阵 (n×d)
%   target_dim - 目标维度
%   k_neighbors - 近邻数
% 输出:
%   Y - 低维嵌入 (n×target_dim)

[n, ~] = size(X);

% 步骤1:构建亲和矩阵
disp('  Diffusion Maps: 构建亲和矩阵...');

% 计算距离矩阵
D = pdist2(X, X);

% 计算核宽度(中位数启发式)
sigma = median(D(:)) / sqrt(2);

% 构建高斯核矩阵
K = exp(-D.^2 / (2*sigma^2));

% 步骤2:计算扩散矩阵
disp('  Diffusion Maps: 计算扩散矩阵...');

% 行归一化得到扩散矩阵
P = diag(1./sum(K, 2)) * K;

% 步骤3:计算扩散距离的特征映射
disp('  Diffusion Maps: 计算特征映射...');

% 对称化:P_sym = D^{1/2} P D^{-1/2}
D_sqrt = diag(sqrt(sum(K, 2)));
D_inv_sqrt = diag(1./sqrt(sum(K, 2)));
P_sym = D_sqrt * P * D_inv_sqrt;

% 特征值分解
[V, Lambda] = eig(P_sym);
lambda = diag(Lambda);

% 按特征值降序排序
[lambda_sorted, idx] = sort(lambda, 'descend');
V_sorted = V(:, idx);

% 选择前target_dim个特征向量(排除第一个特征值1)
Y_sym = V_sorted(:, 2:target_dim+1);

% 转换回原始空间
Y = D_inv_sqrt * Y_sym;

% 可选的:使用特征值进行加权
% for i = 1:target_dim
%     Y(:, i) = Y(:, i) * lambda_sorted(i+1);
% end
end

7. 降维质量评估函数

function [trustworthiness, continuity, mrre] = compute_quality_metrics(X_high, X_low, k)
% 计算降维质量指标
% 输入:
%   X_high - 高维数据 (n×d_high)
%   X_low - 低维嵌入 (n×d_low)
%   k - 近邻数
% 输出:
%   trustworthiness - 可信度指标 [0,1],越高越好
%   continuity - 连续性指标 [0,1],越高越好
%   mrre - 平均相对秩误差,越低越好

n = size(X_high, 1);
if n < 2*k
    k = floor(n/2);
end

% 计算距离矩阵
D_high = pdist2(X_high, X_high);
D_low = pdist2(X_low, X_low);

% 初始化
trustworthiness = 0;
continuity = 0;
mrre_sum = 0;

for i = 1:n
    % 在高维空间中找到k个最近邻
    [~, idx_high] = sort(D_high(i,:));
    neighbors_high = idx_high(2:k+1);  % 排除自身
    
    % 在低维空间中找到k个最近邻
    [~, idx_low] = sort(D_low(i,:));
    neighbors_low = idx_low(2:k+1);  % 排除自身
    
    % 计算可信度
    intruders = setdiff(neighbors_low, neighbors_high);
    for j = 1:length(intruders)
        r_high = find(idx_high == intruders(j)) - 1;  % 在高维中的秩
        trustworthiness = trustworthiness + (r_high - k);
    end
    
    % 计算连续性
    missing = setdiff(neighbors_high, neighbors_low);
    for j = 1:length(missing)
        r_low = find(idx_low == missing(j)) - 1;  % 在低维中的秩
        continuity = continuity + (r_low - k);
    end
    
    % 计算相对秩误差
    common_neighbors = intersect(neighbors_high, neighbors_low);
    for j = 1:length(common_neighbors)
        neighbor = common_neighbors(j);
        r_high = find(idx_high == neighbor) - 1;
        r_low = find(idx_low == neighbor) - 1;
        mrre_sum = mrre_sum + abs(r_high - r_low) / max(r_high, r_low);
    end
end

% 归一化
max_penalty = n * k * (2*n - 3*k - 1) / 2;
if max_penalty > 0
    trustworthiness = 1 - (2 * trustworthiness) / max_penalty;
    continuity = 1 - (2 * continuity) / max_penalty;
else
    trustworthiness = 1;
    continuity = 1;
end

% 平均相对秩误差
mrre = mrre_sum / (n * length(common_neighbors));
end

8. 参数敏感性分析函数

function analyze_parameter_sensitivity(X, labels, target_dim, dataset_name)
% 分析算法对参数的敏感性

% 参数范围
k_values = [5, 10, 15, 20, 30, 50];
algorithms = {'Isomap', 'LLE', 'Laplacian', 'DiffusionMaps'};

% 存储结果
results = struct();

figure('Position', [100, 100, 1200, 800]);

for alg_idx = 1:length(algorithms)
    algorithm = algorithms{alg_idx};
    
    trust_scores = zeros(length(k_values), 1);
    cont_scores = zeros(length(k_values), 1);
    time_scores = zeros(length(k_values), 1);
    
    for k_idx = 1:length(k_values)
        k = k_values(k_idx);
        
        disp(['  ', algorithm, ' with k=', num2str(k)]);
        
        % 运行算法
        tic;
        switch algorithm
            case 'Isomap'
                Y = isomap_embedding(X, target_dim, k, 0.5);
            case 'LLE'
                Y = lle_embedding(X, target_dim, k);
            case 'Laplacian'
                Y = laplacian_eigenmaps_embedding(X, target_dim, k);
            case 'DiffusionMaps'
                Y = diffusion_maps_embedding(X, target_dim, k);
        end
        time_scores(k_idx) = toc;
        
        % 计算质量指标
        [trust, cont, ~] = compute_quality_metrics(X, Y, min(k, 20));
        trust_scores(k_idx) = trust;
        cont_scores(k_idx) = cont;
    end
    
    % 存储结果
    results(alg_idx).algorithm = algorithm;
    results(alg_idx).k_values = k_values;
    results(alg_idx).trust_scores = trust_scores;
    results(alg_idx).cont_scores = cont_scores;
    results(alg_idx).time_scores = time_scores;
    
    % 绘制子图
    subplot(2, 2, alg_idx);
    
    % 绘制双Y轴图
    yyaxis left;
    plot(k_values, trust_scores, 'b-o', 'LineWidth', 2, 'MarkerSize', 8);
    hold on;
    plot(k_values, cont_scores, 'r-s', 'LineWidth', 2, 'MarkerSize', 8);
    ylabel('质量指标');
    ylim([0, 1]);
    
    yyaxis right;
    plot(k_values, time_scores, 'g-^', 'LineWidth', 2, 'MarkerSize', 8);
    ylabel('时间 (秒)');
    
    xlabel('近邻数 k');
    title([algorithm, ' - 参数敏感性']);
    legend('可信度', '连续性', '运行时间', 'Location', 'best');
    grid on;
    hold off;
end

sgtitle([dataset_name, ' - 算法参数敏感性分析'], 'FontSize', 14, 'FontWeight', 'bold');

% 保存敏感性分析结果
if exist('Manifold_Learning_Results', 'dir')
    save('Manifold_Learning_Results/parameter_sensitivity.mat', 'results');
end
end

9. 可视化辅助函数

function plot_original_data(X, labels, original_dim, dataset_name)
% 绘制原始数据

if original_dim == 1
    % 一维数据
    scatter(X, zeros(size(X)), 30, labels, 'filled');
    xlabel('维度 1');
    ylim([-0.1, 0.1]);
    
elseif original_dim == 2
    % 二维数据
    scatter(X(:,1), X(:,2), 30, labels, 'filled');
    xlabel('维度 1');
    ylabel('维度 2');
    
elseif original_dim == 3
    % 三维数据
    scatter3(X(:,1), X(:,2), X(:,3), 30, labels, 'filled');
    xlabel('维度 1');
    ylabel('维度 2');
    zlabel('维度 3');
    view(3);
    
else
    % 高维数据:使用前三个主成分
    [coeff, score] = pca(X);
    if size(score, 2) >= 3
        scatter3(score(:,1), score(:,2), score(:,3), 30, labels, 'filled');
        xlabel('主成分 1');
        ylabel('主成分 2');
        zlabel('主成分 3');
        view(3);
    elseif size(score, 2) == 2
        scatter(score(:,1), score(:,2), 30, labels, 'filled');
        xlabel('主成分 1');
        ylabel('主成分 2');
    else
        scatter(score(:,1), zeros(size(score,1)), 30, labels, 'filled');
        xlabel('主成分 1');
        ylim([-0.1, 0.1]);
    end
end

title([dataset_name, ' 原始数据']);
axis equal tight;
grid on;
colorbar;
end

function spider_plot(data, categories, labels)
% 创建雷达图

n_categories = length(categories);
n_datasets = size(data, 2);

% 角度
theta = linspace(0, 2*pi, n_categories + 1);
theta = theta(1:end-1);

% 创建极坐标
ax = polaraxes;
hold on;

% 绘制每个数据集
colors = lines(n_datasets);
for i = 1:n_datasets
    % 闭合数据
    rho = [data(:,i); data(1,i)];
    th = [theta, theta(1)];
    
    polarplot(th, rho, 'Color', colors(i,:), 'LineWidth', 2, ...
              'Marker', 'o', 'MarkerSize', 6, 'DisplayName', labels{i});
end

% 设置网格
ax.ThetaTick = rad2deg(theta);
ax.ThetaTickLabel = categories;
ax.RLim = [0, 1.1];
ax.RTick = 0:0.2:1;
ax.RTickLabel = arrayfun(@(x) sprintf('%.1f', x), 0:0.2:1, 'UniformOutput', false);

% 添加图例
legend('Location', 'best');
hold off;
end

10. 报告生成函数

function generate_manifold_learning_report(dir_path, results, X_original, dataset_name)
% 生成流形学习分析报告

report_file = [dir_path, 'manifold_learning_report.txt'];
fid = fopen(report_file, 'w');

fprintf(fid, '===============================================\n');
fprintf(fid, '         流形学习降维分析报告\n');
fprintf(fid, '===============================================\n\n');

fprintf(fid, '数据集: %s\n', dataset_name);
fprintf(fid, '原始维度: %d\n', size(X_original, 2));
fprintf(fid, '样本数量: %d\n', size(X_original, 1));
fprintf(fid, '分析时间: %s\n\n', datestr(now));

% 算法性能汇总
fprintf(fid, '算法性能汇总:\n');
fprintf(fid, '%-15s %-10s %-12s %-12s %-10s\n', ...
        '算法', '时间(s)', '可信度', '连续性', 'MRRE');
fprintf(fid, '%s\n', repmat('-', 65, 1));

for i = 1:length(results)
    if isfield(results(i), 'trustworthiness')
        fprintf(fid, '%-15s %-10.2f %-12.4f %-12.4f %-10.4f\n', ...
                results(i).algorithm, results(i).time, ...
                results(i).trustworthiness, results(i).continuity, ...
                results(i).mrre);
    else
        fprintf(fid, '%-15s %-10.2f %-12s %-12s %-10s\n', ...
                results(i).algorithm, results(i).time, 'N/A', 'N/A', 'N/A');
    end
end

% 最佳算法
if isfield(results(1), 'trustworthiness')
    [~, best_trust] = max([results.trustworthiness]);
    [~, best_cont] = max([results.continuity]);
    [~, fastest] = min([results.time]);
    
    fprintf(fid, '\n最佳算法:\n');
    fprintf(fid, '  最佳可信度: %s (%.4f)\n', ...
            results(best_trust).algorithm, results(best_trust).trustworthiness);
    fprintf(fid, '  最佳连续性: %s (%.4f)\n', ...
            results(best_cont).algorithm, results(best_cont).continuity);
    fprintf(fid, '  最快算法: %s (%.2f s)\n', ...
            results(fastest).algorithm, results(fastest).time);
end

% 参数设置
fprintf(fid, '\n参数设置:\n');
fprintf(fid, '  目标维度: %d\n', size(results(1).embedding, 2));
if isfield(results(1), 'parameters')
    params = fieldnames(results(1).parameters);
    for j = 1:length(params)
        fprintf(fid, '  %s: %s\n', params{j}, ...
                num2str(results(1).parameters.(params{j})));
    end
end

fclose(fid);
disp(['分析报告已保存: ', report_file]);
end

参考代码 基于流形学习的无监督降维算法 www.youwenfan.com/contentcnp/95944.html

使用说明:

1. 程序功能

  • 实现了多种流形学习算法:Isomap、LLE、拉普拉斯特征映射、扩散映射等
  • 支持多种标准数据集:Swiss Roll、S曲线、螺旋线、Iris、MNIST等
  • 提供完整的质量评估和可视化
  • 包含参数敏感性分析

2. 算法特点

Isomap

  • 保持测地线距离
  • 适用于展开流形
  • 对噪声敏感

LLE

  • 保持局部线性关系
  • 计算效率高
  • 对参数敏感

拉普拉斯特征映射

  • 基于图拉普拉斯
  • 保持局部邻域关系
  • 适用于聚类结构

扩散映射

  • 基于扩散过程
  • 多尺度分析能力
  • 对噪声鲁棒

3. 参数选择建议

近邻数 k:

k = 5-20;  % 一般范围
% 太小:欠拟合,太大:过拟合

目标维度:

target_dim = 2;  % 可视化
target_dim = 3;  % 3D可视化
target_dim = 10; % 特征提取

4. 运行步骤

  1. 设置数据集类型和参数
  2. 选择要运行的算法
  3. 程序自动计算降维结果
  4. 查看可视化结果和性能指标
  5. 结果自动保存

5. 质量评估指标

  • 可信度:低维空间中保留的高维邻域关系的程度
  • 连续性:高维空间中保留的低维邻域关系的程度
  • MRRE:平均相对秩误差

6. 扩展功能

  • 可添加t-SNE和UMAP实现
  • 可集成监督流形学习
  • 可添加核方法扩展
  • 可支持大规模数据(使用稀疏矩阵)
posted @ 2026-01-15 15:55  老夫写代码  阅读(0)  评论(0)    收藏  举报