TensorFlow深度学习实战(19)——受限玻尔兹曼机

article/2025/7/31 13:00:07

TensorFlow深度学习实战(19)——受限玻尔兹曼机

    • 0. 前言
    • 1. 受限玻尔兹曼机
      • 1.1 受限玻尔兹曼机架构
      • 1.2 受限玻尔兹曼机的数学原理
    • 2. 使用受限玻尔兹曼机重建图像
    • 3. 深度信念网络
    • 小结
    • 系列链接

0. 前言

受限玻尔兹曼机 (Restricted Boltzmann Machine, RBM) 是一种无监督学习的概率图模型,用于学习数据的特征表示。它是由两层神经元组成的网络,其中一层是可见层 (visible layer),用于表示输入数据;另一层是隐层 (hidden layer),用于捕捉数据的潜在特征,而深度信念网络是堆叠的 RBM。本节中,将介绍 RBM 的基本原理,并使用 TensorFlow 实现 RBM 和深度信念网络用于重建图像。

1. 受限玻尔兹曼机

1.1 受限玻尔兹曼机架构

受限玻尔兹曼机 (Restricted Boltzmann Machine, RBM) 是一种双层神经网络,一层称为可见层 (visible layer),另一层称为隐层 (hidden layer)。因为只有两层,因此称为浅层神经网络。RBM 最早由 Paul Smolensky1986 年提出,后来由 Geoffrey Hinton2006 年提出使用对比散度 (Contrastive Divergence, CD) 作为训练方法。所有可见层的神经元(称为可见单元,visible unit )都与隐层的所有神经元(称为隐单元,hidden unit )连接,但有一个限制——同一层中的神经元之间不能连接。RBM 中的所有神经元本质上都是二进制的,要么激活,要么不激活。
RBM 可以用于降维、特征提取和协同过滤。RBM 的训练可以分为三个部分:前向传递 (forward pass)、反向传递 (backward pass) 以及比较 (comparison)。

1.2 受限玻尔兹曼机的数学原理

接下来,我们从数学原理方面介绍 RBM,将 RBM 的操作分为两个过程:
前向传递: 可见单元 V V V 的信息通过权重 W W W 和偏置 c c c 传递到隐单元 h 0 h_0 h0。隐单元可能会激活或不激活,这取决于随机概率 σ \sigma σ,通常使用 sigmoid 函数:
ρ ( v 0 ∣ h 0 ) = σ ( V T W + c ) \rho (v_0|h_0)=\sigma(V^TW+c) ρ(v0h0)=σ(VTW+c)
反向传递: 隐单元的表示 h 0 h_0 h0 通过相同的权重 W W W,但使用不同的偏置 c c c,传递回可见单元,从而模型重建输入。同样,取决于随机概率 σ \sigma σ
ρ ( v i ∣ h 0 ) = σ ( V T h 0 + c ) \rho(v_i|h_0)=\sigma(V^Th_0+c) ρ(vih0)=σ(VTh0+c)
重复执行以上两个过程 k k k 次,或者直到收敛。根据研究, k = 1 k=1 k=1 可以得到良好的结果,因此本节将 k k k 设置为 1 1 1
可见向量 V V V 和隐向量 h h h 的联合能量表示如下:
E ( v , h ) = − b T V − c T h − V T W h E(v,h)=-b^TV-c^Th-V^TWh E(v,h)=bTVcThVTWh
每个可见向量 V V V 还关联有自由能量:
F ( v ) = − b T V − ∑ j ∈ h i d d e n l o g ( 1 + e x p ( c j + V T W ) ) F(v)=-b^TV-\sum_{j\in hidden}log(1+exp(c_j+V^TW)) F(v)=bTVjhiddenlog(1+exp(cj+VTW))
使用对比散度目标函数,即 M e a n ( F ( V o r i g i n a l ) ) − M e a n ( F ( V r e c o n s t r u c t e d ) ) Mean(F(V_{original})) - Mean(F(V_{reconstructed})) Mean(F(Voriginal))Mean(F(Vreconstructed)),权重的变化由下式表示:
d W = η [ ( V T h ) i n p u t − ( V T h ) r e c o n s t r u c t e d ] dW=\eta[(V^Th)_{input}-(V^Th)_{reconstructed}] dW=η[(VTh)input(VTh)reconstructed]
其中, η \eta η 是学习率,偏置 b b b c c c 变化的表达式与此类似。

2. 使用受限玻尔兹曼机重建图像

接下来,使用 TensorFlow 构建一个受限玻尔兹曼机 (Restricted Boltzmann Machine, RBM) 模型,用于重建 MNIST 手写数字图像。

(1) 导入 TensorFlowNumPyMatplotlib 库:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

(2) 定义 RBM 类。RBM 类的 __init__() 函数初始化可见层的神经元数量 input_size 和隐层的神经元数量 output_size,初始化隐层和可见层的权重和偏置,本节中将它们初始化为零。也可以尝试随机初始化:

#Class that defines the behavior of the RBM
class RBM(object):def __init__(self, input_size, output_size, lr=1.0, batchsize=100):"""m: Number of neurons in visible layern: number of neurons in hidden layer"""#Defining the hyperparametersself._input_size = input_size #Size of Visibleself._output_size = output_size #Size of outpself.learning_rate = lr #The step used in gradient descentself.batchsize = batchsize #The size of how much data will be used for training per sub iteration#Initializing weights and biases as matrices full of zeroesself.w = tf.zeros([input_size, output_size], np.float32) #Creates and initializes the weights with 0self.hb = tf.zeros([output_size], np.float32) #Creates and initializes the hidden biases with 0self.vb = tf.zeros([input_size], np.float32) #Creates and initializes the visible biases with 0

定义前向和反向传递方法:

    #Forward Passdef prob_h_given_v(self, visible, w, hb):#Sigmoid return tf.nn.sigmoid(tf.matmul(visible, w) + hb)#Backward Passdef prob_v_given_h(self, hidden, w, vb):return tf.nn.sigmoid(tf.matmul(hidden, tf.transpose(w)) + vb)

创建生成随机二进制值的函数。这是因为隐层和可见层的单元更新是使用随机概率的,这取决于每个单元的输入(对于隐层)以及从上到下的反向输入(对于可见层):

    #Generate the sample probabilitydef sample_prob(self, probs):return tf.nn.relu(tf.sign(probs - tf.random.uniform(tf.shape(probs))))

定义函数重建输入数据:

    def rbm_reconstruct(self,X):h = tf.nn.sigmoid(tf.matmul(X, self.w) + self.hb)reconstruct = tf.nn.sigmoid(tf.matmul(h, tf.transpose(self.w)) + self.vb)return reconstruct

定义 train() 函数用于训练 RBM。该函数计算对比散度的正梯度和负梯度,并使用权重更新公式来更新权重和偏置:

    #Training method for the modeldef train(self, X, epochs=10):     loss = []for epoch in range(epochs):#For each step/batchfor start, end in zip(range(0, len(X), self.batchsize),range(self.batchsize,len(X), self.batchsize)):batch = X[start:end]#Initialize with sample probabilitiesh0 = self.sample_prob(self.prob_h_given_v(batch, self.w, self.hb))v1 = self.sample_prob(self.prob_v_given_h(h0, self.w, self.vb))h1 = self.prob_h_given_v(v1, self.w, self.hb)#Create the Gradientspositive_grad = tf.matmul(tf.transpose(batch), h0)negative_grad = tf.matmul(tf.transpose(v1), h1)#Update learning rates self.w = self.w + self.learning_rate *(positive_grad - negative_grad) / tf.dtypes.cast(tf.shape(batch)[0],tf.float32)self.vb = self.vb +  self.learning_rate * tf.reduce_mean(batch - v1, 0)self.hb = self.hb +  self.learning_rate * tf.reduce_mean(h0 - h1, 0)#Find the error rateerr = tf.reduce_mean(tf.square(batch - v1))print ('Epoch: %d' % epoch,'reconstruction error: %f' % err)loss.append(err)return loss

(3) 实例化一个 RBM 对象并在 MNIST 数据集上进行训练:

(train_data, _), (test_data, _) =  tf.keras.datasets.mnist.load_data()
train_data = train_data/np.float32(255)
train_data = np.reshape(train_data, (train_data.shape[0], 784))test_data = test_data/np.float32(255)
test_data = np.reshape(test_data, (test_data.shape[0], 784))#Size of inputs is the number of inputs in the training set
input_size = train_data.shape[1]
rbm = RBM(input_size, 200)err = rbm.train(train_data,50)

(4) 绘制学习曲线:

plt.plot(err)
plt.xlabel('epochs')
plt.ylabel('cost')
plt.show()

训练过程监控

(5) 可视化重建图像:

out = rbm.rbm_reconstruct(test_data)# Plotting original and reconstructed images
row, col = 2, 8
idx = np.random.randint(0, 100, row * col // 2)
f, axarr = plt.subplots(row, col, sharex=True, sharey=True, figsize=(20,4))
for fig, row in zip([test_data,out], axarr):for i,ax in zip(idx,row):ax.imshow(tf.reshape(fig[i],[28, 28]), cmap='Greys_r')ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)
plt.show()

重建图像如下所示:

重建图像

第一行是输入的手写图像,第二行是重建的图像,可以看到这些图像与人类手写的数字非常相似。

3. 深度信念网络

我们已经了解了受限玻尔兹曼机 (Restricted Boltzmann Machine, RBM),并知道如何使用对比散度进行训练,接下来,我们将介绍第一个成功的深度神经网络架构——深度信念网络 (Deep Belief Network, DBN)。DBN 架构在 2006 年由 Hinton 提出,在此模型之前,训练深度架构非常困难,不仅是由于计算资源有限,还因为梯度消失问题。在 DBN 中首次展示了如何通过贪婪的逐层训练来训练深度架构。
简单来说,DBN 只是堆叠的 RBM,每个 RBM 都使用对比散度单独训练。从训练第一个 RBM 层开始,训练完成后,训练第二个 RBM 层。第二个 RBM 的可见单元接收第一个 RBM 隐单元的输出作为输入数据。每次添加 RBM 层时重复以上过程。

(1) 堆叠 RBM 类。为了构建 DBN,需要在 RBM 类中定义一个额外的函数 rbm_output(),用于将前一 RBM 隐单元的输出传递到下一个 RBM 中:

class RBM(object):def __init__(self, input_size, output_size, lr=1.0, batchsize=100):"""m: Number of neurons in visible layern: number of neurons in hidden layer"""#Defining the hyperparametersself._input_size = input_size #Size of Visibleself._output_size = output_size #Size of outpself.learning_rate = lr #The step used in gradient descentself.batchsize = batchsize #The size of how much data will be used for training per sub iteration#Initializing weights and biases as matrices full of zeroesself.w = tf.zeros([input_size, output_size], np.float32) #Creates and initializes the weights with 0self.hb = tf.zeros([output_size], np.float32) #Creates and initializes the hidden biases with 0self.vb = tf.zeros([input_size], np.float32) #Creates and initializes the visible biases with 0#Forward Passdef prob_h_given_v(self, visible, w, hb):#Sigmoid return tf.nn.sigmoid(tf.matmul(visible, w) + hb)#Backward Passdef prob_v_given_h(self, hidden, w, vb):return tf.nn.sigmoid(tf.matmul(hidden, tf.transpose(w)) + vb)#Generate the sample probabilitydef sample_prob(self, probs):return tf.nn.relu(tf.sign(probs - tf.random.uniform(tf.shape(probs))))#Training method for the modeldef train(self, X, epochs=10):     loss = []for epoch in range(epochs):#For each step/batchfor start, end in zip(range(0, len(X), self.batchsize),range(self.batchsize,len(X), self.batchsize)):batch = X[start:end]#Initialize with sample probabilitiesh0 = self.sample_prob(self.prob_h_given_v(batch, self.w, self.hb))v1 = self.sample_prob(self.prob_v_given_h(h0, self.w, self.vb))h1 = self.prob_h_given_v(v1, self.w, self.hb)#Create the Gradientspositive_grad = tf.matmul(tf.transpose(batch), h0)negative_grad = tf.matmul(tf.transpose(v1), h1)#Update learning rates self.w = self.w + self.learning_rate *(positive_grad - negative_grad) / tf.dtypes.cast(tf.shape(batch)[0],tf.float32)self.vb = self.vb +  self.learning_rate * tf.reduce_mean(batch - v1, 0)self.hb = self.hb +  self.learning_rate * tf.reduce_mean(h0 - h1, 0)#Find the error rateerr = tf.reduce_mean(tf.square(batch - v1))print ('Epoch: %d' % epoch,'reconstruction error: %f' % err)loss.append(err)return loss#Create expected output for our DBNdef rbm_output(self, X):out = tf.nn.sigmoid(tf.matmul(X, self.w) + self.hb)return outdef rbm_reconstruct(self,X):h = tf.nn.sigmoid(tf.matmul(X, self.w) + self.hb)reconstruct = tf.nn.sigmoid(tf.matmul(h, tf.transpose(self.w)) + self.vb)return reconstruct

(2) 使用 RBM 类创建一个堆叠的 RBM 结构,第一个 RBM500 个隐单元,第二个有 200 个隐单元,第三个有 50 个隐单元:

RBM_hidden_sizes = [500, 200 , 50 ] #create 2 layers of RBM with size 400 and 100#Since we are training, set input as training data
inpX = train_data#Create list to hold our RBMs
rbm_list = []#Size of inputs is the number of inputs in the training set
input_size = train_data.shape[1]#For each RBM we want to generate
for i, size in enumerate(RBM_hidden_sizes):print ('RBM: ',i,' ',input_size,'->', size)rbm_list.append(RBM(input_size, size))input_size = size
"""
RBM:  0   784 -> 500
RBM:  1   500 -> 200
RBM:  2   200 -> 50
"""

(3) 对于第一个 RBMMNIST 数据作为输入。第一个 RBM 的输出作为输入传递到第二个 RBM,以此类推,通过连续的 RBM 层:

#For each RBM in our list
for rbm in rbm_list:print ('Next RBM:')#Train a new onerbm.train(tf.cast(inpX,tf.float32)) #Return the output layerinpX = rbm.rbm_output(inpX)out = rbm_list[0].rbm_reconstruct(test_data)
# Plotting original and reconstructed images
row, col = 2, 8
idx = np.random.randint(0, 100, row * col // 2)
f, axarr = plt.subplots(row, col, sharex=True, sharey=True, figsize=(20,4))
for fig, row in zip([test_data,out], axarr):for i,ax in zip(idx,row):ax.imshow(tf.reshape(fig[i],[28, 28]), cmap='Greys_r')ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)
plt.show()

本节中,这三个堆叠的受限玻尔兹曼机以无监督学习方式进行训练。DBN 还可以通过监督学习进行训练,为此,需要对训练好的 RBM 的权重进行微调,并在最后添加一个全连接层。

小结

受限玻尔兹曼机 (Restricted Boltzmann Machine, RBM) 是一种强大的无监督学习模型,可以用于特征学习、数据降维、图像生成等任务。尽管其训练过程复杂且计算开销较大,但它为深度学习的发展奠定了基础,如深度信念网络 (Deep Belief Network, DBN)。

系列链接

TensorFlow深度学习实战(1)——神经网络与模型训练过程详解
TensorFlow深度学习实战(2)——使用TensorFlow构建神经网络
TensorFlow深度学习实战(3)——深度学习中常用激活函数详解
TensorFlow深度学习实战(4)——正则化技术详解
TensorFlow深度学习实战(5)——神经网络性能优化技术详解
TensorFlow深度学习实战(6)——回归分析详解
TensorFlow深度学习实战(7)——分类任务详解
TensorFlow深度学习实战(8)——卷积神经网络
TensorFlow深度学习实战(9)——构建VGG模型实现图像分类
TensorFlow深度学习实战(10)——迁移学习详解
TensorFlow深度学习实战(11)——风格迁移详解
TensorFlow深度学习实战(12)——词嵌入技术详解
TensorFlow深度学习实战(13)——神经嵌入详解
TensorFlow深度学习实战(14)——循环神经网络详解
TensorFlow深度学习实战(15)——编码器-解码器架构
TensorFlow深度学习实战(16)——注意力机制详解
TensorFlow深度学习实战(17)——主成分分析详解
TensorFlow深度学习实战(18)——K-means 聚类详解


http://www.hkcw.cn/article/WGfaDHCEFL.shtml

相关文章

设计模式——桥接设计模式(结构型)

摘要 桥接设计模式是一种结构型设计模式,用于将抽象与实现解耦,使二者可以独立变化。它通过将一个类拆分为“抽象”和“实现”两部分,并通过桥接关系组合,避免了类继承层次结构过于庞大。桥接模式包含抽象类、扩充抽象类、实现类…

java反射

简介 获取Class 误区 解释一下 “类” 和 “Class对象” 的区别,以及为什么每个类都有关联的 Class 对象: 🧩 核心概念:类 vs Class对象 想象你有一本《汽车使用说明书》: 类 这本说明书本身(纸上的文…

C++ 之 多态 【虚函数表、多态的原理、动态绑定与静态绑定】

目录 前言 1.多态的原理 1.1虚函数表 1.2派生类中的虚表 1.3虚函数、虚表存放位置 1.4多态的原理 1.5多态条件的思考 2.动态绑定与静态绑定 3.单继承和虚继承中的虚函数表 3.1单继承中的虚函数表 3.2多继承(非菱形继承)中的虚函数表 4.问答题 前言 需要声明的&#x…

28 C 语言作用域详解:作用域特性(全局、局部、块级)、应用场景、注意事项

1 作用域简介 作用域定义了代码中标识符(如变量、常量、数组、函数等)的可见性与可访问范围,即标识符在程序的哪些位置能够被引用或访问。在 C 语言中,作用域主要分为三类: 全局作用域局部作用域块级作用域 需注意&am…

day03-Vue-Element

1 Ajax 1.1 Ajax介绍 1.1.1 Ajax概述 我们前端页面中的数据,如下图所示的表格中的学生信息,应该来自于后台,那么我们的后台和前端是互不影响的2个程序,那么我们前端应该如何从后台获取数据呢?因为是2个程序&#xf…

智慧交通设计方案

该文档是智慧交通设计方案,交通设计位于综合交通规划后、道路工程设计前,目标是优化交通系统及设施,实现交通安全、高效、可持续发展。内容涵盖区域交通组织优化(含需求管理、速度管理等)、平面交叉口设计(要素、改善措施)、专项交通设计(公共交通、慢行系统等)、智能…

SAP学习笔记 - 开发17 - 前端Fiori开发 Component 配置(组件化)

上一章讲了Fiori前端开发中的国际化。 SAP学习笔记 - 开发16 - 前端Fiori开发 Properties文件(国际化) ,语言切换实例,Fiori 国际化(常用语言列表,关键规则,注意事项)-CSDN博客 本…

leetcode刷题日记——二叉树的层平均值

[ 题目描述 ]: [ 思路 ]: BFS,通过层次遍历求得每层的和,然后取平均数,存入结果数组树中节点个数在1-10000之间,那么结果数组最大为10000个结果,层数最多为 2n-1>10000,可以推…

Google Android 14设备和应用通知 受限制的设置 出于安全考虑......

重要提示: 文中部分步骤仅适用于 Android 13 及更高版本。了解如何查看 Android 版本。 启用受限制的设置后,应用将能够访问敏感信息,而这可能使您的个人数据面临风险。除非您信任该应用的开发者,否则我们不建议您允许访问受限制…

【小米拥抱AI】小米开源视觉大模型—— MiMo-VL

MiMo-VL-7B模型的开发包含两个序贯训练过程:(1)四阶段预训练,涵盖投影器预热、视觉-语言对齐、通用多模态预训练及长上下文监督微调(SFT),最终生成MiMo-VL-7B-SFT模型;(2…

自编码器Auto-encoder(李宏毅)

目录 编码器的概念: 为什么需要编码器? 编码器什么原理? 去噪自编码器: 自编码器的应用: 特征解耦 离散隐表征 编码器的概念: 重构:输入一张图片,通过编码器转化成向量,要求再…

Claude 4 升级:从问答助手到任务执行者 | AI大咖说

Claude 4 升级:从问答助手到任务执行者 Claude 4 升级历程 2025-05-22日,Anthropic 正式发布了他们的新 AI 模型 Claude 4。这标志着 AI 不再仅仅是一个智能问答系统,而是开始具备独立完成复杂任务的能力。CEO Dario Amodei 在发布会中强调…

Day42 Python打卡训练营

知识点回顾 1.回调函数 2.lambda函数 3.hook函数的模块钩子和张量钩子 4.Grad-CAM的示例 作业:理解下今天的代码即可 1.回调函数 Hook本质是回调函数,所以我们先介绍一下回调函数 回调函数是作为参数传递给其他函数的函数,其目的是在某个特…

2002-2022年 城市市政公用设施水平、环境、绿地等数据-社科经管实证数据

2002-2022年城市市政公用设施水平、环境、绿地等数据-社科经管https://download.csdn.net/download/paofuluolijiang/90880456 https://download.csdn.net/download/paofuluolijiang/90880456 《2002-2022年城市市政公用设水平、环境、绿地等数据-社科经管实证数据》整理自多源…

uni-app学习笔记十七-css和scss的使用

SCSS 和 CSS的异同点 我们可以使用css和scss来设置样式。其中SCSS(Sassy CSS)是 CSS 预处理器 Sass(Syntactically Awesome Stylesheets)的一种语法格式,而 CSS(Cascading Style Sheets)是标准…

达梦分布式集群DPC_分布式事务理解_yxy

达梦分布式集群DPC_分布式事务理解 1 分布式事务是什么?2 分布式事务怎么实现?2.1 两阶段提交保障一致性2.1.1 预提交2.1.2 提交 2.2 RAFT协议保障数据强一致2.3 全局事务管理2.3.1 全局事务信息的登记流程2.3.2 数据可见性判断规则 1 分布式事务是什么&…

性能优化 - 案例篇:缓冲区

文章目录 Pre1. 引言2. 缓冲概念与类比3. Java I/O 中的缓冲实现3.1 FileReader vs BufferedReader:装饰者模式设计3.2 BufferedInputStream 源码剖析3.2.1 缓冲区大小的权衡与默认值 4. 异步日志中的缓冲:Logback 异步日志原理与配置要点4.1 Logback 异…

【目标检测】检测网络中neck的核心作用

1. neck最主要的作用就是特征融合,融合就是将具有不同大小感受野的特征图进行了耦合,从而增强了特征图的表达能力。 2. neck决定了head的数量,进而潜在决定了不同尺度样本如何分配到不同的head,这一点可以看做是将整个网络的多尺…

基于机器学习的心脏病预测模型构建与可解释性分析

一、引言 心脏病是威胁人类健康的重要疾病之一,早期预测和诊断对防治心脏病具有重要意义。本文利用公开的心脏病数据集,通过机器学习算法构建预测模型,并使用 SHAP 值进行模型可解释性分析,旨在为心脏病的辅助诊断提供参考。 二、…