深度学习-吴恩达深度学习重点

吴恩达深度学习重点

改善深层神经网络

训练-开发-测试集划分

传统:100-1000-10000 70%/30% 训练/测试 60%/20%/20% 训练/开发(交叉验证)/测试 大数据:1000000 98%/1%/1% 训练/开发/测试 或者 99.5%/0.25%/0.25% 训练/开发/测试

如果训练集和开发/测试集的分布不同,也不太致命,最好保证开发集和测试集的分布是一致的,有时候只有开发集没有测试集也是可以的。

偏差与方差-Bias vs Variance

Optimal/Base Error理论最优值是机器学习不可能超过的上限,常用的近似方式就是以人类的能力为Optimal/Base Error.

如果Optimal/Base Error很小,并且训练集和开发集分布相同:

  • 高偏差高方差(偏差,方差近似):欠拟合-->更大的网络,更新网络结构,训练时间加长,
  • 高偏差高方差(偏差大,方差更大):欠拟合同时部分数据过拟合。这种情形在高维数据中会出现,即某些维度过拟合。
  • 低偏差高方差:过拟合-->更多数据,正则化,更新网络结构
  • 低偏差低方差:正好

正则化

L2:\(+\frac{\lambda}{2m}\sum_l||W^{[l]}||^2_F\)

L1:\(+\frac{\lambda}{m}\sum_l|W^{[l]}|\)

Dropout:每一轮训练中随机使一些点失效。不可与梯度验证合用。CV中几乎是默认选项。

数据扩增(Data augemntation):数据做些修改作为新数据(图片旋转、扭曲、图片剪裁、加噪声)

Early Stopping: 当损失函数不在随着迭代次数下降时停止训练,本质时减少训练次数。但是不利于正交化,降低损失函数和early stopping正则化是相悖的。

归一化输入

归一化输入可以使训练的速度更快。注意不要分别计算测试集和开发集的均值和方差,而是先统一归一化整体数据集,再划分训练集、开发集和测试集。

梯度消失和梯度爆炸

在很多层的神经网络中,参数可能非常大或者非常接近0,因为每一层乘参数都是指数增长/降低的一部分。很长一段时间以来,梯度消失和爆炸都是深度学习难以解决的问题。

一个部分解决的方案是合理的初始化参数

激活函数Relu-->np.random.randn(shape)*np.sqrt(2/n[l-1])

激活函数tanh-->np.random.randn(shape)*np.sqrt(1/n[l-1])(Xavier)

梯度检查

双边差计算近似梯度\(f'(\theta)\approx \frac{f(\theta+\epsilon)-f(\theta-\epsilon)}{2*\epsilon}\),其中\(\epsilon\)是一个很小的值,例如0.001.

注记:

  • 梯度检查只用于debug
  • 查看误差大的项尝试debug
  • 记住正则化也影响梯度检查
  • 不能和dropout一起用
  • 如果实在怕错,那么使用机器学习框架吧(tensorflow, keras, pytorch)

优化算法

mini-batch

\(X^{[l]\{t\}(s)}\):第\(l\)层,mini-batch中第\(t\)组中第\(s\)个样本。一般的 mini-batch 大小为 64 到 1024,考虑到电脑内存设置和使用的方式,如果mini-batch 大小是2的n次方,代码会运行地快一些。

指数加权平均

\(V_t=\beta×V_{t-1} + (1-\beta)×\theta_t, \beta=0.9,0.99\dotsb\),大概计算了\(1/(1-\beta)\)轮的平均数据。

但是指数加权平均在初始化的时候很不准确,需要偏差修正\[ V_t=\beta×V_{t-1} + (1-\beta)×\theta_t \\ V_t = V_t /(1-\beta^t) \]\(t\rightarrow \infty时, 1-\beta^t\rightarrow 1\)

Momentum 动量法梯度下降

实际上就是指数加权平均/移动平均的梯度下降: \[ dV_t = \beta×dV_{t-1} + (1-\beta) dW_t \\ (偏差修正也可以不要)\\ dV_t = dV_t/(1-\beta^t) \\ W_t = W_t - \alpha* dV_t\\ 通常\beta = 0.9 \] 其原理在于使用移动平均,抵消了振荡。 momentum_vs_vanilla.png
动量法效果--红色为动量法

RMSprop均方根法

对于上面的这个椭圆形的抛物面(图中的椭圆代表等高线),沿着横轴收敛速度是最快的,所以我们希望在横轴(假设记为w1)方向步长大一些,在纵轴(假设记为w2)方向步长小一些。这时候可以通过RMSprop实现,分维度来看,迭代更新公式如下: \[ \begin{cases} s_1=\beta_1 s_1+(1-\beta_1)dw_1^2 \\ s_2=\beta_2 s_2+(1-\beta_2)dw_2^2 \end{cases}\\ \begin{cases} w_1=w_1-\alpha \frac{dw_1}{\sqrt{s_1+\epsilon}} \\ w_2=w_2-\alpha \frac{dw_2}{\sqrt{s_2+\epsilon}} \end{cases} \] 观察上面的公式可以看到,\(s_i\)是对梯度的平方做了一次平滑。在更新\(w_i\)时,先用梯度除以\(\sqrt{s_i+\epsilon}\),相当于对梯度做了一次归一化。如果某个方向上梯度震荡很大,应该减小其步长;而震荡大,则这个方向的\(s_i\)也较大,除完之后,归一化的梯度就小了;如果某个方向上梯度震荡很小,应该增大其步长;而震荡小,则这个方向的\(s_i\)也较小,归一化的梯度就大了。因此,通过RMSprop,我们可以调整不同维度上的步长,加快收敛速度。把上式合并后,RMSprop迭代更新公式如下: \[ \begin{cases} s=\beta s+(1-\beta)dw^2 \\ w=w-\alpha\frac{dw}{\sqrt{s+\epsilon}} \end{cases} \] 注意,这里的\(s,w\)都是多维向量。\(β\)的典型值是0.999。公式中还有一个\(ϵ\),这是一个很小的数,是为了防止分母为0,典型值是\(10^{−8}\)

Adam

Adam = Momentum+RMSprop \[ \begin{cases} v=\beta_1 v+(1-\beta_1)dw \\ s=\beta_2 s+(1-\beta_2)dw^2 \\ w=w-\alpha\frac{v}{\sqrt{s+\epsilon}} \end{cases} \] 典型值:\(β_1=0.9,β_2=0.999,ϵ=10^{−8}\)。Adam算法相当于先把原始梯度做一个指数加权平均,再做一次归一化处理,然后再更新梯度值。

其他新算法还有AdaMax,Nadam=Nag+Adam。

学习率

PS:1 epoch 代表每遍历所有训练数据一次,mini-batch中,\(1 epoch = M/mini-batch-size\)

几种常见学习率衰减法: \[ \begin{aligned} &\alpha =\alpha_0*\frac{1}{1+decay\_rate*epoch\_num}\\ &\alpha =\alpha_0*decay\_rate^{epoch\_num}\\ &\alpha =\alpha_0* \frac{k}{\sqrt{epoch\_num}} \end{aligned} \]

有时也会用一个离散下降的学习率,也就是某个步骤有某个学习率,一会之后,学习率减少了一半,一会儿减少一半,一会儿又一半,这就是离散下降(discrete stair cease)的意思。

局部最优点和鞍点

一个具有高维度空间的函数,如果梯度为 0,那么在每个方向,它可能是凸函数,也可能是凹函数。如果你在 2 万维空间中,那么想要得到局部最优,所有的 2 万个方向都需要是这样,但发生的机率也许很小,也许是\(2^{−20000}\),你更有可能遇到有些方向的曲线会这样向上弯曲,另一些方向曲线向下弯,而不是所有的都向上弯曲,因此在高维度空间,你更可能碰到鞍点,而不会碰到局部最优。

所以我们从深度学习历史中学到的一课就是,我们对低维度空间的大部分直觉,比如你可以画出上面的图,并不能应用到高维度空间中。

超参数调试、Batch正则化和Softmax回归

超参数调参经验

随机一点,从粗到细,有重点

合适的范围:线性,log,1-线性+log等等

Batch Norm

我们知道对输入进行归一化可以提升模型训练的速度,假设我们对每一个隐藏层进行归一化,是否能够更快的提升速度呢?答案是可以的,这就是Batch Normalization。在深层网络训练的过程中,由于网络中参数变化而引起内部结点数据分布发生变化的这一过程被称作Internal Covariate Shift。Internal Covariate Shift会导致上层网络需要不停调整来适应输入数据分布的变化,导致网络学习速度的降低,同时网络的训练过程容易陷入梯度饱和区,减缓网络收敛速度。

因此,我们在非线性函数之前把第\(l\)层的数据先归一化,即 \[ \begin{aligned} &Z^{[l]}=W^{[l]}A^{[l-1]}+b^{[l]}\\ &\mu=\frac{1}{m}\sum_{i=1}^m Z^{[l](i)}\\ &\sigma=\frac{1}{m}\sum_{i=1}^m (Z^{[l](i)}-\mu)^2\\ &\hat Z^{[l]}=\frac{Z^{[l]}-\mu}{\sqrt{\sigma^2+\epsilon}} \end{aligned} \] 需要指出的是BN算法一般针对mini-batch梯度下降,因此\(\mu,\sigma^2\)的计算量不会很大。\(\epsilon=10^{-8}\)为了不让分母为0。

Normalization操作我们虽然缓解了ICS问题,让每一层网络的输入数据分布都变得稳定,但却导致了数据表达能力的缺失。也就是我们通过变换操作改变了原有数据的信息表达(representation ability of the network),使得底层网络学习到的参数信息丢失。另一方面,通过让每一层的输入分布均值为0,方差为1,会使得输入在经过sigmoid或tanh激活函数时,容易陷入非线性激活函数的线性区域。

因此,BN又引入了两个可学习(learnable)的参数\(\gamma\)\(\beta\)。这两个参数的引入是为了恢复数据本身的表达能力,对规范化后的数据进行线性变换,即 \[ \tilde Z^{[l]}=\gamma \hat Z^{[l]}+\beta\\ A^{[l]}=g(\tilde Z^{[l]}) \] 通过上面的步骤,我们就在一定程度上保证了输入数据的表达能力。补充: 在进行normalization的过程中,由于我们的规范化操作会对减去均值,因此,偏置项 [公式] 可以被忽略掉或可以被置为0。

在测试数据中,使用mini-batch的均值和方差的移动平均作为测试数据的均值和方差。

Softmax

Softmax函数用于多分类问题,定义方式如下: \[ A_i=\frac{e^{Z_i}}{\sum_j e^{Z_j}} \] 使用这种定义一是因为其满足概率条件和为1,且特征对概率的影响是乘性的;同时方便交叉熵损失函数计算。二是反向传播求导方便。

softmax VS k个二元分类器

如果你在开发一个音乐分类的应用,需要对k种类型的音乐进行识别,那么是选择使用 softmax 分类器呢,还是使用 logistic 回归算法建立 k 个独立的二元分类器呢?

这一选择取决于你的类别之间是否互斥,例如,如果你有四个类别的音乐,分别为:古典音乐、乡村音乐、摇滚乐和爵士乐,那么你可以假设每个训练样本只会被打上一个标签(即:一首歌只能属于这四种音乐类型的其中一种),此时你应该使用类别数 k = 4 的softmax回归。(如果在你的数据集中,有的歌曲不属于以上四类的其中任何一类,那么你可以添加一个“其他类”,并将类别数 k 设为5。)

如果你的四个类别如下:人声音乐、舞曲、影视原声、流行歌曲,那么这些类别之间并不是互斥的。例如:一首歌曲可以来源于影视原声,同时也包含人声 。这种情况下,使用4个二分类的 logistic 回归分类器更为合适。这样,对于每个新的音乐作品 ,我们的算法可以分别判断它是否属于各个类别。

现在我们来看一个计算视觉领域的例子,你的任务是将图像分到三个不同类别中。(i) 假设这三个类别分别是:室内场景、户外城区场景、户外荒野场景。你会使用sofmax回归还是 3个logistic 回归分类器呢? (ii) 现在假设这三个类别分别是室内场景、黑白图片、包含人物的图片,你又会选择 softmax 回归还是多个 logistic 回归分类器呢?

在第一个例子中,三个类别是互斥的,因此更适于选择softmax回归分类器 。而在第二个例子中,建立三个独立的 logistic回归分类器更加合适。

机器学习策略

单一数字评估指标

  • TP:实际为正,预测为正的样本数量
  • FP:实际为负,预测为正的样本数量
  • FN:实际为正,预测为负的样本数量
  • TN:实际为负,预测为负的样本数量
  • TP+FP:表示所有预测为正的样本数量
  • TN+FN:表示所有预测为负的样本数量
  • TP+FN:表示实际为正的样本数量
  • TN+FP:表示实际为负的样本数量
混淆矩阵
混淆矩阵

准确率(accuracy):准确率是分类正确的样本占总样本个数,即 \[ accuracy=\frac{TP+TN}{TP+FP+FN+TN} \] 准确率是分类问题中最简单最直观的评价指标,但存在明显的缺陷。比如正负样本的比例不均衡。假设样本中正样本占 95%,负样本占5%,那分类器只需要一直预测为正,就可以得到95% 的准确率,但其实际性能是非常低下的。

精确率(precision):精确率指模型预测为正的样本中实际也为正的样本占被预测为正的样本的比例。计算公式为 \[ precision=\frac{TP}{TP+FP} \] 细分:Macro、Micro、weighted

召回率(recall):召回率指实际为正的样本中,预测也为正的样本占实际为正的样本的比例。计算公式为 \[ recall = \frac{TP}{TP+FN} \]

F1-score:精确率和召回率的加权平均值,计算公式为 \[ F1 = \frac{2*precision*recall}{precision+recall} \] Precision 体现了模型对负样本的区分能力,Precision 越高,模型对负样本的区分能力越强。

Recall 体现了模型对正样本的识别能力,Recall 越高,模型对正样本的识别能力越强。

F1-score 是两者的综合,F1-score 越高,说明模型越稳健。

优化指标和满足指标

优化目标:最小化或最大化

限制目标:大于,小于,等于

人的表现

理论最优:贝叶斯最优错误率(Bayes optimal error)

很多场景下人的性能接近贝叶斯最优错误率,同时很多数据是人标注的。而机器学习接近或超过人的能力后,很难在迅速提高。

可避免的偏差:训练集上的错误率和理论(或人)的错误率之间的差距。

对人类水平有大概的估计可以让你做出对贝叶斯错误率的估计,这样可以让你更快地作出决定是否应该专注于减少算法的偏差,或者减少算法的方差。这个决策技巧通常很有效,直到你的系统性能开始超越人类,那么你对贝叶斯错误率的估计就不再准确了,但这些技巧还是可以帮你做出明确的决定。

人工误差分析(适用于机器学习还没到人的水平)

训练集标记错误:随机错误问题大不;系统性错误会有影响。

开发集标记错误:如果这些标记错误严重影响了你在开发集上评估算法的能力,那么就应该去花时间修正错误的标签。但是,如果它们没有严重影响到你用开发集评估成本偏差的能力,那么可能就不应该花宝贵的时间去处理。但是需要指出,开发集和测试集需要一起标记修正错误。

训练/开发/测试集划分:有大量相关数据(辅助训练)和核心数据的情形下,把核心数据放在开发/测试集,而不是训练集,即使这样会导致训练集和开发集分布不太一致也无所谓。

数据分布不匹配时的偏差与方差的分析:如果训练数据和开发数据分布不同,那么训练错误率和开发集错误率之间就不仅仅是方差问题,有可能本来开发集的数据就更难处理。为了区分时方差还是数据差异,就需要构造一个和训练集同分布的训练开发集(例如random shuffle后再划分),来查看方差问题。整体过程就如下:

optimal<-可避免偏差->train set<-方差->train-dev set<-数据不匹配(差距正负都有可能)>dev set<-开发集过拟合->test set

数据不匹配处理方式:人工审阅训练集和开发集查找二者差别==>寻找更接近开发集的数据/加工训练集数据使其更与开发集更相似

迁移学习:串行

应用场景:类似问题之间,从数据量很多的问题迁移到数据量相对小的问题,低层次特征有相似性。

足够多新数据,预训练(pre-training)==> 微调(fine tuning)。

小数据集,只需要重新训练最后几层网络。因为,原理上来说很多低层特征是类似的。

多任务学习:并行

多任务学习能让你训练一个神经网络来执行许多任务。

应用场景:任务间共享相似的低层特征;每个任务需要的数据量相似,且任务间有一定对等性(这个准则不绝对);可以训练一个足够大的神经网络,足以做好所有的工作。

Softmax(判断互斥) vs 多个神经网络(判断不互斥) vs 一个神经网络多个判断(不互斥)

端到端学习

端到端:忽略中间处理步骤,把深度神经网络作为一个黑盒子。

端到端深度学习的挑战之一是,你可能需要大量数据才能让系统表现良好。

卷积神经网络CNN

步骤:图像-->卷积-->(非线性函数)-->池化-->全连接-->结果

经典神经网络

PS:非线性函数在卷积conv之后

  1. Lenet5(conv的参数,padding等可以根据实际输入调整,关键是结构)
  • conv 5*5*1*6 valid s=1
  • pooling 2*2 same s=2
  • conv 5*5*6*16 valid s=1
  • pooling: 2*2 same s=2
  • flatten and FC
  1. AlexNet
  • input :\(227*227*3\)()
  • conv: \(11*11*3*96, s=4--> 55*55*96\)
  • maxpool: \(3*3, s=2 ,-->27*27*96\)
  • conv: \(5*5*96*256, s=1, padding=same,--> 27*27*256\)
  • maxpool: \(3*3,s=2, -->13*13*256\)
  • conv: \(3*3*256*384,s=1, padding=same\) 两次 \(-->13*13*385\)
  • conv: \(3*3*384*256, s=1, padding=same-->13*13*256\)
  • maxpool: \(3*3,s=2-->6*6*256=9216\)
  • flatten: \(9216 --> FC(4096) --> FC(4096) -->softmax(1000)\)
  1. VGG16(conv: 3*3, s=1 ,same; maxpool: 2*2, s=2)
  • conv, c=64 两次
  • maxpool
  • conv, c=128 两次
  • maxpool
  • conv, c=256 三次
  • maxpool
  • conv, c=512 三次
  • maxpool
  • conv, c=512 三次
  • maxpool
  • FC input-->4096-->4096-->1000-->softmax
  • VGG16:16个卷积和全连接层,约1.38亿参数

循环神经网络RNN

RNN很适合处理序列数据/模型。\(x^{\lt t\gt}-->y^{\lt t\gt}\) \[ x^{\lt t\gt (i)}:第i个样本序列第t个序列项\\ T_x^{i}:样本i的长度 \]

基本结构

RNN_desc

RNN_desc

如果把上面左上角有W的那个带箭头的圈(或者大图中左边部分)去掉,它就变成了最普通的全连接神经网络。x是一个向量,它表示输入层的值(这里面没有画出来表示神经元节点的圆圈);s是一个向量,它表示隐藏层的值(这里隐藏层面画了一个节点,你也可以想象这一层其实是多个节点,节点数与向量s的维度相同);U是输入层到隐藏层的权重矩阵;o也是一个向量,它表示输出层的值;V是隐藏层到输出层的权重矩阵。那么,现在我们来看看W是什么。循环神经网络的隐藏层的值s不仅仅取决于当前这次的输入x,还取决于上一次隐藏层的值s。权重矩阵 W就是隐藏层上一次的值作为这一次的输入的权重。

RNN只能使用之前输入的信息,而忽略之后的输入,因此有人提出BRNN,双向RNN来利用当前点以后的输入信息。

\[ \begin{aligned} \mathrm{o}_t&=g(V\mathrm{s}_t+b_2)\qquad\qquad\quad(式1)\\ \mathrm{s}_t&=f(U\mathrm{x}_t+W\mathrm{s}_{t-1}+b_1)\qquad(式2)\\ \end{aligned} \] 式1是输出层的计算公式,输出层是一个全连接层。V是输出层的权重矩阵,g是激活函数。式2是隐藏层的计算公式,它是循环层。U是输入x的权重矩阵,W是上一次的值\(s_{t-1}\)作为这一次的输入的权重矩阵,f是激活函数。一般激活函数使用tanh或relu。

GRU与LSTM

记住一些信息,形成长依赖。

生成对抗网络GAN

强化学习