人工智能学习笔记大数据,机器学习,人工智能

【教程】Tensorflow vs PyTorch —— 正则化

2020-03-12  本文已影响0人  Hongtao洪滔

Image from unsplash.com by @tadekl

在机器学习的过程中,过拟合((overfiting)是一个非常常见的问题。解决过拟合有非常多的方法,比如增加样本数量,减少模型复杂度,Early Stopping 等。在无法增加样本个数,模型不变的情况下,正则化和dropout 是处理overfiting 最常见的方法。

获取文章代码请关注微信公众号"tensor_torch" 二维码见文末

1. 正则化

模型之所会出现过拟合的情况,是因为模型死记硬背了太多训练集中数据的特征而失去了范化能力。其特征就是在训练集有很低的损失函数,但是对于验证数据集的分类或预测效果却比较差。

造成过拟合其中的一个原因是某些权重在训练的过程中被放大,而正则化就相当于给权重加了一个惩罚因子,防止其变得过大。

具体操作就是将权重放在损失函数中进行后向传播。由于训练的目的是减小损失函数,所以在减小损失函数的过程中,权重的大小也被减少了。L1和L2正则化就是将权重的1范数(绝对值)和2范数(平方)添加到损失函数中一起训练,在降低损失函数的过程中同样减低了权重的大小。所以正则化的过程又叫做 Weight Decay。

Tensorflow 和 PyTorch 都提供了方便的正则化的方法。

在 Tensorflow 中,我们调用 keras.layers.Dense 对象时设置kernel_regularizer这个参数即可。
在 PyTorch 中,需要在 optimizer 中设置 weight_decay 即可,注意这里是 L2 正则化。

#---------------------------Tensorflow----------------------------

class FC_model(keras.Model):
    def __init__(self):
        super().__init__()
    
        # Regulariztion applied here
        self.model = keras.Sequential(
            [layers.Dense(200, kernel_regularizer=keras.regularizers.l2(0.001)),
            layers.ReLU(),
            layers.Dense(100,kernel_regularizer=keras.regularizers.l2(0.001)),
            layers.ReLU(),
            layers.Dense(10)]
            )
    
    def call(self,x):
        x = self.model(x)
        
        return x
    
#---------------------------PyTorch----------------------------------------
# L2 regularization == weight_decay in the optimizers
optimizer = torch.optim.Adam(network.parameters(),
                            lr=learning_rate, weight_decay=0.01)

2. Dropout

Dropout 就是在训练过程中,随机关闭一些神经元,从而提高模型范化能力。在Tensorflow 和 PyTorch 中均是在构建 model 的过程中在神经网络层之间插入 Dropout 层,具体来讲:

在 Tensorflow 中我们在构建 model 的过程中调用 keras.layers.Dropout(dorp_rate)
在 PyTorch 中 构建 model 过程中调用 torch.nn.Dropout(drop_rate)

#---------------------------Tensorflow----------------------------
class FC_model(keras.Model):
    def __init__(self):
        super().__init__()
    
        self.model = keras.Sequential(
            [layers.Dense(200),
            layers.ReLU(),
            layers.Dropout(0.4),
            layers.Dense(100),
            layers.ReLU(),
            layers.Dropout(0.4),             
            layers.Dense(10)]
            )
    
    def call(self,x):
        x = self.model(x)
        
        return x
#---------------------------PyTorch----------------------------------------
class FC_NN(nn.Module):
    def __init__(self):
        super().__init__()
    
        self.model = nn.Sequential(
            nn.Linear(28*28, 200),
            nn.ReLU(inplace=True),
            nn.Dropout(0.4),
            nn.Linear(200, 100),
            nn.ReLU(inplace=True),
            nn.Dropout(0.4),
            nn.Linear(100,10)
            )
    
    def forward(self, x):
        x = self.model(x)
        
        return x

3. 学习率下降

这里再补充一个训练神经网络的小技巧,就是 learning rate decay。 我们知道在用梯度下降训练神经网络的过程中,learning rate 越小,梯度下降得越慢。但是如果增加 learning rate 又容易造成损失函数在最小值附近徘徊不容易到达最低点的情况。

为了解决这个问题,我们可以使用学习速率下降的方法,在初期使用大的学习速率,在后期让其逐步减少从而让损失函数能够稳步探底。

在应用学习速率下降的过程中,Tensorflow 和 PyTorch的处理思路不同。在 Tensorflow 的训练过程中,我们可以用optimizer.learning_rate 获取当前的学习速率,或者通过赋值改变这个学习速率。换句话说就是可以在训练的过过程中干预和控制学习速率的大小。

这里我们在训练过程中提取 learning rate 并乘以一个小于 1 的下降率lr_decay ,知道 learning rate 小于我们设定的最小 learning rate (lr_min)。

# set initial learning rate and minimum learning rate
lr_init = 0.2
lr_min = 1e-6
lr_decay = 0.995

optimizer = tf.optimizers.SGD(learning_rate=lr_init)

global_step = 0

for epoch in range(epochs):
    
    for step, (x, y) in enumerate(ds_train):
        x = tf.reshape(x, [-1, 28*28])
        with tf.GradientTape() as tape:            
            logits = model(x)
            
            losses = tf.losses.sparse_categorical_crossentropy(y,logits,from_logits=True)
            loss = tf.reduce_mean(losses)
            
        grads = tape.gradient(loss, model.variables)
        
        # Decay learning rate here 
        if optimizer.learning_rate > lr_min:
          optimizer.learning_rate = optimizer.learning_rate * lr_decay
        
        optimizer.apply_gradients(zip(grads, model.variables))
        
        ...
# Print current learning rate         
        
    print('accuracy: ', accuracy, 'learing rate: ', optimizer.learning_rate.numpy())

PyToch 采用的是另一种策略,即设置 scheduler 当损失函数在若干步之后不再下降时,即减小学习速率。

scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=200)

...
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        # Update learning rate here
        scheduler.step(loss)
...

# Print current learning rate 
        print("learning rate: ", optimizer.param_groups[0]['lr'])

相关文章

【教程】Tensorflow vs PyTorch —— 可视化 Tensorboard vs Visdom
【教程】Tensorflow vs PyTorch —— 神经网络的搭建和训练
【教程】Tensorflow vs PyTorch —— 自动求导
【教程】Tensorflow vs PyTorch —— 数学运算
【教程】Tensorflow vs PyTorch —— 张量的基本操作
Tensorflow 2 vs PyTorch 对比学习教程开启
Tensorflow 2.0 --- ResNet 实战 CIFAR100 数据集
Tensorflow2.0——可视化工具tensorboard
Tensorflow2.0-数据加载和预处理
Tensorflow 2.0 快速入门 —— 引入Keras 自定义模型
Tensorflow 2.0 快速入门 —— 自动求导与线性回归
Tensorflow 2.0 轻松实现迁移学习
Tensorflow入门——Eager模式像原生Python一样简洁优雅
Tensorflow 2.0 —— 与 Keras 的深度融合


如果喜欢本教程,欢迎关注微信公众号和代码仓(如果喜欢不要忘了给星哟!),

image
上一篇下一篇

猜你喜欢

热点阅读