MPCA算法:张量降维的完整指南

MPCA(Multilinear Principal Component Analysis)算法,这是一种专门用于张量数据降维的强大工具。

MPCA算法核心思想

与传统PCA的区别

特性传统PCAMPCA
数据形式向量(2阶张量)高阶张量
数据结构忽略多维结构保留张量结构
降维方式单一投影矩阵多个模式投影矩阵

MPCA数学原理

1. 张量基础概念

% 张量表示:X ∈ ℝ^{I₁ × I₂ × ... × Iₙ}
% 模式-n展开:将张量展开为矩阵

2. MPCA目标函数

MPCA的目标是找到一组投影矩阵 {U⁽¹⁾, U⁽²⁾, …, U⁽ⁿ⁾},使得投影后的张量在降维的同时最大程度保留原始变异信息。

目标函数
max⁡{U(n)}∑i=1N∥Yi−Yˉ∥F2\max_{\{U^{(n)}\}} \sum_{i=1}^{N} \| \mathcal{Y}_i - \bar{\mathcal{Y}} \|_F^2max{U(n)}i=1NYiYˉF2
其中 Yi=Xi×1U(1)T×2U(2)T⋯×NU(N)T\mathcal{Y}_i = \mathcal{X}_i \times_1 U^{(1)T} \times_2 U^{(2)T} \cdots \times_N U^{(N)T}Yi=Xi×1U(1)T×2U(2)T×NU(N)T

MATLAB实现

1. 核心MPCA类实现

classdef MPCA < handle
    properties
        % 投影矩阵
        U_proj        % 元胞数组,存储各模式投影矩阵
        mean_tensor   % 训练数据的均值张量
        explained_variance  % 各模式解释方差
        original_dims       % 原始维度
        target_dims         % 目标维度
    end
    
    methods
        function obj = MPCA()
            % MPCA构造函数
            obj.U_proj = {};
            obj.mean_tensor = [];
            obj.explained_variance = [];
        end

2. 张量工具函数

        function X_mat = tensor_unfold(obj, X, mode)
            % 张量模式展开
            dims = size(X);
            N = ndims(X);
            
            % 重新排列维度
            new_order = [mode, setdiff(1:N, mode)];
            X_permuted = permute(X, new_order);
            
            % 重塑为矩阵
            X_mat = reshape(X_permuted, dims(mode), prod(dims)/dims(mode));
        end
        
        function X_tensor = tensor_fold(obj, X_mat, mode, target_dims)
            % 矩阵折叠回张量
            N = length(target_dims);
            
            % 计算折叠后的维度
            folded_dims = target_dims;
            folded_dims(mode) = size(X_mat, 1);
            
            % 重塑为张量
            X_reshaped = reshape(X_mat, folded_dims);
            
            % 逆排列恢复原始维度顺序
            [~, inverse_order] = sort([mode, setdiff(1:N, mode)]);
            X_tensor = permute(X_reshaped, inverse_order);
        end

3. MPCA训练算法

        function fit(obj, X_train, target_dims, varargin)
            % MPCA训练函数
            % 输入:
            %   X_train: 训练张量样本(维度: I₁ × I₂ × ... × Iₙ × N_samples)
            %   target_dims: 目标维度数组
            %   varargin: 可选参数(最大迭代次数、容忍度等)
            
            p = inputParser;
            addParameter(p, 'max_iter', 100, @isnumeric);
            addParameter(p, 'tolerance', 1e-6, @isnumeric);
            addParameter(p, 'verbose', true, @islogical);
            parse(p, varargin{:});
            
            max_iter = p.Results.max_iter;
            tolerance = p.Results.tolerance;
            verbose = p.Results.verbose;
            
            % 获取张量维度信息
            tensor_dims = size(X_train);
            N_modes = length(tensor_dims) - 1;  % 最后一个维度是样本数
            num_samples = tensor_dims(end);
            
            obj.original_dims = tensor_dims(1:end-1);
            obj.target_dims = target_dims;
            
            if verbose
                fprintf('开始MPCA训练...\n');
                fprintf('原始维度: %s\n', mat2str(obj.original_dims));
                fprintf('目标维度: %s\n', mat2str(target_dims));
                fprintf('样本数量: %d\n', num_samples);
            end
            
            % 步骤1: 中心化数据
            obj.mean_tensor = mean(X_train, ndims(X_train));
            X_centered = X_train - repmat(obj.mean_tensor, [ones(1, N_modes), num_samples]);
            
            % 步骤2: 初始化投影矩阵
            obj.U_proj = cell(1, N_modes);
            for n = 1:N_modes
                obj.U_proj{n} = randn(tensor_dims(n), target_dims(n));
                % 正交化
                [obj.U_proj{n}, ~] = qr(obj.U_proj{n}, 0);
            end
            
            % 步骤3: 交替优化
            prev_total_variance = 0;
            
            for iter = 1:max_iter
                if verbose && mod(iter, 10) == 0
                    fprintf('迭代 %d/%d...\n', iter, max_iter);
                end
                
                % 对每个模式交替优化
                for n = 1:N_modes
                    % 构造辅助张量(固定其他模式)
                    X_projected = obj.partial_project(X_centered, n);
                    
                    % 模式-n展开
                    Xn = obj.tensor_unfold(X_projected, n);
                    
                    % 计算协方差矩阵
                    cov_matrix = Xn * Xn';
                    
                    % 特征分解
                    [U, S, ~] = svd(cov_matrix, 'econ');
                    
                    % 选择前target_dims(n)个特征向量
                    obj.U_proj{n} = U(:, 1:target_dims(n));
                end
                
                % 计算当前总方差
                current_variance = obj.calculate_total_variance(X_centered);
                
                % 检查收敛
                if iter > 1 && abs(current_variance - prev_total_variance) < tolerance
                    if verbose
                        fprintf('在迭代 %d 收敛\n', iter);
                    end
                    break;
                end
                
                prev_total_variance = current_variance;
            end
            
            % 计算解释方差
            obj.calculate_explained_variance(X_centered);
            
            if verbose
                fprintf('MPCA训练完成\n');
                obj.display_results();
            end
        end

4. 投影与重构函数

        function Y = transform(obj, X)
            % 将新张量投影到低维空间
            % X: 输入张量(可以是单个张量或张量样本集)
            
            if ndims(X) == length(obj.original_dims)
                % 单个张量
                X_centered = X - obj.mean_tensor;
                Y = X_centered;
                for n = 1:length(obj.U_proj)
                    Y = obj.mode_n_product(Y, obj.U_proj{n}', n);
                end
            else
                % 张量样本集
                num_samples = size(X, ndims(X));
                Y_dims = [obj.target_dims, num_samples];
                Y = zeros(Y_dims);
                
                for i = 1:num_samples
                    % 提取单个样本
                    subs = repmat({':'}, 1, ndims(X)-1);
                    X_i = X(subs{:}, i);
                    
                    % 中心化并投影
                    X_centered = X_i - obj.mean_tensor;
                    Y_i = X_centered;
                    for n = 1:length(obj.U_proj)
                        Y_i = obj.mode_n_product(Y_i, obj.U_proj{n}', n);
                    end
                    
                    % 存储结果
                    Y(subs{:}, i) = Y_i;
                end
            end
        end
        
        function X_recon = inverse_transform(obj, Y)
            % 从低维表示重构原始张量
            if ndims(Y) == length(obj.target_dims)
                % 单个低维张量
                X_recon = Y;
                for n = length(obj.U_proj):-1:1
                    X_recon = obj.mode_n_product(X_recon, obj.U_proj{n}, n);
                end
                X_recon = X_recon + obj.mean_tensor;
            else
                % 低维张量样本集
                num_samples = size(Y, ndims(Y));
                X_dims = [obj.original_dims, num_samples];
                X_recon = zeros(X_dims);
                
                for i = 1:num_samples
                    subs = repmat({':'}, 1, ndims(Y)-1);
                    Y_i = Y(subs{:}, i);
                    
                    X_recon_i = Y_i;
                    for n = length(obj.U_proj):-1:1
                        X_recon_i = obj.mode_n_product(X_recon_i, obj.U_proj{n}, n);
                    end
                    X_recon_i = X_recon_i + obj.mean_tensor;
                    
                    X_recon(subs{:}, i) = X_recon_i;
                end
            end
        end

参考代码 MPCA算法,用于张量的降维 www.youwenfan.com/contentcsl/60159.html

应用示例:人脸图像数据集

1. 数据准备与预处理

% 模拟人脸图像数据(3阶张量:高度×宽度×样本数)
function [tensor_data, labels] = generate_face_data(num_samples, image_size)
    % 生成模拟人脸数据
    tensor_data = zeros([image_size, num_samples]);
    labels = randi([1, 5], num_samples, 1);  % 5个不同的人
    
    for i = 1:num_samples
        % 生成基础人脸模板(高斯分布模拟面部特征)
        base_face = generate_base_face(image_size, labels(i));
        
        % 添加个体变异和噪声
        individual_variation = 0.1 * randn(image_size);
        noise = 0.05 * randn(image_size);
        
        tensor_data(:, :, i) = base_face + individual_variation + noise;
    end
end

function base_face = generate_base_face(image_size, person_id)
    [X, Y] = meshgrid(1:image_size(2), 1:image_size(1));
    center = image_size / 2;
    
    % 根据不同的人ID生成不同的面部特征
    switch person_id
        case 1
            % 圆脸
            base_face = exp(-((X-center(2)).^2 + (Y-center(1)).^2) / (0.3*min(image_size))^2);
        case 2
            % 椭圆脸
            base_face = exp(-((X-center(2)).^2/0.4 + (Y-center(1)).^2/0.6) / (0.3*min(image_size))^2);
        otherwise
            base_face = exp(-((X-center(2)).^2 + (Y-center(1)).^2) / (0.35*min(image_size))^2);
    end
end

2. MPCA降维与可视化

% 主演示程序
function demonstrate_MPCA()
    clear; close all; clc;
    
    fprintf('=== MPCA算法演示 ===\n');
    
    % 生成模拟数据
    image_size = [64, 64];  % 图像尺寸
    num_samples = 200;
    num_test = 50;
    
    [train_data, train_labels] = generate_face_data(num_samples, image_size);
    [test_data, test_labels] = generate_face_data(num_test, image_size);
    
    fprintf('数据维度: %s\n', mat2str(size(train_data)));
    
    % MPCA降维
    target_dims = [16, 16];  % 目标维度
    
    mpca = MPCA();
    mpca.fit(train_data, target_dims, 'max_iter', 50, 'verbose', true);
    
    % 训练数据投影
    train_lowdim = mpca.transform(train_data);
    fprintf('降维后维度: %s\n', mat2str(size(train_lowdim)));
    
    % 测试数据投影
    test_lowdim = mpca.transform(test_data);
    
    % 重构测试样本
    test_recon = mpca.inverse_transform(test_lowdim);
    
    % 可视化结果
    visualize_mpca_results(train_data, test_data, test_recon, train_lowdim, mpca);
    
    % 性能评估
    evaluate_mpca_performance(train_data, test_data, test_recon, mpca);
end

3. 结果可视化函数

function visualize_mpca_results(original_train, original_test, reconstructed, lowdim, mpca)
    figure('Position', [100, 100, 1400, 1000]);
    
    % 1. 原始图像 vs 重构图像
    subplot(2,3,1);
    sample_idx = 1;
    original_img = original_test(:,:,sample_idx);
    recon_img = reconstructed(:,:,sample_idx);
    
    montage({original_img, recon_img}, 'Size', [1, 2]);
    title('原始图像 vs 重构图像');
    
    % 2. 重构误差分布
    subplot(2,3,2);
    reconstruction_errors = zeros(size(original_test, 3), 1);
    for i = 1:size(original_test, 3)
        diff = original_test(:,:,i) - reconstructed(:,:,i);
        reconstruction_errors(i) = norm(diff(:)) / norm(original_test(:,:,i)(:));
    end
    histogram(reconstruction_errors, 20);
    xlabel('相对重构误差');
    ylabel('频数');
    title('重构误差分布');
    grid on;
    
    % 3. 低维空间可视化(前2个维度)
    subplot(2,3,3);
    if ndims(lowdim) == 3
        lowdim_2d = reshape(lowdim, [], size(lowdim, 3));
        [coeff, score] = pca(lowdim_2d');
        
        scatter(score(:,1), score(:,2), 30, 'filled');
        xlabel('第一主成分');
        ylabel('第二主成分');
        title('低维空间中的样本分布');
        grid on;
    end
    
    % 4. 解释方差
    subplot(2,3,4);
    if ~isempty(mpca.explained_variance)
        bar(mpca.explained_variance);
        xlabel('模式');
        ylabel('解释方差比例');
        title('各模式解释方差');
        grid on;
    end
    
    % 5. 投影矩阵可视化
    subplot(2,3,5);
    U1 = mpca.U_proj{1};
    imagesc(U1(:,1:min(10, size(U1,2))));
    colorbar;
    title('模式-1投影矩阵(前10列)');
    xlabel('投影方向');
    ylabel('原始维度');
    
    % 6. 压缩比计算
    subplot(2,3,6);
    original_size = prod(mpca.original_dims);
    compressed_size = prod(mpca.target_dims);
    compression_ratio = original_size / compressed_size;
    
    labels = {'原始数据', '压缩后数据'};
    sizes = [original_size, compressed_size] / 1e3;  % 转换为千单位
    bar(sizes);
    set(gca, 'XTickLabel', labels);
    ylabel('数据量 (千元素)');
    title(sprintf('压缩比: %.2f:1', compression_ratio));
    grid on;
end

性能评估与比较

1. MPCA性能评估

function evaluate_mpca_performance(train_data, test_data, test_recon, mpca)
    fprintf('\n=== MPCA性能评估 ===\n');
    
    % 计算重构误差
    mse_errors = zeros(size(test_data, 3), 1);
    for i = 1:size(test_data, 3)
        mse_errors(i) = mean((test_data(:,:,i) - test_recon(:,:,i)).^2, 'all');
    end
    
    fprintf('平均重构MSE: %.4f\n', mean(mse_errors));
    fprintf('重构MSE标准差: %.4f\n', std(mse_errors));
    
    % 计算压缩比
    original_size = prod(mpca.original_dims);
    compressed_size = prod(mpca.target_dims);
    compression_ratio = original_size / compressed_size;
    fprintf('压缩比: %.2f:1\n', compression_ratio);
    
    % 计算信息保留率
    total_variance_original = sum(var(reshape(train_data, [], size(train_data,3)), 2));
    train_lowdim = mpca.transform(train_data);
    total_variance_compressed = sum(var(reshape(train_lowdim, [], size(train_lowdim,3)), 2));
    variance_retained = total_variance_compressed / total_variance_original;
    fprintf('方差保留率: %.2f%%\n', variance_retained * 100);
end

2. 与传统PCA比较

function compare_with_PCA(tensor_data, target_dims)
    % 将张量数据展平为向量
    [d1, d2, num_samples] = size(tensor_data);
    X_flat = reshape(tensor_data, d1*d2, num_samples)';
    
    % 传统PCA
    [coeff, score, ~, ~, explained] = pca(X_flat);
    
    % 选择主成分数量(达到类似压缩比)
    target_pc = round(prod(target_dims) * 1.2);  % 稍多维度以公平比较
    
    % PCA重构
    X_recon_pca = score(:,1:target_pc) * coeff(:,1:target_pc)';
    X_recon_pca = reshape(X_recon_pca', d1, d2, num_samples);
    
    % MPCA重构
    mpca = MPCA();
    mpca.fit(tensor_data, target_dims, 'max_iter', 50, 'verbose', false);
    X_recon_mpca = mpca.inverse_transform(mpca.transform(tensor_data));
    
    % 比较重构质量
    mse_pca = mean((tensor_data - X_recon_pca).^2, 'all');
    mse_mpca = mean((tensor_data - X_recon_mpca).^2, 'all');
    
    fprintf('\n=== MPCA vs PCA 比较 ===\n');
    fprintf('PCA重构MSE: %.4f\n', mse_pca);
    fprintf('MPCA重构MSE: %.4f\n', mse_mpca);
    fprintf('MPCA相对改进: %.2f%%\n', (mse_pca - mse_mpca)/mse_pca*100);
end

MPCA算法优势与应用场景

主要优势

  1. 结构保持:保留张量的多维结构信息
  2. 维度灵活性:可独立控制每个模式的降维程度
  3. 计算效率:相比将张量展平后使用PCA,计算更高效
  4. 解释性强:每个模式的投影矩阵具有明确的物理意义

典型应用场景

应用领域张量结构MPCA作用
人脸识别图像×光照×姿态特征提取,降维
视频分析帧×行×列×时间时空特征提取
神经科学脑区×时间×被试多被试脑信号分析
推荐系统用户×物品×时间多维偏好建模

这个MPCA实现提供了张量降维的强大工具,特别适合处理具有多维结构的数据。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值