个人主页:欢迎来到 Papicatch的博客
课设专栏 :学生成绩管理系统
专业知识专栏: 专业知识
文章目录
🍉引言
🍉受限玻尔兹曼机
🍈RBM的结构
🍍RBM的架构图
🍍RBM的经典实现
🍍代码实现
🍍代码分析
🍉总结
🍉引言
在当今科技飞速发展的时代,人工智能的研究不断取得突破性的进展。其中,受限玻尔兹曼机作为一种重要的模型,正逐渐引起人们的广泛关注。它独特的结构和强大的学习能力,为解决各种复杂的问题提供了新的思路和方法。受限玻尔兹曼机不仅在理论研究上具有深刻的意义,在实际应用中也展现出了巨大的潜力,例如图像识别、语音处理、自然语言处理等领域。
🍉受限玻尔兹曼机
受限玻尔兹曼机(Restricted Boltzmann Machine,RBM)是一种生成性随机人工神经网络,也是一种无向概率图模型,并且受限为二分图。
整个模型有两层,即可见层(包含可见单元)和隐藏层(包含隐单元),满足层内无连接,层间全连接。这种限制使得它在神经元之间的连接上有特定的规则,来自两组单元中的每一组的一对节点(通常称为“可见”和“隐藏”单元)可以在它们之间具有对称连接,而组内的节点之间没有连接。相比一般的玻尔兹曼机,这种限制允许使用更有效的训练算法。
RBM 通常由二值隐单元和可见单元组成,其中权重矩阵 中的每个元素指定了隐单元 和可见层单元 之间边的权重。
此外,对于每个可见层单元 有偏置项 ,对每个隐层单元 有偏置项 。具体来说,需满足以下条件
其能量函数对于一组给定的状态 定义为:
由能量函数可以给出状态 的联合概率分布:
其中, 是归一化常数,计算式为 ,其计算复杂度为 。可见层的边缘分布: ;隐藏层的边缘分布: 。
RBM 的一个重要性质是,由于它是一个二分图,层内没有边相连,因而隐藏层的激活状态在给定可见层节点取值的情况下是条件独立的,类似地,可见层节点的激活状态在给定隐藏层节点取值的情况下也条件独立,用数学公式表示为:
由此可以推导得出在给定可视层 的基础上,隐层第 个节点为 1 或者为 0 的概率为:
在给定隐层 的基础上,可视层第 个节点为 1 或者为 0 的概率为:
在训练 RBM 时,关键是计算模型中的参数 。通常采用对数损失函数,并考虑最大化对数似然函数。但直接按梯度公式计算梯度的复杂度很高,因为其中涉及到归一化常数 的计算,而 的计算复杂度为 。
为解决这个问题,一般使用基于马尔可夫链蒙特卡罗(MCMC)的方法来模拟计算梯度,如 Geoffrey Hinton 提出的对比散度(contrastive divergence,CD)算法。该算法给定样本 后,取初始值 ,然后执行 步 Gibbs 采样,先后采样得到 和 。Gibbs 采样得到的样本服从联合分布 ,利用采样得到的 可以估算梯度公式中期望项的近似值,从而得到梯度的近似值,之后在每一步利用梯度上升法进行参数更新。
RBM 可用于降维、分类、协同过滤、特征学习、生成模型等任务。根据任务的不同,它可以使用监督学习或无监督学习的方法进行训练。例如在推荐系统中,可以把每个用户对各个物品的评分作为可见层神经元的输入,从而进行训练。
RBM 在深度学习中有重要应用,它可以通过“堆叠”形成深层信念网络等更复杂的结构。但 RBM 也存在一些局限性,例如在处理大规模数据时可能效率不高,对初始值敏感等。不过,研究人员仍在不断探索和改进 RBM 及其相关算法,以拓展其应用领域和提高性能。
🍈RBM的结构
🍍RBM的架构图
🍍RBM的经典实现
🍍代码实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn import preprocessing
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
# 加载 MNIST 数据集
mnist = fetch_openml('mnist_784', version=1, cache=True)
X = mnist.data
y = mnist.target
# 数据预处理
X = preprocessing.MinMaxScaler().fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
class RBM:
def __init__(self, n_visible, n_hidden, learning_rate=0.1, n_epochs=100):
"""
初始化 RBM 模型
参数:
n_visible:可见层神经元数量(输入数据的维度)
n_hidden:隐藏层神经元数量
learning_rate:学习率
n_epochs:训练轮数
"""
self.n_visible = n_visible
self.n_hidden = n_hidden
self.learning_rate = learning_rate
self.n_epochs = n_epochs
# 随机初始化权重矩阵 W,偏置向量 bv(可见层)和 bh(隐藏层)
self.W = np.random.randn(n_visible, n_hidden) * 0.1
self.bv = np.zeros(n_visible)
self.bh = np.zeros(n_hidden)
def sigmoid(self, x):
"""
Sigmoid 激活函数
参数:
x:输入值
返回:
Sigmoid 函数的输出
"""
return 1 / (1 + np.exp(-x))
def sample_hidden(self, v):
"""
根据给定的可见层状态 v 采样隐藏层
参数:
v:可见层状态
返回:
隐藏层的激活概率 p_hidden 和采样后的隐藏层状态 h
"""
hidden_activation = np.dot(v, self.W) + self.bh
p_hidden = self.sigmoid(hidden_activation)
return p_hidden, np.random.binomial(1, p_hidden)
def sample_visible(self, h):
"""
根据给定的隐藏层状态 h 采样可见层
参数:
h:隐藏层状态
返回:
可见层的激活概率 p_visible 和采样后的可见层状态 v_prime
"""
visible_activation = np.dot(h, self.W.T) + self.bv
p_visible = self.sigmoid(visible_activation)
return p_visible, np.random.binomial(1, p_visible)
def train(self, X):
"""
训练 RBM 模型
参数:
X:训练数据
"""
for epoch in range(self.n_epochs):
for v in X:
# 正向传播:根据输入的可见层状态 v 计算隐藏层的激活概率和采样后的隐藏层状态
p_hidden, h = self.sample_hidden(v)
# 反向传播:根据采样得到的隐藏层状态 h 计算可见层的激活概率和采样后的可见层状态 v_prime
p_visible, v_prime = self.sample_visible(h)
# 更新参数
# 计算权重更新量 dW
dW = np.outer(v, p_hidden) - np.outer(v_prime, p_hidden)
# 更新权重 W
self.W += self.learning_rate * dW
# 更新可见层偏置 bv
self.bv += self.learning_rate * (v - v_prime)
# 更新隐藏层偏置 bh
self.bh += self.learning_rate * (p_hidden - np.mean(p_hidden))
def reconstruct(self, X):
"""
对输入数据进行重建
参数:
X:输入数据
返回:
重建后的可见层状态
"""
h = np.zeros((X.shape[0], self.n_hidden))
for i, v in enumerate(X):
_, h[i] = self.sample_hidden(v)
_, v_prime = self.sample_visible(h)
return v_prime
# 初始化 RBM 模型,设置可见层神经元数量为 784(MNIST 图像的维度),隐藏层神经元数量为 128
rbm = RBM(n_visible=784, n_hidden=128, learning_rate=0.1, n_epochs=50)
# 训练模型
rbm.train(X_train)
# 重建测试集图像
reconstructed_images = rbm.reconstruct(X_test)
# 展示原始图像和重建图像
n_images = 5
for i in range(n_images):
original_image = X_test[i].reshape(28, 28)
reconstructed_image = reconstructed_images[i].reshape(28, 28)
plt.subplot(2, n_images, i + 1)
plt.imshow(original_image, cmap='gray')
plt.axis('off')
plt.subplot(2, n_images, i + 1 + n_images)
plt.imshow(reconstructed_image, cmap='gray')
plt.axis('off')
plt.show()
🍍代码分析
RBM
类的 __init__
方法:
- 初始化模型的参数,包括可见层和隐藏层的神经元数量、学习率和训练轮数。
- 随机初始化权重矩阵
W
、可见层偏置bv
和隐藏层偏置bh
。
sigmoid
方法:定义了 Sigmoid 激活函数,用于计算神经元的激活概率。
sample_hidden
方法:
- 计算给定可见层状态下隐藏层的激活值。
- 通过激活值计算隐藏层的激活概率。
- 基于激活概率进行二项分布采样得到隐藏层的状态。
sample_visible
方法:与 sample_hidden
类似,用于根据隐藏层状态采样可见层状态。
train
方法:
- 在每一轮训练中,遍历训练数据中的每个样本。
- 进行正向传播,从可见层到隐藏层的采样。
- 进行反向传播,从隐藏层到可见层的采样。
- 根据采样结果计算权重和偏置的更新量,并进行更新。
reconstruct
方法:
- 首先对输入数据采样得到隐藏层状态。
- 然后根据隐藏层状态采样重建可见层状态。
在主程序中:
- 加载 MNIST 数据集并进行预处理和划分。
- 初始化 RBM 模型并进行训练。
- 对测试集数据进行重建,并展示原始图像和重建图像的对比。
这段代码主要实现了一个受限玻尔兹曼机(RBM)模型,并将其应用于 MNIST 数据集的图像重建任务。
首先,代码从开放数据集中加载 MNIST 数据,进行预处理和划分。然后定义了 RBM
类,在类的初始化方法中,设定了模型的关键参数,包括可见层和隐藏层的神经元数量、学习率以及训练轮数,并随机初始化了权重和偏置。
RBM
类中包含了 sigmoid
激活函数,以及用于正向和反向传播的 sample_hidden
和 sample_visible
方法。训练方法 train
通过不断的正向和反向传播,并基于采样结果更新权重和偏置来优化模型。reconstruct
方法用于对输入数据进行重建。
在主程序中,初始化并训练 RBM 模型,最后对测试集数据进行重建,并通过图像展示原始图像和重建图像的对比,以直观评估模型的重建效果。
🍉总结
受限玻尔兹曼机(RBM)是一种具有独特结构和强大学习能力的概率图模型。
在结构上,RBM 由两层神经元组成,即可见层和隐藏层。层内神经元无连接,层间神经元全连接。这种结构简化了计算,同时也使得模型能够有效地学习数据中的特征和模式。
在学习过程中,RBM 通过不断调整参数(包括权重、可见层偏置和隐藏层偏置)来优化模型。常见的学习算法如对比散度(CD)算法,通过采样和近似计算梯度来更新参数。
RBM 具有多种应用,例如在数据降维方面,它能够将高维数据映射到低维的隐藏层表示;在特征学习中,能够自动从原始数据中提取有意义的特征;在生成模型中,可以生成新的数据样本。
然而,RBM 也存在一些局限性。例如,训练时间可能较长,尤其是在处理大规模数据时;对初始参数的设置较为敏感;模型的解释性相对较复杂等。
尽管如此,RBM 在深度学习领域仍然具有重要地位,其思想和方法为后续更复杂的深度模型的发展提供了基础和启发。