# DL2

课程早就过了一遍，但是写出来感觉没啥价值于，只是徒增一份网络垃圾。

重新编排了一下。我想了想，目的在于提炼重点吧，这样看过课或者没看过课都能从中了解到这门课到底讲了哪些东西。

\[toc]

## 第一周-深度学习的实践层面

第一周，我们讲了如何配置训练集，验证集和测试集，如何分析偏差和方差，如何处理高偏差或高方差以及高偏差和高方差并存的问题，如何在神经网络中应用不同形式的正则化，如 𝐿2 正则化和 dropout，还有加快神经网络训练速度的技巧，最后是梯度检验。

### 1.1 训练，验证，测试集

#### 数据为王

调参是一种经验，我们所把握住的只有数据。

在机器学习中，我们通常将样本分成**训练集，验证集和测试集**三部分，

* **验证集**的目的就是验证不同的算法，检验哪种算法更有效。
* **测试集**的主要目的是正确评估分类器的性能。

**数据集规模相对较小**

适用传统的划分比例，比如：

* 可以按照 70%的验证集和 30%测试集。
* 或者 60%训练，20%验证和 20%测试集来划分。

**数据集较大**

即百万级别，这样验证集和测试集占数据的总量比例会趋向于变得更小。验证集和测试集要小于数据总量的 20% 或 10%。

**验证集当成训练集**

在实际应用中，如果只有一个训练集和一个验证集，而没有独立的测试集，遇到这种情况，**训练集还被人们称为训练集，而验证集则被称为测试集**。

实际上，如果你不需要无偏评估算法性能，那么这样是可以的。

### 1.2 偏差，方差

#### 什么是偏差，方差

理解偏差和方差的两个关键数据是**训练集误差**（Train set error）和**验证集误差**（Dev set error）。

假定训练集误差是 1%，为了方便论证，假定验证集误差是 11%，可以看出训练集设置得非常好，而验证集设置相对较差，我们可能*过度拟合了训练集*，在某种程度上，验证集并没有充分利用交叉验证集的作用，像这种情况，我们称之为**高方差**。~~（方差 variance，为啥这样起名，理解为是机器他们内部的模型或者算法出现了问题，起名叫方差）~~

假设训练集误差是 15%，验证集误差是 16%，假设该案例中人的错误率几乎为 0%，人们浏览这些图片，分辨出是不是猫。算法并没有在训练集中得到很好训练，如果训练数据的*拟合度不高*，就是数据欠拟合，就可以说这种算法偏差比较高,我们称之为**高偏差**。~~（偏差 bias，为啥这样起名，理解为机器内部模型和算法没问题，但是和外部人类相比，是有问题的，起名叫偏差）~~

*一个好的模型的偏差和方差应该都很低。*

直观上来看。

* 高方差是过拟合的结果
* 高偏差是欠拟合的结果

#### 高方差和高偏差可以同时存在

首先说说过拟合，欠拟合，高偏差，高方差有什么区别？

过拟合会导致高方差，

欠拟合会导致高偏差。

我的理解是不能画上等号的原因是，过拟合会导致高方差现象，而不是过拟合就是高方差本身。

![训练集误差很高，结果测试集误差更高，这就是高偏差和高方差并存](https://files.mdnice.com/user/10328/adb7a8d2-66f6-4077-b93b-7ce9df40795a.png)

### 1.3 机器学习基础

紧接上节，我们的目的是为了低偏差，低方差。~~其实，就是要确保模型的鲁棒性。你要问我，为什么要创造这两个名词，我只能告诉你，这就是科学吧。~~

**先检查偏差**

我们应该先检查是否存在偏差，即欠拟合，意思可以理解为，如果连我们创造出的这个模型，连我们在小样本上测试都不合格达标，那更别说在实际情况中了。

**再检查方差**

往往我们还是可以找到在我们的小样本中合适的模型或者算法。~~实在找不到，我们就用多元函数拟合么，非常复杂的那种，x 的 1000 次幂的那种，可想而知，这种仅在我们的训练集中可用。~~ 偏差我们一定可以降低，那方差呢，如何确保我们不过拟合？

**正则化可以减少方差，即减少过拟合。**

### 1.4 正则化

**除了正则化，我们还可以准备更多的数据**

解决过拟合的两个方法，一个是正则化，另一个是准备更多数据。

~~那为什么我们要研究正则化呢？ 我们想想，数据集要能大到张罗所有的实际情况，直接过拟合呗，我们也无需考虑方差问题了。~~

**什么是正则化**

*正则化很简单，其实就是在损失函数中增加约束(惩罚)*。防止机器他学过头了。增加约束的不同，我们有了 L1 正则化，L2 正则化。

用逻辑回归举例说明正则化： 对于逻辑回归只有两个参数 w，b。只需要添加参数 $\lambda$。

$$
J(w,b)  = \frac{1}{m}\sum\_{i=1}^m L\left(\hat{y}^{(i)}, y^{(i)}\right)

* \frac{\lambda}{2m}\omega^2
  $$

> - 为什么只正则化 w，而不加上 b 呢，这是因为 w 是一个高维参数矢量，已经可以表达高偏差的问题。
>
>   加上 b 则可有可无了。
> - 为什么在损失函数上加正则化项？损失函数又叫代价函数，是用来评判一个模型的好坏的。如果模型的参数维度过高，必定有过拟合的风险

此上，我们称为 L2 正则化。

至于 L1 正则化，则是加上 $\sum^{n*x}*{j=1}\omega$。

如果用 L1 正则化，w 最终会稀疏的， ![image](https://files.mdnice.com/user/10328/19379d08-2978-4362-b21d-9c524b5ae4b4.png)

对于很多原函数等高曲线，和某个菱形相交的时候及其容易相交在坐标轴（比如上图），也就是说最终的结果，解的某些维度及其容易是 0，这也就是我们所说的 L1 更容易得到稀疏解（解向量中 0 比较多）的原因。

*(l1 相比于 l2 为什么容易获得稀疏解？ - 知乎* <https://www.zhihu.com/question/37096933>*)*

也就是说 𝑤 向量中有很多 0，有人说这样有利于压缩模型，因为集合中参数均为 0，存储模型所占用的内存更少。实际上，虽然 𝐿1 正则化使模型变得稀疏，却没有降低太多存储内存，所以我认为这并不是 𝐿1 正则化的目的，至少不是为了压缩模型，人们在训练网络时，越来越倾向于使用 𝐿2 正则化。

* 在编写代码中，我们通常用 lamdb，而不是全称，避免与 python 中保留字冲突。

，因此 𝐿2 范数正则化也被称为“权重衰减”，

#### 补充-关于范数

![image](https://gitee.com/stevenlyf/picture/raw/master/img/ddafcdc7-5947-4d7a-b8d9-43ab5ead5972.png) 范数的本质是距离，存在的意义是为了实现比较。

比如，在一维实数集合中，我们随便取两个点 4 和 9，我们知道 9 比 4 大，但是到了二维实数空间中，取两个点（1，1）和（0，3），这个时候我们就没办法比较它们之间的大小，因为它们不是可以比较的实数，于是我们引入范数这个概念，把我们的（1，1）和（0，3）通过范数分别映射到实数 $\sqrt{2}$ 和 3 ，这样我们就比较这两个点了。

所以你可以看到，范数它其实是一个函数，它把不能比较的向量转换成可以比较的实数。

链接：<https://www.zhihu.com/question/21868680/answer/136376374> 。

### 1.5 为什么正则化有利于预防过拟合

简单来说，权重衰减会导致网络虽然很深，但是当权重矩阵设置为接近 0 时，网络衰减成很小的网络，如同一个逻辑回归单元。

这是极限的情况。

可以想象会有一个中间态，对于网络在欠拟合和过拟合之间。可以消除高方差的影响。

### 1.6 dropout 正则化

实际上可以理解为将网络中个别节点失活。~~却是这种方法很怪异。~~

![image](https://gitee.com/stevenlyf/picture/raw/master/img/c509b988-5bbf-451e-95f8-4b2adb3743ef.png)

1、inverted dropout（反向随机失活） 这里举例某一层实施 dropout。 d3 = np.random.rand(a3.shape\[0],a3.shape\[1])

然后*看他是否小于某数*，我们称之为 keep-prob。 如果 keep-prob 为 0.8，即消除任意一个隐藏单元的概率为 0.2。

随机生成的为 $d^{\[3]}$，即上面的代码 d3。

接下来是激活函数 $a^{\[3]}$

尤其重要的是我们要用/keep-prob 修正一下 期望值。

### 1.7 理解 dropout

Dropout 可以随机删除网络中的神经单元，他为什么可以通过正则化发挥如此大的作用呢？

直观上理解：不要依赖于任何一个特征，因为该单元的输入可能随时被清除，因此该单元通过这种方式传播下去，并为单元的四个输入增加一点权重，通过传播所有权重，dropout 将产生收缩权重的平方范数的效果，和之前讲的 𝐿2 正则化类似；实施 dropout 的结果它会压缩权重，并完成一些预防过拟合的外层正则化；𝐿2 对不同权重的衰减是不同的，它取决于 激活函数倍增的大小。

总结一下，dropout 的功能类似于 𝐿2 正则化，与 𝐿2 正则化不同的是应用方式不同会带来 一点点小变化，甚至更适用于不同的输入范围。

对于每一层，权重矩阵多且大的可以设置 keep-out 为 0.5，小权重矩阵可以设置为 0.7。

有点像在处理 𝐿2 正则化的正则化参数 𝜆。

**补充**

dropout 在 cv 中使用很广泛，因为像素过多。

dropout 的缺点就是，难以进行复查，或者绘制图片，因为每次都会有不同。

### 1.8 其他正则化方法

其他减少神经网络过拟合的方法。

**一、数据扩增**

增大数据集，从而防止过拟合。

通过随意*翻转*和*裁剪*图片，我们可以增大数据集，额外生成假训练数据。

和全新的，独立的猫咪图片数据相比，这些额外的假的数据无法包含像全新数据那么多的信息，但我们这么做基本没有花费，代价几乎为零，除了一些对抗性代价。以这种方式扩增算法数据，进而正则化数据集，减少过拟合比较廉价。

**二、early stopping**

及时停止训练防止过拟合。

![随着时间推进，在训练集时误差减小，在验证集则会反弹](https://gitee.com/stevenlyf/picture/raw/master/img/c509b988-5bbf-451e-95f8-4b2adb3743ef.png)

机器学习过程包括几个步骤，其中一步是选择一个算法来优化代价函数 𝐽，我们有很多种工具来解决这个问题，如梯度下降，后面我会介绍其它算法，例如 Momentum， RMSprop 和 Adam 等等，但是优化代价函数 𝐽 之后，我也不想发生过拟合，也有一些工具可以解决该问题，比如正则化，扩增数据等等。

### 1.9 归一化输入

训练神经网络，其中一个加速训练的方法就是归一化输入。

不解释，输入的数据进行归一化，或者叫做规范化。

![归一化后梯度下降更方便](https://gitee.com/stevenlyf/picture/raw/master/img/c509b988-5bbf-451e-95f8-4b2adb3743ef.png)

### 1.10 梯度消失/梯度爆炸

~~我感觉吴恩达老师讲的很生动形象，但不是很具有说服力。~~ 拿线性网络来想象， 第一张图的每一层权重是 1.5 倍的单位矩阵，每一层累积下来，以指数倍爆炸增长。 第二张图同理，梯度消失。

![会在多层中产生梯度爆炸](https://gitee.com/stevenlyf/picture/raw/master/img/c509b988-5bbf-451e-95f8-4b2adb3743ef.png)

![会产生梯度消失](https://gitee.com/stevenlyf/picture/raw/master/img/03b4a531-f5c6-4982-a374-a9f7a5f5ad87.png)

### 1.11 神经网络权重的初始化

神经网络权重的初始化也是很讲究的。

$z=w\_1x\_1+w\_2x\_2+....+w\_nx\_n$ 暂时忽略 b，为了预防 z 值过大或过小，你可以看到 𝑛 越大，你希望 $w\_i$ 越小，因为 z 是 $w\_ix\_i$ 的和，

最简单的办法，就是设置 $w\_i=\frac{1}{n}$

实际上，我们这样初始化权重：

w = np.random.randn(shape)\*np.sqrt$(\frac{1}{n^{\[l-1]}})$

* 如果使用的是 Rule 激活函数，设置为 $\frac{2}{n}$ 会更好。
* 如果是 tanh 函数，则使用 $\sqrt{\frac{1}{n^{l-1}}}$

实际上，我认为所有这些公式只是给你一个起点，它们给出初始化权重矩阵的方差的默认值， 如果你想添加方差， 方差参数则是另一个你需要调整的超级参数， 可以*给公式添加一个乘数参数*，调优作为超级参数激增一份子的乘子参数。有时调优该超级参数效果一般，这并不是我想调优的首要超级参数，但我发现调优过程中产生的问题，虽然调优该参数能起到一定作用，但考虑到相比调优，其它超级参数的重要性，我通常把它的优先级放得比较低。

### 1.12 梯度的数值逼近（跳过）

这节课实际上说的是用数值逼近的方法简便计算导数的方法。

我们讲了如何使用*双边误差*来判断别人给你的函数 𝑔(𝜃)，是否正确实现了函数 𝑓 的偏导，现在我们可以使用这个方法来检验反向传播是否得以正确实施，如果不正确，它可能有 bug 需要你来解决。

### 1.13 梯度检验（跳过）

在实施 backprop 时，有一个测试叫做梯度检验，它的作用是确保 backprop 正确实施。 因为有时候，你虽然写下了这些方程式，却不能 100%确定，执行 backprop 的所有细节都是正确的。

![image](https://gitee.com/stevenlyf/picture/raw/master/img/742c9594-53b6-40db-af54-e4fd6d1fa578.png)

回顾这一周，我们讲了

* 如何配置训练集，验证集和测试集，
* 如何分析偏差和方差，如何处理高偏差或高方差以及高偏差和高方 差并存的问题，
* 如何在神经网络中应用不同形式的正则化，如 𝐿2 正则化和 dropout
* 加快神经网络训练速度的技巧
* 梯度检验。

## 第二周-优化算法

本周是学习如何加快神经网络的学习速度。

### 2.1 Mini-batch 梯度下降

**为什么要 Mini-batch**

之前我们将样本全部向量化放入训练中，无疑向量化是加速的，但是如果数据量过大，一步一步的迭代训练将会是极其耗费时间的，因此，我们可以采用小批量训练的方式，加速 ⏩ 训练。

比如 500 万数据集中，分割成 1000 个样本的小的子集训练。

**符号表示**

接下来介绍新的符号

* $X^{{1}}$ 即分割后的一个小的训练子集。
* $Y^{{1}}$

使用 mini-batch 梯度下降法训练样本的一步，我写下的代码也可被称为进行“一代” （ epoch）的训练。一代这个词意味着只是一次遍历了训练集。

使用 batch 梯度下降法，一次遍历训练集只能让你做一个梯度下降，使用 mini-batch 梯度下降法，一次遍历训练集，能让你做 5000 个梯度下降。当然正常来说你想要多次遍历训练集，还需要为另一个 while 循环设置另一个 for 循环。所以你可以一直处理遍历训练集， 直到最后你能收敛到一个合适的精度。

### 2.2 理解 Mini-batch 梯度下降

![左图是一次性训练样本，每次都会迭代下降；右图batch训练则在局部有波动](https://gitee.com/stevenlyf/picture/raw/master/img/88e0c0aa-908e-4dba-a872-9a191918cb3a.png)

样本数目较大的话，一般的 mini-batch 大小为 64 到 512，考虑到电脑内存设置和使用的方式，如果 minibatch 大小是 2 的 𝑛 次方，代码会运行地快一些，**64 到 512 的 mini-batch 比较常见。**

### 2.3 指数加权平均数

**引出指数加权平均**

![如何拟合这些数据](https://gitee.com/stevenlyf/picture/raw/master/img/73b4834a-7087-4439-86e1-ac6016fea8da.png)

![指数平均公式](https://gitee.com/stevenlyf/picture/raw/master/img/4a8e7d8d-229c-458a-af3a-15646a6577f8.png)

我们将 0.9 普遍化 即 $v*t = \beta v*{t-1} + (1-\beta)) \theta\_t$

**进一步理解指数加权平均**

将连续几天的平均一下 $1/(1-\beta)$

比如 0.98，是 1(1-0.98)=50

![绿线](https://gitee.com/stevenlyf/picture/raw/master/img/32955610-212b-4ce0-bad8-a395a0f18d80.png)

因为当 𝛽 = 0.98，相当于给前一天的值加了太多权重，只有 0.02 的权重给了当日的值。

$\beta$ 为 0.5 时 ![黄线](https://gitee.com/stevenlyf/picture/raw/master/img/a17eeb05-73e6-4ab1-bb58-f12f9417b4d5.png)

### 2.4 理解指数加权平均数

$v*t = \beta v*{t-1} + (1-\beta)) \theta\_t$ ![image](https://gitee.com/stevenlyf/picture/raw/master/img/a17eeb05-73e6-4ab1-bb58-f12f9417b4d5.png)

![image](https://gitee.com/stevenlyf/picture/raw/master/img/7c6f8b4c-cf85-411c-8dca-a283bf09ea6e.png)

### 2.5 指数加权平均的偏差修正

**为什么需要偏差修正**

由于第一天计算时初始值 v0=0，会产生问题。比如，第一天 40 度，而 v0=0，因此只有 $（1-\beta）\theta\_t$

**如何修正偏差**

因此初期时我们不使用 $v\_t$，而是使用 $\frac{v\_t}{1-\beta^t}$。

**补充**

为什么后期，我们不使用偏差修正，因为到后面，前期的数值衰减到几乎为 0，没有影响，因此，可能大部分人都会硬生生熬过最初阶段，为了拿到后期数据。

### 2.6 动量梯度下降法 Momentum

**引出 Momentum**

梯度下降还是不够快，我们需要优化他，最终还是从更新权重时出发。

![莫烦举例，相当于把一个喝醉酒的人走了山路，依靠惯性总会减小之字形摆动](https://gitee.com/stevenlyf/picture/raw/master/img/a27d1a0e-ce7a-4ec0-bf9d-00f0b846085f.jpg)

从指数平均的角度，其实 Momentum 就是求了梯度的指数平均。 ![image](https://gitee.com/stevenlyf/picture/raw/master/img/2fb131e6-ec1c-4b6c-9897-d64ed9b932c1.png) 看这张图会发现，梯度下降时波动过大。这与学习率有关，但是我们希望在横轴上学习率增加加快，而纵轴上学习率减小

我们将 dw，db 这样处理 $$v\_{db} = \beta v\_{db} + (1-\beta)db$$

然后再重新赋值权重 $W:= W - av\_{dw}$

![每个符号的含义解释](https://gitee.com/stevenlyf/picture/raw/master/img/0f83131b-ab3b-4398-9a02-93a33b021955.png)

![$\beta$ 为0.9时比较合适](https://gitee.com/stevenlyf/picture/raw/master/img/0f83131b-ab3b-4398-9a02-93a33b021955.png)

**注意**

注意，有的文献中可能会将 $（1-\beta）$ 删去，但这并不会影响最终结果，而只是学习率的最佳值有变化。

### 2.7 RMSprop 均方根

root mean square prop 算法

![莫烦解释，给一个喝醉的人穿草鞋，让他走路脚疼，从而逼他直走](https://files.mdnice.com/user/10328/b71ef066-6691-49e4-a42a-04625945ad37.jpg)

$$S\_{dw} = \beta S\_{dw} + (1 - \beta) dW^2$$

$$S\_{db} = \beta S\_{db} + (1-\beta) db^2$$

更新权重时，这样：

$$W:=W - \alpha \frac{dW}{\sqrt{S\_{dw}}}$$

$$b:=b - \alpha \frac{db}{\sqrt{S\_{db}}}$$

### 2.8 Adam 优化算法

Adaptive Moment Estimation，即把上节和上上节算法结合一起。

$$
\begin{align}
v\_dw = 0 \\
S\_dw = 0 \\
v\_db = 0 \\
S\_db = 0 \\
\end{align}
$$

$$
\begin{align}
v\_{dw} =\beta\_1 v\_{dw} + (1-\beta\_1) dw \\
v\_{db} =\beta\_1 v\_{db} + (1-\beta\_1) db \\
S\_{dw} = \beta\_2 S\_{dw} + (1 - \beta\_2) (dw)^2 \\
S\_{db} = \beta\_2 S\_{db} + (1 - \beta\_2) (db)^2 \\
\end{align}
$$

相当于 Momentum 更新了超参数 $\beta\_1$，RMSprop 更新了超参数 $\beta\_2$

偏差修正

$$
\begin{align}
v\_{dw}^{corrected} = \frac{v\_{dw}}{1-\beta\_1^t} \\
v\_{db}^{corrected} = \frac{v\_{db}}{1-\beta\_1^t} \\
S\_{dw}^{corrected} = \frac{S\_{dw}}{1-\beta\_2^t} \\
S\_{db}^{corrected} = \frac{S\_{db}}{1-\beta\_2^t}
\end{align}
$$

更新权重

$$
\begin{align}
W:=W - \frac{\alpha v^{corrected}*{dW}}{\sqrt{S^{corrected}*{dW}}+\epsilon} \\
b:=b - \frac{\alpha v^{corrected}*{db}}{\sqrt{S^{corrected}*{db}}+\epsilon}
\end{align}
$$

超参数 $\beta\_1$ 建议 0.9

$\beta\_2$ 建议 0.999

$\epsilon$ 建议 $10^{-8}$

但是往往实际中使用的是缺省值。即不需要考虑取值。

### 2.9 学习率衰减

学习率设置为 $$a = \frac{1}{1+decayrate\*epoch\_{num}} a\_0$$

decay-rate 称为衰减率，

epoch-num 为代数(第几次遍历数据集)，

𝛼0 为初始学习率。

再者，还有其他选择

$$
\begin{align}
a &= 0.95^{epoch-num} a\_0  \\
a & = \frac{k}{\sqrt{epoch\_{num}}} a\_0 \\
a & = \frac{k}{\sqrt{t}} a\_0
\end{align}
$$

（t为 mini-batch 的数字）。

### 2.10 局部最优的问题

鞍点不同于局部最优。

事实上，如果你要创建一个神经网络，通常梯度为零的点并不是这个图中的局部最优点，实际上成本函数的零梯度点，通常是鞍点。

鞍点这段平稳段会导致学习速度十分缓慢。

## 第三周-超参数调试，Batch、正则化和程序框架

### 3.1 调试处理

![image](https://files.mdnice.com/user/10328/ce4946d3-1c69-40aa-ab96-69920ba58247.png)

### 3.2 为超参数选择合适的范围

### 3.3 超参数调试实践

### 3.4 归一化网络的激活函数

之前，我们归一化过输入值，这里，我们更进一步，连激活值也归一化。

实践中，往往归一化 Z。即激活函数之前的那一步。

![image](https://files.mdnice.com/user/10328/fd62cd78-bd0a-4120-93ad-ad56215cdfc5.png)

加上 $\epsilon$，防止 $\sigma$ 为 0。

但是一旦归一化后，每一层都有平均值 0 和方差 1，

### 3.5 将 Batch Norm 拟合进神经网络

### 3.6 Batch Norm 为什么奏效

### 3.7 测试时的 Batch Norm

### 3.8 softmax 回归

![image](https://files.mdnice.com/user/10328/7f392054-0702-408b-b7a2-1092e77e56a4.png)

### 3.9 训练一个 softmax 分类器

### 3.10 深度学习框架
