MATLAB实现自编码器(三)——堆栈自编码器Stacked Autoencoders实现手写数字分类

在前面两篇博客的基础上,可以实现单层自编码器网络(一个解码器+一个解码器)。对于多层自编码器的实现,MATLAB给出了堆栈自编码器用于图像分类的网页Train Stacked Autoencoders for Image Classification
,本文对其进行翻译和学习。

堆栈自编码器Stacked Autoencoders

具有多个隐藏层的神经网络可用于解决图像等复杂数据的分类问题。每个层都可以在不同的抽象级别学习特性。然而,训练具有多个隐藏层的神经网络在实践中可能是困难的。一种有效训练多层神经网络的方法是一次训练一层。可以通过为每个隐藏层训练一种称为自编码器的特殊网络来实现这一点。

下面的例子展示了如何训练具有两个隐藏层的神经网络来对数字图像进行分类。首先,使用自编码器以无监督的方式单独训练隐藏层。然后训练最后一个softmax层,并将这些层连接在一起,形成一个堆叠的网络,在有监督的情况下对其进行最后一次训练。

代码实现

代码较长,因此注释也比较多,但是其基本思想并不复杂,实现的过程也容易理解。

%% Train Stacked Autoencoders for Image Classification训练用于图像分类的堆栈自编码器
%% 导入训练集
% 此示例始终使用合成数据进行训练和测试。已通过对使用不同字体创建的数字图像应用随机仿射变换来生成合成图像
% 每个数字图像为 28×28 像素,共有 5000 个训练样本。您可以加载训练数据,并查看其中一些图像
% Load the training data into memory 加载自带的手写数字数据集
clear;
clc;
[xTrainImages,tTrain] = digitTrainCellArrayData;
% 展示图像
clf
for i = 1:20
    subplot(4,5,i);
    imshow(xTrainImages{i});
end
%% Training the first autoencoder 训练第一个自编码器
% 首先在不使用标签的情况下基于训练数据训练稀疏自编码器。
% 自编码器是一种神经网络,该网络会尝试在其输出端复制其输入。因此,其输入的大小将与其输出的大小相同。
% 当隐含层中的神经元数量小于输入的大小时,自编码器将学习输入的压缩表示。
% 神经网络在训练前具有随机初始化的权重。因此,每次训练的结果都不同。为避免此行为,请显式设置随机数生成器种子。
rng('default')%确保随机数
hiddenSize1 = 100;%设置自编码器的隐含层的大小。对于要训练的自编码器,最好使隐含层的大小小于输入大小。
% 训练设置
autoenc1 = trainAutoencoder(xTrainImages,hiddenSize1, ... 
    'MaxEpochs',400, ...    % 最大训练轮次400'L2WeightRegularization',0.004, ...   % L2正则项对网络权重的影响,通常非常小
    'SparsityRegularization',4, ...       % 稀疏正则项的系数
    'SparsityProportion',0.15, ...        % 稀疏比例
    'ScaleData', false);     %输入数据不进行缩放
% 查看第一个自编码器的结构
view(autoenc1)   
% 可视化第一个自编码器的权重
% 自编码器的编码器部分所学习的映射可用于从数据中提取特征。
% 编码器中的每个神经元都具有一个与之相关联的权重向量,该向量将进行相应调整以响应特定可视化特征。您可以查看这些特征的表示。
figure()
plotWeights(autoenc1);
% 可以看到,自编码器学习的特征代表了数字图像中的弯曲和笔划图案。
% 自编码器的隐含层的 100 维输出是输入的压缩版本,它汇总了对上面可视化特征的响应。
% 基于从训练数据中提取的一组向量训练下一个自编码器。首先,必须使用经过训练的自编码器中的编码器生成特征。
feat1 = encode(autoenc1,xTrainImages); % 自编码器1的输出
%% Training the second autoencoder  训练第二个自编码器
% 以相似的方式训练第二个自编码器,主要区别在于使用第一个自编码器的输出作为第二个自编码器的输入。
% 还需要将隐含表示的大小减小到 50,以便第二个自编码器中的编码器学习输入数据的更小表示。
hiddenSize2 = 50; 
autoenc2 = trainAutoencoder(feat1,hiddenSize2, ...
    'MaxEpochs',100, ...
    'L2WeightRegularization',0.002, ...
    'SparsityRegularization',4, ...
    'SparsityProportion',0.1, ...
    'ScaleData', false);
% 查看第二个自编码器的结构
view(autoenc2)
% 自编码器2的输出
feat2 = encode(autoenc2,feat1);
%% Training the final softmax layer 训练最后的分类层softmax
% 训练数据中的原始向量具有 784 个维度。原始数据通过第一个编码器后,维度减小到 100 维。
% 应用第二个编码器后,维度进一步减小到 50 维。
% 训练最后一层softmax层以对 50 维特征向量进行分类。
% 与自编码器不同,这里使用训练数据的标签以有监督方式训练 softmax 层。
softnet = trainSoftmaxLayer(feat2,tTrain,'MaxEpochs',400);%trainSoftmaxLayer(输入特征,输出标签,参数(循环次数),参数值)
% 显示softmax网络
view(softnet)
% 将自编码器中的编码器与 softmax 层堆叠在一起,以形成用于分类的堆叠网络
deepnet = stack(autoenc1,autoenc2,softnet);%网络合成
view(deepnet) % 深度网络的显示
%% 构建测试集并进行测试
% 在搭建了完整网络之后,可以基于测试集计算结果。要将图像用于堆叠网络,必须将测试图像重构为矩阵。
% 这可以通过先堆叠图像的各列以形成向量,然后根据这些向量形成矩阵来完成。
% 获取每个图像中的像素数
imageWidth = 28;
imageHeight = 28;
inputSize = imageWidth*imageHeight; % 输入矩阵的大小
% 载入测试图像
[xTestImages,tTest] = digitTestCellArrayData;
% 图像转换为向量并放在矩阵中
xTest = zeros(inputSize,numel(xTestImages)); %生成一个0矩阵,numel计算图像中的元素个数
for i = 1:numel(xTestImages)
    xTest(:,i) = xTestImages{i}(:);
end
% 网络测试
y = deepnet(xTest); %测试结果输出
plotconfusion(tTest,y); % 测试结果对比,使用混淆矩阵来可视化结果
%% Fine tuning the deep neural network 微调深度神经网络
% 通过对整个多层网络执行反向传播,可以改进堆叠神经网络的结果,此过程通常称为微调。
% 通过以有监督方式基于训练数据重新训练网络来进行微调。在执行此操作之前,必须将训练图像重构为矩阵,就像对测试图像所做的那样。
xTrain = zeros(inputSize,numel(xTrainImages));
for i = 1:numel(xTrainImages)
    xTrain(:,i) = xTrainImages{i}(:);
end
% 进行微调
deepnet = train(deepnet,xTrain,tTrain);
%再次显示结果并对比
y = deepnet(xTest);
plotconfusion(tTest,y); 

  • 9
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值