Deep learning:四十二(Denoise Autoencoder简单理解)
前言:
当采用无监督的方法分层预训练深度网络的权值时,为了学习到较鲁棒的特征,可以在网络的可视层(即数据的输入层)引入随机噪声,这种方法称为Denoise Autoencoder(简称dAE),由Bengio在08年提出,见其文章Extracting and composing robust features with denoising autoencoders.使用dAE时,可以用被破坏的输入数据重构出原始的数据(指没被破坏的数据),所以它训练出来的特征会更鲁棒。本篇博文主要是根据Benigio的那篇文章简单介绍下dAE,然后通过2个简单的实验来说明实际编程中该怎样应用dAE。这2个实验都是网络上现成的工具稍加改变而成,其中一个就是matlab的Deep Learning toolbox,见https://github.com/rasmusbergpalm/DeepLearnToolbox,另一个是与python相关的theano,参考:http://deeplearning.net/tutorial/dA.html.
基础知识:
首先来看看Bengio论文中关于dAE的示意图,如下:
由上图可知,样本x按照qD分布加入随机噪声后变为
,按照文章的意思,这里并不是加入高斯噪声,而是以一定概率使输入层节点的值清为0,这点与上篇博文介绍的dropout(Deep
learning:四十一(Dropout简单理解))很类似,只不过dropout作用在隐含层。此时输入到可视层的数据变为,隐含层输出为y,然后由y重构x的输出z,注意此时这里不是重构
,而是x.
Bengio对dAE的直观解释为:1.dAE有点类似人体的感官系统,比如人眼看物体时,如果物体某一小部分被遮住了,人依然能够将其识别出来,2.多模态信息输入人体时(比如声音,图像等),少了其中某些模态的信息有时影响也不大。3.普通的autoencoder的本质是学习一个相等函数,即输入和重构后的输出相等,这种相等函数的表示有个缺点就是当测试样本和训练样本不符合同一分布,即相差较大时,效果不好,明显,dAE在这方面的处理有所进步。
当然作者也从数学上给出了一定的解释。
1.
流形学习的观点。一般情况下,高维的数据都处于一个较低维的流形曲面上,而使用dAE得到的特征就基本处于这个曲面上,如下图所示。而普通的autoencoder,即使是加入了稀疏约束,其提取出的特征也不是都在这个低维曲面上(虽然这样也能提取出原始数据的主要信息)。
2.自顶向下的生成模型观点的解释。3.信息论观点的解释。4.随机法观点的解释。这几个观点的解释数学有一部分数学公式,大家具体去仔细看他的paper。
当在训练深度网络时,且采用了无监督方法预训练权值,通常,Dropout和Denoise
Autoencoder在使用时有一个小地方不同:Dropout在分层预训练权值的过程中是不参与的,只是后面的微调部分引入;而Denoise
Autoencoder是在每层预训练的过程中作为输入层被引入,在进行微调时不参与。另外,一般的重构误差可以采用均方误差的形式,但是如果输入和输出的向量元素都是位变量,则一般采用交叉熵来表示两者的差异。
实验过程:
实验一:
同样是用mnist手写数字识别数据库,训练样本数为60000,测试样本为10000,采用matlab的Deep
Learning工具箱(https://github.com/rasmusbergpalm/DeepLearnToolbox),2个隐含层,每个隐含层节点个数都是100,即整体网络结构为:784-100-100-10.
实验对比了有无使用denoise技术时识别的错误率以及两种情况下学习到了的特征形状,其实验结果如下所示:
没采用denoise的autoencoder时特征图显示:
测试样本误差率:9.33%
采用了denoise
autoencoder时的特征图显示:
测试样本误差率:8.26%
由实验结果图可知,加入了噪声后的自编码器学习到的特征要稍好些(没有去调参数,如果能调得一手好参的话,效果会更好)。
实验一主要部分的代码及注释:
Test.m:
%% //导入数据
load mnist_uint8;
train_x = double(train_x)/;
test_x = double(test_x)/;
train_y = double(train_y);
test_y = double(test_y); %% //实验一:采用denoising autoencoder进行预训练
rng();
sae = saesetup([ ]); % //其实这里nn中的W已经被随机初始化过
sae.ae{}.activation_function = 'sigm';
sae.ae{}.learningRate = ;
sae.ae{}.inputZeroMaskedFraction = .;
sae.ae{}.activation_function = 'sigm';
sae.ae{}.learningRate = ;
sae.ae{}.inputZeroMaskedFraction = .; %这里的denoise autocoder相当于隐含层的dropout,但它是分层训练的
opts.numepochs = ;
opts.batchsize = ;
sae = saetrain(sae, train_x, opts);% //无监督学习,不需要传入标签值,学习好的权重放在sae中,
% //并且train_x是最后一个隐含层的输出。由于是分层预训练
% //的,所以每次训练其实只考虑了一个隐含层,隐含层的输入有
% //相应的denoise操作
visualize(sae.ae{}.W{}(:,:end)')
% Use the SDAE to initialize a FFNN
nn = nnsetup([ ]);
nn.activation_function = 'sigm';
nn.learningRate = ;
%add pretrained weights
nn.W{} = sae.ae{}.W{}; % //将sae训练好了的权值赋给nn网络作为初始值,覆盖了前面的随机初始化
nn.W{} = sae.ae{}.W{};
% Train the FFNN
opts.numepochs = ;
opts.batchsize = ;
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进行预训练
rng();
sae = saesetup([ ]); % //其实这里nn中的W已经被随机初始化过
sae.ae{}.activation_function = 'sigm';
sae.ae{}.learningRate = ;
sae.ae{}.inputZeroMaskedFraction = 0.5;
sae.ae{}.activation_function = 'sigm';
sae.ae{}.learningRate = ;
sae.ae{}.inputZeroMaskedFraction = 0.5; %这里的denoise autocoder相当于隐含层的dropout,但它是分层训练的
opts.numepochs = ;
opts.batchsize = ;
sae = saetrain(sae, train_x, opts);% //无监督学习,不需要传入标签值,学习好的权重放在sae中,
% //并且train_x是最后一个隐含层的输出。由于是分层预训练
% //的,所以每次训练其实只考虑了一个隐含层,隐含层的输入有
% //相应的denoise操作
figure,visualize(sae.ae{}.W{}(:,:end)')
% Use the SDAE to initialize a FFNN
nn = nnsetup([ ]);
nn.activation_function = 'sigm';
nn.learningRate = ;
%add pretrained weights
nn.W{} = sae.ae{}.W{}; % //将sae训练好了的权值赋给nn网络作为初始值,覆盖了前面的随机初始化
nn.W{} = sae.ae{}.W{};
% Train the FFNN
opts.numepochs = ;
opts.batchsize = ;
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)
也可以类似于上篇博文跟踪Dropout代码一样,这里去跟踪下dAE代码。使用sae时将输入层加入50%噪声的语句:
sae.ae{1}.inputZeroMaskedFraction = 0.5;
继续跟踪到sae的训练过程,其训练过程也是采用nntrain()函数,里面有如下代码:
if(nn.inputZeroMaskedFraction ~= ) batch_x = batch_x.*(rand(size(batch_x))>nn.inputZeroMaskedFraction); % //在输入数据上加入噪声,rand()为0-1之间的均匀分布
代码一目了然。
实验二:
这部分的实验基本上就是网页教程上的:http://deeplearning.net/tutorial/dA.html,具体细节可以参考教程的内容,里面讲得比较详细。由于其dAE的实现是用了theano库,所以首先需要安装theano以及与之相关的一系列库,比如在ubuntu下安装就可以参考网页Installing
Theano和Easy
Installation of an optimized Theano on Ubuntu,
很容易成功(注意在测试时有些不重要的小failure可以忽略掉)。下面是我安装theano时的各版本号:
ubuntu 13.04,linux操作系统.
python:
2.7.4,编程语言包.
python-numpy 1.7.1,python的数学运算包,包含矩阵运算.
python-scipy 0.11,有利于稀疏矩阵运算.
python-pip,1.1,python的包管理软件.
python-nose,1.1.2,有利于thenao的测试.
libopenblas-dev,0.2.6,用来管理头文件的.
git,1.8.1,用来下载软件版本的.
gcc,4.7.3,用来编译c的.
theano,0.6.0rc3,多维矩阵操作,优化,可与GPU结合的python库.
这个实验也是用的mnist数据库,不过只用了一个隐含层节点,节点个数为500.
实验目的只是为了对比在使用denoise前后的autoencoder学习到的特征形状的区别。
没用denoise时的特征:
使用了denoise时的特征:
由图可见,加入了denoise后学习到的特征更具有代表性。
实验二主要部分的代码及注释:
dA.py:
#_*_coding:UTF-8_*_
import cPickle
import gzip
import os
import sys
import time
import numpy
import theano
import theano.tensor as T #theano中一些常见的符号操作在子库tensor中
from theano.tensor.shared_randomstreams import RandomStreams
from logistic_sgd import load_data
from utils import tile_raster_images
import PIL.Image #绘图所用 class dA(object):
def __init__(self, numpy_rng, theano_rng=None, input=None,
n_visible=784, n_hidden=500,
W=None, bhid=None, bvis=None):
self.n_visible = n_visible
self.n_hidden = n_hidden
if not theano_rng:
theano_rng = RandomStreams(numpy_rng.randint(2 ** 30))
if not W:
initial_W = numpy.asarray(numpy_rng.uniform(
low=-4 * numpy.sqrt(6. / (n_hidden + n_visible)),
high=4 * numpy.sqrt(6. / (n_hidden + n_visible)),
size=(n_visible, n_hidden)), dtype=theano.config.floatX)
W = theano.shared(value=initial_W, name='W', borrow=True) #W,bvis,bhid都为共享变量
if not bvis:
bvis = theano.shared(value=numpy.zeros(n_visible, dtype=theano.config.floatX), borrow=True)
if not bhid:
bhid = theano.shared(value=numpy.zeros(n_hidden, dtype=theano.config.floatX), name='b', borrow=True)
self.W = W
self.b = bhid
self.b_prime = bvis
self.W_prime = self.W.T
self.theano_rng = theano_rng
if input == None:
self.x = T.dmatrix(name='input')
else:
self.x = input #保存输入数据
self.params = [self.W, self.b, self.b_prime] def get_corrupted_input(self, input, corruption_level):
return self.theano_rng.binomial(size=input.shape, n=1,
p=1 - corruption_level,
dtype=theano.config.floatX) * input #binomial()函数为产生0,1的分布,这里是设置产生1的概率为p def get_hidden_values(self, input):
return T.nnet.sigmoid(T.dot(input, self.W) + self.b) def get_reconstructed_input(self, hidden):
return T.nnet.sigmoid(T.dot(hidden, self.W_prime) + self.b_prime) def get_cost_updates(self, corruption_level, learning_rate): #每调用该函数一次,就算出了前向传播的误差cost,网络参数及其导数
tilde_x = self.get_corrupted_input(self.x, corruption_level)
y = self.get_hidden_values(tilde_x)
z = self.get_reconstructed_input(y)
L = - T.sum(self.x * T.log(z) + (1 - self.x) * T.log(1 - z), axis=1)
cost = T.mean(L)
gparams = T.grad(cost, self.params)
updates = []
for param, gparam in zip(self.params, gparams):
updates.append((param, param - learning_rate * gparam)) #append列表中存的是参数和其导数构成的元组
return (cost, updates) # 测试函数
def test_dA(learning_rate=0.1, training_epochs=15,
dataset='data/mnist.pkl.gz',
batch_size=20, output_folder='dA_plots'):
datasets = load_data(dataset)
train_set_x, train_set_y = datasets[0] #train_set_x矩阵中每一行代表一个样本
n_train_batches = train_set_x.get_value(borrow=True).shape[0] / batch_size #求出batch的个数
index = T.lscalar() # index to a [mini]batch
x = T.matrix('x') # the data is presented as rasterized images
if not os.path.isdir(output_folder):
os.makedirs(output_folder)
os.chdir(output_folder) # 没有使用denoise时
rng = numpy.random.RandomState(123)
theano_rng = RandomStreams(rng.randint(2 ** 30))
da = dA(numpy_rng=rng, theano_rng=theano_rng, input=x,
n_visible=28 * 28, n_hidden=500) # 创建dA对象时,并不需要数据x,只是给对象da中的一些网络结构参数赋值
cost, updates = da.get_cost_updates(corruption_level=0.,
learning_rate=learning_rate)
train_da = theano.function([index], cost, updates=updates, #theano.function()为定义一个符号函数,这里的自变量为indexy
givens={x: train_set_x[index * batch_size: (index + 1) * batch_size]}) #输出变量为cost
start_time = time.clock()
for epoch in xrange(training_epochs):
c = []
for batch_index in xrange(n_train_batches):
c.append(train_da(batch_index))
print 'Training epoch %d, cost ' % epoch, numpy.mean(c)
end_time = time.clock()
training_time = (end_time - start_time)
print >> sys.stderr, ('The no corruption code for file ' +
os.path.split(__file__)[1] +
' ran for %.2fm' % ((training_time) / 60.))
image = PIL.Image.fromarray(
tile_raster_images(X=da.W.get_value(borrow=True).T,
img_shape=(28, 28), tile_shape=(10, 10),
tile_spacing=(1, 1)))
image.save('filters_corruption_0.png') # 使用了denoise时
rng = numpy.random.RandomState(123)
theano_rng = RandomStreams(rng.randint(2 ** 30))
da = dA(numpy_rng=rng, theano_rng=theano_rng, input=x,
n_visible=28 * 28, n_hidden=500)
cost, updates = da.get_cost_updates(corruption_level=0.3,
learning_rate=learning_rate) #将输入样本每个像素点以30%的概率被清0
train_da = theano.function([index], cost, updates=updates,
givens={x: train_set_x[index * batch_size:
(index + 1) * batch_size]})
start_time = time.clock()
for epoch in xrange(training_epochs):
c = []
for batch_index in xrange(n_train_batches):
c.append(train_da(batch_index))
print 'Training epoch %d, cost ' % epoch, numpy.mean(c)
end_time = time.clock()
training_time = (end_time - start_time)
print >> sys.stderr, ('The 30% corruption code for file ' +
os.path.split(__file__)[1] +
' ran for %.2fm' % (training_time / 60.))
image = PIL.Image.fromarray(tile_raster_images(
X=da.W.get_value(borrow=True).T,
img_shape=(28, 28), tile_shape=(10, 10),
tile_spacing=(1, 1)))
image.save('filters_corruption_30.png')
os.chdir('../') if __name__ == '__main__':
test_dA()
其中与dAE相关的代码为:
def get_corrupted_input(self, input, corruption_level):
return self.theano_rng.binomial(size=input.shape, n=1,p=1 - corruption_level,\
dtype=theano.config.floatX) * input #binomial()函数为产生0,1的分布,这里是设置产生1的概率
参考资料:
Vincent, P., et al. (2008). Extracting and composing robust features with denoising autoencoders. Proceedings of the 25th international conference on Machine learning, ACM.
https://github.com/rasmusbergpalm/DeepLearnToolbox
http://deeplearning.net/tutorial/dA.html
Deep learning:四十一(Dropout简单理解)
Easy Installation of an optimized Theano on Ubuntu
Deep learning:四十二(Denoise Autoencoder简单理解)的更多相关文章
- Deep learning:四十八(Contractive AutoEncoder简单理解)
Contractive autoencoder是autoencoder的一个变种,其实就是在autoencoder上加入了一个规则项,它简称CAE(对应中文翻译为?).通常情况下,对权值进行惩罚后的a ...
- Denoise Autoencoder简单理解
自编码器通过学习隐含特征来表达原始数据,那什么是denoise autoencoder呢? 关于Autoencoder参考:http://blog.csdn.net/on2way/article/de ...
- linux设备驱动归纳总结(十二):简单的数码相框【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-116926.html linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxx ...
- NeHe OpenGL教程 第四十二课:多重视口
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- 【Linux开发】linux设备驱动归纳总结(十二):简单的数码相框
linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- 第四十二个知识点:看看你的C代码为蒙哥马利乘法,你能确定它可能在哪里泄漏侧信道路吗?
第四十二个知识点:看看你的C代码为蒙哥马利乘法,你能确定它可能在哪里泄漏侧信道路吗? 几个月前(回到3月份),您可能还记得我在这个系列的52件东西中发布了第23件(可以在这里找到).这篇文章的标题是& ...
- 网站开发进阶(四十二)巧用clear:both
网站开发进阶(四十二)巧用clear:both 前言 我们在制作网页中用div+css或者称xhtml+css都会遇到一些很诡异的情况,明明布局正确,但是整个画面却混乱起来了,有时候在IE6下看的很正 ...
- Gradle 1.12用户指南翻译——第四十二章. Announce插件
本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- SQL注入之Sqli-labs系列第四十一关(基于堆叠注入的盲注)和四十二关四十三关四十四关四十五关
0x1普通测试方式 (1)输入and1=1和and1=2测试,返回错误,证明存在注入 (2)union select联合查询 (3)查询表名 (4)其他 payload: ,( ,( 0x2 堆叠注入 ...
随机推荐
- PHP中实现MySQL嵌套事务的两种解决方案
PHP中实现MySQL嵌套事务的两种解决方案 一.问题起源 在MySQL的官方文档中有明确的说明不支持嵌套事务: Transactions cannot be nested. This is a co ...
- redhat7 yum安装
redhat 的更新包只对注册的用户生效,所以我们自己手动更改成CentOS 的更新包,CentOS几乎和redhat是一样的,所以无需担心软件包是否可安装,安装之后是否有问题,另外CentOS公司去 ...
- Linux环境下Oracle数据库启动停止命令
切换root至oracle数据库账号 su – oracle 查看数据库服务状态: ps -ef |grep oracle netstat –an|grep 1521 查看数据库监听状态: [orac ...
- mfc
(1)编写mfc程序的基本步骤: 1.资源编辑: 2.关联控件变量: 3.编写新的类和成员函数: 4.添加消息处理函数. (2)消息映射机制: (3)常用控件: (4)界面美化:
- mongodb( 实现join)
mongodb提供ref和populate的方法,支持类似join的SQL操作.本文给出一个实际的例子: 1. 数据1: var daob = new Schema({ user: { type: S ...
- 原创教程:《metasploit新手指南》介绍及下载
原创教程:<metasploit新手指南>介绍及下载 1.1 作者简介 这份教程并不是“玄魂工作室”原创,但是我还是要力推给大家.相比那些一连几年都在问“我怎么才能入门”的人而言,我们更欣 ...
- 在GitHub注册账户的过程
(1)第一步:首先起一个属于自己用户的名字(username),用户名字只能包含字母数字的字符或者单个连字符,不能只用单个连字符开始或者结束(only contain alphanumeric cha ...
- java提高篇(二五)-----HashTable
在java中与有两个类都提供了一个多种用途的hashTable机制,他们都可以将可以key和value结合起来构成键值对通过put(key,value)方法保存起来,然后通过get(key ...
- FB引擎系列-之CloudSand
CloudSand,欲打破之前的集中版本制作的模式, http://code.taobao.org/p/cloudsand包含服务器端代码(php)和客户端代码(unity) EasyDown的时 ...
- SOA服务设计与实现的几个语言无关的原则速记
一.SOA定义 SOA即面向服务架构(Service-Oriented Architecture).在SOA中,一切皆服务.一个服务是通过消息交换来调用的程序,一个信息系统是共同完成一个特定任务的一组 ...