【机器学习】深度学习概论(二)

五、受限玻尔兹曼机(Restricted Boltzmann Machine,RBM)

cd92844354fd82de0dda2e407a255bb3.jpeg

5.1 RBM介绍

ac3c3d62a55ab04d25874f23db8fd57b.jpeg

示例代码:

Python 编写了一个简单的 RBM 实现,并用一些假数据训练了它。然后,他展示了如何用 RBM 来解释用户的电影偏好,以及如何用 RBM 来生成电影推荐:

使用一些假数据训练了RBM。

  • 爱丽丝:(哈利波特 = 1,阿凡达 = 1,LOTR 3 = 1,角斗士 = 0,泰坦尼克号 = 0,闪光 = 0)。SF/奇幻大粉丝。

  • 鲍勃:(哈利波特 = 1,阿凡达 = 0,LOTR 3 = 1,角斗士 = 0,泰坦尼克号 = 0,闪光 = 0)。SF/奇幻迷,但不喜欢《阿凡达》。

  • 卡罗尔:(哈利波特 = 1,阿凡达 = 1,LOTR 3 = 1,角斗士 = 0,泰坦尼克号 = 0,闪光 = 0)。SF/奇幻大粉丝。

  • 大卫:(哈利波特 = 0,阿凡达 = 0,LOTR 3 = 1,角斗士 = 1,泰坦尼克号 = 1,闪光 = 0)。奥斯卡大奖得主的粉丝。

  • 埃里克:(哈利波特 = 0,阿凡达 = 0,LOTR 3 = 1,角斗士 = 1,泰坦尼克号 = 1,闪光 = 0)。奥斯卡奖得主的粉丝,泰坦尼克号除外。

  • 弗雷德:(哈利波特 = 0,阿凡达 = 0,LOTR 3 = 1,角斗士 = 1,泰坦尼克号 = 1,闪光 = 0)。奥斯卡大奖得主的粉丝。

该网络学习了以下权重:

548d3601f2c5346b051d114ea1b184f3.png

请注意,第一个隐藏单元似乎对应于奥斯卡奖得主,第二个隐藏单元似乎对应于 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)),high=0.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))

输出结果:

a02cf3b28e5c85960fe24bd6de98a550.png

5.2 深度玻尔兹曼机

深度玻尔兹曼机(Deep Boltzmann Machine,DBM)是一种基于能量的生成模型,它可以用来学习复杂数据的概率分布。DBM由多层隐变量组成,每层隐变量之间没有连接,但是每层隐变量都与下一层可见变量或上一层隐变量相连。DBM的最底层是可见层,它表示观测到的数据,例如图像、文本或音频。DBM的目标是最大化数据的对数似然,即让模型生成的数据尽可能接近真实数据。DBM的训练过程涉及到两个阶段:预训练和微调。预训练是使用贪婪逐层算法,将每两层隐变量视为一个受限玻尔兹曼机(Restricted Boltzmann Machine,RBM),并用对比散度(Contrastive Divergence,CD)算法进行无监督学习。微调是使用随机最大似然(Stochastic Maximum Likelihood,SML)算法,对整个模型进行联合优化,以提高模型的泛化能力。

DBM具有以下几个优点:

  • DBM可以从高维、非线性、非高斯的数据中学习出抽象的特征表示,从而实现数据的降维和特征提取。

  • DBM可以用于生成新的数据样本,例如生成新的图像或文本,从而实现数据的增强和创造。

  • DBM可以用于多种任务,例如分类、回归、聚类、协同过滤、推荐系统等,只需在模型的顶层添加一个适当的输出层即可。

DBM也有以下几个缺点:

  • DBM的训练过程比较复杂和耗时,需要大量的计算资源和数据量。

  • DBM的训练过程涉及到很多超参数的选择,例如学习率、批量大小、采样步数、正则化项等,这些超参数对模型的性能有很大的影响,但是很难确定最优的值。

  • DBM的理论分析比较困难,很多性质和定理还没有得到严格的证明,例如模型的收敛性、稳定性、可解释性等

5.3 深度置信网

深度置信网(Deep Belief Network,DBN)是一种基于图模型的生成模型,它由多层受限玻尔兹曼机(RBM)堆叠而成。DBN的最底层是可见层,它表示观测到的数据,例如图像、文本或音频。DBN的最顶层是一个无向图,它表示数据的高层抽象特征。DBN的中间层是有向图,它表示数据的中间层特征。DBN的目标是最大化数据的对数似然,即让模型生成的数据尽可能接近真实数据。DBN的训练过程涉及到两个阶段:预训练和微调。预训练是使用贪婪逐层算法,将每两层视为一个RBM,并用CD算法进行无监督学习。微调是使用反向传播(Backpropagation,BP)算法,对整个模型进行有监督学习,以提高模型的泛化能力。

DBN具有以下几个优点:

  • DBN可以从高维、非线性、非高斯的数据中学习出抽象的特征表示,从而实现数据的降维和特征提取。

  • DBN可以用于生成新的数据样本,例如生成新的图像或文本,从而实现数据的增强和创造。

  • DBN可以用于多种任务,例如分类、回归、聚类、协同过滤、推荐系统等,只需在模型的顶层添加一个适当的输出层即可。

DBN也有以下几个缺点:

  • DBN的训练过程比较复杂和耗时,需要大量的计算资源和数据量。

  • DBN的训练过程涉及到很多超参数的选择,例如学习率、批量大小、采样步数、正则化项等,这些超参数对模型的性能有很大的影响,但是很难确定最优的值。

  • DBN的理论分析比较困难,很多性质和定理还没有得到严格的证明,例如模型的收敛性、稳定性、可解释性等

附录:

受限玻尔兹曼机应用场景

a5beb9b5b283ab132f8a7c152b5b1ce6.png

各种激活函数的优缺点

e1100bf2fbb47f081b8343292fe5f731.png

各种激活函数各有优缺点,在深度学习中都有其适用场景。

  • 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/227054.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL MVCC精讲

版本链 我们前面说过,对于使用InnoDB存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列(row_id并不是必要的,我们创建的表中有主键或者非NULL的UNIQUE键时都不会包含row_id列): trx_id&#xff…

[ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择

文章目录 一、前言二、Amazon SNS 服务(Amazon Simple Notification Service)三、Amazon SQS 服务(Amazon Simple Queue Service)四、SNS 与 SQS 的区别(本文重点)4.1 基于推送和轮询区别4.2 消费者数量对应…

Hadoop之Yarn 详细教程

1、yarn 的基本介绍和产生背景 YARN 是 Hadoop2 引入的通用的资源管理和任务调度的平台,可以在 YARN 上运行 MapReduce、Tez、Spark 等多种计算框架,只要计算框架实现了 YARN 所定义的 接口,都可以运行在这套通用的 Hadoop 资源管理和任务调…

[足式机器人]Part4 南科大高等机器人控制课 CH12 Robotic Motion Control

本文仅供学习使用 本文参考: B站:CLEAR_LAB 笔者带更新-运动学 课程主讲教师: Prof. Wei Zhang 课程链接 : https://www.wzhanglab.site/teaching/mee-5114-advanced-control-for-robotics/ 南科大高等机器人控制课 Ch12 Robotic …

uni-appcss语法

锋哥原创的uni-app视频教程: 2023版uniapp从入门到上天视频教程(Java后端无废话版),火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版),火爆更新中...共计23条视频,包括:第1讲 uni…

PPT录制视频的方法,轻松提升演示效果!

在现代工作和学习中,ppt是一种常见的演示工具,而将ppt转化为视频形式更能方便分享和传播。本文将介绍两种ppt录制视频的方法,每一种方法都将有详细的步骤和简要的介绍,通过这些方法,你可以轻松将ppt制作成视频&#xf…

秋招复习篇之代码规范

目录 前言 1、变量命名 2、代码空格 1)操作符左右一定有空格, 2)分隔符(, 和;)前一位没有空格,后一位保持空格,例如: 3)大括号和函数保持同一行,并有一个空格…

双语!性能优越|融合黏菌和差分变异的量子哈里斯鹰算法SDMQHHO

前面的文章里卡卡介绍了哈里斯鹰优化算法(Harris Hawks Optimization, HHO).HHO是 Heidari等[1]于2019年提出的一种新型元启发式算法,设计灵感来源于哈里斯鹰在捕食猎物过程中的合作行为以及突然袭击的狩猎风格,具有需调参数少、原理简单易实现、局部搜索…

4.20 构建onnx结构模型-Reduce

前言 构建onnx方式通常有两种: 1、通过代码转换成onnx结构,比如pytorch —> onnx 2、通过onnx 自定义结点,图,生成onnx结构 本文主要是简单学习和使用两种不同onnx结构, 下面以 Reduce 结点进行分析 方式 方法…

002文章解读与程序——中国电机工程学报EI\CSCD\北大核心《计及源荷不确定性的综合能源生产单元运行调度与容量配置两阶段随机优化》已提供下载资源

👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆下载资源链接&#x1f4…

Java——猫猫图鉴微信小程序(前后端分离版)

目录 一、开源项目 二、项目来源 三、使用框架 四、小程序功能 1、用户功能 2、管理员功能 五、使用docker快速部署 六、更新信息 审核说明 一、开源项目 猫咪信息点-ruoyi-cat: 1、一直想做点项目进行学习与练手,所以做了一个对自己来说可以完成的…

【Linux系统化学习】进程终止的奥秘

个人主页点击直达:小白不是程序媛 Linux专栏:Liunx系统化学习 代码仓库:Gitee 目录 获取函数返回值 退出码 进程退出的场景 错误码 信号终止异常代码 进程的终止 main函数直接return exit函数 _exit函数 获取函数返回值 在C语言学…

Linux驱动开发学习笔记6《蜂鸣器实验》

目录 一、蜂鸣器驱动原理 二、硬件原理分析 三、实验程序编写 1、 修改设备树文件 (1)添加pinctrl节点 (2)添加BEEP设备节点 (3)检查PIN 是否被其他外设使用 2、蜂鸣器驱动程序编写 3、编写测试AP…

uniapp多级动态表单规则

最近有个新的业务、主要涉及多层级的动态表单提交,其中又涉及很多类型,踩了很多坑之后,终于研发完毕。 传来的数据格式处理 传来的数据格式涉及比较多的内容,以下举例一个,涉及到规则的填写 规则写法有两种&#xff…

数据结构(一)

本文是在原本数据结构与算法闯关的基础上总结得来,加入了自己的理解和部分习题讲解 原活动链接 邀请码: JL57F5 目录 算法和数据结构1、什么是算法?2、什么是数据结构?3、算法和数据结构之间的关系4、时间复杂度5、数据结构 : 什么是数组&#xff1f…

帆软FineBi V6版本经验总结

帆软FineBi V6版本经验总结 BI分析出现背景 ​ 现在是一个大数据的时代,每时每刻都有海量的明细数据出现。这时大数据时代用户思维是:1、数据的爆炸式增长,人们比起明细数据,更在意样本的整体特征、相互关系。2、基于明细的“小…

城市分站优化系统源码:提升百度关键排名 附带完整的搭建教程

城市分站优化已成为企业网络营销的重要手段,今天来给大家分享一款城市分站优化系统源码。 以下是部分代码示例: 系统特色功能一览: 1.多城市分站管理:该系统支持多个城市分站的管理,用户可以根据业务需求,…

Uniapp软件库全新带勋章功能(包含前后端源码)

源码介绍: Uniapp开发的软件库全新带勋章功能,搭建好后台 在前端找到 util 这个文件 把两个js文件上面的填上自己的域名,电脑需要下载:HBuilderX 登录账号 没有账号就注册账号, 然后上传文件,打包选择 “…

企业私有云容器化架构

什么是虚拟化: 虚拟化(Virtualization)技术最早出现在 20 世纪 60 年代的 IBM 大型机系统,在70年代的 System 370 系列中逐渐流行起来,这些机器通过一种叫虚拟机监控器(Virtual Machine Monitor,VMM&#x…

Unity中Shader裁剪空间推导(在Shader中使用)

文章目录 前言一、在Shader中使用转化矩阵1、在顶点着色器中定义转化矩阵2、用 UNITY_NEAR_CLIP_VALUE 区分平台矩阵3、定义一个枚举用于区分当前是处于什么相机 二、我们在DirectX平台下,看看效果1、正交相机下2、透视相机下3、最终代码 前言 在上一篇文章中&…