动量、学习率、Early Stopping、Dropout

动量和学习率

1、动量(momentum)

梯度更新:

动量:

其中Z表示的是前一次梯度的方向,根据矢量三角形法则,选取下次的运动方向。

在这里插入图片描述
不加动量的情况下,方向变化比较尖锐,没有考虑历史变化的情况,且容易局部最优。
在这里插入图片描述
加动量后,变化更加的缓和,依靠惯性,可能跳出局部最优解。

optimizer = SGD(learning_rate=0.02, momentum=0.9)
optimizer = RMSprop(learning_rate=0.02, momentum=0.9)
optimizer = Adam(learning_rate=0.02, beta_1=0.9, beta_2=0.999)

2、学习率(learning_rate)

运用梯度下降算法进行优化时,权重的更新规则中,在梯度项前会乘以一个系数,这个系数就叫学习速率。
在这里插入图片描述
上图左边的是学习率太小,梯度更新速度太慢;右边是学习率太大,更新速度太快,最后可能找不到最优解。所以需要学习率能够动态的变化,可以根据自己的需要添加变化条件。

当validation accuracy满足 no-improvement-in-n规则时,本来我们是要early stopping的,但是我们可以不stop,而是让learning rate减半,之后让程序继续跑。下一次validation accuracy又满足no-improvement-in-n规则时,我们同样再将learning rate减半(此时变为原始learni rate的四分之一)…继续这个过程,直到learning rate变为原来的1/1024再终止程序。(1/1024还是1/512还是其他可以根据实际确定)。【PS:也可以选择每一次将learning rate除以10,而不是除以2.】

optimizer = SGD(learning_rate=0.02)

for epoch in range(100):
    #get loss
    
    # change learning_rate
    optimizer.learning_rate() = 0.2 * (100-epoch)/100
    
    #update weights
#Assuming optimizer uses lr = 0.05 for all groups
#lr = 0.05       if epoch < 30
#lr = 0.005      if 30 <= epoch < 60
#lr = 0.0005     if 60 <= epoch < 90

3、Early Stopping

所谓early stopping,即在每一个epoch结束时(一个epoch即对所有训练数据的一轮遍历)计算 validation data的accuracy,当accuracy不再提高时,就停止训练。这是很自然的做法,因为accuracy不再提高了,训练下去也没用。另外,这样做还能防止overfitting(过拟合)。

那么,怎么样才算是validation accuracy不再提高呢?并不是说validation accuracy一降下来,它就是“不再提高”,因为可能经过这个epoch后,accuracy降低了,但是随后的epoch又让accuracy升上去了,所以不能根据一两次的连续降低就判断“不再提高”。正确的做法是,在训练的过程中,记录最佳的validation accuracy,当连续10次epoch(或者更多次)没达到最佳accuracy时,你可以认为“不再提高”,此时使用early stopping。这个策略就叫“ no-improvement-in-n”,n即epoch的次数,可以根据实际情况取10、20、30….

4、Dropout

当一个复杂的前馈神经网络被训练在小的数据集时,容易造成过拟合。为了防止过拟合,可以通过阻止特征检测器的共同作用来提高神经网络的性能。

Dropout说的简单一点就是:我们在前向传播的时候,让某个神经元的激活值以一定的概率p停止工作,这样可以使模型泛化性更强,因为它不会太依赖某些局部的特征,如图1所示。
图1:使用Dropout的神经网络模型
Dropout具体工作流程
假设我们要训练这样一个神经网络,如图2所示。
图2:标准的神经网络
输入是x输出是y,正常的流程是:我们首先把x通过网络前向传播,然后把误差反向传播以决定如何更新参数让网络进行学习。使用Dropout之后,过程变成如下:

(1)首先随机(临时)删掉网络中一半的隐藏神经元,输入输出神经元保持不变(图3中虚线为部分临时被删除的神经元)
图3:部分临时被删除的神经元
(2) 然后把输入x通过修改后的网络前向传播,然后把得到的损失结果通过修改的网络反向传播。一小批训练样本执行完这个过程后,在没有被删除的神经元上按照随机梯度下降法更新对应的参数(w,b)。

(3)然后继续重复这一过程:

. 恢复被删掉的神经元(此时被删除的神经元保持原样,而没有被删除的神经元已经有所更新)
. 从隐藏层神经元中随机选择一个一半大小的子集临时删除掉(备份被删除神经元的参数)。
. 对一小批训练样本,先前向传播然后反向传播损失并根据随机梯度下降法更新参数(w,b) (没有被删除的那一部分参数得到更新,删除的神经元参数保持被删除前的结果)。
不断重复这一过程。

可以在网络层中直接调用dropout。

network = Sequential([layers.Dense(256, activation='relu'),
                     layers.Dropout(0.5), # 0.5 rate to drop
                     layers.Dense(128, activation='relu'),
                     layers.Dropout(0.5), # 0.5 rate to drop
                     layers.Dense(64, activation='relu'),
                     layers.Dense(32, activation='relu'),
                     layers.Dense(10)])

添加了dropout后training和test部分不一样,需要人为的区分。

for step, (x,y) in enumerate(db):

    with tf.GradientTape() as tape:
        # [b, 28, 28] => [b, 784]
        x = tf.reshape(x, (-1, 28*28))
        # [b, 784] => [b, 10]
        out = network(x, training=True)
    
    
    #test
    out = network(x, training=False)  

完整代码:

import  os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'

import  tensorflow as tf
from    tensorflow.keras import datasets, layers, optimizers, Sequential, metrics


def preprocess(x, y):

    x = tf.cast(x, dtype=tf.float32) / 255.
    y = tf.cast(y, dtype=tf.int32)

    return x,y


batchsz = 128
(x, y), (x_val, y_val) = datasets.mnist.load_data()
print('datasets:', x.shape, y.shape, x.min(), x.max())



db = tf.data.Dataset.from_tensor_slices((x,y))
db = db.map(preprocess).shuffle(60000).batch(batchsz).repeat(10)

ds_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))
ds_val = ds_val.map(preprocess).batch(batchsz) 




network = Sequential([layers.Dense(256, activation='relu'),
                     layers.Dropout(0.5), # 0.5 rate to drop
                     layers.Dense(128, activation='relu'),
                     layers.Dropout(0.5), # 0.5 rate to drop
                     layers.Dense(64, activation='relu'),
                     layers.Dense(32, activation='relu'),
                     layers.Dense(10)])
network.build(input_shape=(None, 28*28))
network.summary()

optimizer = optimizers.Adam(lr=0.01)



for step, (x,y) in enumerate(db):

    with tf.GradientTape() as tape:
        # [b, 28, 28] => [b, 784]
        x = tf.reshape(x, (-1, 28*28))
        # [b, 784] => [b, 10]
        out = network(x, training=True)
        # [b] => [b, 10]
        y_onehot = tf.one_hot(y, depth=10) 
        # [b]
        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
 

    grads = tape.gradient(loss, network.trainable_variables)
    optimizer.apply_gradients(zip(grads, network.trainable_variables))


    if step % 100 == 0:

        print(step, 'loss:', float(loss), 'loss_regularization:', float(loss_regularization)) 


    # evaluate
    if step % 500 == 0:
        total, total_correct = 0., 0

        for step, (x, y) in enumerate(ds_val): 
            # [b, 28, 28] => [b, 784]
            x = tf.reshape(x, (-1, 28*28))
            # [b, 784] => [b, 10] 
            out = network(x, training=True)  
            # [b, 10] => [b] 
            pred = tf.argmax(out, axis=1) 
            pred = tf.cast(pred, dtype=tf.int32)
            # bool type 
            correct = tf.equal(pred, y)
            # bool tensor => int tensor => numpy
            total_correct += tf.reduce_sum(tf.cast(correct, dtype=tf.int32)).numpy()
            total += x.shape[0]

        print(step, 'Evaluate Acc with drop:', total_correct/total)

        total, total_correct = 0., 0

        for step, (x, y) in enumerate(ds_val): 
            # [b, 28, 28] => [b, 784]
            x = tf.reshape(x, (-1, 28*28))
            # [b, 784] => [b, 10] 
            out = network(x, training=False)  
            # [b, 10] => [b] 
            pred = tf.argmax(out, axis=1) 
            pred = tf.cast(pred, dtype=tf.int32)
            # bool type 
            correct = tf.equal(pred, y)
            # bool tensor => int tensor => numpy
            total_correct += tf.reduce_sum(tf.cast(correct, dtype=tf.int32)).numpy()
            total += x.shape[0]

        print(step, 'Evaluate Acc without drop:', total_correct/total)

参考:
https://blog.csdn.net/chezhai/article/details
深度学习中Dropout原理解析

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: PyTorch Early Stopping是一种用于训练深度学习模型的技术。当训练模型时,我们通常会设置一个固定的训练轮数,然后在每个训练轮结束后评估模型的性能。然而,有时模型在训练过程中会出现过拟合的情况,即模型在训练集上表现良好,但在未见过的数据上表现不佳。 为了解决过拟合问题,Early Stopping技术引入了一个称为“patience”的超参数。Patience表示在模型性能不再提升时需要等待的训练轮数。具体来说,当模型在超过patience个训练轮数后性能没有明显提升时,训练将被提前停止,从而避免了继续训练过拟合的模型。 实现Early Stopping的一种常见方法是使用验证集(validation set)。在每个训练轮结束后,将训练好的模型在验证集上进行评估,并记录模型的性能指标,如损失函数或准确率。如果模型的性能指标在连续的patience个训练轮中都没有明显提升,那么就说明模型已经达到了性能的极限,此时训练过程将被停止。 PyTorch提供了一些开源的工具库,如torch.optim和torchvision等,这些工具库中包含了Early Stopping的实现。在使用PyTorch进行深度学习模型训练时,我们可以通过在每个训练轮结束后进行模型性能评估,并比较连续的几次评估结果,来判断是否需要提前停止训练。 总而言之,PyTorch Early Stopping是一种用于避免模型过拟合的技术,通过在每个训练轮结束后评估模型性能,并设置适当的patience值,可以在训练过程中及时停止模型的训练,从而获得更好的泛化能力和性能。 ### 回答2: PyTorch是一个广泛使用的开源深度学习框架,而Early Stopping则是一种用于训练过程中自动停止模型训练的技术。PyTorch提供了一种方便的方法来实现Early StoppingEarly Stopping主要通过监控模型在验证集上的性能指标来判断是否停止训练。在训练过程中,可以在每个训练周期结束后对验证集进行评估,并根据评估结果来判断当前模型的性能是否有所提升。 通常情况下,可以设置一个patience参数,该参数表示如果在连续多个训练周期中性能指标没有提升,就认为模型已经停止改进,从而停止训练。在模型训练过程中,当连续多个周期中性能指标没有提升时,可以通过设置一个计数器来进行累计,并与patience进行比较。 当计数器达到patience时,可以选择在当前训练周期结束后停止训练,并保存最佳模型参数。这个最佳模型参数是根据验证集上的性能指标来确定的,通常是在训练过程中保存验证集上性能最好的模型参数。 通过使用Early Stopping技术,可以防止模型过拟合,并能更加高效地训练深度学习模型。PyTorch提供了一些库函数和回调函数,可以方便地在训练过程中实现Early Stopping。例如,可以使用`torchbearer`库来实现Early Stopping,并设置patience参数来控制训练的停止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值