防止或减轻过拟合的方式(一)——正则化
在进行模型搭建时常用的解决过拟合的方法有以下几种:
· 采用更多的数据
· 迫使模型的复杂度降低(减少层数、正则化)
· dropout(提高鲁棒性)
· 提早结束训练过程
· 数据增强
这里重点讲正则化(regularization)
假定对于一个二分类问题,它的交叉熵损失函数为
J(ω) = - 1/m Σ [ yilnyi' + (1-yi)ln(1-yi') ]
所谓正则化,即在损失函数的基础上加上一个范数,当加上L1范数时,被称为L1正则化,当加上L2范数时,被称为L2正则化
其思想就是在损失函数中加入被称为正则化项(Regularizer)的惩罚
L1(θ) = ||θ||1 = Σ|θi|
L2(θ) = ||θ||22= Σ|θi|2
待优化的函数就从J(ω)变为了J(ω)+λL1(θ)或J(ω)+λL2(θ)
那么如何给网络结构添加这样的结构?代码如下:
l2_model = keras.Sequential([ keras.layers.Dense(16,kernal_regularizer=keras.regularizers.l2(0.001)), keras.layers.Dense(16,kernel_regularizer=keras.regularizers.l2(0.001)), keras.layers.Dense(1,activation=tf.nn.sigmoid) ])
更加灵活的添加方式如下:
for step,(x,y) in enumerate(db): with tf.GradientTape() as tape: # …… loss = tf.reduce_mean(tf.losses.categorical_crossentropy(y_onehot,out,from_logits=True)) loss_regularization = [] for p in network.trainable_variables: loss_regularization.append(tf.nn.l2_loss(p)) loss_regularization = tf.reduce_sum(tf.stack(loss_regularization)) loss = loss +0.0001 * loss_regularization grad = tape.gradient(loss,network.trainable_variables) optimizer.apply_gradients(zip(grad,network.trainable_variables))
最小化J(ω)+λL(θ)意味着需要在偏好小范数权重和拟合训练数据之间找到一个平衡,其根本思想是通过限制权重的大小,降低模型拟合训练集中存在噪音的概率,从而减轻过拟合。需要注意的是,这两种正则化在使用时存在两个主要的区别,首先L1正则化会让参数变得更稀疏(会有更多的参数变为0),而L2正则化不会;其次,计算L1正则化的公式不可导,而计算L2正则化的公式可导,这就导致了在优化时计算L2正则化损失函数的偏导数要更加简洁,而计算L1正则化损失函数的偏导数要更加复杂。