防止神经网络过拟合的常用方法包括:
- 获取更多的训练数据;
- 减小网络容量;
- 添加权重正则化;
- 添加dropout;
1、获取更多的训练数据
这个方法防止过拟合是适用于所有机器学习模型的,也是万能的方法,但现实却是不可能获取到所有的数据。
2、减小网络容量
减小网络容量是指减小神经网络的层数和隐藏单元。为什么减小网络容量可以防止过拟合?首先我们来了解一下神经网络的层数和隐藏单元与过拟合和欠拟合的关系。同时我们也可以解决神经网络的两个问题:
1、如何确定网络层数;
2、如何确定各层的隐藏单元;
隐藏单元越多,神经网络所能识别的特征也就越多;层数越多,后面识别的特征也就越具体。同样,隐藏单元越少,神经网络所能识别的特征也就越少,这就容易欠拟合;层数越少,后面识别的特征也就越模糊,也容易出现欠拟合。
3、添加权重正则化
权重正则化来源于奥卡姆剃刀原理:如果一件事情有两种解释,那么最可能正确的解释就是最简单的那个,即假设更少的那个。这个原理用在机器学习模型上就是,简单模型比复杂模型更合理、更可能正确。
权重正则化有两种形式:
- L1正则化:添加的成本与权重系数的绝对值成正比;
- L2正则化:添加的成本与权重系数的平方成正比,神经网络的L2正则化也叫权重衰减。
首先来看看以下两组函数:
第一组:
{
A
:
x
+
y
+
1
=
0
B
:
10
x
+
10
y
+
10
=
0
\begin{cases} \text A:x +y +1 = 0 \\ \text B:10x +10y +10 =0 \end{cases}
{A:x+y+1=0B:10x+10y+10=0
第二组:
{
A
:
x
+
y
+
1
=
0
B
:
x
+
y
+
0.01
x
y
+
1
=
0
\begin{cases} \text A:x +y +1 = 0 \\ \text B: x + y + 0.01xy + 1 =0 \end{cases}
{A:x+y+1=0B:x+y+0.01xy+1=0
第一组函数其实效果一样的,损失也一样,但是明显A函数比B函数更好,添加权重正则化,可以让模型选择A函数;
第二组函数假设它们都能很好地分类,但我们应该选择A函数,因为B函数很容易过拟合,添加权重正则化,也可以让模型选择A函数;
from keras import regularizers
model = model.Sequential()
model.add(layers.Dense(16,kernel_regularizer=regularizers.l2(0.001),activation='relu',input_shape=(10000,))
l2(0.001)的意思是该层权重矩阵的每个系数都会使网络总损失增加0.001*weight_coefficient_value(权重系数)。这个惩罚只在训练时添加,所以这个网络的训练损失会比测试缶失大很多。
4、添加dropout正则化
dropout比率是被设为0的特征所占的比例,通常在0.2~0.5范围内。测试时没有单元被舍弃,而该层的输出值需要按dropout比率缩小,因为这时比训练时有更多的单元被激活,需要加以平衡。
model = model.Sequential()
model.add(layers.Dense(4,activation='relu',input_shape=(4,)))
model.add(layers.Droput(0.5))
model.add(layers.Dense(1))
假设Dense层我们训练得到的权重矩阵为:
dense_weight =
[
0.3
0.2
1.5
0.0
0.6
0.1
0.0
0.3
0.2
1.9
0.3
1.2
0.7
0.5
1.0
0.0
]
\begin{bmatrix} 0.3 & 0.2 & 1.5 & 0.0 \\ 0.6 & 0.1 & 0.0 & 0.3 \\ 0.2 & 1.9 & 0.3 & 1.2 \\ 0.7 & 0.5 & 1.0 & 0.0 \\ \end{bmatrix}
⎣⎢⎢⎡0.30.60.20.70.20.11.90.51.50.00.31.00.00.31.20.0⎦⎥⎥⎤
Droput丢弃比率为0.5,经过Dropout后得到的权重矩阵为:
dropout_weight =
[
0.0
0.2
1.5
0.0
0.6
0.0
0.0
0.3
0.0
1.9
0.3
0.0
0.7
0.0
0.0
0.0
]
\begin{bmatrix} 0.0 & 0.2 & 1.5 & 0.0 \\ 0.6 & 0.0 & 0.0 & 0.3 \\ 0.0 & 1.9 & 0.3 & 0.0 \\ 0.7 & 0.0 & 0.0 & 0.0 \\ \end{bmatrix}
⎣⎢⎢⎡0.00.60.00.70.20.01.90.01.50.00.30.00.00.30.00.0⎦⎥⎥⎤
那么训练时的权重总值为:
train_weight_count = |dropout_weight| = 5.5
而测试时,因为没有单元被舍弃,所以测试时的权重总值为:
test_weight_count = |dense_weight| = 10.8
可以想像,同一个样本数据在训练时和测试时得到的结果将会远远不相等,为了尽量让它们相等,有两种方式:
- 测试时,将输出按dropout比率缩小,训练时输出不变;
- 训练时,将输出按dropout比率放大,测试时输出不变;