首页 > 技术文章 > 小白学习莫烦pytorch笔记——Drop out解决过拟合

goudongxi 2020-08-30 11:22 原文

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import matplotlib.pyplot as plt

torch.manual_seed(1)

# hyper parameters
N_SAMPLES = 20
N_HIDDEN = 300

# training data linspace返回的是[20]的一维向量,也就是一个向量,它的size只是一个数字[20]。unsqueeze之后为(20, 1)
x = torch.unsqueeze(torch.linspace(-1, 1, N_SAMPLES), 1)
t = torch.linspace(-1, 1, N_SAMPLES)
# 20行1列的0作均值 20行1列的1作标准差 normal生成一个20行1列的tensor,其中的每个元素都是从0均值1标准差中正态sample出来的
# y是一个20行1列的tensor
y = x + 0.3*torch.normal(torch.zeros(N_SAMPLES, 1), torch.ones(N_SAMPLES, 1))
x, y = Variable(x), Variable(y)

# 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))
with torch.no_grad():
test_x, test_y = Variable(test_x), Variable(test_y)

# show data
# plt.scatter(x,y,c= '颜色可选',marker= '点的样式', cmap= '颜色变化',alpha=“透明度”, linewidths=“线宽”,s= '点的大小')
# 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()

net_overfitting = nn.Sequential(
nn.Linear(1, N_HIDDEN),
nn.ReLU(),
nn.Linear(N_HIDDEN, N_HIDDEN),
nn.ReLU(),
nn.Linear(N_HIDDEN, 1)
)

net_dropped = nn.Sequential(
nn.Linear(1, N_HIDDEN),
nn.Dropout(0.5), # 300个每个输入有50%概率被屏蔽掉
nn.ReLU(),
nn.Linear(N_HIDDEN, N_HIDDEN),
nn.Dropout(0.5),
nn.ReLU(),
nn.Linear(N_HIDDEN, 1),
)

optimizer_ofit = torch.optim.Adam(net_overfitting.parameters(), lr=0.01)
optimizer_drop = torch.optim.Adam(net_dropped.parameters(), lr=0.01)

loss_func = nn.MSELoss()

plt.ion()

# train
for t in range(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_drop.zero_grad()
optimizer_ofit.zero_grad()
loss_drop.backward()
loss_ofit.backward()
optimizer_ofit.step()
optimizer_drop.step()

if t % 10 == 0:
net_overfitting.eval()
net_dropped.eval() # 上面的是net_dropped.train()模式,对于dropout测试时需要用eval()模式

test_pred_ofit = net_overfitting(test_x)
test_pred_drop = net_dropped(test_x)

# 可视化
# 训练数据的sample
plt.cla()
plt.scatter(x.data.numpy(), y.data.numpy(), c='magenta', s=50, alpha=0.5, label='train')
# 测试数据的sample
plt.scatter(test_x.data.numpy(), test_y.data.numpy(), c='cyan', s=50, alpha=0.5, label='test')
# 过拟合测试的折线图 r-和b-- 是颜色+线形 -是实线 --是点划线 :是虚线 + 是十字线
plt.plot(test_x.data.numpy(), test_pred_ofit.data.numpy(), 'r-', label='overfitting')
# dropout测试的折线图
plt.plot(test_x.data.numpy(), test_pred_drop.data.numpy(), 'b--', label='drop out 50%')
plt.text(x=-0.5, y=-1.4, s="overfitting loss=%.4f" % loss_func(test_pred_ofit, test_y),
       fontdict={'size': 20, 'color': 'red'})
plt.text(x=-0.5, y=-1.8, s="dropout loss=%.4f" % loss_func(test_pred_drop, test_y),
       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()
通常过拟合出现的原因是:
1、数据量比较少
2、神经网络太复杂(比如隐藏层过多)

解决过拟合的方法:
1、增加数据量
2、使用正则化
          L1指正则化项是abs(w) L2指正则化项是(w)^2
有一种专门用于神经网络上的正则化方法叫做Dropout因为每次训练时都会删掉一些连接,则会使每次训练
         的输出不是过分依赖于某些特定的神经元L1和L2是打压参数w,但是Dropout是使输出没法过分依赖于w

 

 





推荐阅读