本文概述
- 机器学习三十二教程
- 感知器:早期的深度学习算法
- 深度学习前馈神经网络
- 汽车编码器
- 受限玻尔兹曼机
- 深度网络
- 卷积网络
- 实例
- 总结
- 附录:资源
这可能归因于社交网络用户生成的大量原始数据, 其中许多数据需要进行分析, 高级数据科学解决方案的兴起, 以及归因于GPGPU的廉价计算能力。
但是, 除了这些现象之外, 人工智能的新趋势, 尤其是机器学习中的一种新趋势, 即” 深度学习” , 在很大程度上推动了这种复兴。在本教程中, 我将向你介绍深度学习背后的关键概念和算法, 从最简单的组合单元开始, 再建立到Java机器学习的概念。
(要进行全面披露:我也是Java深度学习库的作者, 可以在此处使用, 并且本文的示例是使用上述库实现的。如果喜欢, 可以通过在GitHub上加星号来支持它。 , 我将不胜感激。用法说明可在首页上找到。)
机器学习三十二教程 如果你不熟悉, 请查看以下有关机器学习的介绍:
通用步骤如下:
- 我们提供了一些带有标记示例的算法, 例如10张带有标签1(“ 狗” )的狗的图像和10张带有0标签(” Not dog” )的其他事物的图像-请注意, 我们主要是坚持接受监督, 对此职位进行二进制分类。
- 该算法” 学习” 以识别狗的图像, 并在获得新图像后希望产生正确的标签(如果是狗的图像则为1, 否则为0)。
感知器:早期的深度学习算法 最早的监督训练算法之一是感知器算法, 它是基本的神经网络构建块。
假设我们在飞机上有n个点, 分别标记为” 0″ 和” 1″ 。我们给了一个新的观点, 我们想猜测它的标签(类似于上面的” 狗” 和” 不狗” 的情况)。我们该怎么做呢?
一种方法可能是查看最近的邻居并返回该点的标签。但是, 稍微聪明一点的方法是选择一条最能分隔标记数据的行, 并将其用作分类器。
文章图片
在这种情况下, 每条输入数据都将表示为向量x =(x_1, x_2), 并且我们的函数将类似于” 如果在行下方, 则为’ 0′ , 如果在行上方, 则为’ 1′ ” 。
为了用数学方式表示, 让我们的分隔符由权重w和垂直偏移(或偏差)b的向量定义。然后, 我们的函数将输入和权重与加权和传递函数结合在一起:
文章图片
然后, 该传递函数的结果将被馈送到激活函数中以产生标记。在上面的示例中, 我们的激活函数是阈值截止(例如, 如果大于某个值, 则为1):
文章图片
训练感知器
感知器的训练包括向其提供多个训练样本, 并计算每个样本的输出。在每个样本之后, 权重w的调整方式应使输出误差最小, 该误差定义为所需(目标)输出与实际输出之间的差。还有其他误差函数, 例如均方误差, 但是训练的基本原理保持不变。
单个感知器缺点
深度学习的单一感知器方法有一个主要缺点:它只能学习线性可分离的函数。这个缺点有多大?使用XOR, 这是一个相对简单的函数, 请注意, 它不能通过线性分隔符进行分类(请注意, 失败的尝试如下):
文章图片
为了解决这个问题, 我们需要使用多层感知器, 也称为前馈神经网络:实际上, 我们将这些感知器组合在一起, 以创建一种更强大的学习机制。
深度学习前馈神经网络 神经网络实际上只是感知器的组成, 它们以不同的方式连接并且在不同的激活函数上运行。
文章图片
首先, 我们将看一下前馈神经网络, 它具有以下属性:
- 输入, 输出以及一个或多个隐藏层。上图显示了一个具有3个单元的输入层, 4个单元的隐藏层和2个单元的输出层的网络(术语单元和神经元是可互换的)。
- 每个单元都是一个单一的感知器, 就像上面描述的那样。
- 输入层的单位用作隐藏层单位的输入, 而隐藏层单位是输出层的输入。
- 两个神经元之间的每个连接都具有权重w(类似于感知器权重)。
- t层的每个单元通常都连接到上一层t-1的每个单元(尽管你可以通过将其权重设置为0来断开连接)。
- 要处理输入数据, 你可以将输入向量” 钳位” 到输入层, 将每个输入单元的向量值设置为” 输出” 。在这种特定情况下, 网络可以处理3维输入向量(由于3个输入单元)。例如, 如果输入向量为[7, 1, 2], 则可以将顶部输入单元的输出设置为7, 将中间单元的输出设置为1, 依此类推。然后, 使用每个隐藏单元的加权总和传递函数将这些值向前传播到隐藏单元(因此称为正向传播), 然后依次计算其输出(激活函数)。
- 输出层以与隐藏层相同的方式计算其输出。输出层的结果是网络的输出。
如果我们每个感知器只允许使用线性激活函数怎么办?然后, 我们网络的最终输出仍将是输入的某种线性函数, 只是通过在整个网络中收集的大量不同权重进行调整。换句话说, 一堆线性函数的线性组成仍然仅仅是线性函数。如果我们仅限于线性激活函数, 那么前馈神经网络的功能将比感知器强大得多, 无论它具有多少层。
一堆线性函数的线性组成仍然仅仅是线性函数, 因此大多数神经网络都使用非线性激活函数。
因此, 大多数神经网络都使用非线性激活函数, 例如逻辑, tanh, 二进制或整流器。没有它们, 网络将只能学习作为其输入线性组合的功能。
训练感知器
用于监督多层感知器的最常见的深度学习算法称为反向传播。基本程序:
- 提供了一个训练样本, 并通过网络向前传播。
- 计算输出误差, 通常是均方误差:
文章图片
从概念上讲, 网络被训练为” 重新创建” 输入, 即, 输入和目标数据相同。换句话说:你尝试输出与输入相同的内容, 但是以某种方式进行了压缩。这是一种令人困惑的方法, 因此让我们来看一个示例。
压缩输入:灰度图像
假设训练数据由28× 28灰度图像组成, 并且每个像素的值都固定在一个输入层神经元上(即输入层将有784个神经元)。然后, 输出层将具有与输入层相同的单元数(784), 每个输出单元的目标值将是图像一个像素的灰度值。
这种架构背后的直觉是, 网络将不会学习训练数据与其标签之间的” 映射” , 而是会学习数据本身的内部结构和特征。 (因此, 隐藏层也称为特征检测器。)通常, 隐藏单元的数量少于输入/输出层, 这迫使网络仅学习最重要的特征并实现降维。
我们希望中间的几个小节点在概念上学习数据, 从而生成紧凑的表示形式。
实际上, 我们希望中间的几个小节点能够真正在概念级别上学习数据, 从而生成紧凑的表示形式, 从而以某种方式捕获输入的核心特征。
流感病
为了进一步演示自动编码器, 让我们看看另一个应用程序。
在这种情况下, 我们将使用由流感症状组成的简单数据集(有关想法, 请致谢此博客文章)。如果你有兴趣, 可以在testAEBackpropagation方法中找到此示例的代码。
数据集分解的方式如下:
- 有六个二进制输入功能。
- 前三个是疾病的症状。例如, 1 0 0 0 0 0表示该患者患有高温, 而0 1 0 0 0 0表示咳嗽, 1 1 0 0 0 0表示咳嗽和高温等。
- 最后三个特征是” 反” 症状。当患者患有其中一种疾病时, 他或她患病的可能性就较小。例如, 0 0 0 1 0 0表示该患者有流感疫苗。可能有两种功能组合使用:0 1 0 1 0 0表示疫苗患者咳嗽, 依此类推。
- 111000、101000、110000、011000、011100 =生病
- 000111、001110、000101、000011、000110 =健康
经过几百次迭代, 我们观察到, 当将” 病态” 样本中的每个样本提供给机器学习网络时, 两个隐藏单元之一(每个” 病态” 样本中的相同单元)始终显示出比激活状态更高的激活值。其他。相反, 当呈现” 健康” 样本时, 另一个隐藏单元的激活度更高。
回到机器学习
从本质上讲, 我们的两个隐藏部门已经学会了流感症状数据集的紧凑表示。为了了解这与学习的关系, 我们回到过度拟合的问题。通过训练我们的网络以学习数据的紧凑表示形式, 我们倾向于采用简单的表示形式, 而不是过度拟合训练数据的高度复杂的假设。
在某种程度上, 我们倾向于使用这些更简单的表示形式, 从而尝试以更真实的方式学习数据。
受限玻尔兹曼机 下一步的逻辑步骤是查看受限玻尔兹曼机(RBM), 这是一种生成型随机神经网络, 可以学习其输入集上的概率分布。
文章图片
RBM由隐藏, 可见和偏置层组成。与前馈网络不同, 可见层和隐藏层之间的连接是无向的(值可以在可见到隐藏和隐藏到可见的方向上传播)并且完全连接(给定层中的每个单元都连接到接下来的每个单元-如果我们允许任何层中的任何单元连接到任何其他层, 那么我们将拥有一台Boltzmann(而不是受限的Boltzmann)机器。
标准RBM具有隐藏和可见的二进制单位:即, 在伯努利分布下, 单位激活为0或1, 但是存在具有其他非线性的变量。
尽管研究人员已经了解RBM已有一段时间了, 但是最近引入的对比发散无监督训练算法引起了人们的兴趣。
对比发散
单步对比发散算法(CD-1)的工作方式如下:
- 正相:
- 输入样本v钳位到输入层。
- v以类似于前馈网络的方式传播到隐藏层。隐藏层激活的结果为h。
- 负相:
- 将h传播回结果为v’ 的可见层(可见层和隐藏层之间的连接是无向的, 因此可以在两个方向上移动)。
- 通过激活结果h’将新的v’传播回隐藏层。
- 体重更新:
文章图片
自动编码器t的隐藏层充当自动编码器t + 1的输入层。第一个自动编码器的输入层是整个网络的输入层。贪婪的逐层训练过程如下:
- 使用反向传播方法将所有可用的训练数据单独训练第一个自动编码器(t = 1, 或上图中的红色连接, 但带有附加的输出层)。
- 训练第二个自动编码器t = 2(绿色连接)。由于t = 2的输入层是t = 1的隐藏层, 我们不再对t = 1的输出层感兴趣, 因此将其从网络中删除。训练通过将输入样本钳位到t = 1的输入层开始, 然后将其向前传播到t = 2的输出层。接下来, 使用反向传播更新t = 2的权重(隐藏输入和隐藏输出)。 t = 2使用所有训练样本, 类似于t = 1。
- 对所有图层重复上述步骤(即, 删除之前的自动编码器的输出层, 将其替换为另一个自动编码器, 然后进行反向传播训练)。
- 步骤1-3称为预训练, 并权重正确初始化。但是, 输入数据和输出标签之间没有映射。例如, 如果培训网络来识别手写数字图像, 则仍然无法将单位从最后一个特征检测器(即最后一个自动编码器的隐藏层)映射到图像的数字类型。在这种情况下, 最常见的解决方案是将一个或多个完全连接的层添加到最后一层(蓝色连接)。现在可以将整个网络视为多层感知器, 并使用反向传播对其进行训练(此步骤也称为微调)。
深度信仰网络
与自动编码器一样, 我们也可以堆叠Boltzmann机器来创建称为深度置信网络(DBN)的类。
文章图片
在这种情况下, RBM ??t的隐藏层充当RBM t + 1的可见层。第一个RBM的输入层是整个网络的输入层, 贪婪的层级预训练的工作方式如下:
- 使用对比散度和所有训练样本来训练第一个RBM t = 1。
- 训练第二个RBM t = 2。由于t = 2的可见层是t = 1的隐藏层, 因此训练是通过将输入样本钳位到t = 1的可见层开始的, 然后将其向前传播到t = 1的隐藏层。然后, 该数据用于启动t = 2的对比散度训练。
- 对所有图层重复上述过程。
- 与堆叠式自动编码器类似, 在预训练之后, 可以通过将一个或多个完全连接的层连接到最终RBM隐藏层来扩展网络。这形成了多层感知器, 然后可以使用反向传播对其进行微调。
(注意:有关构建和训练堆叠式自动编码器或深度置信网络的更多信息, 请在此处查看示例代码。)
卷积网络 作为最终的深度学习架构, 让我们看一下卷积网络, 这是一种非常有趣且特殊的前馈网络, 非常适合图像识别。
文章图片
图片来自DeepLearning.net
在查看卷积网络的实际结构之前, 我们首先定义一个图像滤波器或一个具有相关权重的正方形区域。将滤镜应用于整个输入图像, 并且你通常会应用多个滤镜。例如, 你可以将四个6× 6滤镜应用于给定的输入图像。然后, 坐标为1, 1的输出像素是左上角为1, 1的输入像素的6× 6平方和过滤器的权重(也是6× 6平方)的加权和。输出像素2, 1是左上角为2, 1的输入正方形的结果, 依此类推。
涵盖了这些网络, 它们由以下属性定义:
- 卷积层将多个过滤器应用于输入。例如, 图像的第一卷积层可以具有四个6× 6滤镜。在图像上应用一个滤镜的结果称为特征图(FM), 特征图的数量等于滤镜的数量。如果上一层也是卷积的, 则滤波器将以不同的权重应用于所有FM中, 因此每个输入FM都连接到每个输出FM。整个图像上共享权重背后的直觉是, 无论特征的位置如何, 都将对其进行检测, 而过滤器的多样性允许它们中的每一个检测不同的特征集。
- 二次采样层减小了输入的大小。例如, 如果输入由32× 32图像组成, 并且图层的子采样区域为2× 2, 则输出值为16× 16图像, 这意味着将输入图像的4个像素(每个2× 2正方形)组合为一个输出像素。子采样有多种方法, 但是最流行的是最大池, 平均池和随机池。
- 通常将最后一个子采样(或卷积)层连接到一个或多个完全连接的层, 其中最后一个代表目标数据。
- 使用修改后的反向传播进行训练, 该反向传播考虑了子采样层并基于该滤波器所应用的所有值来更新卷积滤波器权重。
实例 既然我们已经介绍了最常见的神经网络变体, 我想我会写一些有关实施这些深度学习结构所面临的挑战的文章。
从广义上讲, 我创建深度学习库的目标是(并且至今)是建立一个满足以下条件的基于神经网络的框架:
- 一种能够表示不同模型的通用架构(例如, 我们上面看到的神经网络的所有变体)。
- 使用各种训练算法(反向传播, 对比发散等)的能力。
- 表现不错。
结构体
让我们从基础开始:
- NeuralNetworkImpl是所有神经网络模型的基类。
- 每个网络包含一组层。
- 每层都有一个连接列表, 其中连接是两层之间的链接, 因此网络是有向无环图。
它还允许一层成为多个网络的一部分。例如, 深度信任网络中的层也是其相应RBM中的层。
另外, 该体系结构允许在预训练阶段将DBN视为堆叠的RBM列表, 而在微调阶段将DBN视为堆叠的RBM, 这在直观上既方便又在编程上很方便。
数据传播
下一个模块负责通过网络传播数据, 该过程分为两个步骤:
- 确定图层的顺序。例如, 为了从多层感知器获得结果, 数据被” 钳制” 到输入层(因此, 这是要计算的第一层)并一直传播到输出层。为了在反向传播期间更新权重, 必须从输出层开始以广度优先的顺序在每个层中传播输出错误。这可以通过使用LayerOrderStrategy的各种实现来实现, 该实现利用网络的图结构, 并采用不同的图遍历方法。一些示例包括广度优先策略和特定层的目标。顺序实际上是由层之间的连接确定的, 因此该策略将返回连接的有序列表。
- 计算激活值。每个层都有一个关联的ConnectionCalculator, 它可以获取连接列表(来自上一步)和输入值(来自其他层), 并计算最终的激活次数。例如, 在简单的S型前馈网络中, 隐藏层的ConnectionCalculator接受输入层和偏置层的值(分别是输入数据和1s的数组)以及单元之间的权重(如果完全连接, 则为层, 权重实际上以矩阵形式存储在FullyConnected连接中), 计算权重之和, 并将结果输入到S型函数中。连接计算器实现各种传递(例如, 加权和, 卷积)和激活(例如, 对于多层感知器的逻辑和tanh, 对于RBM的二进制)的功能。它们中的大多数可以使用Aparapi在GPU上执行, 并且可以与小批量训练一起使用。
Aparapi对连接计算器施加了一些重要限制:
- 仅允许使用原始数据类型的一维数组(和变量)。
- 仅可从GPU可执行代码调用Aparapi内核类本身的成员方法。
训练
训练模块实现了各种训练算法。它依赖于前两个模块。例如, BackPropagationTrainer(所有培训师都在使用Trainer基类)将前馈层计算器用于前馈阶段, 并使用特殊的广度第一层计算器来传播错误并更新权重。
我最新的工作是对Java 8的支持和其他一些改进, 很快将被合并为master。
总结 本Java深度学习教程的目的是向你简要介绍深度学习算法领域, 从组成的最基本单位(感知器)开始, 直至各种有效且流行的架构(例如受限的Boltzmann架构)不断发展机。
神经网络背后的思想已经存在了很长时间。但是今天, 如果你不了解深度网络或进行深度学习的其他方式, 就无法踏入机器学习社区。炒作不应该被误解为理由, 但是随着GPGPU计算的发展以及Geoffrey Hinton, Yoshua Bengio, Yann LeCun和Andrew Ng等研究人员取得的令人瞩目的进步, 该领域无疑显示了很多希望。没有比现在更好的时间去熟悉和参与。
附录:资源 如果你有兴趣了解更多信息, 我发现以下资源对我的工作很有帮助:
- DeepLearning.net:面向所有深度学习的门户。它有一些不错的教程, 软件库和不错的阅读清单。
- 活跃的Google+社区。
- 两个非常好的课程:Coursera上提供的机器学习和用于机器学习的神经网络。
- 斯坦福大学神经网络教程。
推荐阅读
- Trie数据结构(被忽视的宝石)
- 创建在类路径资源[applicationcontext]中定义名为“工厂”的bean时出错。:在设置bean属性“dataSource”时,无法解析对bean“dataSource”的引用;嵌套异常是
- parsing XML document from class path resource [applicationtext.xml]; nested exception is java.io.Fil
- android 创建view间关系
- 如何将Azure DevOps中的代码发布到Azure App Service中
- android绘制流程
- 用命令行方式升级Android SDK
- APP测试的内容
- Eclipse中通过Android模拟器调用OpenGL ES2 0函数操作步骤