本文概述
近年来, 人工智能领域的复兴。 Google, Microsoft和Facebook等主要参与者创建了自己的研究团队, 并进行了一些令人印象深刻的收购, 从而超越了学术界。
这可能归因于社交网络用户生成的大量原始数据, 其中许多数据需要进行分析, 高级数据科学解决方案的兴起, 以及归因于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, 二进制或整流器。没有它们, 网络将只能学习作为其输入线性组合的功能。
训练感知器
用于监督多层感知器的最常见的深度学习算法称为反向传播。基本程序:
- 提供了一个训练样本, 并通过网络向前传播。
-
计算输出误差, 通常是均方误差:
其中t是目标值, y是实际网络输出。其他错误计算也是可以接受的, 但是MSE是一个不错的选择。
-
使用称为随机梯度下降的方法可以将网络错误降到最低。
梯度下降是通用的, 但是在神经网络的情况下, 这将是训练误差与输入参数的函数关系图。每个权重的最佳值是误差达到全局最小值的值。在训练阶段, 权重以小步长(在每个训练样本或几个样本的小批量之后)进行更新, 以使它们始终试图达到全局最小值—但这并不是一件容易的事, 因为你通常以局部极小值结束, 如右侧的极小值。例如, 如果权重值为0.6, 则需要将其更改为0.4。
该图表示最简单的情况, 其中错误取决于单个参数。但是, 网络错误取决于每个网络的权重, 并且错误函数要复杂得多。
幸运的是, 反向传播提供了一种针对输出错误更新两个神经元之间的权重的方法。推导本身很复杂, 但是给定节点的权重更新具有以下(简单)形式:
其中E是输出误差, w_i是输入i到神经元的权重。
本质上, 目标是相对于权重i在梯度方向上移动。关键术语当然是误差的导数, 这种误差并不总是容易计算的:对于大型网络中间的随机隐藏节点的随机权重, 你如何找到该导数?
答案:通过反向传播。首先在公式非常简单的输出单元(基于目标值和预测值之间的差)计算误差, 然后以巧妙的方式通过网络传播回去, 从而使我们能够在训练和(希望)达到最低要求。
隐藏层
隐藏层特别令人感兴趣。通过通用逼近定理, 可以训练具有有限数量神经元的单个隐藏层网络, 以逼近任意随机函数。换句话说, 单个隐藏层功能强大, 足以学习任何功能。就是说, 在实践中, 我们经常会在多个隐藏层(即更深的网络)中学习得更好。
隐藏层是网络存储训练数据的内部抽象表示的位置。
隐藏层是网络存储训练数据的内部抽象表示的地方, 类似于人脑(大大简化的类比)对现实世界的内部表示的方式。在本教程中, 我们将探讨与隐藏层配合使用的不同方法。
示例网络
你可以在此处看到一个简单的(4-2-3层)前馈神经网络, 该网络通过testMLPSigmoidBP方法对用Java实现的IRIS数据集进行分类。数据集包含三类虹膜植物, 具有萼片长度, 花瓣长度等特征。网络为每类提供50个样本。要素固定在输入单元上, 而每个输出单元对应于数据集的单个类别:” 1/0/0″表示植物属于Setosa类, ” 0/1/0″表示杂色, 而” 0/0/1″表示维珍妮卡)。分类错误为2/150(即, 它对150个样本中的2个样本进行了错误分类)。
大型网络的问题
一个神经网络可以具有多个隐藏层:在这种情况下, 更高的层是在先前的层之上”构建”新的抽象。正如我们前面提到的, 你通常可以在较大的网络中学习更好的实践。
但是, 增加隐藏层的数量会导致两个已知问题:
- 消失的梯度:随着我们添加越来越多的隐藏层, 反向传播在将信息传递到较低层的作用越来越小。实际上, 随着信息传回, 相对于网络的权重, 梯度开始消失并变小。
- 过度拟合:也许是机器学习中的中心问题。简而言之, 过度拟合描述了过于紧密地拟合训练数据的现象, 可能是因为假设过于复杂。在这种情况下, 你的学习者最终会很好地拟合训练数据, 但在实际示例中的表现会差很多。
让我们看一下解决这些问题的一些深度学习算法。
汽车编码器
大多数入门机器学习课程倾向于以前馈神经网络停止。但是, 可能的网络空间要丰富得多, 所以让我们继续。
自动编码器通常是前馈神经网络, 旨在学习数据集的压缩分布式表示(编码)。
从概念上讲, 网络被训练为”重新创建”输入, 即, 输入和目标数据相同。换句话说:你尝试输出与输入相同的内容, 但是以某种方式进行了压缩。这是一种令人困惑的方法, 因此让我们来看一个示例。
压缩输入:灰度图像
假设训练数据由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’传播回隐藏层。
-
体重更新:
其中a是学习率, 而v, v’, h, h’和w是向量。
该算法的直觉是, 正相位(h给定v)反映了网络对现实世界数据的内部表示。同时, 负阶段表示尝试根据此内部表示(v给定h)重新创建数据。主要目标是使生成的数据尽可能接近真实世界, 这反映在权重更新公式中。
换句话说, 网络对如何表示输入数据有一定的了解, 因此它会尝试根据此感知来再现数据。如果其再现距离现实还不够接近, 则进行调整并重试。
重返流感
为了证明对比差异, 我们将使用与以前相同的症状数据集。测试网络是RBM, 具有六个可见单元和两个隐藏单元。我们将使用对比发散训练网络, 将症状v固定在可见层。在测试过程中, 症状再次呈现给可见层。然后, 数据将传播到隐藏层。隐藏单元代表病态/健康状态, 与自动编码器的架构非常相似(将数据从可见层传播到隐藏层)。
经过几百次迭代, 我们可以观察到与自动编码器相同的结果:当显示任何”病态”样本时, 其中一个隐藏单元的激活值更高, 而对于”健康”样本, 另一个隐藏单元的激活值更高。
你可以在testContrastiveDivergence方法中看到该示例的实际操作。
深度网络
现在, 我们证明了自动编码器和RBM的隐藏层可以用作有效的特征检测器;但是很少能直接使用这些功能。实际上, 上面的数据集更多的是例外而不是规则。相反, 我们需要找到一种间接使用这些检测到的功能的方法。
幸运的是, 人们发现可以将这些结构堆叠起来以形成深层网络。可以一次一次地贪婪地训练这些网络, 以帮助克服逐渐消失的梯度和与经典反向传播相关的过度拟合问题。
生成的结构通常非常强大, 可产生令人印象深刻的结果。以Google著名的”猫”论文为例, 他们使用特殊的深度自动编码器根据未标记的数据”学习”人和猫的面部检测。
让我们仔细看看。
堆叠式自动编码器
顾名思义, 该网络由多个堆叠的自动编码器组成。
自动编码器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隐藏层来扩展网络。这形成了多层感知器, 然后可以使用反向传播对其进行微调。
此过程类似于堆叠式自动编码器, 但自动编码器被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正方形)组合为一个输出像素。子采样有多种方法, 但是最流行的是最大池, 平均池和随机池。
- 通常将最后一个子采样(或卷积)层连接到一个或多个完全连接的层, 其中最后一个代表目标数据。
- 使用修改后的反向传播进行训练, 该反向传播考虑了子采样层并基于该滤波器所应用的所有值来更新卷积滤波器权重。
你可以在此处看到在MNIST数据集(手写字母的灰度图像)上经过训练(使用反向传播)的卷积网络的几个示例, 特别是在testLeNet *方法中(我建议使用testLeNetTiny2, 因为它实现了大约2%的低错误率)在相对较短的时间内)。这里还提供了类似网络的JavaScript可视化效果。
实例
既然我们已经介绍了最常见的神经网络变体, 我想我会写一些有关实施这些深度学习结构所面临的挑战的文章。
从广义上讲, 我创建深度学习库的目标是(并且至今)是建立一个满足以下条件的基于神经网络的框架:
- 一种能够表示不同模型的通用架构(例如, 我们上面看到的神经网络的所有变体)。
- 使用各种训练算法(反向传播, 对比发散等)的能力。
- 表现不错。
为了满足这些要求, 我采用了分层(或模块化)的方法来设计软件。
结构体
让我们从基础开始:
- NeuralNetworkImpl是所有神经网络模型的基类。
- 每个网络包含一组层。
- 每层都有一个连接列表, 其中连接是两层之间的链接, 因此网络是有向无环图。
这种结构足够敏捷, 可以用于经典的前馈网络, RBM和像ImageNet这样的更复杂的体系结构。
它还允许一层成为多个网络的一部分。例如, 深度信任网络中的层也是其相应RBM中的层。
另外, 该体系结构允许在预训练阶段将DBN视为堆叠的RBM列表, 而在微调阶段将DBN视为堆叠的RBM, 这在直观上既方便又在编程上很方便。
数据传播
下一个模块负责通过网络传播数据, 该过程分为两个步骤:
- 确定图层的顺序。例如, 为了从多层感知器获得结果, 数据被”钳制”到输入层(因此, 这是要计算的第一层)并一直传播到输出层。为了在反向传播期间更新权重, 必须从输出层开始以广度优先的顺序在每个层中传播输出错误。这可以通过使用LayerOrderStrategy的各种实现来实现, 该实现利用网络的图结构, 并采用不同的图遍历方法。一些示例包括广度优先策略和特定层的目标。顺序实际上是由层之间的连接确定的, 因此该策略将返回连接的有序列表。
- 计算激活值。每个层都有一个关联的ConnectionCalculator, 它可以获取连接列表(来自上一步)和输入值(来自其他层), 并计算最终的激活次数。例如, 在简单的S型前馈网络中, 隐藏层的ConnectionCalculator接受输入层和偏置层的值(分别是输入数据和1s的数组)以及单元之间的权重(如果完全连接, 则为层, 权重实际上以矩阵形式存储在FullyConnected连接中), 计算权重之和, 并将结果输入到S型函数中。连接计算器实现各种传递(例如, 加权和, 卷积)和激活(例如, 对于多层感知器的逻辑和tanh, 对于RBM的二进制)的功能。它们中的大多数可以使用Aparapi在GPU上执行, 并且可以与小批量训练一起使用。
使用Aparapi进行GPU计算
正如我前面提到的那样, 近年来神经网络兴起的原因之一是它们的训练方法非常有助于并行性, 从而使你可以通过使用GPGPU显着加快训练速度。在这种情况下, 我选择使用Aparapi库来添加GPU支持。
Aparapi对连接计算器施加了一些重要限制:
- 仅允许使用原始数据类型的一维数组(和变量)。
- 仅可从GPU可执行代码调用Aparapi内核类本身的成员方法。
这样, 大多数数据(权重, 输入和输出数组)存储在Matrix实例中, 该实例在内部使用一维浮点数组。所有Aparapi连接计算器都使用AparapiWeightedSum(用于完全连接的层和加权和输入功能), AparapiSubsampling2D(用于子采样层)或AparapiConv2D(用于卷积层)。这些限制中的某些可以通过引入异构系统体系结构来克服。 Aparapi还允许在CPU和GPU上运行相同的代码。
训练
训练模块实现了各种训练算法。它依赖于前两个模块。例如, BackPropagationTrainer(所有培训师都在使用Trainer基类)将前馈层计算器用于前馈阶段, 并使用特殊的广度第一层计算器来传播错误并更新权重。
我最新的工作是对Java 8的支持和其他一些改进, 很快将被合并为master。
总结
本Java深度学习教程的目的是向你简要介绍深度学习算法领域, 从组成的最基本单位(感知器)开始, 直至各种有效且流行的架构(例如受限的Boltzmann架构)不断发展机。
神经网络背后的思想已经存在了很长时间。但是今天, 如果你不了解深度网络或进行深度学习的其他方式, 就无法踏入机器学习社区。炒作不应该被误解为理由, 但是随着GPGPU计算的发展以及Geoffrey Hinton, Yoshua Bengio, Yann LeCun和Andrew Ng等研究人员取得的令人瞩目的进步, 该领域无疑显示了很多希望。没有比现在更好的时间去熟悉和参与。
附录:资源
如果你有兴趣了解更多信息, 我发现以下资源对我的工作很有帮助:
- DeepLearning.net:面向所有深度学习的门户。它有一些不错的教程, 软件库和不错的阅读清单。
- 活跃的Google+社区。
- 两个非常好的课程:Coursera上提供的机器学习和用于机器学习的神经网络。
- 斯坦福大学神经网络教程。
相关:教育蓬松鸟:强化学习教程