0
点赞
收藏
分享

微信扫一扫

PyTorch基础(part6)--Dropout

圣杰 2022-01-24 阅读 83

学习笔记,仅供参考,有错必纠


文章目录


Dropout

Dropout可以抵抗过拟合的状态,但是不是在所有情况下使用Dropout,模型精度都会提高,一般而言在更为复杂的模型中Dropout会发挥更大的作用.

代码

初始设置

# 支持多行输出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all' #默认为'last'

导包

# 导入常用的包
import numpy as np
from torch import nn,optim
from torch.autograd import Variable
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import torch

载入数据

# 载入数据
train_dataset = datasets.MNIST(root = './data/', # 载入的数据存放的位置
                               train = True, # 载入训练集数据
                               transform = transforms.ToTensor(), # 将载入进来的数据变成Tensor
                               download = True) # 是否下载数据
test_dataset = datasets.MNIST(root = './data/', # 载入的数据存放的位置
                               train = False, # 载入测试集数据
                               transform = transforms.ToTensor(), # 将载入进来的数据变成Tensor
                               download = True) # 是否下载数据
# 批次大小
batch_size = 64

# 装载训练集
train_loader = DataLoader(dataset=train_dataset,
                         batch_size=batch_size,
                         shuffle=True)

# 装载训练集
test_loader = DataLoader(dataset=test_dataset,
                         batch_size=batch_size,
                         shuffle=True)

模型

这里我们使用具有多层网络结构的模型,并加入Dropout操作.

# 定义网络结构
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 构建次序结构,首先定义一个隐藏层,并使50%的神经元不工作(针对隐藏层神经元),最后增加一个激活函数
        self.layer1 = nn.Sequential(nn.Linear(784,500), nn.Dropout(p = 0.5), nn.Tanh())
        # 再定义一个隐藏层
        self.layer2 = nn.Sequential(nn.Linear(500,300), nn.Dropout(p = 0.5), nn.Tanh())
        # 输出层
        self.layer3 = nn.Sequential(nn.Linear(300,10), nn.Softmax(dim=1))
        
        
    def forward(self,x):
        # ([64, 1, 28, 28])->(64,784)
        x = x.view(x.size()[0], -1)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        return x
LR = 0.5
# 定义模型
model = Net()
# 定义代价函数为交叉熵代价函数
mse_loss = nn.CrossEntropyLoss()
# 定义优化器
optimizer = optim.SGD(model.parameters(), LR)

在自定义训练和测试函数中,我们分别增加两个方法,model.train()model.eval() ,这model.train()方法可以使训练集中的Dropout在训练模型时发挥作用,而model.eval()则可以使模型在测试过程中不工作.

def train():
    model.train()
    for i,data in enumerate(train_loader):
        # 获得一个批次的数据和标签
        inputs, labels = data
        # 获得模型预测结果(64,10)
        out = model(inputs)
        # 计算loss,交叉熵代价函数out(batch,C), labels(batch)
        loss = mse_loss(out, labels)
        # 梯度清0
        optimizer.zero_grad()
        # 计算梯度
        loss.backward()
        # 修改权值
        optimizer.step()

def test():
    model.eval()
    
    # 计算训练集准确率
    correct = 0
    for i,data in enumerate(train_loader):
        # 获得一个批次的数据和标签
        inputs, labels = data
        # 获得模型预测结果(64,10)
        out = model(inputs)
        # 获得最大值,以及最大值所在的位置
        _, predicted = torch.max(out, 1)
        # 预测正确的数量
        correct += (predicted == labels).sum()
    print("Train acc:{0}".format(correct.item()/len(train_dataset)))
    
    # 计算测试集准确率
    correct = 0
    for i,data in enumerate(test_loader):
        # 获得一个批次的数据和标签
        inputs, labels = data
        # 获得模型预测结果(64,10)
        out = model(inputs)
        # 获得最大值,以及最大值所在的位置
        _, predicted = torch.max(out, 1)
        # 预测正确的数量
        correct += (predicted == labels).sum()
    print("Test acc:{0}".format(correct.item()/len(test_dataset)))
    
for epoch in range(15):
    print('epoch:',epoch)
    train()
    test()
epoch: 0
Train acc:0.9074333333333333
Test acc:0.9102
epoch: 1
Train acc:0.9326166666666666
Test acc:0.9317
epoch: 2
Train acc:0.9373
Test acc:0.937
epoch: 3
Train acc:0.9478333333333333
Test acc:0.9457
epoch: 4

对比上一篇blog中的训练准确率,在训练相同次数的情况下,使用交叉熵代价函数的效果会更好一些.

举报

相关推荐

0 条评论