“ 看到网上的一篇博文,简单的介绍了当前热门的神经网络。翻译成中文与大家分享。原文链接:http://blog.kaggle.com/2017/11/27/introduction-to-neural-net
人工神经网络风靡一时。人们不禁要问,这个琅琅上口的名字到底在算法领域中拥有什么样的地位。我曾经看到业务经理很热切地提到他们的产品使用“人工神经网络”和“深度学习”。他们是否会同样热切的说他们的产品使用“连接的圈子模型”还是“失败并惩罚的机器”?但毫无疑问,人工神经网络在图像识别,自然语言处理,自动交易和自动驾驶汽车等众多应用中取得了成功,这一点已经显而易见。作为一个没有完全理解他们的专业数据科学家,我尴尬的像一个没有台锯的建设者。
我们将从一个激励问题开始。这里我们有一组灰度图像,每个图片是一个2×2的像素网格,其中每个像素在0(白色)和255(黑色)之间取值。目标是建立一个模型,以“阶梯”模式识别图像。
此处我们只关注找到一个可以合理地拟合数据的方法。之后在去思考拟合算法本身的问题。
对于每一个图像,我们用
,
,
,
表示像素,并生成输入向量
x=[
,
,
,
],我们希望模型可以预测图像的真(有阶梯模式)假(没有阶梯模式)状态。
图像序号 | X1 | X2 | X3 | X4 | IsStairs |
---|---|---|---|---|---|
1 | 252 | 4 | 155 | 175 | 真 |
2 | 175 | 10 | 186 | 200 | 真 |
3 | 82 | 131 | 230 | 100 | 假 |
... | ... | ... | ... | ... | ... |
498 | 36 | 187 | 43 | 249 | 假 |
499 | 1 | 160 | 169 | 242 | 真 |
500 | 198 | 134 | 22 | 188 | 假 |
一个简单的模型,我们可以建立一个单层感知器。感知器使用输入的加权线性组合来返回预测分数。如果预测分数超过选定的阈值,则感知器预测为真,否则它预测为假。更正式地说,
整理后,可重新写为:
其中
就是预测分数。图形上,我们可以将感知器表示为输入节点流入输出节点。
对于我们的例子,假设我们建立下面的感知器:
如下是感知器如何在我们的一些训练图像上执行的。
这肯定比随机猜测更好。所有阶梯模式在底部像素上表现的更暗,有更大的x3和x4值。尽管如此,这个模型还是有一些明显的问题。
案例A
从图像x = [100,0,0,125]开始,将x3从0增加到60。
案例B
从上个案例的最后一张图片开始,x = [100,0,60,125]。将x3从60增加到120
直观地说,案例A的
值比案例B增加更多。然而,由于我们的感知器模型是一个线性方程,两个案例中,同样对x3增加60,导致
都增加了0.12。线性感知器还有更多的问题,但是我们先来解决这两个问题。
我们可以通过将我们的感知器包装在一个S形函数内(随后选择不同的权重)来解决上述问题1和2。回想一下,sigmoid函数是一个S形曲线,在0和1之间的垂直轴上有界,因此经常被用来模拟二元事件的概率。
遵循这个想法,我们可以用下面的图片和方程来更新我们的模型。
看起来很熟悉?这是我们的老朋友,逻辑回归。将这个模型解释为具有S型“激活函数”的线性感知器,会很好的帮助我们解释概括这个模型。而且,由于我们现在将\ widehat y解释为概率,我们必须相应地更新我们的决策规则。
继续我们的问题,假设我们提出了下面的拟合模型:
观察这个模型在与上一节相同的样本图像上的表现。
显然,这解决了上面的问题1。现在来仔细观察它是如何解决问题2的。
案例A
从图像x = [100,0,0,125]开始,将x3从0增加到60。
案例B
从上个案例的最后一张图片开始,x = [100,0,60,125]。将x3从60增加到120
请注意,S形曲线的曲率如何导致案例A随着
增加而“开火”(快速增加),但是随着z持续增加而减慢。这与我们的直觉相一致,即案例A相对于案例B,应该更快速的反映出阶梯模式。
不幸的是这个模型仍然有问题。
与每个变量具有单调关系。如果我们想识别轻微的阴影阶梯怎么办?
。我们目前的模式无法实现这一点。
我们可以通过 在我们的感知器模型上增加一个额外的层来解决上述两个问题。我们将构建几个像上面那样的基本模型,然后将每个基本模型的输出作为输入提供给另一个感知器。这个模型实际上是一个普通的神经网络。让我们通过一些例子,看看它是如何工作的。
示例1:识别阶梯模式
和
都足够大时才能被激活。
或者,
和
足够大,或者
和
足够大时被触发。(请注意,
并
不能同时为大)
示例2:识别浅色阴影的楼梯
,
,和
,
和
单层感知器具有单个输出层。因此,我们刚刚建立的模型将被称为 双层感知器,因为它们有一个输出层用来作为另一个输出层的输入。我们可以把这些类似的模型称作神经网络,他们在这方面的网络有 3 层:输入层,隐藏层和输出层。
在我们的例子中,我们使用了一个sigmoid激活函数。但是,我们可以使用其他激活函数。 tanh和 relu 是常见的选择。激活函数必须是非线性的,否则神经网络将简化为等价的单层感知器。
通过在最终输出层中使用多个节点,我们可以轻松地将我们的模型扩展到多分类问题。这里的想法是,每个输出节点都对应于我们试图预测类别
中的一个。不同于使用sigmoid函数,将结果压缩到[0,1]区间中,我们可以使用softmax函数 将矢量从
映射到
,并使得得到的矢量元素总和为1。换句话说,我们可以设计该网络,使得其输出矢量[
,
...,
]。
您可能想知道:“我们可以扩展我们的简单神经网络,使其输出层从第四层流入(然后是第五和第六)吗?”。答案是肯定的,这就是通常所说的“深度学习”。在实践中它可以是非常有效的。但是,值得注意的是,任何一个超过一层隐藏层的网络,都可以通过一个只具有一个隐藏层的网络来模拟。实际上,根据通用逼近定理,可以使用具有单个隐藏层的神经网络逼近任何连续函数 。深层神经网络架构偏向于选择单隐层架构的原因在于,单隐藏层在拟合过程中可以更快地收敛。
下面我们来到拟合过程。到目前为止,我们已经讨论了神经网络如何 能够 有效地工作,但是我们还没有讨论如何用神经网络拟合有标记的训练样本。一个等同的问题是:“给定一些标注的训练样本,我们如何选择网络的最佳权重?”。梯度下降是常见的答案(虽然MLE也可以)。继续我们的示例问题,梯度下降过程如下:
。(这被称为向前传播)
和
,然后减小
导致损失下降。因此我们更新
(其中0.001是我们预定的“步长”)。
至少这是基本的想法。实际上,这带来了一些挑战。
在拟合过程中,我们需要计算的其中一个就是
每个重量的梯度 。这是棘手的,因为
依赖于输出层中的每个节点,并且每个节点依赖于之前层中的每个节点,依此类推。这意味着计算
是一个连锁的噩梦。(请记住,许多实际的神经网络有数十层,上面有成千上万的节点。)处理这个问题的关键是要认识到,当你应用链式规则时,大多数
重用相同的中间导数。如果你仔细追踪这个,你可以避免重新计算同样的东西几千次。
另一个诀窍是使用特殊的激活函数,其导数可以写成它们的值的函数。例如,
的导数 =
。这很方便,因为在正向传播时,当我们计算每个训练样本的
时,我们必须计算
。在反向传播期间,我们可以在计算梯度时重用这些值 ,从而节省时间和内存。
第三个诀窍是把训练数据分成“小批量”,并逐一更新每个批次的权重。例如,如果将训练数据划分到{batch1,batch2,batch3},则训练数据将首先
之后在每次更新之后重新计算梯度 。
最后一个值得一提的技术是使用GPU而不是CPU,因为GPU更适合并行执行大量计算。
这不是神经网络问题,是一个梯度下降问题。在梯度下降过程中,权重可能会陷入局部最小值。权重也可能超过最小值。处理这个问题的一个诀窍是选择不同的步长。另一个技巧是增加网络中的节点和/或层数。(小心过拟合)。
我们如何编写一个通用的程序来适应任何数量的节点和层次的神经网络?答案是,“用 Tensorflow就可以”。但是,如果你真的想,最困难的部分是计算损失函数的梯度。解决这个问题的诀窍就是认识到你可以梯度计算表示为一个递归函数。5层的神经网络只是一个4层的神经网络流入一个感知器。4层的神经网络只是一个3层的神经网络流入一个感知器,以此类推。这更正式地被称为 自动分化。