自动编码器系列

AutoEncoder

1.人工神经网络(ANN)本身就是具有层次结构的系统.

2.如果给定一个神经网络,我们假设其输出与输入是相同的,然后训练调整其参数,得到每一层中的权重。自然地,我们就得到了输入I的几种不同表示(每一层代表一种表示),这些表示就是特征。

3.自动编码器就是利用这些特征,尽可能复现输入信号的神经网络。

具体过程简单的说明如下:

1)给定无标签数据,用非监督学习学习特征:

 

之前的神经网络,我们采取的是有输入,有样本的方法,再采取nnff、nnbp的方法直到收敛。而自动编码器则没有用到样本,需要自己学习。学习的过程如下:

 

 

我们将input输入一个encoder编码器,得到一个code,将这个code放进decoder,检验它是否很接近input,如果decoder输出信息表示两者很像,那么我们通过调整encoder和decoder的参数使重构误差最小。

 

2)通过编码器产生特征,然后训练下一层。这样逐层训练:

 

3)有监督微调:

     经过上面的方法,我们就可以得到很多层了。至于需要多少层(或者深度需要多少,这个目前本身就没有一个科学的评价方法)需要自己试验调了。到这里,这个AutoEncoder还不能用来分类数据,因为它还没有学习如何去连结一个输入和一个类。它只是学会了如何去重构或者复现它的输入而已。

那么,为了实现分类,我们就可以在AutoEncoder的最顶的编码层添加一个分类器(例如罗杰斯特回归、SVM等),然后通过标准的多层神经网络的监督训练方法(梯度下降法)去训练。

也就是说,这时候,我们需要将最后层的特征code输入到最后的分类器,通过有标签样本,通过监督学习进行微调,这也分两种,一个是只调整分类器(黑色部分):

 

       另一种:通过有标签样本,微调整个系统:(如果有足够多的数据,这个是最好的。end-to-end learning端对端学习)

 

一旦监督训练完成,这个网络就可以用来分类了。神经网络的最顶层可以作为一个线性分类器,然后我们可以用一个更好性能的分类器去取代它。

      在研究中可以发现,如果在原有的特征中加入这些自动学习得到的特征可以大大提高精确度,甚至在分类问题中比目前最好的分类算法效果还要好!

(Sparse Autoencoder)

这节课来学习下Deep learning领域比较出名的一类算法——sparse autoencoder,即稀疏模式的自动编码。我们知道,deep learning也叫做unsupervised learning,所以这里的sparseautoencoder也应是无监督的。按照前面的博文:Deep learning:一(基础知识_1),Deep learning:七(基础知识_2)所讲,如果是有监督的学习的话,在神经网络中,我们只需要确定神经网络的结构就可以求出损失函数的表达式了(当然,该表达式需对网络的参数进行”惩罚”,以便使每个参数不要太大),同时也能够求出损失函数偏导函数的表达式,然后利用优化算法求出网络最优的参数。应该清楚的是,损失函数的表达式中,需要用到有标注值的样本。那么这里的sparseautoencoder为什么能够无监督学习呢?难道它的损失函数的表达式中不需要标注的样本值(即通常所说的y值)么?其实在稀疏编码中”标注值”也是需要的,只不过它的输出理论值是本身输入的特征值x,其实这里的标注值y=x。这样做的好处是,网络的隐含层能够很好的代替输入的特征,因为它能够比较准确的还原出那些输入特征值。Sparseautoencoder的一个网络结构图如下所示:

 

 

损失函数的求法:

  无稀疏约束时网络的损失函数表达式如下:

 

  稀疏编码是对网络的隐含层的输出有了约束,即隐含层节点输出的平均值应尽量为0,这样的话,大部分的隐含层节点都处于非activite状态。因此,此时的sparseautoencoder损失函数表达式为:

 

  后面那项为KL距离,其表达式如下:

 

  隐含层节点输出平均值求法如下:

  

  其中的参数一般取很小,比如说0.05,也就是小概率发生事件的概率。这说明要求隐含层的每一个节点的输出均值接近0.05(其实就是接近0,因为网络中activite函数为sigmoid函数),这样就达到稀疏的目的了。KL距离在这里表示的是两个向量之间的差异值。从约束函数表达式中可以看出,差异越大则”惩罚越大”,因此最终的隐含层节点的输出会接近0.05。

 

损失函数的偏导数的求法:

  如果不加入稀疏规则,则正常情况下由损失函数求损失函数偏导数的过程如下:

 

  而加入了稀疏性后,神经元节点的误差表达式由公式:

 

  变成公式:

 

梯度下降法求解:

  有了损失函数及其偏导数后就可以采用梯度下降法来求网络最优化的参数了,整个流程如下所示:

  从上面的公式可以看出,损失函数的偏导其实是个累加过程,每来一个样本数据就累加一次。这是因为损失函数本身就是由每个训练样本的损失叠加而成的,而按照加法的求导法则,损失函数的偏导也应该是由各个训练样本所损失的偏导叠加而成。从这里可以看出,训练样本输入网络的顺序并不重要,因为每个训练样本所进行的操作是等价的,后面样本的输入所产生的结果并不依靠前一次输入结果(只是简单的累加而已,而这里的累加是顺序无关的)。

代码其实也就是体现在增加一个惩罚因子而已,分布在nnbp函数上(第24行)

function nn= nnbp(nn)

%NNBP performs backpropagation

% nn= nnbp(nn) returns anneural network structurewith updated weights

   

    n = nn.n;

    sparsityError =0;

    switch nn.output

        case'sigm'

            d{n}=- nn.e .*(nn.a{n}.*(1- nn.a{n}));

        case{'softmax','linear'}

            d{n}=- nn.e;

    end

    for i=(n-1):-1:2

        %Derivative of theactivationfunction激活函数的导数

        switch nn.activation_function

            case'sigm'

               d_act = nn.a{i}.*(1- nn.a{i});  %P15

            case'tanh_opt'

               d_act =1.7159*2/3*(1-1/(1.7159)^2* nn.a{i}.^2);

        end

       

        if(nn.nonSparsityPenalty>0)

            pi = repmat(nn.p{i}, size(nn.a{i},1),1);

           sparsityError =[zeros(size(nn.a{i},1),1) nn.nonSparsityPenalty*(-nn.sparsityTarget./ pi +(1- nn.sparsityTarget)./(1- pi))];

        end

       

        %Backpropagate firstderivatives

        if i+1==n%inthiscasein d{n} there isnot the bias term to be removed             

            d{i}=(d{i+1}* nn.W{i}+ sparsityError).* d_act;%Bishop(5.56)

        else%inthiscasein d{i} the bias termhas to be removed

            d{i}=(d{i+1}(:,2:end)* nn.W{i}+ sparsityError).* d_act;%P13

        end

        

        if(nn.dropoutFraction>0)

            d{i}= d{i}.*[ones(size(d{i},1),1) nn.dropOutMask{i}];

        end

 

    end

 

    for i=1:(n-1)

        if i+1==n

            nn.dW{i}=(d{i+1}' * nn.a{i}) / size(d{i + 1}, 1);%P14

        else

            nn.dW{i} = (d{i + 1}(:,2:end)'* nn.a{i})/ size(d{i+1},1);     

        end

    end

end

(引用自:http://blog.csdn.net/zouxy09/article/details/8775524)

denoising autoencoder:

  denoising其实就是在autoencoder的基础上,给输入的x加入噪声,就相当于dropout用在输入层

  toolbox中的也实现非常简单:

   在nntrain.m中:

     batch_x =batch_x.*(rand(size(batch_x))>nn.inputZeroMaskedFraction)

   也就是随即把大小为(nn.inputZeroMaskedFraction)的一部分x赋成0,denoising autoencoder的表现好像比sparse autoencoder要强一些

代码体现为:

 for l=1: numbatches

        batch_x = train_x(kk((l-1)* batchsize+1: l* batchsize),:);

       

        %Add noise to input(forusein denoising autoencoder)   加入noise,这是denoising autoencoder需要使用到的部分

        if(nn.inputZeroMaskedFraction~=0) %请参见《ExtractingandComposingRobustFeatureswithDenoisingAutoencoders》这篇论文

            batch_x= batch_x.*(rand(size(batch_x))>nn.inputZeroMaskedFraction);%具体加入的方法就是把训练样例中的一些数据调整变为0,inputZeroMaskedFraction表示了调整的比例 

        end

       

        batch_y = train_y(kk((l-1)* batchsize+1: l* batchsize),:);

 

 

来源: <http://blog.csdn.net/dark_scope/article/details/9942775>

 

Contractive Auto-Encoders:

Contractiveautoencoder是autoencoder的一个变种,其实就是在autoencoder上加入了一个规则项,它简称CAE(对应中文翻译为?)。通常情况下,对权值进行惩罚后的autoencoder数学表达形式为:

 

  这是直接对W的值进行惩罚的,而今天要讲的CAE其数学表达式同样非常简单,如下:

 

  其中的 是隐含层输出值关于权重的雅克比矩阵,而  表示的是该雅克比矩阵的F范数的平方,即雅克比矩阵中每个元素求平方

  然后求和,更具体的数学表达式为:

 

CAE只找到了py代码,这个还得学完了Python才能解读ORZ

来源: <http://www.cnblogs.com/tornadomeet/p/3434651.html>

 Stacked Auto-Encoders(SAE)

最后的STACK是一个集大成的编码器,它阐述的意思是设置多几层(或者是很多层)的隐含层,使最后学习得到的结果更准确。其实我们可以想象,多层网络比单层神经网络能学习到更复杂的表达。比如说用k层神经网络能学习到的函数(且每层网络节点个数时多项式的)如果要用k-1层神经网络来学习,则这k-1层神经网络节点的个数必须是指数级庞大的数字。

 

  不同层的网络学习到的特征是由最底层到最高层慢慢上升的。比如在图像的学习中,第一个隐含层层网络可能学习的是边缘特征,第二隐含层就学习到的是轮廓什么的,后面的就会更高级有可能是图像目标中的一个部位,也就是是底层隐含层学习底层特征,高层隐含层学习高层特征。

 

  这种多层神经网络的结构和人体大脑皮层的多层感知结构非常类似,所以说有一定的生物理论基础。

来源: <http://www.cnblogs.com/tornadomeet/archive/2013/03/25/2980357.html>

 

posted @ 2015-09-22 17:45  程序员的戎马一生  阅读(377)  评论(0编辑  收藏  举报