DeepLearning: denoising autoencoder

本文参考hogo在youtube上的视频:https://www.youtube.com/watch?v=t2NQ_c5BFOc&index=49&list=PL6Xpj9I5qXYEcOhn7TqghAJ6NAPrNmUBH

一、理论基础

在训练autoencoder模型时,为了防止过拟合,我们经常采用denoising策略,即在输入中加入噪声,让模型去重构加噪声前的数据,这样的模型泛化能力强,并且对比较鲁棒,抗噪能力强。

加噪方法:

  1、以概率v将输入置为0

  2、加高斯噪声

输入为x,根据概率加噪后得到,重构误差表示:x与,即:

黑色曲线表示原输入的流行,红点表示的样本是加了噪声后的结果,即输入以一定的概率偏离原分布,那么denoising 模型就是要抗这种干扰,拟合出黑色曲线。

在下图上,曲线上的数字2是原输入,偏离曲线的2是加了噪声后的输入,那么denoising autoencoder模型就是要重构出曲线上的2而非加了噪声的2.

二、实验部分

本实验使用deepLearn Toolbox中的sae,关于deepLearnToolbox见博文http://www.cnblogs.com/dupuleng/articles/4340293.html

结果:左图是原始的autoencoder,右图是denoising autoencoder

错误率分别为: 0.394000  0.252000

为加速训练,作者使用的数据规模只有2000,因此错误率比较大,但可以看出denoising的泛化能力更强,将错误率降低了14个百分点。

视频中hogo提供的例子更能看出加噪的作用,我们可以看出加噪后的模型学习出的边缘特征更加明显,但到底要以什么比例加噪?这需要以具体问题具体对待。

实验主要代码:

%% //导入数据
load mnist_uint8;
train_num = 2000;
train_x = double(train_x)/255; train_x = train_x(1:train_num,:);
test_x = double(test_x)/255; test_x = test_x(1:train_num,:);
train_y = double(train_y); train_y = train_y(1:train_num,:);
test_y = double(test_y); test_y = test_y(1:train_num , : );

%% //实验一:采用denoising autoencoder进行预训练
rand('state',0)
sae = saesetup([784 100 100]); % //其实这里nn中的W已经被随机初始化过
sae.ae{1}.activation_function = 'sigm';
sae.ae{1}.learningRate = 1;
sae.ae{1}.inputZeroMaskedFraction = 0.;

opts.numepochs = 10;
opts.batchsize = 100;
sae = saetrain(sae, train_x, opts);% //无监督学习,不需要传入标签值,学习好的权重放在sae中,
% //并且train_x是最后一个隐含层的输出。
visualize(sae.ae{1}.W{1}(:,2:end)')
% Use the SDAE to initialize a FFNN
nn = nnsetup([784 100 100 10]);
nn.activation_function = 'sigm';
nn.learningRate = 1;
%add pretrained weights
nn.W{1} = sae.ae{1}.W{1}; % //将sae训练好了的权值赋给nn网络作为初始值,覆盖了前面的随机初始化
% Train the FFNN
opts.numepochs = 10;
opts.batchsize = 100;
nn = nntrain(nn, train_x, train_y, opts);
[er, bad] = nntest(nn, test_x, test_y);
str = sprintf('testing error rate is: %f',er);
disp(str)


%% //实验二:采用denoising autoencoder进行预训练 maskFraction = 0.5
%rng(0);
rand('state',0)
sae = saesetup([784 100 100]); % //其实这里nn中的W已经被随机初始化过
sae.ae{1}.activation_function = 'sigm';
sae.ae{1}.learningRate = 1;
sae.ae{1}.inputZeroMaskedFraction = 0.5;
opts.numepochs = 10;
opts.batchsize = 100;
sae = saetrain(sae, train_x, opts);% //无监督学习,不需要传入标签值,学习好的权重放在sae中,
% //并且train_x是最后一个隐含层的输出。由于是分层预训练
% //的,所以每次训练其实只考虑了一个隐含层,隐含层的输入有
% //相应的denoise操作
figure,visualize(sae.ae{1}.W{1}(:,2:end)')
% Use the SDAE to initialize a FFNN
nn = nnsetup([784 100 100 10]);
nn.activation_function = 'sigm';
nn.learningRate = 1;
%add pretrained weights
nn.W{1} = sae.ae{1}.W{1}; % //将sae训练好了的权值赋给nn网络作为初始值,覆盖了前面的随机初始化
% Train the FFNN
opts.numepochs = 10;
opts.batchsize = 100;
nn = nntrain(nn, train_x, train_y, opts);
[er, bad] = nntest(nn, test_x, test_y);
str = sprintf('maskFraction = 0.5, testing error rate is: %f',er);
disp(str)

  参考文献:

https://www.youtube.com/watch?v=t2NQ_c5BFOc&index=49&list=PL6Xpj9I5qXYEcOhn7TqghAJ6NAPrNmUBH

http://www.cnblogs.com/dupuleng/articles/4340293.html

 

posted @ 2015-03-15 21:15  dupuleng  阅读(1509)  评论(0)    收藏  举报