方法概述
避免过拟合的方法有很多,常用的方法有early stopping、数据集扩增、正则化、dropout。下面就概述一下,具体请参照优化算法(1)
early stoping:在发生过拟合之前提前结束。理论上是可以的,但是这个点不好把握。
数据集扩增:就是让模型见到更多的情况,可以最大化地满足全样本,但实际应用中对于未来事件的预测不理想。
正则化:通过映入范数,增强模型的泛化能力。包括L1、L2.
dropout:是网络模型中的一种方法。每次训练时舍去一些节点来增强泛化能力。
下面我们来具体看看如何实现后两种方法。
正则化
所谓的正则化, 其实就是在神经网络计算损失值的过程中, 在损失后面再加一项。 这样损失值所代表的输出与标准结果间的误差就会受到干扰, 导致学习参数w和b无法按照目标方向来调整, 实现模型无法与样本完全拟合的结果, 从而达到防止过拟合的效果
这个干扰项一定要有下面这样的特性:
1、当欠拟合时,希望它对模型误差的影响越小越好,以便让模型快速拟合实际
2、当过拟合时,希望他对模型误差的影响越大越好,以便让模型不要产生过拟合的情况。
由上面两个特性,引入两个范数:L1和L2
L1:所有学习参数w的绝对值的和。
L2:所有学习参数w的平方和然后求平方根
上图中的第一个式子是L1范式,另一个就是L2范式。loss为等式左边的结果,less(0)代表真实的loss值,less(0)后面的那一项就代表正则化,λ为一个可以调整的参数,用来控制正则化对loss的影响。对于L2,将其乘以1/2是为了反向传播时对其求导可以将数据规整。
tensorflow中的正则化
L1正则化:tf.contrib.layers.l1_regularizer(lambda)(w):lambda是正则化参数
L2正则化:tf.contrib.layers.l2_regularizer(lambda)(w):lambda是正则化参数
但是对于高版本的tensorflow的contrib不稳定,从而在高级一点的版本中删除了contrib这个库。如果想使用L2正则化就得用下面的办法:
L2的正则化函数为:tf.nn.l2_loss(t,name=None)
L1的正则化函数在tensorflow是没有自己组装的,可以自己写:tf.reduce_sum(tf.abs(w))
通过正则化改善过拟合
使用contrib里的方法:
tf.add_to_collection(‘list1’,var):将变量加入到列表list1中。
tf.get_collection(‘list1’):获得列表list1里面的所有变量。
tf.add_n(list1):将列表list1中所有的变量加起来并返回。
1 | import tensorflow as tf |
1 | #使用方法 |
使用nn里的方法:
使用正则化非常简单,只需要在计算损失值时加上loss的正则化。
1 | reg=0.01 |
dropout
还有一种防止过拟合的方法是dropout。这个方法的做法是:在训练过程中,每次随机选择一部分节点不要去“学习”
因为从样本数据的分析来看,数据本身是不可能很纯净的,也就是任何一个模型不能100%把数据完全分开,在某一类中一定会有一些异常数据,过拟合的问题恰恰是把这些异常数据当初规律来学习了。我们希望把异常数据过滤掉,只关心有用的规律数据。
异常数据的特点是,它与主流样本中的规律都不同,但是量非常少,相当于在一个样本中出现的概率比主流数据出现的概率低很多。我们可以利用这一点,通过在每次模型中忽略一些节点的数据学习,将小概率的异常数据获得学习的机会降低,这样这些异常数据对模型的影响就会更小了。
注意:由于dropout让一部分节点不去“学习”,所以在增加模型的泛化能力的同时,会使学习速度降低,使模型不太容易学成。所以在使用的过程中需要合理地调节到底丢弃多少节点,并不是丢弃的节点越多越好。
tensorflow中的dropout
tf.nn.dropout(x,keep_prob,noise_shape=None,seed=None,name=None)
x: 输入的模型节点。
keep_prob: 保持率。 如果为1, 则代表全部进行学习; 如果为0.8, 则代表丢弃20%的节点, 只让80%的节点参与学习。
noise_shape: 代表指定x中, 哪些维度可以使用dropout技术。 为None时, 表示所有维度都使用dropout技术。 也可以将某个维度标志为1, 来代表该维度使用dropout技术。 例如: x的形状为[n, len, w, ch], 使用noise_shape为[n, 1, 1,ch], 这表明会对x中的第二维度len和第三维度w进行dropout。
seed: 随机选取节点的过程中随机数的种子值。
全连接网络的深浅关系
在实际中,如果想使用浅层神经网络拟合复杂非线性函数,就需要靠增加的神经元个数来实现。神经元过多意味着需要训练的参数过多,这会增加网络的学习难度,并影响网络的泛化能力。因此,在增加网络结构时,一般倾向于使用更多的模型,来减少网络中所需要神经元的数量,使网络有更好的泛化能力。