pytorch筆記13--過擬合&dropout

導致過擬合的原因:訓練網絡的數據量太少;網絡神經元太多; 

解決過擬合:增加訓練時的數據量;正規化;dropout(每次隨機丟棄一定數量的neuron,防止對神經元的過分依賴)

1. 訓練過程用兩個不同的網絡測試,動圖如下:(自己截動圖很麻煩,所以從網上拿來的)

2. 自己運行的結果圖如下:可以看到沒加dropout的網絡幾乎照顧到了每一個訓練數據(過擬合),但是對測試數據來說效果就很差了;

注意:加了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()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章