人工神经网络
人工神经网络
其本质是基于上世纪五十年代的理论,即模拟生物神经元的工作流程。
其发展是由于计算机性能的飞速提升。
感知器算法(PLA)
1957年的古老算法,只是简单的希望从一些输入输出对(X,Y)中通过学习算法获得权重W和b。
算法流程
- 随机选择W和b
- 去一个训练样本(X,y)
- 若 W^T X + b > 0 且 y = -1 , 则: w = W - X , b = b - 1
- 若 W^T X + b < 0 且 y = +1 , 则: w = W + X , b = b + 1
- 再取另一个(X,y),循环步骤2
- 直到所有输入输出对都不满足2中的两个条件,退出循环。
可以证明,在若干步后,通过改变W和b总会将两组数据给分开。
线性代数优化
核心就是用增广矩阵相乘 还是等于原来的 W^T X + b ,由此简化计算,只求增广W。
定义一个增广向量 X‘ ,
1. 若 y = -1,则 X' = [X,1]
2. 若 y = +1,则 X' = [X,-1]
定义一个增广 W’ = [w,b]
- 输入 X’
- 随机取 W‘
- 挑一个 X’ ,若W’^T X’ < 0,则 W’ = W’ + X’
- 循环步骤3,直到所有的X‘都满足条件为止
感知器算法收敛定理
对PLA,我们需要考虑以下两个问题:
- PLA迭代一定会停下来吗?如果线性不可分怎么办?
- PLA停下来的时候,是否能保证?如果没有停下来,是否有?
PLA什么时候会停下来呢?根据PLA的定义,当找到一条直线,能将所有平面上的点都分类正确,那么PLA就停止了。要达到这个终止条件,就必须保证D是线性可分(linear separable)。如果是非线性可分的,那么,PLA就不会停止。
数学归纳法证明
证明了存在a,使得整个式子满足条件,我们还需定量的证明。
至多经过D平方步后,W将会收敛到最佳状态。
多层神经网络算法(Multiple Layer Neural Network)
一层神经网络可以判断是否在直线一侧
二层神经网络可以判断是否存在特定区域内
三层神经网络可以判断是否存在区域内
二层神经网络可以处理非线性问题
其本质是在一层神经元结果输出后,增加一个非线性函数去处理一层的结果,导致整个结果从线性变成非线性。
引进的非线性函数 f(X) 是什么?
如:阶跃函数
举例说明:
判断是点否存在特定区域内
如果是一个由三条线段围成的区域,我们需要用三个神经元去模拟这三条边界,只有都满足条件时才会输出+1,否则都是-1。第一层参数用来模拟边界,第二层参数用来输出是否存在与区域内,是个与或非的关系。
如果决策面是四边形,则第一层需要四个神经元来模拟这四条边界。同理若是圆形或不规则形状,则需要使用许多直线去逼近,即使用很多的神经元去模拟。
三层神经网络可以模拟所有决策面
如果决策面不止一个,我们可以用过一层模拟决策边界,二层模拟单个决策面,三层输出是否存在与某个决策区域内。扩展图中的2个决策区域到N个区域,即三层神经网络是可以模拟所有的决策面的。
反向传播算法(BP)
核心思想是:梯度下降法求局部极值。
以二层神经网络为例
算法步骤
随机初始化(W,b)
训练样本(X,Y),带入网络,可以求出所有的(Z,a,y)
链式法则求偏导(反向传播)
更新:
当所有偏导都为0时退出。
其具体步骤就是,先随机初始化W,b,算出一个y,再利用目标函数求出损失E,利用E对W,b求偏导,更新W,b以此往复。
目标函数
此处的目标函数是最简单的平方损失函数
激活函数(非线性函数)
我们最开始使用的阶跃函数,虽然满足推导,但是在反向传播时无法求偏导,导致无法反向传播修正参数。
所以我们有以下几种可行的激活函数可选:
Sigmoid函数
梯度平滑,但倾向于梯度消失,且输出不以0为中心,会降低权重更新效率。
Tanh 双曲正切函数
ReLU 激活函数
输入为正时,计算速度快。但输入为负时完全失效。
Leaky ReLU
leaky Relu 是针对Relu在输入为负时,完全失效的问题,补充了对输入为负的情况。
参数设置
训练建议
梯度下降的几种方案
BGD批量梯度下降
BGD 采用整个训练集的数据来计算 cost function 对参数的梯度:
缺点:
由于这种方法是在一次更新中,就对整个数据集计算梯度,所以计算起来非常慢,遇到很大量的数据集也会非常棘手,而且不能投入新数据实时更新模型。
1 | for i in range(nb_epochs): |
我们会事先定义一个迭代次数 epoch,首先计算梯度向量 params_grad,然后沿着梯度的方向更新参数 params,learning rate 决定了我们每一步迈多大。
Batch gradient descent 对于凸函数可以收敛到全局极小值,对于非凸函数可以收敛到局部极小值。
SGD随机梯度下降
梯度更新规则:
和 BGD 的一次用所有数据计算梯度相比,SGD 每次更新时对每个样本进行梯度更新,对于很大的数据集来说,可能会有相似的样本,这样 BGD 在计算梯度时会出现冗余,而 SGD 一次只进行一次更新,就没有冗余,而且比较快,并且可以新增样本。
1 | for i in range(nb_epochs): |
缺点:
SGD 因为更新比较频繁,会造成 cost function 有严重的震荡。
BGD 可以收敛到局部极小值,当然 SGD 的震荡可能会跳到更好的局部极小值处。
当我们稍微减小 learning rate,SGD 和 BGD 的收敛性是一样的。
MSGD小批量梯度下降
综合上述两个方法,选择一批数据进行计算,调整参数。这样它可以降低参数更新时的方差,收敛更稳定,另一方面可以充分地利用深度学习库中高度优化的矩阵操作来进行更有效的梯度计算。
和 SGD 的区别是每一次循环不是作用于每个样本,而是具有 n 个样本的批次。
1 | for i in range(nb_epochs): |
超参数设定值: n 一般取值在 50~256
缺点:(两大缺点)
不能保证很好的收敛性,learning rate 如果选择的太小,收敛速度会很慢,如果太大,loss function 就会在极小值处不停地震荡甚至偏离。
SGD对所有参数更新时应用同样的 learning rate,如果我们的数据是稀疏的,我们更希望对出现频率低的特征进行大一点的更新。LR会随着更新的次数逐渐变小。
激活函数选择
参见上述。
训练数据初始化
建议做均值方程归一化。
W,b的初始化
梯度消失现象:
如果W^T X + b 一开始很大或很小,对于sigmoid或者Tanh激活函数,那么梯度将趋于0,反向传播前面与之相关的梯度也趋于0,导致训练缓慢。因此,我们要使W^T X + b 一开始在0附近。
Batch Normalization
为了迎合某些激活函数需要将输入集中在0附近效果比较好,我们需要做标准化。但是输入可以做,隐藏层如何做标准化呢?
每一层都做标准化
在进入激活函数之前,在加一层BN,使数据集中在0-1的范围,让输入值经过激励函数的敏感部分。
但是如果只是集中在0-1,又过于线性,不能很好体现数据的特征,所以,我们又对BN层做 W^T X‘ + b,X’ 是 标准化后的数据。
相当于在原来每层直接又做了一个标准化数据的一层。
BN 添加位置
Batch normalization 的 batch 是批数据, 把数据分成小批小批进行 SGD. 而且在每批数据进行前向传递 forward propagation 的时候, 对每一层都进行 normalization 的处理,
BN 效果
Batch normalization 也可以被看做一个层面. 在一层层的添加神经网络的时候, 我们先有数据 X, 再添加全连接层, 全连接层的计算结果会经过 激励函数 成为下一层的输入, 接着重复之前的操作. Batch Normalization (BN) 就被添加在每一个全连接和激励函数之间.
目标函数的选择
对于人工神经网络的问题,我们通常不直接使用均方误差,而是使用softmax函数+信息熵作为目标函数。
softmax函数
对输出的值归一化为概率值
假设在进入softmax函数之前,已经有模型输出值,其中是要预测的类别数,模型可以是网络的输出,其输出个数为,即输出为。
所以对每个样本,它属于类别的概率为:
通过上式可以保证,即属于各个类别的概率和为1。
信息熵
多分类的问题上,真实的类标签可以看作是分布,对某个样本属于哪个类别可以用One-hot的编码方式,是一个维度为的向量,比如在5个类别的分类中,[0, 1, 0, 0, 0]
表示该样本属于第二个类,其概率值为1。该分布中,当属于它的真实类别。同时,分类模型经过softmax函数之后,也是一个概率分布,因为。它也是一个维度为的向量,如[0.1, 0.8, 0.05, 0.05, 0]
。
对一个样本来说,真实类标签分布与模型预测的类标签分布可以用交叉熵来表示:
参数的更新策略
解决SGD梯度方向不一致的问题:
- AdaGrad
- RMSProp
解决SGD梯度随机性的问题:
- Mementum 角动量,让每一次算出的方向,都对下一次加权产生影响。
Adam:综合上述两种方法。
参考: