什么网站专做衣服,自己给别人做网站挣钱吗,网站备案 拉黑,宜宾建设机械网站五、受限玻尔兹曼机#xff08;Restricted Boltzmann Machine#xff0c;RBM#xff09; 5.1 RBM介绍 示例代码#xff1a; Python 编写了一个简单的 RBM 实现#xff0c;并用一些假数据训练了它。然后#xff0c;他展示了如何用 RBM 来解释用户的电影偏好#xff0c;以… 五、受限玻尔兹曼机Restricted Boltzmann MachineRBM 5.1 RBM介绍 示例代码 Python 编写了一个简单的 RBM 实现并用一些假数据训练了它。然后他展示了如何用 RBM 来解释用户的电影偏好以及如何用 RBM 来生成电影推荐 使用一些假数据训练了RBM。 爱丽丝哈利波特 1阿凡达 1LOTR 3 1角斗士 0泰坦尼克号 0闪光 0。SF/奇幻大粉丝。鲍勃哈利波特 1阿凡达 0LOTR 3 1角斗士 0泰坦尼克号 0闪光 0。SF/奇幻迷但不喜欢《阿凡达》。卡罗尔哈利波特 1阿凡达 1LOTR 3 1角斗士 0泰坦尼克号 0闪光 0。SF/奇幻大粉丝。大卫哈利波特 0阿凡达 0LOTR 3 1角斗士 1泰坦尼克号 1闪光 0。奥斯卡大奖得主的粉丝。埃里克哈利波特 0阿凡达 0LOTR 3 1角斗士 1泰坦尼克号 1闪光 0。奥斯卡奖得主的粉丝泰坦尼克号除外。弗雷德哈利波特 0阿凡达 0LOTR 3 1角斗士 1泰坦尼克号 1闪光 0。奥斯卡大奖得主的粉丝。 该网络学习了以下权重 请注意第一个隐藏单元似乎对应于奥斯卡奖得主第二个隐藏单元似乎对应于 SF/奇幻电影正如我们所希望的那样。 如果我们给 RBM 一个新用户 George他将 Harry Potter 0 Avatar 0 LOTR 3 0 Gladiator 1 Titanic 1 Glitter 0 作为他的偏好会发生什么它打开了奥斯卡奖得主单元但不是 SF/奇幻单元正确地猜测乔治可能喜欢奥斯卡奖得主的电影。 如果我们只激活 SF/幻想单元并运行一系列不同的 RBM会发生什么在我的试验中它打开了哈利波特、阿凡达和 LOTR 3 三次;它打开了《阿凡达》和《LOTR 3》但没有打开《哈利波特》一次;它打开了哈利波特和 LOTR 3但没有打开阿凡达两次。请注意根据我们的训练示例这些生成的偏好确实符合我们期望真正的 SF/奇幻粉丝想要观看的内容。 # 导入未来模块用于兼容不同版本的Python
from __future__ import print_function
# 导入numpy库用于科学计算
import numpy as np# 定义一个类表示受限玻尔兹曼机
class RBM:# 定义初始化方法接受可见层单元数和隐藏层单元数作为参数def __init__(self, num_visible, num_hidden):# 将隐藏层单元数和可见层单元数赋值给类的属性self.num_hidden num_hiddenself.num_visible num_visible# 设置一个调试打印的标志用于控制是否打印训练信息self.debug_print True# 创建一个随机数生成器指定随机种子为1234np_rng np.random.RandomState(1234)# 创建一个权重矩阵用于存储可见层和隐藏层之间的连接权重# 权重矩阵的形状为(num_visible, num_hidden)即每一列对应一个隐藏单元每一行对应一个可见单元# 权重矩阵的初始值为均匀分布在[-0.1 * np.sqrt(6. / (num_hidden num_visible)),# 0.1 * np.sqrt(6. / (num_hidden num_visible))]之间的随机数这个范围是根据论文中的建议选择的self.weights np.asarray(np_rng.uniform(low-0.1 * np.sqrt(6. / (num_hidden num_visible)),high0.1 * np.sqrt(6. / (num_hidden num_visible)),size(num_visible, num_hidden)))# 在权重矩阵的第一行和第一列插入零用于表示偏置单元的权重# 偏置单元是一种特殊的单元它的值始终为1用于增加模型的灵活性# 第一行的权重表示隐藏层的偏置第一列的权重表示可见层的偏置self.weights np.insert(self.weights, 0, 0, axis 0)self.weights np.insert(self.weights, 0, 0, axis 1)# 定义一个训练方法接受数据最大训练轮数学习率等参数def train(self, data, max_epochs 1000, learning_rate 0.1):# 获取数据的样本数即第一个维度的大小num_examples data.shape[0]# 在数据的第一列插入1用于表示偏置单元的值data np.insert(data, 0, 1, axis 1)# 遍历训练轮数for epoch in range(max_epochs): # 将数据作为可见层的状态计算隐藏层的激活值# 这是正向传播的过程也称为正相对比散度阶段或者现实阶段# 激活值等于数据与权重矩阵的点积形状为(num_examples, num_hidden 1)pos_hidden_activations np.dot(data, self.weights) # 计算隐藏层的激活概率即隐藏层的单元以一定的概率被激活取值为1# 激活概率是通过逻辑斯蒂函数或称为Sigmoid函数计算的它可以将任意值映射到(0,1)之间# 形状仍为(num_examples, num_hidden 1)pos_hidden_probs self._logistic(pos_hidden_activations)# 将第一列的激活概率设为1用于表示偏置单元的值pos_hidden_probs[:,0] 1 # Fix the bias unit.# 根据隐藏层的激活概率生成隐藏层的状态# 隐藏层的状态是一个二值的矩阵形状为(num_examples, num_hidden 1)# 隐藏层的状态等于激活概率是否大于一个随机数如果大于则为1否则为0pos_hidden_states pos_hidden_probs np.random.rand(num_examples, self.num_hidden 1)# 注意我们在计算关联矩阵时使用的是隐藏层的激活概率而不是隐藏层的状态# 我们也可以使用状态具体可以参考Hinton的论文《A Practical Guide to Training Restricted Boltzmann Machines》的第三节# 关联矩阵是可见层和隐藏层的状态的外积形状为(num_visible 1, num_hidden 1)pos_associations np.dot(data.T, pos_hidden_probs)# 从隐藏层的状态重构可见层的激活值# 这是反向传播的过程也称为负相对比散度阶段或者梦境阶段# 激活值等于隐藏层的状态与权重矩阵的转置的点积形状为(num_examples, num_visible 1)neg_visible_activations np.dot(pos_hidden_states, self.weights.T)# 计算可见层的激活概率即可见层的单元以一定的概率被激活取值为1# 激活概率是通过逻辑斯蒂函数或称为Sigmoid函数计算的它可以将任意值映射到(0,1)之间# 形状仍为(num_examples, num_visible 1)neg_visible_probs self._logistic(neg_visible_activations)# 将第一列的激活概率设为1用于表示偏置单元的值neg_visible_probs[:,0] 1 # Fix the bias unit.# 从可见层的激活概率计算隐藏层的激活值# 激活值等于可见层的激活概率与权重矩阵的点积形状为(num_examples, num_hidden 1)neg_hidden_activations np.dot(neg_visible_probs, self.weights)# 计算隐藏层的激活概率即隐藏层的单元以一定的概率被激活取值为1# 激活概率是通过逻辑斯蒂函数或称为Sigmoid函数计算的它可以将任意值映射到(0,1)之间# 形状仍为(num_examples, num_hidden 1)neg_hidden_probs self._logistic(neg_hidden_activations)# 注意我们在计算关联矩阵时使用的是可见层和隐藏层的激活概率而不是状态# 关联矩阵是可见层和隐藏层的激活概率的外积形状为(num_visible 1, num_hidden 1)neg_associations np.dot(neg_visible_probs.T, neg_hidden_probs)# 更新权重矩阵# 权重矩阵的更新量等于学习率乘以正相关联矩阵减去负相关联矩阵再除以样本数# 这样可以使得正相的概率增大负相的概率减小从而最大化数据的似然度# 更新权重矩阵使用学习率、正相联和负相联的差值除以样本数作为增量self.weights learning_rate * ((pos_associations - neg_associations) / num_examples)# 计算误差使用数据和负可见概率的差的平方和error np.sum((data - neg_visible_probs) ** 2)# 如果开启了调试打印打印出每个迭代的误差if self.debug_print:print(Epoch %s: error is %s % (epoch, error))# 定义一个方法用于从可见层运行网络得到隐藏层的状态def run_visible(self, data):# 获取样本数num_examples data.shape[0]# 创建一个矩阵每一行是一个训练样本对应的隐藏单元加上一个偏置单元hidden_states np.ones((num_examples, self.num_hidden 1))# 在数据的第一列插入偏置单元值为1data np.insert(data, 0, 1, axis 1)# 计算隐藏单元的激活值hidden_activations np.dot(data, self.weights)# 计算隐藏单元被激活的概率hidden_probs self._logistic(hidden_activations)# 根据概率随机激活隐藏单元hidden_states[:,:] hidden_probs np.random.rand(num_examples, self.num_hidden 1)# 始终将偏置单元设置为1# hidden_states[:,0] 1# 忽略偏置单元hidden_states hidden_states[:,1:]return hidden_states# 定义一个方法用于从隐藏层运行网络得到可见层的状态# TODO: 去除这个方法和run_visible之间的代码重复def run_hidden(self, data):# 获取样本数num_examples data.shape[0]# 创建一个矩阵每一行是一个训练样本对应的可见单元加上一个偏置单元visible_states np.ones((num_examples, self.num_visible 1))# 在数据的第一列插入偏置单元值为1data np.insert(data, 0, 1, axis 1)# 计算可见单元的激活值visible_activations np.dot(data, self.weights.T)# 计算可见单元被激活的概率visible_probs self._logistic(visible_activations)# 根据概率随机激活可见单元visible_states[:,:] visible_probs np.random.rand(num_examples, self.num_visible 1)# 始终将偏置单元设置为1# visible_states[:,0] 1# 忽略偏置单元visible_states visible_states[:,1:]return visible_states# 定义一个方法用于生成梦境样本即从网络中随机抽取可见层的状态def daydream(self, num_samples):# 创建一个矩阵每一行是一个可见单元加上一个偏置单元的样本samples np.ones((num_samples, self.num_visible 1))# 从均匀分布中取第一个样本samples[0,1:] np.random.rand(self.num_visible)# 开始交替的吉布斯采样# 注意我们保持隐藏单元的二进制状态但是将可见单元作为实数概率# 参见 Hinton 的 A Practical Guide to Training Restricted Boltzmann Machines 的第三节# 了解更多原因for i in range(1, num_samples):visible samples[i-1,:]# 计算隐藏单元的激活值hidden_activations np.dot(visible, self.weights) # 计算隐藏单元被激活的概率hidden_probs self._logistic(hidden_activations)# 根据概率随机激活隐藏单元hidden_states hidden_probs np.random.rand(self.num_hidden 1)# 始终将偏置单元设置为1hidden_states[0] 1# 重新计算可见单元被激活的概率visible_activations np.dot(hidden_states, self.weights.T)visible_probs self._logistic(visible_activations)visible_states visible_probs np.random.rand(self.num_visible 1)samples[i,:] visible_states# 忽略偏置单元第一列因为它们总是被设置为1return samples[:,1:] # 判断是否是主模块如果是则执行以下代码
if __name__ __main__:# 创建一个受限玻尔兹曼机的实例指定可见层单元数为6隐藏层单元数为2r RBM(num_visible 6, num_hidden 2)# 创建一个训练数据的数组每一行是一个样本每一列是一个特征# 这里的数据是一个二值的矩阵表示6个特征的存在或缺失training_data np.array([[1,1,1,0,0,0],[1,0,1,0,0,0],[1,1,1,0,0,0],[0,0,1,1,1,0], [0,0,1,1,0,0],[0,0,1,1,1,0]])# 调用训练方法指定最大训练轮数为5000r.train(training_data, max_epochs 5000)# 打印出训练后的权重矩阵print(r.weights)# 创建一个用户数据的数组表示一个新的样本user np.array([[0,0,0,1,1,0]])# 打印出从可见层运行网络得到的隐藏层的状态print(r.run_visible(user)) 输出结果 5.2 深度玻尔兹曼机 深度玻尔兹曼机Deep Boltzmann MachineDBM是一种基于能量的生成模型它可以用来学习复杂数据的概率分布。DBM由多层隐变量组成每层隐变量之间没有连接但是每层隐变量都与下一层可见变量或上一层隐变量相连。DBM的最底层是可见层它表示观测到的数据例如图像、文本或音频。DBM的目标是最大化数据的对数似然即让模型生成的数据尽可能接近真实数据。DBM的训练过程涉及到两个阶段预训练和微调。预训练是使用贪婪逐层算法将每两层隐变量视为一个受限玻尔兹曼机Restricted Boltzmann MachineRBM并用对比散度Contrastive DivergenceCD算法进行无监督学习。微调是使用随机最大似然Stochastic Maximum LikelihoodSML算法对整个模型进行联合优化以提高模型的泛化能力。 DBM具有以下几个优点 DBM可以从高维、非线性、非高斯的数据中学习出抽象的特征表示从而实现数据的降维和特征提取。DBM可以用于生成新的数据样本例如生成新的图像或文本从而实现数据的增强和创造。DBM可以用于多种任务例如分类、回归、聚类、协同过滤、推荐系统等只需在模型的顶层添加一个适当的输出层即可。 DBM也有以下几个缺点 DBM的训练过程比较复杂和耗时需要大量的计算资源和数据量。DBM的训练过程涉及到很多超参数的选择例如学习率、批量大小、采样步数、正则化项等这些超参数对模型的性能有很大的影响但是很难确定最优的值。DBM的理论分析比较困难很多性质和定理还没有得到严格的证明例如模型的收敛性、稳定性、可解释性等 5.3 深度置信网 深度置信网Deep Belief NetworkDBN是一种基于图模型的生成模型它由多层受限玻尔兹曼机RBM堆叠而成。DBN的最底层是可见层它表示观测到的数据例如图像、文本或音频。DBN的最顶层是一个无向图它表示数据的高层抽象特征。DBN的中间层是有向图它表示数据的中间层特征。DBN的目标是最大化数据的对数似然即让模型生成的数据尽可能接近真实数据。DBN的训练过程涉及到两个阶段预训练和微调。预训练是使用贪婪逐层算法将每两层视为一个RBM并用CD算法进行无监督学习。微调是使用反向传播BackpropagationBP算法对整个模型进行有监督学习以提高模型的泛化能力。 DBN具有以下几个优点 DBN可以从高维、非线性、非高斯的数据中学习出抽象的特征表示从而实现数据的降维和特征提取。DBN可以用于生成新的数据样本例如生成新的图像或文本从而实现数据的增强和创造。DBN可以用于多种任务例如分类、回归、聚类、协同过滤、推荐系统等只需在模型的顶层添加一个适当的输出层即可。 DBN也有以下几个缺点 DBN的训练过程比较复杂和耗时需要大量的计算资源和数据量。DBN的训练过程涉及到很多超参数的选择例如学习率、批量大小、采样步数、正则化项等这些超参数对模型的性能有很大的影响但是很难确定最优的值。DBN的理论分析比较困难很多性质和定理还没有得到严格的证明例如模型的收敛性、稳定性、可解释性等 附录 受限玻尔兹曼机应用场景 各种激活函数的优缺点 各种激活函数各有优缺点在深度学习中都有其适用场景。 Sigmoid和Tanh函数是传统的激活函数具有输出范围有限、优化稳定等优点但容易过饱和梯度弥散。ReLU函数是近年来流行的激活函数具有计算速度快、容易训练等优点但容易发生“死神经元”问题。Leaky ReLU、ELU和SELU等函数是ReLU函数的改进版本解决了“死神经元”问题。softmax函数常用于多分类任务可以用来输出概率分布 参考网址 https://blog.echen.me/2011/07/18/introduction-to-restricted-boltzmann-machines/ https://github.com/python-pillow/Pillow/ Python 图像库 https://blog.echen.me/2011/07/18/introduction-to-restricted-boltzmann-machines/ 受限玻尔兹曼机简介 (echen.me) The End