稀疏自动编码器MATLAB 实现

稀疏自动编码器 MATLAB 代码,包含:

  • 单隐藏层自动编码器(输入→隐藏→输出)
  • 稀疏惩罚(KL 散度,目标激活概率 ρ)
  • 权重衰减(L2 正则化)
  • 批量梯度下降训练
  • 可视化隐藏层特征(当输入为图像时)

一、核心函数:sparseAutoencoder.m

function [optTheta, costHistory] = sparseAutoencoder(inputSize, hiddenSize, ...
    X, lambda, beta, rho, maxIter)
% 稀疏自动编码器训练
% 输入:
%   inputSize  - 输入层神经元数
%   hiddenSize - 隐藏层神经元数
%   X          - 训练数据 (inputSize × m)
%   lambda     - 权重衰减系数
%   beta       - 稀疏惩罚系数
%   rho        - 稀疏目标(期望激活概率)
%   maxIter    - 最大迭代次数
% 输出:
%   optTheta   - 优化后的参数向量
%   costHistory- 每次迭代的损失值

% 初始化参数
epsilon_init = 0.12;
W1 = rand(hiddenSize, inputSize) * 2 * epsilon_init - epsilon_init;
W2 = rand(inputSize, hiddenSize) * 2 * epsilon_init - epsilon_init;
b1 = zeros(hiddenSize, 1);
b2 = zeros(inputSize, 1);

% 展平为向量
theta = [W1(:); W2(:); b1(:); b2(:)];

% 选项(使用 L-BFGS 优化)
options = optimoptions('fminunc', ...
    'Algorithm', 'quasi-newton', ...
    'MaxIterations', maxIter, ...
    'Display', 'iter', ...
    'SpecifyObjectiveGradient', true);

% 优化
[optTheta, cost] = fminunc(@(t) saeCost(t, inputSize, hiddenSize, ...
    X, lambda, beta, rho), theta, options);

costHistory = cost; % 实际 fminunc 只返回最终值,若需完整曲线可改用梯度下降
end

function [cost, grad] = saeCost(theta, inputSize, hiddenSize, X, lambda, beta, rho)
% 稀疏自动编码器损失函数与梯度
% 参数提取
W1 = reshape(theta(1:hiddenSize*inputSize), hiddenSize, inputSize);
offset = hiddenSize*inputSize;
W2 = reshape(theta(offset+1:offset+hiddenSize*inputSize), inputSize, hiddenSize);
offset = offset + hiddenSize*inputSize;
b1 = theta(offset+1:offset+hiddenSize);
offset = offset + hiddenSize;
b2 = theta(offset+1:offset+inputSize);

m = size(X, 2);

% 前向传播
z2 = W1 * X + b1;
a2 = sigmoid(z2);          % 隐藏层激活
z3 = W2 * a2 + b2;
a3 = sigmoid(z3);          % 输出层激活

% 重构误差(交叉熵)
cost = -1/m * sum(sum(X .* log(a3) + (1-X) .* log(1-a3)));

% 权重衰减
cost = cost + lambda/2 * (sum(W1(:).^2) + sum(W2(:).^2));

% 稀疏惩罚(KL散度)
rho_hat = mean(a2, 2);     % 隐藏层平均激活
kl_div = sum(rho * log(rho ./ rho_hat) + (1-rho) * log((1-rho) ./ (1-rho_hat)));
cost = cost + beta * kl_div;

% ====== 反向传播 ======
% 输出层误差
delta3 = a3 - X;

% 稀疏惩罚项对隐藏层的贡献
sparsity_term = beta * (-rho./rho_hat + (1-rho)./(1-rho_hat));

% 隐藏层误差
delta2 = (W2' * delta3 + sparsity_term) .* sigmoidGradient(z2);

% 梯度
W1grad = 1/m * delta2 * X' + lambda * W1;
W2grad = 1/m * delta3 * a2' + lambda * W2;
b1grad = 1/m * sum(delta2, 2);
b2grad = 1/m * sum(delta3, 2);

% 展平梯度
grad = [W1grad(:); W2grad(:); b1grad(:); b2grad(:)];
end

function g = sigmoid(z)
    g = 1 ./ (1 + exp(-z));
end

function g = sigmoidGradient(z)
    g = sigmoid(z) .* (1 - sigmoid(z));
end

二、演示脚本:demo_sparseAE.m

该脚本生成模拟数据(或加载 MNIST 子集),训练稀疏自动编码器,并可视化隐藏层权重。

%% 稀疏自动编码器演示
clear; clc; close all;

%% 1. 生成或加载数据
% 使用随机小块图像(8×8 块)
patchSize = 8;
inputSize = patchSize^2;   % 64
numPatches = 10000;

% 生成随机自然图像块(模拟)
patches = rand(inputSize, numPatches);
% 归一化到 [0,1]
patches = bsxfun(@rdivide, patches, max(patches, [], 1));

% 若你有 MNIST 数据,可替换为:
% load mnist_uint8.mat;
% train_x = double(train_x') / 255;
% patches = train_x(:, 1:10000); % 取前10000个样本

%% 2. 设置参数
hiddenSize = 36;          % 隐藏层神经元数
lambda = 0.003;           % 权重衰减系数
beta = 5;                 % 稀疏惩罚系数
rho = 0.1;                % 目标激活概率
maxIter = 400;            % 最大迭代次数

%% 3. 训练稀疏自动编码器
fprintf('开始训练稀疏自动编码器...\n');
tic;
[optTheta, costHist] = sparseAutoencoder(inputSize, hiddenSize, ...
    patches, lambda, beta, rho, maxIter);
toc;

%% 4. 提取并可视化隐藏层权重
% 从优化后的参数中提取 W1
W1 = reshape(optTheta(1:hiddenSize*inputSize), hiddenSize, inputSize);

% 显示权重(每个隐藏单元对应一个 patchSize×patchSize 的图像)
figure;
displayNetwork(W1', patchSize, patchSize, 6, 6);
title('隐藏层学习到的特征(权重)');

%% 5. 重构测试
% 取几个测试样本
testIdx = 1:10;
testX = patches(:, testIdx);

% 前向传播得到重构
W1 = reshape(optTheta(1:hiddenSize*inputSize), hiddenSize, inputSize);
offset = hiddenSize*inputSize;
W2 = reshape(optTheta(offset+1:offset+hiddenSize*inputSize), inputSize, hiddenSize);
offset = offset + hiddenSize*inputSize;
b1 = optTheta(offset+1:offset+hiddenSize);
offset = offset + hiddenSize;
b2 = optTheta(offset+1:offset+inputSize);

z2 = W1 * testX + b1;
a2 = sigmoid(z2);
z3 = W2 * a2 + b2;
reconstructed = sigmoid(z3);

% 显示原图和重构
figure;
for i = 1:10
    subplot(2,10,i);
    imshow(reshape(testX(:,i), patchSize, patchSize), []);
    title('原图');
    subplot(2,10,i+10);
    imshow(reshape(reconstructed(:,i), patchSize, patchSize), []);
    title('重构');
end
sgtitle('原图 vs 重构');

%% 辅助函数:显示网络权重
function displayNetwork(W, h, w, rows, cols)
% W: hiddenSize × inputSize, 每行是一个隐藏单元的权重
% h, w: 每个小图的高度和宽度
% rows, cols: 显示的行数和列数
    figure;
    for i = 1:rows*cols
        subplot(rows, cols, i);
        img = reshape(W(i,:), h, w);
        imshow(img, []);
        axis off;
    end
end

function g = sigmoid(z)
    g = 1 ./ (1 + exp(-z));
end

三、运行说明

  1. 将上述两个函数保存为 .m 文件:
    • sparseAutoencoder.m
    • demo_sparseAE.m
  2. 在 MATLAB 中运行 demo_sparseAE
  3. 若需要更快的训练,可将 maxIter 调小(如 200);若希望更精细的特征,可增大。

四、结果示例

  • 隐藏层特征:训练完成后会显示 6×6 网格的权重图像(每个小图代表一个隐藏单元学到的“基”)。对于自然图像块,通常会学到边缘检测器(类似 Gabor 滤波器)。
  • 重构效果:原图与重构图的对比显示自动编码器能够较好地重建输入。

参考代码 稀疏自动编码器的matlab代码 www.youwenfan.com/contentcnv/81171.html

五、关键参数调优指南

参数 作用 典型范围
hiddenSize 隐藏层神经元数 小于输入维度(压缩)或大于(过完备)
lambda 权重衰减系数 0.001 ~ 0.01
beta 稀疏惩罚强度 1 ~ 10
rho 目标激活概率 0.01 ~ 0.2(越稀疏越小)
maxIter 迭代次数 200 ~ 800

六、扩展建议

  1. 使用真实数据:将 patches 替换为图像块(如从 im2col 提取的 8×8 块),或直接使用 MNIST 手写数字。
  2. 栈式自编码器:训练多个稀疏自动编码器堆叠,逐层预训练深度网络。
  3. 不同激活函数:将 sigmoid 替换为 ReLU 或 tanh,并相应调整梯度。
posted @ 2026-06-14 14:31  yu8yu7  阅读(11)  评论(0)    收藏  举报