IT思维

文章页右侧顶部广告

机器之心:从感知机到深度神经网络,带你入坑深度学习

2018-01-15 12:19:35 0 业界资讯 | , ,

文/李亚洲

公众号/机器之心

机器学习工程师 Adi Chris 最近学习完吴恩达在 Coursera 上的最新课程后,决定写篇博客来记录下自己对这一领域的理解。他建议通过这种方式可以有效地深入理解一个学习主题。除此之外,也希望这篇博客可以帮助到那些有意入坑的朋友。

言归正传。在我正式介绍深度学习是什么东西之前,我想先引入一个简单的例子,借以帮助我们理解为什么需要深度神经网络。

同时,本文附有使用深度神经网络模型求解异或(XOR)问题的代码,发布在 GitHub 上。

GitHub 地址:https://github.com/chrisbangun/medium-post/tree/master/Perceptron-to-DNN

XOR PROBLEM

异或问题

何为异或问题?对于给定的两个二进制输入,我们通过异或逻辑门得到一个预测输出,这一过程即为异或问题。注意,输入不相等时输出为 1,否则为 0。表 1 展示了异或函数的所有可能的输出结果:

那么现在我们就画出数据分布图来探究它的本质。

def plot_data(data, labels):
    """
    argument:
    data: np.array containing the input value
    labels: 1d numpy array containing the expected label
    """
    positives = data[labels == 1, :]
    negatives = data[labels == 0, :]
    plt.scatter(positives[:, 0], positives[:, 1], 
                       color='red', marker='+', s=200)
    plt.scatter(negatives[:, 0], negatives[:, 1], 
                       color='blue', marker='_', s=200)

positives = np.array([[1, 0], [0, 1]])
negatives = np.array([[0, 0], [1, 1]])

data = np.concatenate([positives, negatives])
labels = np.array([1, 1, 0, 0])
plot_data(data, labels)

看到上图后,我们或许会反思,这真的是一个简单问题么?

如你所见,我们的数据并非线性可分的,因此,一些常用的线性模型,例如 logistic 回归可能就不太适合分类我们的数据了。为了给你一个更直观的理解,我用一个简单的线性模型画出了如下图的决策边界。

微调 logistic 回归模型构造决策边界

上面的图清楚的告诉我们,我们需要一个更好的分类器来分离非线性数据。SVM 结合它的核心技巧就是一个不错的选择。但是,在本文中,我们打算重新构建一个神经网络而非 SVM,并带你领略下神经网络解决异或问题的风采。

何为神经网络?

神经网络就是就是找到一个可以模拟人脑工作行为的表现良好的近似函数。图 1 对人类神经元与人工智能网络作了类比。

图 1:(a)人脑神经元结构(b)从生理神经网络类比得出的人工智能网络—图片摘自 cs231n.github.io

你不需要了解太多生物学知识,我会从高度形象的角度来解释人体神经元如何处理信息。

人体的神经元通过树突接受信号。这些信息或信号随后被传递到脑细胞或细胞体。在细胞体内部,所有的信息将被加工生成一个输出。当该输出结果达到某一阈值时,神经元就会兴奋,并通过轴突传递信息,然后通过突触传递到其他相连的神经元。神经元间传输的信号量取决于连接的强度。

前面提到的整个流程某种程度上适用于人工智能网络。你可以把树突想象成人工智能网络中基于突触感知器的被赋予了权重的输入。然后,该输入在人工智能网络的『细胞体』中相加。如果得出的输出值大于阈值单元,那么神经元就会『兴奋』,并将输出传递到其它神经元。

这样你就可以理解人工智能网络就是借鉴基本的生物神经元工作原理建模的吧。

神经网络究竟如何工作?

为了了解神经网络是如何工作的,我们先来看看一个叫感知机的简单的人工神经网络。

对我而言,感知机是我见过的机器学习中最优雅的算法之一。它于 1950 年代被提出,尽管很简单,但它可以说是很多重要的机器学习算法的起点了,例如 logistic 回归、支持向量机甚至深度神经网络。

那么感知机怎么工作昵?我们以图 2 展开讨论。

图 2:感知机

图 2 展示了给定三个输入 x_1、x_2 和 x_3 以及一个可以计算输出值的神经元的感知机算法。Rosenblatt 通过引入权重的概念介绍这一简单的规则,用于生成输出值。权重通常是表示输入对应于输出的重要性的实数。上图中的神经元将会得到两个可能的结果,0 或 1,是由每个输入的加权和 ∑wjxj 决定的大于或小于阈值的结果。因此,感知机的主要思想就是去学到一些可以决定神经元兴奋还是抑制的与输入特征相乘的权重 w。我们可以写出一个如下的数学表达式:

我们现在可以做两件事来修改上述公式:第一,我们把权重相加操作转变成两个向量的点乘。

w (权重) 和 x (输入), 其中 w⋅x ≡ ∑wjxj。接下来,我们可以把阈值移到不等式的另一端并取个新变量名为偏置 b,b 恒等于阈值的负数。通过这些改动,感知机公式重写如下:

现在我们把这些公式套进我们的感知机架构,这样就有了如下所示的完整的单层感知机架构:

图 3:单层感知机架构

通常情况下,单层感知机模型都会使用阶跃函数作为激活函数将结果转化成 0 或 1,因此将输入归到 0 或 1 类。如图 4 所示,负数的输出为 0,正数的输出为 1。

图 4:阶跃函数的图示

对于输入数据线性可分的分类任务,阶跃函数十分有用。但是,由于我们的目的是找到一个用于分离非线性数据的分类器,单层感知机与阶跃函数就毫无意义了。稍后几节,我们将会看到使用非线性激活函数的多层感知机网络模型。

关于我们为什么不用使用阶跃函数,这里有两个主要原因:

1. 目前,结合反向传播使用梯度下降算法是训练一个多层神经网络的有效方法之一(我们稍后会简短的介绍一下)。反向传播的必要条件是使用的激活函数必须可微。然而阶跃函数在 x=0 处不可导,且其它位置导数均为 0。如此一来就无法运用梯度下降法更新权重了。

2. 回想下,神经网络的主要目的就是学习到使预测尽可能接近真实值的权重和偏置。为了达到这一目的,如同很多优化问题,我们希望对权重或偏置上作一个小的改变,在网络输出中只产生一个相对小的变化。而这是一个仅能生成 0 或 1 的函数难以企及的。

激活函数

激活函数是神经网络的一个重要组成部分。一般来说,我们最少有三个需要激活函数的理由:

  • 它帮助神经元学习和理解一些非常