稀疏自编码

原文地址:http://blog.csdn.net/hjimce/article/details/49106869

作者:hjimce

一、相关理论

以前刚开始学CNN的时候,就是通过阅读theano的深度学习相关教程源码,对于CNN的整个过程才有了深入理解。之前虽然懂CNN的原理,但是对于其源码层的实现,到底要怎么搞,却有点模糊,之后学了theano的cnn教程后,才知道原来是利用了四维矩阵进行操作。

理解了theano的CNN实现之后,对四维矩阵有了深刻的印象,后来阅读caffe的源码的时候,数据结构blob我就把它理解为了四维矩阵。在这里把自己以前阅读theano的时候,对之前源码的标注贴一下,以供大家学习,源码来自于:http://deeplearning.net/tutorial/。学习这些源码,同时我们也可以熟悉theano的使用,好处多多。所以建议刚入门深度学习的,一定要好好学theano的深度学习教程,好好解读源码。

本篇博文主要讲解:《稀疏自编码》算法,及其theano实现,属于深度学习的基础知识,高手请绕道。众所周知,机器学习可以大体分为三大类:监督学习、非监督学习和半监督学习。自编码神经网络是一种无监督学习算法,其实如果我们已经对PCA降维、SVD简化,比较熟悉的话,那么你会发现其实稀疏自编跟它们差不多,一样的简单,一样的无聊……

开始前,我们需要知道什么叫无监督学习,说实话,一年前,我连这个都不懂,因为我本身不是学人工智能方向的、也不是计算机专业、信息专业的。以前虽然学过聚类算法,但是那都是自学,没有系统的进行相关理论的学习,故而也不知道其实聚类算法就是无监督学习。说的简单点吧,所谓的无监督学习,就是不需要标签数据,也就是不需要我们对数据做标注,然后才能进行训练,数据直接拿过来,就可以进行训练了。

自编码的网络结构如下:

既然自编码网络是无标签数据,是怎么进行训练的呢?自编码网络很有意思,网络的输入是X,输出也是X,这样就相当于不需要进行数据标注了,属于无监督学习。那么自编码有什么用呢?你觉得让一个网络,输入是input=x,输出output=x,这样有意思吗?

从上面自编码的网络结构图,可以看到一开始输入特征是x1……x6,有六个特征,然后隐藏层的神经元只有3个,最后又用这3个神经元,要使得网络的输出尽量接近x1……x6。这就相当于我们输入了一个6维的特征向量,我们先把它降维,降到3维,然后我们利用这三维的特征向量,进行重构原始的数据。这个跟PCA降维一模一样,只不过PCA是通过求解特征向量,进行降维,是一种线性的降维方式,而自编码可以利用神经网络进行降维,是一种非线性降维,当然自编码隐藏层可以很多个神经元,然后我们使用正则化约束项,进行稀疏约束。

这样好玩吗,有意思吗,把x送进网络中,结果啥也不干,这个便是我学习自编码的时候,最大的疑问了,因为我不知道让一个网络的输入是x,最后输出也是x,这样有什么意义?要解答上面的网络有什么用,我们得从深度学习说起,我们知道,在深度学习中,一般网络都有很多层,因为网络层数一多,训练网络采用的梯度下降,在低层网络会出现梯度弥散的现象,导致了深度网络一直不招人待见。直到2006年的3篇论文改变了这种状况,由Hinton提出了一种深层网络的训练方法,改变了人们对深度学习的态度。Hinton所提出的训练思想,整体过程如下;

1、网络各层参数预训练。我们在以前的神经网络中,参数的初始化都是用随机初始化方法,然而这种方法,对于深层网络,在低层中,参数很难被训练,于是Hinton提出了参数预训练,这个主要就是采用RBM、以及我们本篇博文要讲的自编码,对网络的每一层进行参数初始化。也就是我们这边要学的稀疏自编码就是为了对网络的每一层进行参数初始化,仅仅是为了获得初始的参数值而已。

2、在一个时间里,一个层次的无监督训练,接着之前训练的层次。在每一层学习到的表示作为下一层的输入,对每层网络的进行训练初始化。

3、用有监督训练来调整所有层。

OK,我们回到本篇文章的主题,从上面的解释中,我们知道稀疏自编码仅仅只是为了获得参数的初始值而已。而其实我们上面的网络结构图,仅仅只是为了获取深度学习中,各层网络的初始参数值而已,一般我们训练完上后,就会把重构输出层去掉,只留下隐藏层与输入层的参数。而这些参数值,将作为本层网络,与上层网络的一个连接参数初始值。

二、源码实现

下面还是把theano的相关代码实现,贴一下:

[python] view plaincopy
  1. <span style="font-family:Arial;">import os
  2. import sys
  3. import timeit
  4. import numpy
  5. import theano
  6. import theano.tensor as T
  7. from logistic_sgd import load_data
  8. from utils import tile_raster_images
  9. try:
  10. import PIL.Image as Image
  11. except ImportError:
  12. import Image
  13. '''''代码编写参考文献:Contractive Auto-Encoder class
  14. 这篇文献主要是提出一个约束正则项
  15. 整个总计算过程,参考文献的公式:7'''
  16. class cA(object):
  17. def __init__(self, numpy_rng, input=None, n_visible=784, n_hidden=100,
  18. n_batchsize=1, W=None, bhid=None, bvis=None):
  19. """
  20. input:输入训练数据数据, input与n_batchsize是对应的,input中有n_batchsize个样本
  21. input每一行代表一个样本,共有n_batchsize个样本
  22. n_visible:可见层神经元的个数
  23. n_hidden: 隐藏层神经元个数
  24. n_batchsize:批量训练,每批数据的个数
  25. W:输入当隐藏层的全连接权值矩阵,因为使用了tied weight 所以从隐藏到输入的权值
  26. 矩阵为:W.transpose()
  27. bhid:从输入到隐藏层的偏置单元
  28. bvis:从隐藏层的偏置单元
  29. """
  30. self.n_visible = n_visible
  31. self.n_hidden = n_hidden
  32. self.n_batchsize = n_batchsize
  33. # 如果没有输入W,则在类里面进行初始化
  34. if not W:
  35. '''''W 采用[-a,a]的均匀采样方法进行初始化,因为后面采用s函数,所以
  36. a=4*sqrt(6./(n_visible+n_hidden)) ,矩阵类型theano.config.floatX
  37. 这样才能保证在GPU上运行'''
  38. initial_W = numpy.asarray(
  39. numpy_rng.uniform(
  40. low=-4 * numpy.sqrt(6. / (n_hidden + n_visible)),
  41. high=4 * numpy.sqrt(6. / (n_hidden + n_visible)),
  42. size=(n_visible, n_hidden)
  43. ),
  44. dtype=theano.config.floatX
  45. )
  46. W = theano.shared(value=initial_W, name='W', borrow=True)
  47. if not bvis:
  48. bvis = theano.shared(value=numpy.zeros(n_visible,
  49. dtype=theano.config.floatX),
  50. borrow=True)
  51. if not bhid:
  52. bhid = theano.shared(value=numpy.zeros(n_hidden,
  53. dtype=theano.config.floatX),
  54. name='b',
  55. borrow=True)
  56. self.W = W
  57. # 输入到隐藏的偏置单元
  58. self.b = bhid
  59. # 隐藏到输出的偏置单元
  60. self.b_prime = bvis
  61. # 使用了tied weights, 所以 W_prime 是 W 的转置
  62. self.W_prime = self.W.T
  63. # 如果没有给定input,那么创建一个
  64. if input is None:
  65. self.x = T.dmatrix(name='input')
  66. else:
  67. self.x = input
  68. self.params = [self.W, self.b, self.b_prime]
  69. #1、输入层到隐藏层
  70. def get_hidden_values(self, input):
  71. return T.nnet.sigmoid(T.dot(input, self.W) + self.b)
  72. #2、隐藏层到输出层。重建结果 x' = s(W' h  + b') ,因为文献使用了tied weigth,所以
  73. #W'等于W的转置,这个可以百度搜索:自编码,tied weight等关键词
  74. def get_reconstructed_input(self, hidden):
  75. return T.nnet.sigmoid(T.dot(hidden, self.W_prime) + self.b_prime)
  76. #计算 J_i = h_i (1 - h_i) * W_i
  77. def get_jacobian(self, hidden, W):
  78. return T.reshape(hidden * (1 - hidden),(self.n_batchsize, 1, self.n_hidden))*T.reshape(W, (1, self.n_visible, self.n_hidden))
  79. #权值更新函数
  80. def get_cost_updates(self, contraction_level, learning_rate):
  81. y = self.get_hidden_values(self.x)#输入-》隐藏
  82. z = self.get_reconstructed_input(y)#隐藏-》输出
  83. J = self.get_jacobian(y, self.W)#y*(1-y)*W
  84. #文献Contractive Auto-Encoders:公式4损失函数计算公式
  85. self.L_rec = - T.sum(self.x * T.log(z) +(1 - self.x) * T.log(1 - z),axis=1)
  86. # 因为J是由n_batchsize*n_hidden计算而来,有n_batchsize个样本,所以要求取样本平均值
  87. self.L_jacob = T.sum(J ** 2) / self.n_batchsize
  88. #整个惩罚函数
  89. cost = T.mean(self.L_rec) + contraction_level * T.mean(self.L_jacob)
  90. #对参数求导
  91. gparams = T.grad(cost, self.params)
  92. #梯度下降法更新参数
  93. updates = []
  94. for param, gparam in zip(self.params, gparams):
  95. updates.append((param, param - learning_rate * gparam))
  96. return (cost, updates)
  97. #测试验证上面的类是否正确
  98. def test_cA(learning_rate=0.01, training_epochs=20,
  99. dataset='mnist.pkl.gz',
  100. batch_size=10, output_folder='cA_plots', contraction_level=.1):
  101. """
  102. learning_rate:梯度下降法的学习率
  103. training_epochs: 最大迭代次数
  104. contraction_level:为正则项的权重
  105. """
  106. #datasets[0]为训练集,datasets[1]为验证集,datasets[2]为测试集
  107. datasets = load_data(dataset)
  108. train_set_x, train_set_y = datasets[0]
  109. # 批量下降法,训练的批数
  110. n_train_batches = train_set_x.get_value(borrow=True).shape[0] / batch_size
  111. # allocate symbolic variables for the data
  112. index = T.lscalar()    # 每一批训练数据的索引
  113. x = T.matrix('x')  # 每一批训练数据
  114. if not os.path.isdir(output_folder):
  115. os.makedirs(output_folder)
  116. os.chdir(output_folder)
  117. rng = numpy.random.RandomState(123)
  118. ca = cA(numpy_rng=rng, input=x,
  119. n_visible=28 * 28, n_hidden=500, n_batchsize=batch_size)
  120. cost, updates = ca.get_cost_updates(contraction_level=contraction_level,
  121. learning_rate=learning_rate)
  122. #每一批,训练更新函数,输入参数index
  123. train_ca = theano.function(
  124. [index],
  125. [T.mean(ca.L_rec), ca.L_jacob],
  126. updates=updates,
  127. givens={
  128. x: train_set_x[index * batch_size: (index + 1) * batch_size]
  129. }
  130. )
  131. start_time = timeit.default_timer()
  132. ############
  133. # TRAINING #
  134. ############
  135. # go through training epochs
  136. for epoch in xrange(training_epochs):
  137. # go through trainng set
  138. c = []
  139. for batch_index in xrange(n_train_batches):
  140. c.append(train_ca(batch_index))
  141. c_array = numpy.vstack(c)
  142. print 'Training epoch %d, reconstruction cost ' % epoch, numpy.mean(
  143. c_array[0]), ' jacobian norm ', numpy.mean(numpy.sqrt(c_array[1]))
  144. end_time = timeit.default_timer()
  145. training_time = (end_time - start_time)
  146. print >> sys.stderr, ('The code for file ' + os.path.split(__file__)[1] +
  147. ' ran for %.2fm' % ((training_time) / 60.))
  148. image = Image.fromarray(tile_raster_images(
  149. X=ca.W.get_value(borrow=True).T,
  150. img_shape=(28, 28), tile_shape=(10, 10),
  151. tile_spacing=(1, 1)))
  152. image.save('cae_filters.png')
  153. os.chdir('../')
  154. if __name__ == '__main__':
  155. test_cA()</span>

上面的代码,来自:http://deeplearning.net/tutorial/。主要是根据文献:《Contractive Auto-Encoder 》进行编写的代码,代码中,我们需要知道tie-weight、以及文献所提出的损失函数,所以要阅读上面的源码,还是需要把这篇文献看一下。

参考文献:

1、《Contractive Auto-Encoder》

2、http://deeplearning.net/tutorial/

**********************作者:hjimce   时间:2015.10.13  联系QQ:1393852684   地址:http://blog.csdn.net/hjimce   原创文章,版权所有,转载请保留本行信息(不允许删除)

深度学习(十二)稀疏自编码相关推荐

  1. 花书+吴恩达深度学习(二十)构建模型策略(超参数调试、监督预训练、无监督预训练)

    目录 0. 前言 1. 学习率衰减 2. 调参策略 3. 贪心监督预训练 4. 贪心逐层无监督预训练 如果这篇文章对你有一点小小的帮助,请给个关注,点个赞喔~我会非常开心的~ 花书+吴恩达深度学习(十 ...

  2. 花书+吴恩达深度学习(二六)近似推断(EM, 变分推断)

    文章目录 0. 前言 1. 将推断视为优化问题 1.1 期望最大化 EM 1.2 最大后验推断 MAP 1.3 稀疏编码 2. 变分推断 2.1 离散型潜变量 2.2 连续性潜变量 如果这篇文章对你有 ...

  3. 花书+吴恩达深度学习(二二)自编码器(欠完备,DAE,CAE,PSD)

    文章目录 0. 前言 1. 欠完备自编码器 2. 去噪自编码器 DAE 3. 收缩自编码器 CAE 4. 稀疏自编码器 5. 预测稀疏分解 PSD 如果这篇文章对你有一点小小的帮助,请给个关注,点个赞 ...

  4. 深度学习笔记之稀疏自编码器

    深度学习笔记之稀疏自编码器 引言 引子:题目描述 正确答案: A B C D \mathcal A \mathcal B \mathcal C \mathcal D ABCD 题目解析 介绍:自编码器 ...

  5. 2017年深度学习十大趋势预测

    2017年深度学习十大趋势预测 本文作者曾经多次预测了技术发展的趋势,最近的一次预测是"2011年软件发展的趋势与预测".10项预言中,准确地命中了6项,比如JavaScript ...

  6. 用MXnet实战深度学习之二:Neural art

    用MXnet实战深度学习之二:Neural art - 推酷 题注:本来这是第三集的内容,但是 Eric Xie 勤劳又机智的修复了mxnet和cuDNN的协作问题,我就把这篇当作一个卷积网络Conv ...

  7. PyTorch框架学习十二——损失函数

    PyTorch框架学习十二--损失函数 一.损失函数的作用 二.18种常见损失函数简述 1.L1Loss(MAE) 2.MSELoss 3.SmoothL1Loss 4.交叉熵CrossEntropy ...

  8. LSTM 之父发文:2010-2020,我眼中的深度学习十年简史

    作者 | Jürgen Schmidhuber 译者 | 刘畅.若名 出品 | AI科技大本营(ID:rgznai100) 作为LSTM发明人.深度学习元老,Jürgen Schmidhuber于2月 ...

  9. LSTM之父发文:2010-2020,我眼中的深度学习十年简史

    2020-02-23 15:04:22 作者 | Jürgen Schmidhuber 编译 | 刘畅.若名 出品 | AI科技大本营(ID:rgznai100) 作为LSTM发明人.深度学习元老,J ...

  10. 深度学习(二)向量化 Logistic 回归及其梯度输出

    概述 本篇属于理论篇,你将了解什么是向量化.向量化对神经网络训练优化的重要性,以及如何向量化 Logistic 回归及其梯度输出. 转自猴开发博客:深度学习(二)向量化 Logistic 回归及其梯度 ...

最新文章

  1. RayTracking 光线跟踪算法
  2. RISC-V生态未来的三种可能~
  3. Xilinx IP核专题之PLL IP核介绍(Spartan-6)
  4. python中如何快速判断一个值是否大于、小于、等于某个值?
  5. 生产者/消费者问题的多种Java实现方式--转
  6. VC MFC界面上显示BMP图片
  7. php中const和define,PHP中const和define的区别是什么
  8. java数组及Arrays创建一个int 类型数组 数组元素由键盘录入,每次打印插入排序的结果(数组扩容,数组排序,键盘录入)
  9. 用nifi把hdfs数据导到hive
  10. table中加表单元素怎么验证_使用element-ui +Vue 解决 table 里包含表单验证的问题...
  11. 阅读Unity官方技术blog笔记
  12. 技术人专访:GrapeCity,技术老炮开启低代码新征程
  13. 使用dva框架的总结
  14. 》》css3--动画
  15. 移动应用开发 jQuery Mobile
  16. MTK手机平台充电原理
  17. oracle表重命名 索引,Oracle索引
  18. 靠谱,这个低代码平台贼好用
  19. STM32 硬件IIC 锁死及复位问题
  20. 汽车车载智能终端T-BOX

热门文章

  1. 基于Python的卷积神经网络和特征提取
  2. 点击按钮测试用例标题_怎么写测试用例?
  3. jvm性能调优 - 05对象在JVM内存中的分配和流转
  4. Oracle查询优化-07日期运算
  5. of python检索文献 science web_硕博士都在学的Python神技,有大神带!
  6. linux进程故障如何修复,33.Linux开机过程及启动故障修复
  7. 微信小程序点击页面tab栏切换
  8. SpringMVC学习01之回顾Servlet
  9. easyui复杂表单_EasyUI中实现form表单提交的示例分享
  10. itextpdf添加表格元素_使用iText填充pdf表单