pytorch dropout解决过拟合

2022-10-19 10:18:30

训练时误差降得很低了,但是测试的时候,误差很高,说明过拟合了。这里用dropout来处理过拟合。只要在神经网络中加入dropout层就可以了。

首先来做一些数据

import torchimport matplotlib.pyplotas plt

torch.manual_seed(1)# reproducible

N_SAMPLES=20#定义20个数据点
N_HIDDEN=300# training data
x= torch.unsqueeze(torch.linspace(-1,1, N_SAMPLES),1)
y= x+0.3*torch.normal(torch.zeros(N_SAMPLES,1), torch.ones(N_SAMPLES,1))# test data
test_x= torch.unsqueeze(torch.linspace(-1,1, N_SAMPLES),1)
test_y= test_x+0.3*torch.normal(torch.zeros(N_SAMPLES,1), torch.ones(N_SAMPLES,1))# show data
plt.scatter(x.data.numpy(), y.data.numpy(), c='magenta', s=50, alpha=0.5, label='train')
plt.scatter(test_x.data.numpy(), test_y.data.numpy(), c='cyan', s=50, alpha=0.5, label='test')
plt.legend(loc='upper left')
plt.ylim((-2.5,2.5))
plt.show()

在这里插入图片描述
这里建立两个神经网络,一个是有dropout处理的命名为net_dropout,另一个是没有dropout的命名为net_overfitting

torch.nn.Dropout(0.5)表示随机忽略掉神经元中的50%来训练,随机屏蔽掉其中一半的节点,使其不会传递数据

#这里建立两个神经网络一个是具有过拟合功能的神经网络,一个是普通无过拟合的神经网络
net_overfitting= torch.nn.Sequential(
    torch.nn.Linear(1, N_HIDDEN),
    torch.nn.ReLU(),
    torch.nn.Linear(N_HIDDEN, N_HIDDEN),
    torch.nn.ReLU(),
    torch.nn.Linear(N_HIDDEN,1),)

net_dropped= torch.nn.Sequential(
    torch.nn.Linear(1, N_HIDDEN),
    torch.nn.Dropout(0.5),# drop 50% of the neuron
    torch.nn.ReLU(),
    torch.nn.Linear(N_HIDDEN, N_HIDDEN),
    torch.nn.Dropout(0.5),# drop 50% of the neuron
    torch.nn.ReLU(),
    torch.nn.Linear(N_HIDDEN,1),)print(net_overfitting)print(net_dropped)

在这里插入图片描述

#分别设置两个不同的优化器
optimizer_ofit= torch.optim.Adam(net_overfitting.parameters(), lr=0.01)
optimizer_drop= torch.optim.Adam(net_dropped.parameters(), lr=0.01)
loss_func= torch.nn.MSELoss()

plt.ion()#训练for tinrange(500):
    pred_ofit= net_overfitting(x)
    pred_drop= net_dropped(x)

    loss_ofit= loss_func(pred_ofit, y)
    loss_drop= loss_func(pred_drop, y)

    optimizer_ofit.zero_grad()
    optimizer_drop.zero_grad()
    loss_ofit.backward()
    loss_drop.backward()
    optimizer_ofit.step()
    optimizer_drop.step()# 接着上面来if t%10==0:# 每 10 步画一次图# 将神经网络转换成测试形式, 画好图之后改回 训练形式
        net_overfitting.eval() 
        net_dropped.eval()# 因为 drop 网络在 train 的时候和 test 的时候参数不一样#在测试的时候不需要忽略掉其中一半的神经元去测试,直接使用所有的神经元测试,所以这里取消掉dropout的功能
        
        plt.cla()#测试此时的神经网络的测试效果
        test_pred_ofit= net_overfitting(test_x)
        test_pred_drop= net_dropped(test_x)
        
        plt.scatter(x.data.numpy(), y.data.numpy(), c='magenta', s=50, alpha=0.3, label='train')
        plt.scatter(test_x.data.numpy(), test_y.data.numpy(), c='cyan', s=50, alpha=0.3, label='test')
        plt.plot(test_x.data.numpy(), test_pred_ofit.data.numpy(),'r-', lw=3, label='overfitting')
        plt.plot(test_x.data.numpy(), test_pred_drop.data.numpy(),'b--', lw=3, label='dropout(50%)')
        plt.text(0,-1.2,'overfitting loss=%.4f'% loss_func(test_pred_ofit, test_y).data.numpy(), fontdict={'size':20,'color':'red'})
        plt.text(0,-1.5,'dropout loss=%.4f'% loss_func(test_pred_drop, test_y).data.numpy(), fontdict={'size':20,'color':'blue'})
        plt.legend(loc='upper left'); plt.ylim((-2.5,2.5));plt.pause(0.1)# 将两个网络改回 训练形式,继续下面的训练步骤
        net_overfitting.train()
        net_dropped.train()

plt.ioff()
plt.show()

在这里插入图片描述
发现红线对training_data的loss越来越小,但是在test_data上就误差还是很大,而蓝线虽然没有那么贴合training_data,但是对于test_data的预测比红线要好

可以尝试如果在测试环节,没有把dropout的功能去掉,蓝线对于测试数据的贴合也不是那么好,因为在预测的时候并没有使用到全部的神经元,而是随机忽略掉了一部分神经元

在这里插入图片描述

  • 作者:逆夏11111
  • 原文链接:https://blog.csdn.net/weixin_43955530/article/details/107492975
    更新时间:2022-10-19 10:18:30