pytorch笔记13--过拟合&dropout

导致过拟合的原因:训练网络的数据量太少;网络神经元太多; 

解决过拟合:增加训练时的数据量;正规化;dropout(每次随机丢弃一定数量的neuron,防止对神经元的过分依赖)

1. 训练过程用两个不同的网络测试,动图如下:(自己截动图很麻烦,所以从网上拿来的)

pytorch笔记13--过拟合&dropout_第1张图片

2. 自己运行的结果图如下:可以看到没加dropout的网络几乎照顾到了每一个训练数据(过拟合),但是对测试数据来说效果就很差了;

pytorch笔记13--过拟合&dropout_第2张图片

注意:加了dropout的网络在进行测试时,要声明是测试模式(net.eval()),测试结束再有训练时,要声明是训练模式(net.train())。由于在训练过程中drop了一部分的neuron,所以神经网络在训练和测试时的参数是不同的。

import torch
import matplotlib.pyplot as plt
import torch.nn as nn

torch.manual_seed(1)

# 数据量过少,神经元比数据量多太多,容易引起过拟合
N_SAMPLES=20   # the number of data
N_HIDDENS=300  # the number of hidden units

# 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))


# 搭建两个神经网络,在训练时进行对比:net with dropout, net without dropout(overfitting)
net_overfit=nn.Sequential(
    torch.nn.Linear(1,N_HIDDENS),
    torch.nn.ReLU(),
    torch.nn.Linear(N_HIDDENS,N_HIDDENS),
    torch.nn.ReLU(),
    torch.nn.Linear(N_HIDDENS,1),
)
net_dropout=nn.Sequential(
    torch.nn.Linear(1,N_HIDDENS),
    torch.nn.ReLU(),
    torch.nn.Dropout(0.5),    # drop 50% of the neuron
    torch.nn.Linear(N_HIDDENS,N_HIDDENS),
    torch.nn.ReLU(),
    torch.nn.Dropout(0.5),
    torch.nn.Linear(N_HIDDENS,1)
)

# training
optimizer_overfit=torch.optim.Adam(net_overfit.parameters(),lr=0.01)
optimizer_dropout=torch.optim.Adam(net_dropout.parameters(),lr=0.01)
loss_func=torch.nn.MSELoss()

for epoch in range(500):
    pred_overfit=net_overfit(x)
    pred_dropout=net_dropout(x)

    loss_overfit=loss_func(pred_overfit,y)
    loss_dropout=loss_func(pred_dropout,y)

    optimizer_overfit.zero_grad()
    optimizer_dropout.zero_grad()

    loss_overfit.backward()
    loss_dropout.backward()

    optimizer_overfit.step()
    optimizer_dropout.step()

    # 对两个网络的训练过程进行测试,可视化
    if epoch % 10 == 0:

        # net_overfit.eval()   #对于 net_overfit,这一步可有可无
        net_dropout.eval()   # 改为测试模式,因为有dropout的网络在train和test时的参数不一样,所以要有这一句

        # 可视化过程
        plt.cla()              #清除当前活动的轴,其他轴不受影响
        test_pred_overgit=net_overfit(test_x)
        test_pred_dropout=net_dropout(test_x)

        plt.scatter(x.data.numpy(), y.data.numpy(), label='train_data')
        plt.scatter(test_x.data.numpy(), test_y.data.numpy(), label='test_data')

        plt.plot(test_x.data.numpy(),test_pred_overgit.data.numpy(),label='overfitting',color='black')
        plt.plot(test_x.data.numpy(),test_pred_dropout.data.numpy(),label='dropout',color='red',linestyle='--')

        plt.text(0,-1.2,'overfitting loss=%.4f'%loss_func(test_pred_overgit,test_y).data.numpy())  # 文本显示的位置;
        plt.text(0,-1.5,'dropout loss=%.4f'%loss_func(test_pred_dropout,test_y).data.numpy(),color='red')  # 文本显示的位置;

        plt.xlim(-1.2,1.2)
        plt.ylim(-2,2)

        plt.legend(loc='upper left')
        plt.pause(0.1)

        #  测试完之后要把测试状态改为训练状态
        # net_overfit.train()
        net_dropout.train()
plt.show()

 

你可能感兴趣的:(pytorch)