Pytorch 快速入门

处理数据

Pytorch使用torch.utils.data.DataLoadertorch.utils.data.Dataset来处理数据,其中Dataset用来存储数据集的样本和对应标签,DataLoader根据输入的Datasetbatch_size生成可迭代对象

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor

数据集

Pytorch中的torchtext torchvision torchaudio 提供数据集。其中,本次使用的torchvision.datasets中提供了大量视觉方面的数据集,这里使用其中的FashionMNIST数据集,train参数用来设置载入的是训练集还是测试集。

train_set = datasets.FashionMNIST(
    root='./data/FashionMNIST', 
    train=True, 
    download=True,
    transform=ToTensor()
)
test_set = datasets.FashionMNIST(
    root='./data/FashionMNIST', 
    train=False, 
    download=True,
    transform=ToTensor()
)

在这里插入图片描述
FashionMNIST训练集中有60000个数据,测试集中有10000个数据
在这里插入图片描述
每一条数据以元组的方式存储
在这里插入图片描述
元素第一项是以Tensor格式保存的图像,第二项是整数类型的标签

将数据集train_set,batch_size作为参数传送给DataLoader,可以得到数据集的可迭代对象,支持自动批处理(batch_size)、打乱(shuffle)、多进程读取数据(num_workers)。

batch_size = 100

train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_set, batch_size=batch_size, shuffle=True)
for X, y in train_loader:
    print(f'X shape:{X.shape}, X type:{type(X)}, len X:{len(X)}')
    print(f'y shape:{y.shape}, y type:{type(y)}') 
    break

在这里插入图片描述
迭代DataLoader可以得到处理好的一批次样本和标签,类型为Tensor,样本形状为[100,1,28,28],第一个维度是batch大小,第二个维度是图像的通道,这里是黑白图像只有一个通道,最后两个28是图像的宽高。标签的形状为[100],里面是100个整数类型的标签。

定义模型

Pytorch中的神经网络模型都可以从nn.Mudule类中继承,利用nn.Sequential函数可以快速搭建网络结构,本次实验的网络包含1个展平层nn.Faltten()和3个线性层nn.Linear(),线性层的参数为网络的输入和输出个数,线性层之间通过ReLU激活函数nn.ReLU()
网络的层数、每层的神经元个数都是超参数,需要根据问题的类型自行调整。

device = 'cuda' if torch.cuda.is_available() else 'cpu' # 选择GPU or CPU

#定义模型
class Network(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),
            nn.ReLU(),
            nn.Linear(512, 64),
            nn.ReLU(),
            nn.Linear(64, 10)
        )
        
    def forward(self, feature):
        feature = self.flatten(feature)
        pred = self.linear_relu_stack(feature)
        return pred
        
network = Network().to(device)
print(network)

该网络最后有十个输出,因为FashionMNIST数据集共有十类,网络根据十个输出中的最大值决定是哪一类。
在这里插入图片描述

模型训练

训练模型首先要定义损失函数和优化器,对于分类问题一般使用交叉熵损失nn.CrossEntropyLoss,该损失计算时会自动计算softmax,所以模型中不需要再加入softmax层。优化器这里使用torch.optim.SGD优化器,将学习率lr(learning rate)和要训练的网络的参数network.parameters传递给优化器

lr = 0.001

#定义损失函数
loss_fn = nn.CrossEntropyLoss()
#定义优化器
optimizer = torch.optim.SGD(network.parameters(), lr=lr)

再定义一个函数来统计预测正确的个数,网络的输出应该是一个形状为[100,10]的Tensor,第二的维度中的最大值的下标是网络分类的结果,也就是preds.argmax(dim=1),其形状为[100],与labels 的形状相同。使用item()可以将单元素Tensor直接转换成数值。

def get_num_correct(preds, labels):
    #return preds.argmax(dim=1).eq(labels).sum().item() 也可以这么写
    return (preds.argmax(dim=1) == labels).sum().item()

接下来开始训练模型,定义一个训练模型的函数,将要训练的网络、数据加载器、循环次数、损失函数、优化器作为参数输入。
训练时,函数会从train_loader中遍历每一个batch的数据,送入网络进行预测,并将预测值与数据标签计算损失。接着计算梯度,Pytorch计算梯度时会自动将本次梯度与之前的梯度进行累加,因此计算之前需要先将梯度清零,然后利用backward计算梯度,最后使用优化器更新网络参数。

#训练模型
def train(network, train_loader, epoch_num, loss_fn, optimizer):
    for epoch in range(epoch_num):
        total_loss = 0
        total_correct = 0
        
        for X, y in train_loader:
            X, y = X.to(device), y.to(device)
            # 前向通道 预测、计算loss
            preds = network(X)
            loss = loss_fn(preds, y)
            
            # 反向通道 Backpropagation
            optimizer.zero_grad() # 梯度清零
            loss.backward() # 计算梯度
            optimizer.step() # 更新参数
            
            total_loss += loss.item()
            total_correct += get_num_correct(preds, y)
        
        accuracy = total_correct / len(train_loader.dataset)
        print(f'epoch {epoch}, loss:{total_loss:.2f}, num_correct:{total_correct}, accuracy:{accuracy:.4f}')


epoch_num = 10
train(network, train_loader, epoch_num=epoch_num, loss_fn=loss_fn, optimizer=optimizer)

在这里插入图片描述
随着训练过程,模型的损失函数逐渐下降,预测的精确度逐渐上升

模型测试

最后需要测试模型在测试集上的表现,来确定模型的效果,定义一个函数

#测试模型
def test(network, test_loader, loss_fn):
    network.eval() # 将模型设置为评估状态
    test_loss, num_correct = 0, 0
    batch_index = 0
    with torch.no_grad():
        for X, y in test_loader:
            X, y = X.to(device), y.to(device)
            preds = network(X)
            loss = loss_fn(preds, y)
            
            test_loss += loss.item()
            num_correct += get_num_correct(preds, y)
            print(f'batch {batch_index}, loss:{loss}')
            batch_index += 1
    print(f'test_loss:{test_loss}, num_correct:{num_correct}, accuracy:{num_correct/len(test_loader.dataset):.4f}')
    
test(network, test_loader=test_loader, loss_fn=loss_fn)

在这里插入图片描述
模型在测试集上的表现与训练集基本一致,根据训练集和测试集的表现,可以判断模型是否训练到位,以及是否发生过拟合。

参考来源:
[1]: https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html#optimizing-the-model-parameters

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值