训练集、验证集、测试集(Train, Dev, Test Sets)
当数据量小的时候, 70% 训练, 30% 测试;或 60% 训练、20% 验证、20%测试. 当我们有大于100万条数据时, 测试集验证集各取1万条即可, 足以评估单个分类器.
确保验证集和测试集的数据来自同一分布.
如果不需要无偏估计, 可以不设置测试集. 当没设立测试集的时候, 验证集通常被人们称为测试集.
偏差、方差(Bias, Variance)
高偏差(high bias)称为"欠拟合"(underfitting), 练集误差与验证集误差都高.
高方差(high variance)称为过拟合(overfitting), 训练集误差很低而验证集误差很高. 解决方法是正则化或准备更多的数据.
正则化(Regularization)
逻辑回归中的L1正则化, L2正则化
对于L1正则化, 为代价函数添加L1范数:
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
L
(
a
(
i
)
,
y
(
i
)
)
+
λ
2
m
∣
∣
w
∣
∣
1
J(w, b) = \frac{1}{m} \sum^{m}_{i=1} \mathcal{L}(a^{(i)}, y^{(i)}) + \frac{\lambda}{2m} ||w||_1
J(w,b)=m1i=1∑mL(a(i),y(i))+2mλ∣∣w∣∣1
其中
∣
∣
w
∣
∣
1
=
∑
j
=
1
n
x
∣
w
j
∣
||w||_1 = \sum^{n_x}_{j=1} |w_j|
∣∣w∣∣1=j=1∑nx∣wj∣
使用L1正则化, w最终会是稀疏的(w中含很多0), 有利于压缩模型, 但也没有降低太多内存, 所以不能将压缩作为L1正则化的目的. 通常我们使用L2正则化.
对于L2正则化, 为代价函数添加L2范数:
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
L
(
a
(
i
)
,
y
(
i
)
)
+
λ
2
m
∣
∣
w
∣
∣
2
2
J(w, b) = \frac{1}{m} \sum^{m}_{i=1} \mathcal{L}(a^{(i)}, y^{(i)}) + \frac{\lambda}{2m} ||w||_2^2
J(w,b)=m1i=1∑mL(a(i),y(i))+2mλ∣∣w∣∣22
其中
∣
∣
w
∣
∣
2
2
=
∑
j
=
1
n
x
w
j
2
=
w
T
w
||w||^2_2 = \sum^{n_x}_{j=1} w_j^2 = w^Tw
∣∣w∣∣22=j=1∑nxwj2=wTw
尽管 b b b 也是参数, 但我们没有必要添加 λ 2 m b 2 \frac{\lambda}{2m}b^2 2mλb2 项, 因为 w w w 几乎涵盖了所有参数, 而 b b b 只是众多参数中的一个, 可以忽略不计(当然加上也没问题).
神经网络中的L2正则化
弗罗贝尼乌斯范数(相当于矩阵的L2范数):
∣
∣
w
[
l
]
∣
∣
F
2
=
∑
i
=
1
n
[
l
−
1
]
∑
j
=
1
n
[
l
]
(
w
i
j
[
l
]
)
2
||w^{[l]}||_F^2 = \sum_{i=1}^{n^{[l-1]}} \sum_{j=1}^{n^{[l]}} (w_{ij}^{[l]})^2
∣∣w[l]∣∣F2=i=1∑n[l−1]j=1∑n[l](wij[l])2
则
J ( w , b ) = 1 m ∑ i = 1 m L ( y ^ ( i ) , y ( i ) ) + λ 2 m ∑ l = 1 L ∣ ∣ w ∣ ∣ F 2 J(w, b) = \frac{1}{m} \sum^{m}_{i=1} \mathcal{L}(\hat{y}^{(i)}, y^{(i)}) + \frac{\lambda}{2m} \sum_{l=1}^{L}||w||_F^2 J(w,b)=m1i=1∑mL(y^(i),y(i))+2mλl=1∑L∣∣w∣∣F2
则在反向传播时,
d
w
[
l
]
=
(
from backprop
)
+
λ
m
w
[
l
]
w
[
l
]
=
w
[
l
]
−
α
d
w
[
l
]
\begin{aligned} dw^{[l]} & = (\text{from backprop}) + \frac{\lambda}{m}w^{[l]} \\ w^{[l]} & = w^{[l]} -\alpha dw^{[l]} \\ \end{aligned}
dw[l]w[l]=(from backprop)+mλw[l]=w[l]−αdw[l]
正则项说明, 无论 w [ l ] w^{[l]} w[l] 是什么, 我们都试图使之更小(趋于0). 则计算得的 z [ l ] = w [ l ] a [ l − 1 ] + b [ l ] z^{[l]} = w^{[l]}a^{[l-1]} + b^{[l]} z[l]=w[l]a[l−1]+b[l]此时也更小, z [ l ] z^{[l]} z[l] 更容易(以tanh例)落在激活函数 g ( z [ l ] ) g(z^{[l]}) g(z[l]) 中间那一段接近线性的部分, 以达到简化网络的目的(线性的激活函数使得无论多少层的网络, 效果都和一层一样).
随机失活(Dropout)正则化
对每一轮的训练, Dropout 遍历网络的每一层, 设置神经网络中每一层每个节点的失活概率, 被随机选中失活的节点临时被消除, 不参与本轮的训练, 于是得到一个更小的网络.
最常用的为反向随机失活(Inverted Dropout).
该方法在向前传播时, 根据随机失活的概率 (例如0.2), 将每一层(例如 l l l 层)的 a [ l ] a^{[l]} a[l] 矩阵(a=g(z))中被选中失活的元素置为0. 则该层的 a [ l ] a^{[l]} a[l] 相当于少了 20% 的元素. 为了不影响下一层 z [ l + 1 ] z^{[l+1]} z[l+1] 的期望值, 我们需要 a [ l ] a^{[l]} a[l] /= 0.8 以修正权重.
由于训练时的 " a [ l ] a^{[l]} a[l] /= 0.8" 修复了权重, 在测试阶段无需使用 Dropout.
Dropout 不能与梯度检验同时使用, 因为 Dropout 在梯度下降上的代价函数J难以计算.
其他正则化
数据扩增: 比如训练分类猫咪的图片, 将图片左右翻转、旋转一个小角度、稍微变形处理等, 可以人工合成数据.
Early Stopping: 运行梯度下降时, 我们可以绘制训练误差, 当验证集误差不降反增的时候, 停止训练. 缺点是可能导致代价J值不够小, 却又没解决继续训练可能导致的过拟合问题.
归一化(Normalizing)
输入的归一化有两个步骤: 均值调整为0, 方差归一化. 归一化直观的理解就是使得代价函数更圆, 更容易优化代价函数.
梯度消失/爆炸(Vanishing / Exploding Gradients)
为了方便理解,假设使用了线性激活函数 g(z)=z , 且
W
=
W
[
L
−
1
]
=
.
.
.
=
W
[
2
]
=
W
[
1
]
W=W^{[L-1]}=...=W^{[2]}=W^{[1]}
W=W[L−1]=...=W[2]=W[1]
则
y
^
=
W
[
L
]
W
[
L
−
1
]
.
.
.
W
[
2
]
W
[
1
]
x
=
W
[
L
]
W
L
−
1
x
\begin{aligned} \hat{y} & = W^{[L]}W^{[L-1]}...W^{[2]}W^{[1]}x \\ & = W^{[L]}W^{L-1}x \end{aligned}
y^=W[L]W[L−1]...W[2]W[1]x=W[L]WL−1x
可知若 W W W 中有元素权重为 1.5 , 则最终得到 1. 5 L − 1 1.5^{L-1} 1.5L−1 , 若层数很深, 计算得 y ^ \hat{y} y^ 也很大; 同理若权重为 0.5 , 进行 L − 1 L-1 L−1 次幂运算后值会很小. 这便是梯度爆炸与梯度消失.
有效的解决方案: 由于 z = w 1 x 1 + w 2 x 2 + . . . + w n x n z=w_1x_1+w_2x_2+...+w_nx_n z=w1x1+w2x2+...+wnxn (忽略 b b b ), 为了预防 z z z 太大或太小, 则 n n n 越大时, 期望 w i w_i wi 越小, 则在随机(0~1)初始化 W W W 时, 我们对其乘上一个小于1的倍数, 使之更小.
对于Tanh, 权重乘上 1 n [ l − 1 ] \sqrt{\frac{1}{n^{[l-1]}}} n[l−1]1, 或者 2 n [ l − 1 ] + n [ l ] \sqrt{\frac{2}{n^{[l-1]}+n^{[l]}}} n[l−1]+n[l]2
对于Relu, 权重乘上 2 n [ l − 1 ] \sqrt{\frac{2}{n^{[l-1]}}} n[l−1]2
梯度检验
在反向传播的时候, 如果怕自己
d
θ
[
i
]
=
∂
J
∂
θ
i
d\theta[i] = \frac{\partial J}{\partial \theta_i}
dθ[i]=∂θi∂J 等算错, 可以用导数的定义, 计算
d
θ
a
p
p
r
o
x
[
i
]
=
J
(
θ
1
,
θ
2
,
.
.
.
,
θ
i
+
ε
,
.
.
.
)
−
J
(
θ
1
,
θ
2
,
.
.
.
,
θ
i
−
ε
,
.
.
.
)
2
ε
d\theta_{approx}[i] = \frac{J(\theta_1, \theta_2, ..., \theta_i + \varepsilon, ...) - J(\theta_1, \theta_2, ..., \theta_i - \varepsilon, ...)}{2\varepsilon}
dθapprox[i]=2εJ(θ1,θ2,...,θi+ε,...)−J(θ1,θ2,...,θi−ε,...)
然后根据两者误差估计自己是否算错. 该方法仅用来调试, 且不能同 Dropout 同时使用.