首页 > 编程知识 正文

keras如何加正则化函数,keras过拟合相关解决办法

时间:2023-05-04 05:54:34 阅读:246851 作者:3089

上篇分析了Keras实现Dropout层的原理Keras防止过拟合(一)Dropout层源码细节,Dropout层的加入,可以很好的缓解过拟合问题。除此之外,我们在Keras的模型搭建中,也可以使用L1 L2正则化。

L1正则化与L2正则化

如果对L1、L2正则化完全不了解的,推荐这篇文章机器学习中正则化项L1和L2的直观理解,讲解的十分清楚。
L2正则化比L1更适合解决过拟合问题(L2正则化最后可以得到一个参数都比较小的模型,抗扰动能力强),L1正则化则有利于产生稀疏矩阵、特征选择。所以在解决过拟合问题
实现L1、L2正则化的方法十分简单。L1正则化是将系数的绝对值之和加入损失函数,L2正则化是将系数绝对值平方之和加入损失函数。总结为两步:
1.计算L1或L2正则化的值
2.将其加入最终损失函数

源码细节

源码位于kerasregularizers.py中:

class L1L2(Regularizer): """Regularizer for L1 and L2 regularization. # Arguments l1: Float; L1 regularization factor. l2: Float; L2 regularization factor. """ def __init__(self, l1=0., l2=0.): self.l1 = K.cast_to_floatx(l1) self.l2 = K.cast_to_floatx(l2) def __call__(self, x): regularization = 0. if self.l1: regularization += self.l1 * K.sum(K.abs(x)) if self.l2: regularization += self.l2 * K.sum(K.square(x)) return regularization def get_config(self): return {'l1': float(self.l1), 'l2': float(self.l2)} def l1(l=0.01): return L1L2(l1=l)def l2(l=0.01): return L1L2(l2=l)def l1_l2(l1=0.01, l2=0.01): return L1L2(l1=l1, l2=l2)

计算部分没什么好说的,需要注意的是参数x是正则化系数,最后面的def l1(),def l2()和def l1_l2()。在层中定义正则化时会使用到。

如何将其加入最终损失函数,拿Dense层为例:

#Dense层部分代码def __init__(self, units, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None, **kwargs): self.kernel_regularizer = regularizers.get(kernel_regularizer) self.bias_regularizer = regularizers.get(bias_regularizer) self.activity_regularizer = regularizers.get(activity_regularizer)def build(self, input_shape): assert len(input_shape) >= 2 input_dim = input_shape[-1] self.kernel = self.add_weight(shape=(input_dim, self.units), initializer=self.kernel_initializer, name='kernel', regularizer=self.kernel_regularizer, constraint=self.kernel_constraint)

可以看到,正则化的添加,kernel,bias,activity是分开的。构建模型时,想用哪个,定义哪个。
将正则化值添加进损失函数,主要表现在add_weight部分,keras层都继承自kerasenginebase_layer.py,其中有add_weight的定义:

#add_weight完整代码def add_weight(self, name=None, shape=None, dtype=None, initializer=None, regularizer=None, trainable=True, constraint=None): if shape is None: shape = () initializer = initializers.get(initializer) if dtype is None: dtype = self.dtype weight = K.variable(initializer(shape, dtype=dtype), dtype=dtype, name=name, constraint=constraint) if regularizer is not None: #此部分实现 with K.name_scope('weight_regularizer'): self.add_loss(regularizer(weight))#利用add_loss函数加入 if trainable: self._trainable_weights.append(weight) else: self._non_trainable_weights.append(weight) weight._tracked = True return weight

add_weight函数是用来添加参数的,在其定义中,专门有将正则化值加入损失函数的部分。

模型中加入L1 L2正则化

在Keras已经定义好的层中加入正则化十分简单,在定义层时加入即可:
若我们想给Dense层kernel部分(output=Wx+b中的W)加入正则化(系数设置为0.01)

Dense(256, kernel_regularizer=keras.regularizers.l1(0.01))#加入l1Dense(256, kernel_regularizer=keras.regularizers.l2(0.01))#加入l2Dense(256, kernel_regularizer=keras.regularizers.l1_l2(0.01))#加入l1和l2

LSTM中加入:

LSTM(128, input_shape=(3,256), kernel_regularizer=keras.regularizers.l2(0.01))

也将偏置和激活函数加入:

Dense(256, kernel_regularizer=keras.regularizers.l1(0.01),bias_regularizer=keras.regularizers.l1(0.01),activity_regularizer=keras.regularizers.l1(0.01))

上面也提过,def l1()、def l2() 、def l1_l2(),用来在定义层时调用(keras.regularizers.l1,keras.regularizers.l2,keras.regularizers.l1_l2)。

自定义层加入正则化

关于自定义层如何定义,不在此说明,若有不懂,可以随便搜一下,有很多讲解,keras官方文档也有相关教程。
自定义层如同所有定义好的层一样,继承于base_layer,其参数定义也使用的是add_weight,说到这里,相信大家都明白了。只需要在定义层时,加入regularizers的定义即可,例如LSTM,其中的recurrent部分:

class lstm(Layer): def __init__(self, kernel_regularizer=None, bias_regularizer=None, recurrent_regularizer=None, **kwargs): self.kernel_regularizer = regularizers.get(kernel_regularizer) self.recurrent_regularizer = regularizers.get(recurrent_regularizer) self.bias_regularizer = regularizers.get(bias_regularizer) def build(self, input_shape): self.kernel = self.add_weight(shape=(input_dim, self.units * 4), name='kernel', initializer=self.kernel_initializer, regularizer=self.kernel_regularizer, constraint=self.kernel_constraint) self.recurrent_kernel = self.add_weight( shape=(self.units, self.units * 4), name='recurrent_kernel', initializer=self.recurrent_initializer, regularizer=self.recurrent_regularizer, constraint=self.recurrent_constraint)

给自己定义的参数部分加上你想要的正则化,在_init_中定义,build中的add_weight加入。

云直播播放域名配置 ULive

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。