神经网络
我们目前已经学了线性回归和逻辑回归,但它们都有一个缺点:当分布复杂时,特征会非常多,开销会很大。
比如下面这个例子:
![非线性训练集](https://ws2.sinaimg.cn/large/006tNbRwgy1fva9g3flsrj30br09c0wo.jpg)
在这个图中,如果使用线性的假设函数,则会有较多的、一连串的数据点被错误分类了。而如果我们使用\(x_1\)、\(x_2\)的多项式特征时,则能训练出更好的模型。但是,如果特征数非常大,那么开销也会非常大。比如有\(n=100\)个特征,那么即使我们只采用两两组合的方式(\(x_1^2, x_1x_2, x_1x_3, \dots, x_{100}^2\)),那么最终也会有5000多个组合特征,如果三个特征相组合则会更多。当遇到那么多特征时,先前学的模型不能有效地处理,这时候我们就需要神经网络
。
模型表示
神经网络是在模仿大脑中的神经元或者(生物学中的)神经网络时发明的。所以它的所定义的神经元也和生物学中的神经元很像:
![M-P神经元模型](https://ws4.sinaimg.cn/large/006tNbRwgy1fva9g66tagj30e407twfo.jpg)
整个过程大致如下:
- 首先从左边的圆圈中获取
输入
\(x_i\)。这里有的时候也会有\(x_0\),而\(x_0\)恒为1,所以常常不写出来,它被称为偏置单元(bias unit)
或偏置神经元(bias neuron)
。 - 将\(x_i\)通过 对应的
权重
\(w_i\)传给神经元。这个权重就是原来线性回归和逻辑回归中的参数\(\theta_i\),而在神经网络中常常被称为权重。 - 通过
激活函数
处理并产生神经元的输出。理想中的激活函数是阶跃函数,但因为不连续、不光滑,所以常用\(Sigmoid\)函数作为激活函数(还有\(tanh\)等,这里不做介绍)。
在神经网络中,隐层和输出层节点的输入和输出之间存在函数关系,这个函数就称为激活函数(activation function)。
上面的图中表示了单独的一个神经元,而把许多这样的神经元按照一定的层次结构连接起来,就得到了神经网络:
![神经网络](https://ws2.sinaimg.cn/large/006tNbRwgy1fva9g9l4v6j30oy0fqn41.jpg)
其中,第一层通常也称为输入层,第三层也称为输出层,第二层称为隐层(hidden layer),因为它既不是输入也不是输出,对于外部来说是不可见的。需要注意的是,在神经网络中,有一层输入层和一层输出层,但可能会有不止一层的隐层。
计算流程
在整个神经网络中,从输入\(x_i\)到输出\(h_\Theta(x)\),经历的流程如下:
![计算流程](https://ws1.sinaimg.cn/large/006tNbRwgy1fva9gcydhlj311y0lcdty.jpg)
首先,需要描述两个符号的定义:
\(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,以此类推...