稀疏自编码器及其实现——如何搞基

自编码器是什么?

自编码器本身就是一种BP神经网络。它是一种无监督学习算法。

我们都知道神经网络可以从任意精度逼近任意函数,这里我们让神经网络目标值等于输出值x,也就是模拟一个恒等函数:

太无聊了,是吗?输入等于输出,这网络有什么意义?但是,当我们把自编码神经网络加入某些限制,事情就发生了变化。如图1所示,这就是一个基本的自编码神经网络,可以看到隐含层节点数量要少于输入层节点数量。

图1

举个例子,如果我们输入一张10*10的图像,这样就有100个像素,所以输入层和输出层的节点数量就是100。而我们取隐藏层节点数量为25。注意,这样就会迫使隐藏层节点学习得到输入数据的压缩表示方法,逼得隐藏层要用25维数据重构出100维的数据。这样也就完成了学习过程。

这和我们学习的过程很像,假设一共有100个考点,但是只允许你用25个知识点概括所有这些考点,这就是学习的过程。

稀疏自编码器又是什么?

更一般的,如果隐藏层节点数量很大,甚至比输入层节点数量还要多时,我们仍然可以使用自编码算法,但是这时需要加入稀疏性限制。这就是稀疏自编码器。

什么是稀疏性限制?

简单说就是要保证隐藏神经元在大多数情况下是被抑制的状态。具体表现就是sigmoid函数的输出大多数状态是0,tanh函数的输出大多数状态是-1。这样有什么好处?这样能够迫使隐藏神经元发挥最大的潜力,在很不利的条件下学习到真正的特征。

怎么衡量某个隐藏神经元的激活度?

取平均就好了,假设表示在给定输入x的情况下,隐藏神经元j的激活度,那么自然就有平均激活度

稀疏性惩罚项——相对熵

为了保证这个稀疏度小到我们希望的那么多,比如说,即

我们需要在优化目标函数中加入一个额外的惩罚因子,这个罚因子基于相对熵(KLdivergence):

因此这个罚因子会有如下性质,当时(这里取稀疏性参数为0.2),等于0,而两者差异越来越大时,相对熵会快速趋近于无穷大,如图2所示:

图2

稀疏自编码器训练方式与BP神经网络相对比

稀疏自编码神经网络的代价函数是BP神经网络的代价函数加上一个稀疏性惩罚项:

相应地,残差迭代公式也要进行修正

实现一个稀疏自编码器

数据概览

采用的是Andrew著名的UFLDL给出的样例,其中数据文件叫做IMAGES,这是一个512*512*10的三维数组,里面存了10张图片,每张都是262144像素。执行

<span style="font-size:14px;">loadIMAGES;
imagesc(IMAGES(:,:,6))
colormapgray;</span>

可以看看第6张图的样子,如图3所示,是一张关于森林和雪山的图像。

图3

数据采样

由于数据的图片挺大,我们总不能一上来搞一个每层都2万多节点的神经网络训练吧。我们先采样,这里从10张图片里面随机采样10000个小patch,每个小patch是一个8*8像素小碎片,我们定义训练集是64*10000的矩阵。每一列就是把刚刚的小patch拉成列向量的结果。

这里代码如下

<span style="font-size:14px;">loadIMAGES;    % load images from disk
patchsize= 8;  % we'll use 8x8 patches
%numpatches = 10;
numpatches= 10000;
%Initialize patches with zeros.  Your codewill fill in this matrix--one
%column per patch, 10000 columns.
patches= zeros(patchsize*patchsize, numpatches);
tic
image_size=size(IMAGES);
i=randi(image_size(1)-patchsize+1,1,numpatches);
j=randi(image_size(2)-patchsize+1,1,numpatches);
k=randi(image_size(3),1,numpatches);
fornum=1:numpatches
patches(:,num)=reshape(IMAGES(i(num):i(num)+patchsize-1,j(num):j(num)+patchsize-1,k(num)),1,[]);
end
toc</span>

这里randi函数,randi(iMax,m,n)在闭区间[1,iMax]生成m*n型随机矩阵。而reshape函数的作用是把每个小patch拉成一个列向量。

前200个patch的样子如图4所示:

图4

sparseAutoencoderCost.m

这部分代码是最核心也是最重要的,正如前面所说,现在优化目标函数有了3个部分:均方差项、权重衰减项、稀疏惩罚项。

这里程序需要一部分一部分地调试,否则非常容易得到看似正确但实际效果没有正确代码好的错误结果。这里附上我最新修改版本的代码,去掉了所有显式for循环,使用矢量化编程,简洁了代码,增强运行效率,但也减弱了可读性。

<span style="font-size:14px;">numpatches=size(patches,2);
a2=sigmoid(W1*patches+repmat(b1,1,numpatches));
a3=sigmoid(W2*a2+repmat(b2,1,numpatches));
Rho=sum(a2,2)/numpatches;
Penalty=-sparsityParam./Rho+(1-sparsityParam)./(1-Rho);
Delta3=(a3-patches).*a3.*(1-a3);
Delta2=(W2'*Delta3+beta*repmat(Penalty,1,numpatches)).*a2.*(1-a2);
cost1=sumsqr(a3-patches)/numpatches/2;
cost2=(sumsqr(W1)+sumsqr(W2))*lambda/2;
cost3=beta*sum(sparsityParam*log(sparsityParam./Rho)+(1-sparsityParam)*log((1-sparsityParam)./(1-Rho)));
cost=cost1+cost2+cost3;
W2grad=Delta3*a2'/numpatches+lambda*W2;
b2grad=sum(Delta3,2)/numpatches;
W1grad=Delta2*patches'/numpatches+lambda*W1;
b1grad=sum(Delta2,2)/numpatches;</span>

这里repmat的重复使用是用来复制矩阵的,一定要不遗余力去掉这部分代码中所有的显式for循环,否则执行起来时间会很长。

梯度校验

梯度校验是代码调试的大杀器,这一部分我用到了for循环,效率确实非常低了,所以调试的时候要把校验参数做些调整,令隐藏节点数量为2,采样数量为100,这样就能大大加快校验速度。否则要等相当久的时间。

<span style="font-size:14px;">EPSILON=0.0001;
thetaspslion=zeros(size(theta));
fori=1:size(theta)
thetaspslion(i)=EPSILON;
numgrad(i)=(J(theta+thetaspslion)-J(theta-thetaspslion))/2/EPSILON;
thetaspslion(i)=0;
end</span>

注意:最后运行时一定要关掉梯度校验,不然就要卡死机了。。。

这个梯度校验对于目标函数的3部分的调试一定要循序渐进,心急吃不了热豆腐。均方差项调试正确了以后,会得到如图5所示的图像

图5

而当,均方差项和权重衰减项都调试通过后,得到的图片是这样的

图6

而当所有的目标函数都调试通过以后,接下来就是见证奇迹的时刻!

图7

这就是图像的基,通过稀疏自编码器,我们学习得到了25个8*8的基,这些图像的基就相当于咱们每个视神经细胞所看到的东西,当这些细胞组成阵列,垒成层层叠叠,我们就能看到所有的东西了。

稀疏自编码器作为无监督学习的一层基本模块,这就是我们DeepLearning万里长城的第一步:搞基

稀疏自编码器及其实现——如何搞基

时间: 2024-10-27 10:29:30

稀疏自编码器及其实现——如何搞基的相关文章

稀疏自编码器及事实上现——怎样搞基

自编码器是什么? 自编码器本身就是一种BP神经网络. 它是一种无监督学习算法. 我们都知道神经网络能够从随意精度逼近随意函数,这里我们让神经网络目标值等于输出值x,也就是模拟一个恒等函数: 太无聊了,是吗?输入等于输出,这网络有什么意义?可是.当我们把自编码神经网络增加某些限制,事情就发生了变化. 如图1所看到的,这就是一个主要的自编码神经网络.能够看到隐含层节点数量要少于输入层节点数量. 图1 举个样例,假设我们输入一张10*10的图像,这样就有100个像素,所以输入层和输出层的节点数量就是1

深度学习UFLDL老教程笔记1 稀疏自编码器Ⅱ

稀疏自编码器的学习结构: 稀疏自编码器Ⅰ: 神经网络 反向传导算法 梯度检验与高级优化 稀疏自编码器Ⅱ: 自编码算法与稀疏性 可视化自编码器训练结果 Exercise: Sparse Autoencoder 自编码算法与稀疏性 已经讨论了神经网络在有监督学习中的应用,其中训练样本是有类别标签的(x_i,y_i). 自编码神经网络是一种无监督学习算法,它使用了反向传播算法,并让目标值等于输入值x_i = y_i . 下图是一个自编码神经网络的示例. 一次autoencoder学习,结构三层:输入层

HDU 3949 XOR(高斯消元搞基)

HDU 3949 XOR 题目链接 题意:给定一些数字,问任取几个异或值第k大的 思路:高斯消元搞基,然后从低位外高位去推算 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 10005; int t, n; ll a[N]; void gauss() { int r = 0; for

UFLDL教程练习答案一(稀疏自编码器和矢量化编程实现)

最近想研究下深度学习,一开始就看UFLDL(unsuprisedfeature learning and deep learning)教程了,特将课后习题答案放在这里,作为一个笔记. 笔记: 1:自编码算法是一个无监督学习算法,它通过学习hw,b(x) = x,因此最后的outputlayer单元数与inputlayer单元数量相等,而中间的hiddenlayer可以很大,这是加个稀疏惩罚项,就相当于使中间很多结点的激励值为0,这样就是类似于PCA了. 2:可视化自编码器,习题中可视化的是W1,

JS搞基指南----延迟对象入门提高资料整理

原文:JS搞基指南----延迟对象入门提高资料整理 JavaScript的Deferred是比较高大上的东西,  主要的应用还是主ajax的应用,  因为JS和nodeJS这几年的普及,  前端的代码越来越多,  各种回调套回调再套回调实在太让人崩溃, 所以就从后端拖了一个延迟对象这货, 用来解决回调地狱这个问题 .  我们使用ajax的时候多数都是为ajax添加回调 ,然后异步向服务器发送请求, 比如如下原生的XHR代码: <!DOCTYPE html PUBLIC "-//W3C//D

稀疏自编码器和矢量化编程

相关的公式 证明参考PPT: http://wenku.baidu.com/link?url=dBZZq7TYJOnIw2mwilKsJT_swT52I0OoikmvmgBaYE_NvP_KChFZ-HOURH5LMiLEuSVFcGmJ0bQfkG-ZYk-IRJf7D-w6P9PBec8EZ9IxgFS Python实现代码参考 @author: Paul Rothnieemail : [email protected]https://github.com/siddharth950/Spar

降噪自编码器/稀疏自编码器/栈式自编码器

漫谈autoencoder:降噪自编码器/稀疏自编码器/栈式自编码器(含tensorflow实现) 2018年08月11日 20:45:14 wblgers1234 阅读数 13196更多 分类专栏: 机器学习 深度学习 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/wblgers1234/article/details/81545079 0. 前言   在非监督学习中,最典型的一类神经

深度学习入门教程UFLDL学习实验笔记一:稀疏自编码器

UFLDL即(unsupervised feature learning & deep learning).这是斯坦福网站上的一篇经典教程.顾名思义,你将在这篇这篇文章中学习到无监督特征学习和深度学习的主要观点. UFLDL全文出处在这:http://ufldl.stanford.edu/wiki/index.php/UFLDL%E6%95%99%E7%A8%8B,本文为本人原创,参考了UFLDL的教程,是我自己个人对于这一系列教程的理解以及自己的实验结果.非盈利性质网站转载请在文章开头处著名本

[自编码器] [稀疏自编码器] Auto Encoder原理详解

自编码器是一种有效的提取特征的方法,与PCA无监督降维不同,它实际上是独立于有监督.无监督算法外的自监督算法,Hinton大牛主要就是搞这块的,比如被他当做宝贝的玻尔兹曼机... 下面这个PPT主要讲一下自编码器的原理及其变种. 原文地址:https://www.cnblogs.com/virter/p/9547520.html