在进入深度网络前有几个重要知识点:
关于tanh, sigmoid, relu, softmax激活函数:
sigmoid: y = 1/(1 + e-x) #sigmoid取值在[0, 1]且中心值在0.5,常用于二分类
tanh: y = (ex - e-x)/(ex + e-x) #tanh取值在[-1,1]且中心值在0,相当于sigmoid往下移
relu: y = max(0, x) #深层网络用relu防止梯度爆炸/消失,浅层用sigmoid或tanh
Softmax: 用在多分类网络输出,所有输出和为1
Si=ei / ∑j ej
为什么要取指数?第一个原因是模拟max行为,让大的更大;第二个原因是需要一个可导函数。
梯度消失和梯度爆炸:
Word2vec只有一层隐层,但是反向传播求导时候发现开销特别大,我们可以想象一下RNN这种更深网络时候会发生什么,0.几的数字一层层相乘,已经趋近于0了,这样导致层数较浅的权重没有更新,梯度也就消失了。
梯度爆炸的出现由于初始权重过大,前面层比后面层变化更快,这样就导致权重越来越大,梯度爆炸的现象就发生了。
怎么解决?
- 重新设计网络模型
上面提到更深神经网络会出现梯度消失/爆炸,所以可以通过重新设计层数更少的网络来解决。同时使用更小的批尺寸对网络训练也有好处。另外也许是学习率的原因,学习率过大导致的爆炸问题,减小学习率来调整。
2.使用 ReLU 激活函数
Relu: g(z) = max(0,z) 使一部分神经元输出为0
Leaky relu: g(z) = max(0.01,z)
使用 ReLU 激活函数可以减少梯度爆炸。采用 ReLU 激活函数是最适合隐藏层的新实践。
- 使用LSTM
LSTM通过它内部的“门”可以接下来更新的时候“记住”前几次训练的”残留记忆“,这样通过筛选可以减少梯度爆炸的问题。
4.BatchNorm
神经网络在训练的时候随着网络层数的加深,激活函数的输入值的整体分布逐渐往激活函数的取值区间上下限靠近,从而导致在反向传播时低层的神经网络的梯度消失。而BatchNormalization的作用是通过规范化的手段,将越来越偏的分布拉回到标准化的分布,使得激活函数的输入值落在激活函数对输入比较敏感的区域,从而使梯度变大,加快学习收敛速度,避免梯度消失的问题。
- 使用权重正则化(Weight Regularization)
如果梯度爆炸仍然存在,可以尝试另一种方法,即检查网络权重的大小,并惩罚产生较大权重值的损失函数。该过程被称为权重正则化,通常使用的是 L1 惩罚项(权重绝对值)或 L2 惩罚项(权重平方)。
Loss问题
TF和TF Keras里已经封装的很好了,我整理了一下
1. sigmoid + 交叉熵函数 (二分类)
在tensorflow上体现为sigmoid_cross_entropy_with_logits
而在keras上体现为binary_crossentropy用途与上面的sigmoid_cross_entropy_with_logits是一样的,而binary_crossentropy则先把输出值进行概率包装后,再带入sigmoid_cross_entropy_with_logits数学公式中
2. softmax + 交叉熵函数 (多分类)
在tensorflow上体现为softmax_cross_entropy_with_logits_v2
而在keras中,与此对应的是categorical_crossentropy,采用的算法和上述基本一致,只是需要把y_output按分类值做概率转换。
3. sparse + softmax + 交叉熵函数:(对非one-hot的标签进行交叉熵计算)
在tensorflows中体现为sparse_softmax_cross_entropy_with_logits
而在keras中,与此对应的为sparse_categorical_crossentropy,该函数会调用上述函数,最大的不同在于:1. 其参数y_output被设定为经过softmax之后的值;2. y_output还会被log处理下
不仅要会用,还要挖挖背后的“根”:
1. 均方差函数+sigmoid函数的反向求导:
令L(a, y) = ½ (a - y)2 ,由前述可知,其求导为:L'(a, y) = a - y
而激活函数sigmoid的求导为:a' (z) = a (1 - a)
我们对w2进行求导,由链式法则可知:
dL/dw2 = dL/da2 * da2/dz2 * dz2/dw2
= (a2 - y) * a2(1 - a2) * a1
2. 交叉熵函数+sigmoid函数的反向求导:
令L(a, y) = - [y * ln a + (1 - y) ln (1 - a)],其求导为:L'(a, y) = (a - y) / [a * (1 - a)]
同样激活函数sigmoid的求导为:a' (z) = a (1 - a)
我们依旧对w2进行求导,由链式法则可知:
dL/dw2 = dL/dσ2 * dσ2/dz2 * dz2/dw2
= (a2 - y) / [a2 * (1 - a2)] * a2(1 - a2) * a1
= (a2 - y) * a1
两个公式可以看出均方差求导后含有sigmoid的导数,当sigmoid导数在变量值很大或很小时趋于0,这样的偏导求出来也可能趋近于0,交叉熵求导后就没有sigmoid函数就没有这个问题。当然这个是从公式上。
从机器学习的角度来说,均方差和交叉熵根本就不同。均方差用于线性回归,输出是一堆连续性的y,损失函数是调整预测值y和真实值y的距离(L2距离或者欧几里得距离)。交叉熵是逻辑回归,输出是概率分布,反映预测概率和真实概率的差别。
过拟合的问题:
所谓过拟合,说白了就是训练的过于精致复杂了(下三图),导致换了其他的数据效果大打折扣。
解决过拟合的方法用的比较多的有: 1. 增加数据集 2. 正则化 3. dropout
增加数据集就不多解释了
正则化的本质就是如何让红箭头所指的变小一点,这里引入L1和L2(损失函数后加上惩罚系数)
上面L2公式可以看出,要让J(w)最小,不仅让损失最小,惩罚项也得降到最小。
L1不同的是惩罚项变成w的绝对值,求导时L1的变成1,L2变成w,在靠近0时,L1直接降到0,L2则缓慢下降。所以L1是种比较简单粗暴的方法,直接将不重要的特征或者说不在一个数量级的特征尽快剔除掉,这种只是对比较简单的线性回归有效果,L2则是缓慢削弱某种特征的影响,尽量压缩不至于为0,所以这就是为什么L2用的比较多了。
下图就很直观了:
Dropout: 简单理解就是每次训练时,随机舍去一部分节点不去学习。
基本上每个样本数据都不干净且包含了一些异常数据,过拟合的问题恰恰就是把这些异常数据当成规律来学习。但是异常数据的特点是数量非常少,且与主流样本数据出现概率相比要低很多,我们就是利用这个特性,通过每次模型中忽略的一些节点数据来学习,将小概率异常数据获得学习机会降低,这样异常数据对模型的影响就会小很多。比如 keep_prob = 0.8 表示20%的节点丢弃,让80%的节点参与学习。
Optimizer优化器:
可分为学习率不受梯度影响SGD和受梯度影响两大类Adam
SGD就是最基本的梯度下降,Momentum对SGD做了优化,在梯度方向发生改变时,能够降低参数更新速度,从而减少震荡;在梯度方向相同时,则加速参数更新。
自适应学习类的有很多:Adagrad,Adadelta,RMSprop,Adam
总结一下: SGD 是最普通的优化器, 也可以说没有加速效果, 而 Momentum 是 SGD 的改良版, 它加入了动量原则. 后面的 RMSprop 又是 Momentum 的升级版. 而 Adam 又是 RMSprop 的升级版.
评价指标:错误率,精度,准确率,召回率,F1衡量
- | - | 预测 | 预测 | - |
---|---|---|---|---|
- | - | 1 | 0 | 合计 |
实际 | 1 | True Positive(TP) | False Negative(FN) | 实际为正 |
实际 | 0 | False Positive(FP) | True Negative(FN) | 实际为负 |
合计 | - | 预测为正 | 预测为负 | 总体 |
TP: 真正类,实例是正类,被预测为正类
FN: 假负类, 实例是正类,被预测为负类,漏报
FP: 假正类, 实例是负类,被预测为正类,误报
TN: 真负类, 实例是负类,被预测为负类
记忆方法:第一个字母表示预测是否正确,第二个字母表示预测结果
(ACC)准确率:(TP+TN)/ (TP+TN+FP+FN)
有个问题:当样本正负不均衡时候,准确率反映不了真实情况。
精确率Precision:(预测为正且实际是正的)占(预测为正)的比例 Precision = TP / (TP + FP)
真正类率True Positive Rate(TPR), Recall(预测为正且实际是正的)占(实际为正)的比例 。
TPR = TP / (TP + FN) 也被称为灵敏度Sensitivity, 通俗解释为:正实例被正确预测的比例。
假正类率 False Positive Rate(FPR)(预测为正且实际是负的)占(实际为负)的比例
FPR = FP / (FP + TN) 也被称为特异度,等价于1-Specific,通俗理解为:负实例被误报的比例。
为了解决正负样本不均衡的问题,比如90%是正样本,10%是负样本,这样准确率是有水分的。但用TPR,FPR则不一样,TPR只关注90%正样本中有多少是被覆盖的,FPR只关注负样本中是多少是被错误覆盖的。这两者毫无关系。
F1的核心思想在于尽可能提高Precision和Recall的同时,也希望两者的差异尽可能的小
2/F = 1/P + 1/R F = 2PR / (P + R)
F1 公式实在两者之间找平衡点,F1 SCORE相当于P和R的综合评价指标
ROC,AUC曲线:
无论是上面提到的P,R,还是F1这些指标只能反映模型在某一方面的性能,ROC则可以解决。ROC X轴为假正类FPR(负实例被误报的比例),Y轴是TPR(正实例被正确预测的比例)。下图a,c为ROC曲线,b,d为PR曲线。当负样本的数量增加到原来的10倍后,分类器的结果可以明显的看出,ROC曲线基本保持原貌,而Precision-Recall曲线变化较大。
正因为ROC有个特点,当正负样本分布发生变化时,ROC曲线的形状能够保持不变,而P-R曲线的形状一般会发生较剧烈的变化。ROC阈值低时,会有更多预测为正的样本,TP,FP上升,TN,FN下降,TPR,FPR上升。ROC阈值高时,会有更多预测为负的样本,TP,FP下降,TN,FN上升,TPR,FPR下降。
AUC是ROC曲线下的面积大小,一般取值在0.5 - 1之间,AUC越大说明分类器越可能吧真正的样本排在前面,分类性能越好。AUC=1,把每个实例预测为正例,AUC=0.8非常不错,AUC=0.5瞎猜。