cs224n的笔记,过拟合、预处理、初始化、Batch Normalization

过拟合

过拟合

训练数据很少,或者训练次数很多,会导致过拟合。避免过拟合的方法有如下几种:

  • early stop
  • 数据集扩增
  • 正则化 (L1, L2权重衰减
  • Dropout
  • 决策树剪枝(尽管不属于神经网络)

现在一般用L2正则化+Dropout。

过拟合时拟合系数一般都很大。过拟合需要顾及到所有的数据点,意味着拟合函数波动很大

看到,在某些很小的区间内里,函数值的变化很剧烈。意味着这些小区间的导数值(绝对值)非常大。由于自变量值可大可小,所以只有系数足够大,才能保证导数值足够大。

所以:过拟合时,参数一般都很大参数较小时,意味着模型复杂度更低,对数据的拟合刚刚好, 这也是奥卡姆剃刀法则。

范数

向量范数

\(x \in \mathbb {R}^d\)

范数 定义
1-范数 \(\left \| x\right\|_1 = \sum_i^d \|x_i\|\)绝对值之和
2-范数 \(\left \| x\right\|_2 = \left(\sum_i^d \vert x_i\vert^2\right)^{\frac{1}{2}}\)绝对值平方之和再开方
p-范数 \(\left \| x\right\|_p = \left(\sum_i^d \|x_i\|^p\right)^{\frac{1}{p}}\)绝对值的p次方之和的\(\frac{1}{p}​\)次幂
\(\infty\)-范数 \(\left \| x\right\|_\infty = \max_\limits i \|x_i\|\) ,绝对值的最大值
-\(\infty\)-范数 \(\left \| x\right\|_{-\infty} = \min_\limits i \|x_i\|\) ,绝对值的最小值

矩阵范数

\(A \in \mathbb R^{m \times n}\)

范数 定义
1-范数 \(\left \| A\right\|_1 = \max \limits_{j}\sum_i^m \|a_{ij}\|\)列和范数,矩阵列向量绝对值之和的最大值。
\(\infty\)-范数 \(\left \| A\right\|_\infty = \max_\limits i \sum_{j}^{n}\|a_{ij}\|\)行和范数,所有行向量绝对值之和的最大值。
2-范数 \(\left \| A\right\|_2 = \sqrt{\lambda_{m}}\) , 其中\(\lambda_m\)\(A^TA\)最大特征值
F-范数 \(\left \| A\right\|_F = \left(\sum_i^m \sum_j^n a_{ij}^2\right)^{\frac{1}{2}}\)所有元素的平方之和,再开方。或者不开方, L2正则化就直接平方,不开方。

L2正则化权重衰减

为了避免过拟合,使用L2正则化参数。\(\lambda\)是正则项系数,用来权衡正则项和默认损失的比重\(\lambda\) 的选取很重要。 \[ J_R = J + \lambda \sum_{i=1}^L \left \| W^{(i)}\right \|_F \] L2惩罚更倾向于更小更分散的权重向量,鼓励使用所有维度的特征,而不是只依赖其中的几个,这也避免了过拟合。

标准L2正则化

\(\lambda\)正则项系数\(n\)是数据数量,\(w\)是模型的参数。 \[ C = C_0 + \frac {\lambda} {2n} \sum_w w^2 \] \(C\)对参数\(w\)\(b\)偏导\[ \begin {align} & \frac{\partial C}{\partial w} = \frac{\partial C_0}{\partial w} + \frac{\lambda}{n} w \\ & \frac{\partial C}{\partial b} = \frac{\partial C_0}{\partial b} \\ \end{align} \] 更新参数 :可以看出,正则化\(C\)\(w\)有影响,对\(b\)无影响。
\[ \begin{align} w &= w - \alpha \cdot \frac{\partial C}{\partial w} \\ &= (1 - \frac{\alpha \lambda}{n})w - \alpha \frac{\partial C_0}{\partial w} \\ \end{align} \] 从上式可以看出:

  • 不使用正则化时,\(w\)的系数是1
  • 使用正则化时
  • \(w\)的系数是\(1 - \frac{\alpha \lambda}{n} < 1\) ,效果是减小\(w\), 所以是权重衰减 weight decay
  • 当然,\(w\)具体增大或减小,还取决于后面的导数项

mini-batch随机梯度下降

\(m\) 是这个batch的样本个数,有更新参数如下,即求batch个C对w的平均偏导值 \[ \begin {align} & w = (1 - \frac{\alpha \lambda}{n})w - \frac{\alpha}{m} \cdot \sum_{i=1}^{m}\frac{\partial C_i}{\partial w} \\ & b = b - \frac{\alpha}{m} \cdot \sum_{i=1}^{m}\frac{\partial C_i}{\partial b} \\ \end{align} \] 所以,权重衰减后一般可以减小过拟合。 L2正则化比L1正则化更加发散,权值也会被限制的更小。 一般使用L2正则化。

还有一种方法是最大范数限制:给范数一个上界\(\left \| w \right \| < c\) , 可以在学习率太高的时候网络不会爆炸,因为更新总是有界的。

实例说明

增加网络的层的数量和尺寸时,网络的容量上升,多个神经元一起合作,可以表达各种复杂的函数。

如下图,2分类问题,有噪声数据。

一个隐藏层。神经元数量分别是3、6、20。很明显20过拟合了,拟合了所有的数据。正则化就是处理过拟合的非常好的办法。

对20个神经元的网络,使用正则化,解决过拟合问题。正则化强度\(\lambda\)很重要。

L1正则化

正则化loss如下: \[ C = C_0 + \frac {\lambda} {n} \sum_w |w| \]\(w\)偏导, 其中\(\rm{sgn}(w)\)符号函数\[ \frac{\partial C}{\partial w} = \frac{\partial C_0}{\partial w} + \frac{\lambda}{n} \cdot \rm{sgn}(w) \] 更新参数: \[ w = w - \frac{\alpha \lambda}{n} \cdot \rm{sgn}(w) - \alpha \frac{\partial C_0}{\partial w} \] 分析:\(w\)为正,减小;\(w\)为负,增大。所以L1正则化就是使参数向0靠近,是权重尽可能为0,减小网络复杂度,防止过拟合。

特别地:当\(w=0\)时,不可导,就不要正则化项了。L1正则化更加稀疏。

随机失活Dropout

Dropout是非常有用正则化的办法,它改变了网络结构。一般采用L2正则化+Dropout来防止过拟合

训练的时候,输出不变,随机以概率\(p\)保留神经元,\(1-p\)删除神经元置位0)。每次迭代删除的神经元都不一样。

BP的时候,置位0的神经元的参数就不再更新只更新前向时alive的神经元

预测的时候,要保留所有的神经元,即不使用Dropout。

相当于训练了很多个(指数级数量)小网络(半数网络),在预测的时候综合它们的结果。随着训练的进行,大部分的半数网络都可以给出正确的分类结果。

数据预处理

用的很多的是0中心化。CNN中很少用PCA和白化。

应该:线划分训练、验证、测试集,只是从训练集中求平均值然后各个集再减去这个平均值

中心化

也称作均值减法, 把数据所有维度变成0均值,其实就是减去均值。就是将数据迁移到原点\[ x = x - \rm{avg}(x) = x - \bar x \]

标准化

也称作归一化, 数据所有维度都归一化,使其数值变化范围都近似相等

  • 除以标准差
  • 最大值和最小值按照比例缩放到\((-1 ,1)\) 之间

方差\(s^2 = \frac{1}{n-1} \sum_{i=1}^n (x_i - \bar x)^2\)标准差就是\(s\) 。数据除以标准差,接近标准高斯分布\[ x = \frac{x}{s} \]

PCA

斯坦福PCACSDNPCA和SVD的区别和联系

协方差

协方差就是乘积的期望-期望的乘积\[ \rm{Cov}(X, Y) = E(XY) - E(X)E(Y) \] 协方差的性质如下: \[ \begin{align} & \rm{Cov}(X, Y) = \rm{Conv}(Y, X) \\ \\ & \rm{Cov}(aX, bY) = ab \cdot \rm{Conv}(Y, X) \\ \\ & \rm{Cov}(X, X) = E(X^2) - E^2(X) = D(X) , \quad \text{三方公式}\\ \\ & \rm{Cov}(X, C) = 0 \\ \\ & \rm{Cov}(X, Y) = 0 \leftrightarrow X与Y独立 \end{align} \] 还有别的性质就看考研笔记吧。

奇异值分解 \[ A_{m \times n} = U_{m \times m} \Sigma_{m \times n} V^T_{n \times n} \] \(V_{n \times n}\)\(V\)的列,一组对A正交输入或分析的基向量(线性无关)。这些向量是\(M^TM\) 的特征向量。

\(U_{m \times m}\)\(U\)的列,一组对A正交输出的基向量 。是\(MM^T\)的特征向量。

\(\Sigma_{m \times n}\)对角矩阵。对角元素按照从小到大排列,这些对角元素称为奇异值。 是\(M^TM, MM^T\) 的特征值的非负平方根,并且与U和V的行向量对应。

\(r\)非0奇异值的个数,则A中仅有\(r\)个重要特征,其余特征都是噪声和冗余特征。

奇异值的物理意义

利用SVD进行PCA

先将数据中心化。输入是\(X \in \mathbb R^ {N \times D}\) ,则协方差矩阵 如下: \[ \mathrm{Cov}(X) = \frac{X^TX}{N} \; \in \mathbb R^{D \times D} \] 比如X有a和b两维,均值均是0。那么\(\rm{Cov}(ab)=E(ab)-0=(a_0b_0+a_1b_1+\cdots + a_nb_n) /n\) ,就得到了协方差值。

  • 中心化
  • 计算\(x\)协方差矩阵cov
  • 对协方差矩阵cov进行svd分解,得到u, s, v
  • 去除x的相关性,旋转\(xrot = x \cdot u\) ,此时xrot的协方差矩阵只有对角线才有值,其余均为0
  • 选出大于0的奇异值
  • 数据降维
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def test_pca():
x = np.random.randn(5, 10)
# 中心化
x -= np.mean(x, axis=0)
print (x.shape)
# 协方差
conv = np.dot(x.T, x) / x.shape[0]
print (conv.shape)
print (conv)
u, s, v = np.linalg.svd(conv)
print (s)
print (u.shape, s.shape, v.shape)
# 大于0的奇异值
n_sv = np.where(s > 1e-5)[0].shape[0]
print(n_sv)
# 对数据去除相关性
xrot = np.dot(x, u)
print (xrot.shape)
# 数据降维
xrot_reduced = np.dot(x, u[:, :n_sv])
# 降到了4维
print (xrot_reduced.shape)

白化

斯坦福白化

白化希望特征之间的相关性较低,所有特征具有相同的协方差。白化后,得到均值为0,协方差相等的矩阵。对\(xrot\)除以特征值。 \[ x_{white} = \frac{x_{rot}}{\sqrt{\lambda + \epsilon}} \]

1
x_white = xrot / np.sqrt(s + 1e-5)

缺陷是:可能会夸大数据中的早上,因为把所有维度都拉伸到了相同的数值范围。可能有一些极少差异性(方差小)但大多数是噪声的维度。可以使用平滑来解决。

权重初始化

如果数据恰当归一化以后,可以假设所有权重数值中大约一半为正数,一半为负数。所以期望参数值是0。

千万不能够全零初始化。因为每个神经元的输出相同,BP时梯度也相同,参数更新也相同。神经元之间就失去了不对称性的源头

小随机数初始化

如果神经元刚开始的时候是随机且不相等的,那么它们将计算出不同的更新,并成为网络的不同部分

参数接近于0单不等于0。使用零均值和标准差的高斯分布来生成随机数初始化参数,这样就打破了对称性

1
W = 0.01 * np.random.randn(D,H)

注意:不是参数值初始越小就一定好。参数小,意味着会减小BP中的梯度信号,在深度网络中,就会有问题。

校准方差

随着数据集的增长,随机初始化的神经元的输出数据分布的方差也会增大。可以使用\(\frac{1}{\sqrt{n}}\) 校准方差。n是数据的数量。这样就能保证网络中所有神经元起始时有近似同样的输出分布。这样也能够提高收敛的速度。 感觉实际上就是做了一个归一化。

数学详细推导见cs231n\(s = \sum_{i}^nw_ix_i\) ,假设w和x都服从同样的分布。想要输出s和输入x有同样的方差。 \[ \begin {align} & \because D(s) = n \cdot D(w)D(x), \; D(s) = D(x) \\ & \therefore D(w) = \frac{1}{n} \\ & \because D(w_{old}) = 1, \; D(aX) = a^2 D(X) \\ & \therefore D(w) = \frac{1}{n}D(w_{old}) = D(\frac{1}{\sqrt n} w_{old}) \\ & \therefore w = \frac{1}{\sqrt n} w_{old} \end{align} \] 所以要使用\(\frac{1}{\sqrt{n}}\)来标准化参数:

1
W = 0.01 * np.random.randn(D,H)/ sqrt(n)

经验公式

对于某一层的方差,应该取决于两层的输入和输出神经元的数量,如下: \[ \rm{D}(w) = \frac{2}{n_{in} + n_{out}} \] ReLU来说,方差应该是\(\frac{2}{n}\)

1
W = 0.01 * np.random.randn(D,H) * sqrt(2.0 / n)

稀疏和偏置初始化

一般稀疏初始化用的比较少。一般偏置都初始化为0。

Batch Normalization

莫凡python BN讲解CSDN-BN论文介绍 。Batch Normalization和普通数据标准化类似,是将分散的数据标准化。

Batch Normalization在神经网络非常流行,已经成为一个标准了

训练速度分析

网络训练的时候,每一层网络参数更新,会导致下一层输入数据分布的变化。这个称为Internal Convariate Shift

需要对数据归一化的原因

  • 神经网络的本质是学习数据分布。如果训练数据与测试数据的分布不同,那么泛化能力也大大降低
  • 如果每个batch数据分布不同(batch 梯度下降),每次迭代都要去学习适应不同的分布,会大大降低训练速度

深度网络,前几层数据微小变化,后面几层数据差距会积累放大

一旦某一层网络输入数据发生改变,这层网络就需要去适应学习这个新的数据分布。如果训练数据的分布一直变化,那么就会影响网络的训练速度

敏感度问题

神经网络中,如果使用tanh激活函数,初始权值是0.1。

输入\(x=1\), 正常更新: \[ z = wx = 0.1, \quad a(z_1) = 0.1 \quad \to \quad a^\prime(z) = 0.99 \] 但是如果一开始输入 \(x=20\) ,会导致梯度消失,不更新参数。 \[ z = wx = 2 ,\quad a(z) \approx 1 \quad \to \quad a^\prime(z) = 0 \] 同样地,如果再输入\(x=100\) ,神经元的输出依然是接近于1,不更新参数。 \[ z = wx = 10 ,\quad a(z) \approx 1 \quad \to \quad a^\prime(z) = 0 \] 对于一个变化范围比较大特征维度,神经网络在初始阶段对它已经不敏感没有区分度了!

这样的问题,在神经网络的输入层和中间层都存在。

BN算法

BN算法在每一次迭代中,对每一层的输入都进行归一化。把数据转换为均值为0、方差为1的高斯分布\[ \hat x = \frac{x - E(x)} {\sqrt{D(x) + \epsilon}} \] 非常大的缺陷强行归一化会破坏掉刚刚学习到的特征。 把每层的数据分布都固定了,但不一定是前面一层学习到的数据分布。

牛逼的地方 :设置两个可以学习的变量扩展参数\(\gamma\) ,和平移参数 \(\beta\)用这两个变量去还原上一层应该学习到的数据分布。(但是芳芳说,这一步其实可能没那么重要,要不要都行,CNN的本身会处理得更好)。 \[ y = \gamma \hat x+ \beta \] 这样理解:用这两个参数,让神经网络自己去学习琢磨是前面的标准化是否有优化作用,如果没有优化效果,就用\(\gamma, \beta\)来抵消标准化的操作。

这样,BN就把原来不固定的数据分布,全部转换为固定的数据分布,而这种数据分布恰恰就是要学习到的分布。从而加速了网络的训练

对一个mini-batch进行更新, 输入一个\(batchsize=m\)的数据,学习两个参数,输出\(y\) \[ \begin{align} & \mu = \frac{1}{m} \sum_{i=1}^m x_i & \text{求均值} \\ & \sigma^2 = \frac{1}{m} \sum_{i=1}^m (x_i - \mu)^2 & \text{求方差} \\ & \hat x = \frac{x - E(x)} {\sqrt{\sigma^2 + \epsilon}} & \text{标准化} \\ & y = \gamma \hat x+ \beta & \text{scale and shfit} \end{align} \] 其实就是对输入数据做个归一化: \[ z = wx+b \to z = \rm{BN}(wx + b) \to a = f(z) \] 一般在全连接层和激活函数之间添加BN层。

在测试的时候,由于是没有batch,所以使用固定的均值和标准差,也就是对训练的各个batch的均值和标准差做批处理。 \[ E(x) = E(\mu), \quad D(x) = \frac{b}{b-1} E(\sigma^2) \]

BN的优点

1 训练速度快

2 选择大的初始学习率

初始大学习率,学习率的衰减也很快。快速训练收敛。小的学习率也可以。

3 不再需要Dropout

BN本身就可以提高网络泛化能力,可以不需要Dropout和L2正则化。源神说,现在主流的网络都没有dropout了。但是会使用L2正则化,比较小的正则化。

4 不再需要局部相应归一化

5 可以把训练数据彻底打乱

效果图片展示

对所有数据标准化到一个范围,这样大部分的激活值都不会饱和,都不是-1或者1。

大部分的激活值在各个分布区间都有值。再传递到后面,数据更有价值。