RBM受限波尔兹曼机学习

原文地址

作者:hjimce

[python] view plain copy

  1. #coding=utf-8
  2. import timeit
  3. try:
  4. import PIL.Image as Image
  5. except ImportError:
  6. import Image
  7. import numpy
  8. import theano
  9. import theano.tensor as T
  10. import os
  11. from theano.tensor.shared_randomstreams import RandomStreams
  12. from utils import tile_raster_images
  13. from logistic_sgd import load_data
  14. #RBM网络结构设置,主要是参数初始化
  15. class RBM(object):
  16. def __init__(self,input=None,n_visible=784,n_hidden=500,W=None,hbias=None,vbias=None,numpy_rng=None,theano_rng=None):
  17. self.n_visible = n_visible
  18. self.n_hidden = n_hidden
  19. if numpy_rng is None:
  20. numpy_rng = numpy.random.RandomState(1234)
  21. if theano_rng is None:
  22. theano_rng = RandomStreams(numpy_rng.randint(2 ** 30))
  23. #参数初始化公式 -4*sqrt(6./(n_visible+n_hidden))
  24. if W is None:
  25. initial_W = numpy.asarray(
  26. numpy_rng.uniform(
  27. low=-4 * numpy.sqrt(6. / (n_hidden + n_visible)),
  28. high=4 * numpy.sqrt(6. / (n_hidden + n_visible)),
  29. size=(n_visible, n_hidden)
  30. ),
  31. dtype=theano.config.floatX
  32. )
  33. #在GPU上,多线程权重共享
  34. W = theano.shared(value=initial_W, name='W', borrow=True)
  35. #隐藏层偏置b初始化为0
  36. if hbias is None:
  37. hbias = theano.shared(value=numpy.zeros(n_hidden,dtype=theano.config.floatX),name='hbias',borrow=True)
  38. #可见层偏置项b初始化为0
  39. if vbias is None:
  40. vbias = theano.shared(value=numpy.zeros(n_visible,dtype=theano.config.floatX),name='vbias',borrow=True)
  41. #网络输入
  42. self.input = input
  43. if not input:
  44. self.input = T.matrix('input')
  45. self.W = W
  46. self.hbias = hbias
  47. self.vbias = vbias
  48. self.theano_rng = theano_rng
  49. #网络的所有参数,我们把它们放在一个列表中,以便后续访问
  50. self.params = [self.W, self.hbias, self.vbias]
  51. #能量函数的定义,主要是用于计算可视层的能量
  52. def free_energy(self, v_sample):
  53. ''''' Function to compute the free energy '''
  54. wx_b = T.dot(v_sample, self.W) + self.hbias
  55. vbias_term = T.dot(v_sample, self.vbias)
  56. hidden_term = T.sum(T.log(1 + T.exp(wx_b)), axis=1)
  57. return -hidden_term - vbias_term
  58. #前向传导 从可视层到隐藏层,计算p(h=1|v)
  59. def propup(self, vis):
  60. pre_sigmoid_activation = T.dot(vis, self.W) + self.hbias
  61. return [pre_sigmoid_activation, T.nnet.sigmoid(pre_sigmoid_activation)]
  62. #根据可视层状态 计算隐藏层状态
  63. def sample_h_given_v(self, v0_sample):
  64. #计算隐藏层每个神经元为状态1的概率,即 p(h=1|v)
  65. pre_sigmoid_h1, h1_mean = self.propup(v0_sample)
  66. #根据给定的概率,进行采样,就像抛硬币一样。n表示抛硬币的次数 ,每个神经元随机采样一次,就可以得到每个神经元的状态了
  67. #p是生成1的概率,binomial函数生成的是一个0、1数
  68. h1_sample = self.theano_rng.binomial(size=h1_mean.shape,n=1,p=h1_mean,dtype=theano.config.floatX)
  69. return [pre_sigmoid_h1, h1_mean, h1_sample]
  70. #后向传导,从隐藏层到可视层,计算p(v=1|h)
  71. def propdown(self, hid):
  72. pre_sigmoid_activation = T.dot(hid, self.W.T) + self.vbias
  73. return [pre_sigmoid_activation, T.nnet.sigmoid(pre_sigmoid_activation)]
  74. #根据隐藏层的状态计算可视层状态
  75. def sample_v_given_h(self, h0_sample):
  76. pre_sigmoid_v1, v1_mean = self.propdown(h0_sample)
  77. v1_sample = self.theano_rng.binomial(size=v1_mean.shape,
  78. n=1, p=v1_mean,
  79. dtype=theano.config.floatX)
  80. return [pre_sigmoid_v1, v1_mean, v1_sample]
  81. #计算从隐藏层-》可视层-》隐藏层的一个状态转移过程,相当于一次的Gibbs sampling采样
  82. def gibbs_hvh(self, h0_sample):
  83. pre_sigmoid_v1, v1_mean, v1_sample = self.sample_v_given_h(h0_sample)
  84. pre_sigmoid_h1, h1_mean, h1_sample = self.sample_h_given_v(v1_sample)
  85. return [pre_sigmoid_v1, v1_mean, v1_sample,
  86. pre_sigmoid_h1, h1_mean, h1_sample]
  87. #计算从可视层-》隐藏层-》可视层的状态转移过程,相当于一次的Gibbs sampling采样
  88. def gibbs_vhv(self, v0_sample):
  89. pre_sigmoid_h1, h1_mean, h1_sample = self.sample_h_given_v(v0_sample)
  90. pre_sigmoid_v1, v1_mean, v1_sample = self.sample_v_given_h(h1_sample)
  91. return [pre_sigmoid_h1, h1_mean, h1_sample,
  92. pre_sigmoid_v1, v1_mean, v1_sample]
  93. # k用于设置Gibbs sampling采样次数,也就是相当于来回跑了多少次(来回一趟算一次)
  94. def get_cost_updates(self, lr=0.1, persistent=None, k=1):
  95. # 当我们输入数据的时候,首先根据输入x,计算隐藏层的概率分布,概率分布的采样结果
  96. pre_sigmoid_ph, ph_mean, ph_sample = self.sample_h_given_v(self.input)
  97. # decide how to initialize persistent chain:
  98. # for CD, we use the newly generate hidden sample
  99. # for PCD, we initialize from the old state of the chain
  100. if persistent is None:
  101. chain_start = ph_sample
  102. else:
  103. chain_start = persistent
  104. #让函数来回跑k次
  105. (
  106. [
  107. pre_sigmoid_nvs,
  108. nv_means,
  109. nv_samples,
  110. pre_sigmoid_nhs,
  111. nh_means,
  112. nh_samples
  113. ],
  114. updates
  115. ) = theano.scan(self.gibbs_hvh,outputs_info=[None, None, None, None, None, chain_start],n_steps=k)
  116. #拿到最后一次循环的状态
  117. chain_end = nv_samples[-1]
  118. #构造损失函数
  119. cost = T.mean(self.free_energy(self.input)) - T.mean(
  120. self.free_energy(chain_end))
  121. #计算梯度,然后进行梯度下降更新
  122. gparams = T.grad(cost, self.params, consider_constant=[chain_end])
  123. for gparam, param in zip(gparams, self.params):
  124. updates[param] = param - gparam * T.cast(lr,dtype=theano.config.floatX)
  125. if persistent:
  126. # Note that this works only if persistent is a shared variable
  127. updates[persistent] = nh_samples[-1]
  128. # pseudo-likelihood is a better proxy for PCD
  129. monitoring_cost = self.get_pseudo_likelihood_cost(updates)
  130. else:
  131. # reconstruction cross-entropy is a better proxy for CD
  132. monitoring_cost = self.get_reconstruction_cost(updates,pre_sigmoid_nvs[-1])
  133. return monitoring_cost, updates
  134. # end-snippet-4
  135. def get_pseudo_likelihood_cost(self, updates):
  136. """Stochastic approximation to the pseudo-likelihood"""
  137. # index of bit i in expression p(x_i | x_{\i})
  138. bit_i_idx = theano.shared(value=0, name='bit_i_idx')
  139. # binarize the input image by rounding to nearest integer
  140. xi = T.round(self.input)
  141. # calculate free energy for the given bit configuration
  142. fe_xi = self.free_energy(xi)
  143. # flip bit x_i of matrix xi and preserve all other bits x_{\i}
  144. # Equivalent to xi[:,bit_i_idx] = 1-xi[:, bit_i_idx], but assigns
  145. # the result to xi_flip, instead of working in place on xi.
  146. xi_flip = T.set_subtensor(xi[:, bit_i_idx], 1 - xi[:, bit_i_idx])
  147. # calculate free energy with bit flipped
  148. fe_xi_flip = self.free_energy(xi_flip)
  149. # equivalent to e^(-FE(x_i)) / (e^(-FE(x_i)) + e^(-FE(x_{\i})))
  150. cost = T.mean(self.n_visible * T.log(T.nnet.sigmoid(fe_xi_flip -
  151. fe_xi)))
  152. # increment bit_i_idx % number as part of updates
  153. updates[bit_i_idx] = (bit_i_idx + 1) % self.n_visible
  154. return cost
  155. def get_reconstruction_cost(self, updates, pre_sigmoid_nv):
  156. """Approximation to the reconstruction error
  157. Note that this function requires the pre-sigmoid activation as
  158. input.  To understand why this is so you need to understand a
  159. bit about how Theano works. Whenever you compile a Theano
  160. function, the computational graph that you pass as input gets
  161. optimized for speed and stability.  This is done by changing
  162. several parts of the subgraphs with others.  One such
  163. optimization expresses terms of the form log(sigmoid(x)) in
  164. terms of softplus.  We need this optimization for the
  165. cross-entropy since sigmoid of numbers larger than 30. (or
  166. even less then that) turn to 1. and numbers smaller than
  167. -30. turn to 0 which in terms will force theano to compute
  168. log(0) and therefore we will get either -inf or NaN as
  169. cost. If the value is expressed in terms of softplus we do not
  170. get this undesirable behaviour. This optimization usually
  171. works fine, but here we have a special case. The sigmoid is
  172. applied inside the scan op, while the log is
  173. outside. Therefore Theano will only see log(scan(..)) instead
  174. of log(sigmoid(..)) and will not apply the wanted
  175. optimization. We can not go and replace the sigmoid in scan
  176. with something else also, because this only needs to be done
  177. on the last step. Therefore the easiest and more efficient way
  178. is to get also the pre-sigmoid activation as an output of
  179. scan, and apply both the log and sigmoid outside scan such
  180. that Theano can catch and optimize the expression.
  181. """
  182. cross_entropy = T.mean(
  183. T.sum(
  184. self.input * T.log(T.nnet.sigmoid(pre_sigmoid_nv)) +
  185. (1 - self.input) * T.log(1 - T.nnet.sigmoid(pre_sigmoid_nv)),
  186. axis=1
  187. )
  188. )
  189. return cross_entropy
  190. #
  191. def test_rbm(learning_rate=0.1, training_epochs=15,
  192. dataset='mnist.pkl.gz', batch_size=20,
  193. n_chains=20, n_samples=10, output_folder='rbm_plots',
  194. n_hidden=500):
  195. datasets = load_data(dataset)
  196. train_set_x, train_set_y = datasets[0]
  197. test_set_x, test_set_y = datasets[2]
  198. #计算训练的批数
  199. n_train_batches = train_set_x.get_value(borrow=True).shape[0] / batch_size
  200. index = T.lscalar()    # index to a [mini]batch
  201. x = T.matrix('x')  # the data is presented as rasterized images
  202. rng = numpy.random.RandomState(123)
  203. theano_rng = RandomStreams(rng.randint(2 ** 30))
  204. persistent_chain = theano.shared(numpy.zeros((batch_size, n_hidden),dtype=theano.config.floatX),borrow=True)
  205. #网络构建 ,可视层神经元个数为28*28,隐藏层神经元为500
  206. rbm = RBM(input=x, n_visible=28 * 28,n_hidden=n_hidden, numpy_rng=rng, theano_rng=theano_rng)
  207. # get the cost and the gradient corresponding to one step of CD-15
  208. cost, updates = rbm.get_cost_updates(lr=learning_rate,persistent=persistent_chain, k=15)
  209. #################################
  210. #     Training the RBM          #
  211. #################################
  212. if not os.path.isdir(output_folder):
  213. os.makedirs(output_folder)
  214. os.chdir(output_folder)
  215. # start-snippet-5
  216. # it is ok for a theano function to have no output
  217. # the purpose of train_rbm is solely to update the RBM parameters
  218. train_rbm = theano.function([index],cost,updates=updates,givens={x: train_set_x[index * batch_size: (index + 1) * batch_size]},name='train_rbm')
  219. plotting_time = 0.
  220. start_time = timeit.default_timer()
  221. # go through training epochs
  222. for epoch in xrange(training_epochs):
  223. # go through the training set
  224. mean_cost = []
  225. for batch_index in xrange(n_train_batches):
  226. mean_cost += [train_rbm(batch_index)]
  227. print 'Training epoch %d, cost is ' % epoch, numpy.mean(mean_cost)
  228. # Plot filters after each training epoch
  229. plotting_start = timeit.default_timer()
  230. # Construct image from the weight matrix
  231. image = Image.fromarray(
  232. tile_raster_images(
  233. X=rbm.W.get_value(borrow=True).T,
  234. img_shape=(28, 28),
  235. tile_shape=(10, 10),
  236. tile_spacing=(1, 1)
  237. )
  238. )
  239. image.save('filters_at_epoch_%i.png' % epoch)
  240. plotting_stop = timeit.default_timer()
  241. plotting_time += (plotting_stop - plotting_start)
  242. end_time = timeit.default_timer()
  243. pretraining_time = (end_time - start_time) - plotting_time
  244. print ('Training took %f minutes' % (pretraining_time / 60.))
  245. # end-snippet-5 start-snippet-6
  246. #################################
  247. #     Sampling from the RBM     #
  248. #################################
  249. # find out the number of test samples
  250. number_of_test_samples = test_set_x.get_value(borrow=True).shape[0]
  251. # pick random test examples, with which to initialize the persistent chain
  252. test_idx = rng.randint(number_of_test_samples - n_chains)
  253. persistent_vis_chain = theano.shared(
  254. numpy.asarray(
  255. test_set_x.get_value(borrow=True)[test_idx:test_idx + n_chains],
  256. dtype=theano.config.floatX
  257. )
  258. )
  259. # end-snippet-6 start-snippet-7
  260. plot_every = 1000
  261. # define one step of Gibbs sampling (mf = mean-field) define a
  262. # function that does `plot_every` steps before returning the
  263. # sample for plotting
  264. (
  265. [
  266. presig_hids,
  267. hid_mfs,
  268. hid_samples,
  269. presig_vis,
  270. vis_mfs,
  271. vis_samples
  272. ],
  273. updates
  274. ) = theano.scan(
  275. rbm.gibbs_vhv,
  276. outputs_info=[None, None, None, None, None, persistent_vis_chain],
  277. n_steps=plot_every
  278. )
  279. # add to updates the shared variable that takes care of our persistent
  280. # chain :.
  281. updates.update({persistent_vis_chain: vis_samples[-1]})
  282. # construct the function that implements our persistent chain.
  283. # we generate the "mean field" activations for plotting and the actual
  284. # samples for reinitializing the state of our persistent chain
  285. sample_fn = theano.function(
  286. [],
  287. [
  288. vis_mfs[-1],
  289. vis_samples[-1]
  290. ],
  291. updates=updates,
  292. name='sample_fn'
  293. )
  294. # create a space to store the image for plotting ( we need to leave
  295. # room for the tile_spacing as well)
  296. image_data = numpy.zeros(
  297. (29 * n_samples + 1, 29 * n_chains - 1),
  298. dtype='uint8'
  299. )
  300. for idx in xrange(n_samples):
  301. # generate `plot_every` intermediate samples that we discard,
  302. # because successive samples in the chain are too correlated
  303. vis_mf, vis_sample = sample_fn()
  304. print ' ... plotting sample ', idx
  305. image_data[29 * idx:29 * idx + 28, :] = tile_raster_images(
  306. X=vis_mf,
  307. img_shape=(28, 28),
  308. tile_shape=(1, n_chains),
  309. tile_spacing=(1, 1)
  310. )
  311. # construct image
  312. image = Image.fromarray(image_data)
  313. image.save('samples.png')
  314. # end-snippet-7
  315. os.chdir('../')
  316. if __name__ == '__main__':
  317. test_rbm()
from: http://blog.csdn.net/hjimce/article/details/48949197

深度学习(八)RBM受限波尔兹曼机学习-未完待续相关推荐

  1. Windows x64内核学习笔记(五)—— KPTI(未完待续)

    Windows x64内核学习笔记(五)-- KPTI(未完待续) KPTI 实验一:构造IDT后门并读取Cr3 参考资料 KPTI 描述:KPTI(Kernel page-table isolati ...

  2. DL:受限波尔兹曼机(RBM)能量模型

    受限波尔兹曼机(RBM)能量模型 在学习Hinton的stack autoencoder算法(论文 Reducing the Dimensionality of Data with Neural Ne ...

  3. 神经网络 | 受限波尔兹曼机(附源代码)

    ===================================================== github:https://github.com/MichaelBeechan CSDN: ...

  4. pythonb超分辨成像_Papers | 超分辨 + 深度学习(未完待续)

    1. SRCNN 1.1. Contribution end-to-end深度学习应用在超分辨领域的开山之作(非 end-to-end 见 Story.3 ). 指出了超分辨方向上传统方法( spar ...

  5. 二叉树学习笔记(未完待续)

    摘要 二叉树学习笔记(未完待续). 博客 IT老兵驿站. 前言 昨天(2019-11-07)复习红黑树,发现红黑树和二叉树密不可分,所以这里再复习一下二叉树. 在大学的时候,这块我很认真地学习了一遍. ...

  6. 学习前端的实用网站——未完待续

    学习前端的实用网站--未完待续 一.学习类网站 1.视频教程 2.技术分享 3.大牛博客 4.参考手册 二.功能类网站 1.颜色 2.图标 3.字体 4.素材 三.辅助类网站 一.学习类网站 1.视频 ...

  7. 多标签学习之讲座版 (内部讨论, 未完待续)

    摘要: 多标签学习是一种常见的, 而并非小众的机器学习问题. 本贴为专题讲座准备. 1. 基本数据模型 定义1. 多标签数据为一个二元组: S=(X,Y),(1)S = (\mathbf{X}, \m ...

  8. 【未完待续】综述:用于视频分割(Video Segmentation)的深度学习

    A Survey on Deep Learning Technique for Video Segmentation 0. 摘要 本文回顾视频分割的两条基本研究路线:视频目标分割(object seg ...

  9. 【深度学习】波尔次曼机,受限波尔兹曼机,DBN详解

    神经网络自20世纪50年代发展起来后,因其良好的非线性能力.泛化能力而备受关注.然而,传统的神经网络仍存在一些局限,在上个世纪90年代陷入衰落,主要有以下几个原因: 1.传统的神经网络一般都是单隐层, ...

最新文章

  1. 网络高可用性解决方案
  2. 一道题,最小操作次数使数组元素相等引发的思考
  3. 有线节点与无线节点的混合仿真模拟实验
  4. 前端学习(1949)vue之电商管理系统电商系统之实现分页
  5. lambda写法(多参数)
  6. jsonArray与 jsonObject区别与js取值
  7. php tp框架分页源代码,ThinkPHP3.2框架自带分页功能实现方法示例
  8. java simplejson_JSON.simple首页、文档和下载 - JSON/BSON开发包 - OSCHINA - 中文开源技术交流社区...
  9. 转载:SQL server2005 里面没有management studio!下载SQL开发版本
  10. tomcat组播实现session一致性_java会话技术-Session
  11. 汇编:在BUFFER中定义了的十个带符号字,将其中的负数变成绝对值,并以十进制方式输出
  12. 如何评估一个ECG分析算法或设备
  13. 淘宝/天猫添加收货地址 API
  14. [软件更新]LeadBBS 6.0正式发布(更新日志和下载)
  15. 华硕笔记本进bios按哪个键 华硕手提电脑怎么进bios设置
  16. sql 自定义排序 顺序
  17. mysql的填充因子_sql server填充因子
  18. iOS 通讯录-获取联系人属性
  19. 告诉你,如何成就DBA职业生涯
  20. Semantic Structure-BasedWord Embedding by Incorporating Concept Convergence and Word Divergence

热门文章

  1. 实战SSM_O2O商铺_44【DES加密】 关键配置信息进行DES加密
  2. 实战SSM_O2O商铺_26【商品类别】批量新增商品类别从Dao到View层的开发
  3. TCP/IP 协议标准简单描述
  4. 腾讯面试题 Prometheus-PQL
  5. ar 微信小程序_小程序可以实现AR效果了 微信还为开发者提供了基础能力支持
  6. 学习Kotlin(一)为什么使用Kotlin
  7. c 获取char*的长度_最大的 String 字符长度是多少?
  8. 微信小程序勾选协议与提交按钮联动
  9. 电磁悬浮控制系统仿真设计
  10. pip和conda批量导出、安装第三方依赖库(requirements.txt)