coursera机器学习课程笔记 【week 4】

神经网络

我们目前已经学了线性回归和逻辑回归,但它们都有一个缺点:当分布复杂时,特征会非常多,开销会很大。

比如下面这个例子:

非线性训练集
非线性训练集

在这个图中,如果使用线性的假设函数,则会有较多的、一连串的数据点被错误分类了。而如果我们使用\(x_1\)\(x_2\)的多项式特征时,则能训练出更好的模型。但是,如果特征数非常大,那么开销也会非常大。比如有\(n=100\)个特征,那么即使我们只采用两两组合的方式(\(x_1^2, x_1x_2, x_1x_3, \dots, x_{100}^2\)),那么最终也会有5000多个组合特征,如果三个特征相组合则会更多。当遇到那么多特征时,先前学的模型不能有效地处理,这时候我们就需要神经网络

模型表示

神经网络是在模仿大脑中的神经元或者(生物学中的)神经网络时发明的。所以它的所定义的神经元也和生物学中的神经元很像:

M-P神经元模型
M-P神经元模型

整个过程大致如下:

  1. 首先从左边的圆圈中获取输入\(x_i\)。这里有的时候也会有\(x_0\),而\(x_0\)恒为1,所以常常不写出来,它被称为偏置单元(bias unit)偏置神经元(bias neuron)
  2. \(x_i\)通过 对应的权重\(w_i\)传给神经元。这个权重就是原来线性回归和逻辑回归中的参数\(\theta_i\),而在神经网络中常常被称为权重。
  3. 通过激活函数处理并产生神经元的输出。理想中的激活函数是阶跃函数,但因为不连续、不光滑,所以常用\(Sigmoid\)函数作为激活函数(还有\(tanh\)等,这里不做介绍)。

在神经网络中,隐层和输出层节点的输入和输出之间存在函数关系,这个函数就称为激活函数(activation function)。

上面的图中表示了单独的一个神经元,而把许多这样的神经元按照一定的层次结构连接起来,就得到了神经网络:

神经网络
神经网络

其中,第一层通常也称为输入层,第三层也称为输出层,第二层称为隐层(hidden layer),因为它既不是输入也不是输出,对于外部来说是不可见的。需要注意的是,在神经网络中,有一层输入层和一层输出层,但可能会有不止一层的隐层。

计算流程

在整个神经网络中,从输入\(x_i\)到输出\(h_\Theta(x)\),经历的流程如下:

计算流程
计算流程

首先,需要描述两个符号的定义:

\(a_i^{(j)} =\) "activation" of unit \(i\) in layer \(j\)

$^{(j)} = $ matrix of weights controlling function mapping from layer \(j\) to layer \(j+1\)

那么整体流程就是,依次计算每一层的激活函数,再把输出经过层层处理后,最后得到输出\(h_\theta(x)\)。比如我们看 \[ a_1^{(2)} = g(\Theta_{10}^{(1)}x_0 + \Theta_{11}^{(1)}x_1 + \Theta_{12}^{(1)}x_2 + \Theta_{13}^{(1)}x_3) \] 就是把每个输入和它们相对于\(a_1^{(2)}\)的权重相乘,并求和。需要注意的是,作为自变量的那一层(这里是输入层),需要考虑偏置单元(这里是\(x_0\)),而因变量那一层(这里是\(a^{(2)}\)那一层)则不需要考虑偏置单元。因为偏置单元始终是一个常量,所以需要作为输入,但自己不需要计算。因此,如果层\(j\)中有\(s_j\)个单元,层\(j+1\)中有\(s_{j+1}\)个单元,则矩阵\(\Theta^{(j)}\)的维度是\(s_{j+1} \times (s_j + 1)\)(层\(j+1\)在前)。

向量化

我们可以很容易理解到,每一层的激活函数的计算形式都是相同的。比如我们要求上图中第二层的激活函数,如果把计算向量化,则可以得出这样的公式: \[ \begin{align} z^{(2)} &= \Theta^{(1)}x \\ a^{(2)} &= g(z^{(2)}) \end{align} \] 其中\(\Theta^{(1)}\)\(3 \times 4\)的矩阵,\(x\)是一个四维向量(包括了\(x_0\)),于是\(z^{(2)}\)\(a^{(2)}\)都是三维向量。但是有一个问题,这里第二层是作为了计算的结果,所以只是三维向量而不需要考虑\(a_0^{(2)}\),但是在求第三层的时候还是会需要第二层是四维的呀,怎么办呢?这里可以在计算\(a^{(3)}\)的时候,提前设置\(a_0^{(2)} = 1\)。另外,第一层输入层只不过是没有自己的输入,算是特殊的一层,所以可以写成\(a^{(1)}\)。那么我们的公式就可以同意写成: \[ \begin{align} a_0^{(i)} &= 1 \\ z^{(i)} &= \Theta^{(i-1)}a^{(i-1)} \\ a^{(i)} &= g(z^{(i)}) \end{align} \] 这样,即使中间有多层隐层,也可以这样计算,因为我们把输入层和输出层也看成了"特殊的隐层"。而最后的结果就是输出层的激活函数,在上图的例子中就是 \[ h_\Theta(x) = a^{(3)} = g(z^{(3)}) \]

这个从输入层开始不断计算,直到输出层的过程叫做前向传播(Forward Propagation),这样的网络叫做前馈神经网络(Feedforward neural network)

仔细观察上面的方程组的话,我们会注意到其实神经网络和逻辑回归很类似。对于\(h_\theta(x)\)来说,其计算公式在逻辑回归和神经网络的最后一层中是相同的。只不过在逻辑回归中输入是\(x_i\),而在神经网络中输出是\(a_i^{(2)}\)\(a_i^{(2)}\)又是通过\(x_i\)训练出来的。所以,逻辑回归中不能很好地处理多项式特征,在神经网络中却能经过多层的计算,转化成新的特征,从而很好地考虑到了各特征之间的组合情况。

多类别分类

神经网络中的多类别分类本质上是one-vs-all方法。比如说我们要判断一个数字是0到9之间的哪一个,我们就把输出层改为有10个神经元,每个神经元代表输入是否它对应的数字。这样以来,最后的输出不再是实数,而是一个10维的向量,其中每个元素的值都为0或1.比如说向量\(\begin{bmatrix}1&0&\dots&0\end{bmatrix}^T\)则表示该数字是0,向量\(\begin{bmatrix}0&1&\dots&0\end{bmatrix}^T\)表示该数字为1,以此类推...