目录
多层感知器/全连接神经网络
- 定义:级联多个线性分类器来实现输入到输出的映射。
- 两层全连接网络:max函数是激活函数Relu
- 三层全连接网络:
- 因为线性分类器中只有一个模版记录不够准确,比如有两个马头的模版,w是权值模版,w2的行数必须跟类别个数一样,对w1没有需求。那么可以指定模版行数w1如100行,大约用4-5个模版去存储马,再用w2融合多个模版的匹配结果来实现最终类别打分。
- w1维度是100*3072,b1维度是100*1,f维度是100*1
- w2维度是10*100,b2维度是10*1,f维度是10*1
一、全连接神经网络绘制
- 两层全连接神经网络:
二、激活函数
如果没有激活函数,全连接神经网络又退化成了一个线性分类器
常用的激活函数
- Sigmoid:将数据压缩在0到1之间,非对称
- Relu:大于0的值是值本身,小于0的值是0
- tanh:双曲正切函数,将数据压缩在1到-1之间,对称
- Leaky Relu:使小于0的值都有一个小的斜率0.1
三、网络结构设计
- 指定隐藏层/深度:增加深度更好
- 指定神经元/宽度:神经元越多,非线性能力越强,复杂的分类越强,但也越可能过拟合
- 指定激活函数:同层用同一个激活函数
四、损失函数
softmax
- 定义:输出为概率分布,不仅可以预测分类,还可以预测出分到该类的概率
- 概率化之后,训练好的神经网络需要有标答与之对应,那么就用onehot向量编码表示标答,用1表示真实类别,用0表示其它类别,该向量与分类器预测的维度一致,计算预测分类器与标答的差异,用交叉熵/相对熵来比较。
交叉熵损失
- 使预测分布与真实分布越接近越好
- 真实分布用onehot编码形式来表示
- 熵是信息量的体现,信息最不确定的情况,就是onehot,熵最大,比如比赛赢的概率
- 交叉熵是度量预测与真实两个分布之间的差异关系
- 相对熵/KL散度是度量预测与真实两个分布之间的不相似程度
- 交叉熵 = 熵 + 相对熵
- 当真实分布为onehot时,交叉熵损失简化为:j是真实类别
对比多类支持向量机损失
- 支持向量机只要有一个比其它的分值高1分即可,交叉熵损失需要尽可能保证一个最大,其它尽可能小
五、优化算法
计算图与反向传播
- 有向图,用来表达输入输出以及中间变量之间的计算关系,图中的每个节点对应着一种数学运算。
- PyTorch,TensorFlow
- 正向是计算输入到输出之间的关系
- 反向是计算输出到输入之间的梯度(导数),链式法则一直两梯度相乘,即计算局部梯度时,需要输入值代入导数公式中,得到局部梯度,然后乘以上游梯度,才能得到当前梯度
- 如果梯度很小的情况,会导致梯度消失
计算图的颗粒度(例子)
- -0.77*1=-0.77
- -0.77*e^(-2)=-0.1
- -0.1*(-1)=0.1
- 0.1*1=0.1
- 在tensorflow中把sigmoid函数当作一个计算单元,无需拆解,可以加速运算
常见的门单元
激活函数
1. Sigmoid激活函数:
- 梯度消失:当输入大于10或小于-10时,局部梯度都为0,由于链式法则的乘法特性,会导致梯度消失,梯度为0时,参数无法更新训练
- 梯度爆炸:梯度乘以学习率后得到一个非常大的值,每次更新步长后必须走那么远,从而无法收敛到最低点。需要限制步长,也称梯度裁剪。新梯度权值=旧权值-学习率*当前梯度
2. 双曲正切激活函数:
![]()
- 类似sigmoid,不利于反向梯度传递,会导致梯度消失
3. Relu激活函数:
- 当输入大于0时,局部梯度永远不会为0,不会导致梯度消失,利于梯度流的传递
- 但当输入小于0时,梯度为0
4. Leakly Relu激活函数:
- 使输入永远乘以一个斜率0.1,保证梯度永远不会为0
为了避免梯度消失的问题,尽可能选择Relu和LeaklyRelu作为激活函数,训练过程收敛的快
六、梯度算法改进
梯度下降算法存在的问题
- 随机梯度下降所采集的部分样本中存在数据噪声,无法代表所有数据
- 小批量梯度下降虽然可以解决随机梯度下降的问题,但运行速度依旧慢
- 损失下降的慢,把时间用于无用的震荡中,简单增大步长无法解决这个问题,需要使用动量法和自适应梯度法
- 梯度幅度大的地方,不断震荡;梯度幅度小的地方,行进缓慢
- 局部最小点与拐点梯度为0时,算法无法通过,需要使用动量法和自适应梯度法
动量法
- 利用累加历史梯度信息来更新梯度
- 避免左右震荡,因为左右两边累加会彼此抵消
- 加速收敛,因为单方向的累加会使梯度越来越大,直到收敛
- 动量系数mean:取值范围[0,1),mean为0时等价于梯度下降算法,为1时无法停止训练,建议0.9
- 可以解决局部最小点和拐点,因为动量系数相当于摩擦,可以一点点减速继续前进,找到最优解
- 步骤3用于累加历史梯度信息
- 步骤4用于更新梯度
自适应梯度(AdaGrad,RMSProp)
- 分别改变步长:减小震荡方向步长,增大平坦方向步长
- 判断震荡方向和平坦方向:梯度幅度大平方,较大为震荡,较小为平坦
- AdaGrad自适应梯度法:
- 统计并累加历史梯度的平方值,如果平方值一直很大时,代表该处为震荡处
- 问题:当r变得非常大时,步长会变得非常小,收敛非常慢,用RMSProp改进
- RMSProp自适应梯度法:
- 解决AdaGrad的方法:在每次历史梯度r上增加一个衰减值row,每次当前梯度的平方g*g上增加一个控制项(1-row),混合两个梯度生成累加平方梯度
- 衰减速率row:取值范围[0,1),row控制着需要考虑多少历史值,为0时仅考虑当前梯度的强度,为1时考虑所有历史梯度那么row不起作用了,建议0.999,经过迭代使得累加平方梯度r很小
ADAM
- 同时使用动量和自适应梯度的思想,但是调整传统的SGD+动量法的学习率会比adam更好,找到合适的学习率就是炼丹过程
- 步骤3:v是历史梯度的累加值,用于更新速度,是动量法,决定了要走的方向
- 步骤4:r是历史梯度的平方的累加值,表示当前点是否为震荡方向,用于改变学习率
- 步骤6:根号r那一项用于减小震荡方向步长,增大平坦方向步长
- 步骤5:修正偏差可以解决算法初期的冷启动问题,当mean=0.9时,1-mean=0.1,梯度值仅为0.1,缩小了10倍更新,会使系统初始时走的很慢,累加变量r也会变得很小。修正偏差v冒可以保证不缩小梯度值,
七、训练过程
随机权值初始化:保证正反向传递
- 如何给定一个初始点进行梯度下降,同时保证正向的数据流和反向的梯度正常不消失,也就是保证输出y与输入z具有相同的分布
定义:z为输入,w为权值,z与w独立,f是激活函数,n是输入神经元个数
目标:每次输出和输入有相同的分布,使各层的激活值和局部梯度的方差保持一致,即寻找w的分布使得输出y与输入z的方差一致
- Xavier初始化方法(针对tahn/Sigmoid函数)
- 当均值=0,方差=1/n时,去采样权值时,可以保证输入和输出的变量有相同的分布,可以保证最后一层的输出结果依然符合正态分布
- HE初始化/MSRA方法(针对Relu/LeaklyRelu函数)
- 当均值=0,方差=2/n时,使响应结果更均匀
批归一化Batch Normal:保证正反向传递
- 对神经元的输出进行批归一化:对输出y进行减均值除方差,得到y',以保证当前神经元的输出分布符合0均值1方差,可以解决前向传递过程中的信号消失问题
- 把批归一化插入到全连接层后,非线性激活前
- 通常全连接层之后的输入数据会落在小梯度或无梯度的区域,但是经过批归一化之后,会保证输入数据回到有梯度的地方,再进行激活,可以保证信息流传递正常,保证输出数据是0均值1方差,不会呈现饱和状态,从而解决梯度消失问题
- 定义:
- 步骤4是让神经网络自己选择适合分布的均值和方差
欠拟合,过拟合,Dropout
模型正则化
超参数调优
未完。。。