非线性假设
对于许多实际的机器学习问题,特征个数n是很大的。
随着特征数量n的增加,二次项的个数大约以 的量级增长,此时包含所有的二次项是困难的,如果我们还要引入三次项,那么我们的项的个数将以 的量级增长。
而项数过多时,结果很有可能过拟合。此外,这里也存在运算量过大的问题。
神经网络逻辑单元
在一个计算机的神经网络里,我们将使用一个非常简单的模型来模拟神经元的工作:
黄色的圆圈,可以理解为类似神经元的东西,然后我们通过它的树突(或者说是它的输入神经)传递给它一些信息。然后神经元做一些计算,并通过它的输出神经(即它的轴突)输出计算结果。
这里的
通常值的是:
绘制一个神经网络时,有时会额外增加一个 的输入节点,这个 节点有时也被称作偏置单位(或偏置神经元)。但由于 ,是否画出它,取决于它是否对例子有利。
激励函数
神经网络中的激励函数(activation function),只是对类似非线性函数g(z)的另一个术语称呼:
在之前我们一值称 为模型的参数,但在神经网络的文献里,有时会称 为模型的权重(weight)。
输入层,输出层,隐藏层
- 第一层也被称为输入层,因为我们在这一层输入我们的特征项 , 和 ,当然我们也可以加入值为1的 。
中间层有三个神经元: , 和 ,同理,你可以加上值永远为1的偏置单元 。
中间层,也被称为隐藏层,隐藏层的值在训练过程中是看不到的,所以叫它隐藏层。神经网络可以有不止一个的隐藏层。在神经网络中,任何一个非输入层且非输出层,就被称为隐藏层。
最后一层,也被称为输出层,因为这一层的神经元会输出假设函数的最终计算结果 。
前向传播(forward propagation)的向量化实现
表示第j层的第i个神经元,表示的是第 层的第 个激励。
把隐藏层的三个神经元的计算结果都写出来:
简化上面的式子,改写为:
可见:
这里其实是一个矩阵的乘法运算:
这样一来,就能将神经网络的计算,向量化了。
具体而言,我们定义特征向量x:
其中
并定义 :
我们只需要两个步骤,就可以计算出
向量了:
最后,在输出层,我们还有一个单元,它用来计算 :
这就是计算 的过程,也称为前向传播(forward propagation)。
AND、OR、NOT、XNOR的实现
拟合AND
假设我们有二进制输入 和 ,目标函数是 AND ,为网络分配一些权重(参数):
即,假设函数是:
x1 | x2 | hΘ(x) |
---|---|---|
0 | 0 | g(−30)≈0 |
0 | 1 | g(−10)≈0 |
1 | 0 | g(−10)≈0 |
1 | 1 | g(10)≈1 |
这就是逻辑“与”的计算结果。
拟合OR
即,假设函数是:
x1 | x2 | hΘ(x) |
---|---|---|
0 | 0 | g(−10)≈0 |
0 | 1 | g(10)≈1 |
1 | 0 | g(10)≈1 |
1 | 1 | g(30)≈1 |
拟合NOT
假设函数为:
x1 | hΘ(x) |
---|---|
0 | g(10)≈1 |
1 | g(−10)≈0 |
拟合XNOR
接下来我们使用上面求解的以下三个神经网络,就可以来运算 XNOR 了:
为了拟合 XNOR 的非线性的样本分布:
可以构建以下神经网络的隐藏层:
最终的真值表如下:
x1 | x2 | hΘ(x) | ||
---|---|---|---|---|
0 | 0 | 0 | 1 | 1 |
0 | 1 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 |
1 | 1 | 1 | 0 | 1 |
神经网络的多类别分类
建立一个具有四个输出单元的神经网络,四个类别分别是行人、轿车、摩托车、卡车:
也就是说,此时神经网络的输出是一个思维向量。因此现在的输出需要用一个向量来表示,这个向量中有四个元素,而我们要做的是对第一个输出元素进行分辨图片上是不是一个行人(Pedestrian),然后对第二个元素分辨它是不是一辆轿车(Car),对第三个元素分辨它是不是摩托车(Motorcycle),对第四个元素分辨它是不是一辆卡车(Truck)。
因此,如果判断是行人,输出结果是:
代价函数
以神经网络在分类问题中的应用为例:
:神经网络结构的总层数。对于上面的网络结构,
。
表示第
层的神经元的数量,这其中不包括
层的偏置单元。
(也就是输入层)
在多类别分类(Multi-class classification)问题中,会有K个不同的类,比如说如果我们有四类的话,我们就用下面这种表达形式来代表y。在这类问题里,我们就会有K个输出单元。
在神经网络里,使用的代价函数,应该是逻辑回归里使用的代价函数的一般形式。
逻辑回归的代价函数:
其中 这一项是个额外的正则化项,是一个j从1到n的求和形式。因为我们并没有把偏置项0正则化。
对于神经网络,我们使用的代价函数是这个式子的一般化形式。
神经网络输出了在K维的向量hΘ(x):
用 来表示第i个输出。
最后式子中的这一项 类似于我们在逻辑回归里所用的正则化项,这个求和项看起来确实非常复杂,它所做的就是把这些项全部加起来,也就是对所有的 的值都相加。
反向传播(B-P)
反向传播算法(BP算法)是一种让代价函数最小化的算法,从直观上说就是对每一个节点求误差项: ,即第 层的第 个结点的误差。
用上面的那个四层的神经网络结构做例子:
每一项的输出单元(layer L = 4)
对于每一个输出单元,我们准备计算 项,所以第四层的第 个单元的 就等于这个单元的激励值减去训练样本里的真实值。
下一步就是计算网络中前面几层的误差项δ。
的计算公式:
应用一个相似的公式来求得 :
这里我们没有 项,因为第一层是输入层,不存在误差。
如果你忽略标准化所产生的项,我们可以证明我们想要的偏导项,恰好就是下面这个表达式:
梯度检验(Gradient Checking)
反向传播作为一个有很多细节的算法,在实现的时候会有点复杂,而且有一个不好的方面是在实现反向传播时,会遇到很多细小的错误。
用数值方法计算近似导数的过程:
找到
和
这两个点,然后用一条直线把这两点连起来,求近似导数:
通常 取很小的值,比如可能取 , 的取值在一个很大的范围内都是可行的,实际上,如果你让 非常小,那么数学上上面的式子实际上就是导数。
在实现神经网络时,用for循环来计算代价函数对每个网络中的参数的偏导数估计值gradApprox,然后和我们从反向传播得到的导数DVec进行对比,看是否相等或近似于DVec。如果这两种计算导数的方法给了你相同的结果,或者非常接近的结果,那么我就非常确信我实现的反向传播是正确的。
随机初始化Θ
虽然说在逻辑回归时,初始化所有变量为0是可行的,但在训练神经网络时,这样做是不可行的。
为了解决这个神经网络变量初始化的问题,我们采用随机初始化的方法。对 的每个值进行初始化,范围在 之间 。
选择一个合适的神经网络结构
- 输入单元的数目,由特征 的维度确定。
- 输出层的单元数目,由分类问题中的类别个数确定。
- 如果使用超过一层的隐藏层,每一个隐藏层通常都应该拥有相同的单元数。通常来说,只使用一层隐藏层的结构是较为合理的默认结构。
训练神经网络的步骤
训练神经网络的六个步骤:
构建一个神经网络并且随机初始化权值(Randomly initialize Weight)我们通常把权值初始化为很小的值,接近于0。
执行向前传播算法,也就是对于神经网络的任意一个输入 计算出对应的 。
- 通过代码计算出代价函数 。
- 执行反向传播算法(Backprop)来算出这些偏导数:
使用梯度检查来校验结果。用梯度检查来比较这些已经用反向传播算法得到的偏导数值 与用数值方法得到的估计值进行比较,来检查,确保这两种方法得到值是基本相近的。
通过梯度检查,我们能确保我们的反向传播算法得到的结果是正确的,但必须要说明的一点是,检查结束后我们需要去掉梯度检查的代码,因为梯度检查计算非常慢。
- 使用一个最优化算法(比如说梯度下降算法或者其他更加高级的优化方法,比如说BFGS算法,共轭梯度法,或者其他一些已经内置到fminunc函数中的方法),将所有这些优化方法和反向传播算法相结合,这样我们就能计算出这些偏导数项的值 。