深度学习|PyTorch学习笔记(四)(PyTorch基础实战)

PyTorch实战:以FashionMNIST时装分类为例: 往期学习资料推荐: 1.Pytorch实战笔记_GoAI的博客-CSDN博客
2.Pytorch入门教程_GoAI的博客-CSDN博客
本系列目录: PyTorch学习笔记(一):PyTorch环境安装
PyTorch学习笔记(二):简介与基础知识
PyTorch学习笔记(三):PyTorch主要组成模块
PyTorch学习笔记(四):PyTorch基础实战
PyTorch学习笔记(五):模型定义、修改、保存
后续继续更新!!!!
1.导入必要的包

import os import numpy as np import pandas as pd import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader

2 配置训练环境和超参数
# 配置GPU,这里有两种方式 ## 方案一:使用os.environ os.environ['CUDA_VISIBLE_DEVICES'] = '0' # 方案二:使用“device”,后续对要使用GPU的变量用.to(device)即可 #device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")## 配置其他超参数,如batch_size, num_workers, learning rate, 以及总的epochs batch_size = 256 num_workers = 4# 对于Windows用户,这里应设置为0,否则会出现多线程错误 lr = 1e-4 epochs = 20

3 数据读取和加载 这里同时展示两种方式:
  • 下载并使用PyTorch提供的内置数据集
  • 从网站下载以csv格式存储的数据,读入并转成预期的格式
    第一种数据读入方式只适用于常见的数据集,如MNIST,CIFAR10等,PyTorch官方提供了数据下载。这种方式往往适用于快速测试方法(比如测试下某个idea在MNIST数据集上是否有效)
    第二种数据读入方式需要自己构建Dataset,这对于PyTorch应用于自己的工作中十分重要
同时,还需要对数据进行必要的变换,比如说需要将图片统一为一致的大小,以便后续能够输入网络训练;需要将数据格式转为Tensor类,等等。
from torchvision import transforms# 设置数据变换 image_size = 28 data_transform = transforms.Compose([ transforms.ToPILImage(),# 这一步取决于后续的数据读取方式,如果使用内置数据集则不需要 transforms.Resize(image_size), transforms.ToTensor() ])

## 读取方式一:使用torchvision自带数据集,下载可能需要一段时间 from torchvision import datasetstrain_data = https://www.it610.com/article/datasets.FashionMNIST(root='./', train=True, download=True, transform=data_transform) test_data = https://www.it610.com/article/datasets.FashionMNIST(root='./', train=False, download=True, transform=data_transform)

## 读取方式二:读入csv格式的数据,自行构建Dataset类,即自定义数据集 # csv数据下载链接:https://www.kaggle.com/zalando-research/fashionmnist class FMDataset(Dataset): def __init__(self, df, transform=None): self.df = df self.transform = transform self.images = df.iloc[:,1:].values.astype(np.uint8) self.labels = df.iloc[:, 0].valuesdef __len__(self): return len(self.images)def __getitem__(self, idx): image = self.images[idx].reshape(28,28,1) label = int(self.labels[idx]) if self.transform is not None: image = self.transform(image) else: image = torch.tensor(image/255., dtype=torch.float) label = torch.tensor(label, dtype=torch.long) return image, labeltrain_df = pd.read_csv("./FashionMNIST/fashion-mnist_train.csv") test_df = pd.read_csv("./FashionMNIST/fashion-mnist_test.csv") train_data = https://www.it610.com/article/FMDataset(train_df, data_transform) test_data = FMDataset(test_df, data_transform)

在构建训练和测试数据集完成后,需要定义DataLoader类,以便在训练和测试时加载数据
train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True, num_workers=num_workers, drop_last=True) test_loader = DataLoader(test_data, batch_size=batch_size, shuffle=False, num_workers=num_workers)

读入后,我们可以做一些数据可视化操作,主要是验证我们读入的数据是否正确
import matplotlib.pyplot as plt image, label = next(iter(train_loader)) print(image.shape, label.shape) plt.imshow(image[0][0], cmap="gray")

torch.Size([256, 1, 28, 28]) torch.Size([256])

深度学习|PyTorch学习笔记(四)(PyTorch基础实战)
文章图片
???
4.模型设计
# 使用CNN class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv = nn.Sequential( nn.Conv2d(1, 32, 5), nn.ReLU(), nn.MaxPool2d(2, stride=2), nn.Dropout(0.3), nn.Conv2d(32, 64, 5), nn.ReLU(), nn.MaxPool2d(2, stride=2), nn.Dropout(0.3) ) self.fc = nn.Sequential( nn.Linear(64*4*4, 512), nn.ReLU(), nn.Linear(512, 10) )def forward(self, x): x = self.conv(x) x = x.view(-1, 64*4*4) x = self.fc(x) # x = nn.functional.normalize(x) return x

model = Net() model = model.cuda()

5 设置损失函数和优化器
# 使用交叉熵损失函数 criterion = nn.CrossEntropyLoss()

# 使用Adam优化器 optimizer = optim.Adam(model.parameters(), lr=0.001)

6.训练与测试 各自封装成函数,方便后续调用
关注两者的主要区别:
  • 模型状态设置
  • 是否需要初始化优化器
  • 是否需要将loss传回到网络
  • 是否需要每步更新optimizer
【深度学习|PyTorch学习笔记(四)(PyTorch基础实战)】此外,对于测试或验证过程,可以计算分类准确率
def train(epoch): # 设置训练状态 model.train() train_loss = 0 # 循环读取DataLoader中的全部数据 for data, label in train_loader: # 将数据放到GPU用于后续计算 data, label = data.cuda(), label.cuda() # 将优化器的梯度清0 optimizer.zero_grad() # 将数据输入给模型 output = model(data) # 设置损失函数 loss = criterion(output, label) # 将loss反向传播给网络 loss.backward() # 使用优化器更新模型参数 optimizer.step() # 累加训练损失 train_loss += loss.item() * data.size(0) train_loss = train_loss/len(train_loader.dataset) print('Epoch: {} \tTraining Loss: {:.6f}'.format(epoch, train_loss))

def val(epoch): # 设置验证状态 model.eval() val_loss = 0 gt_labels = [] pred_labels = [] # 不设置梯度 with torch.no_grad(): for data, label in test_loader: data, label = data.cuda(), label.cuda() output = model(data) preds = torch.argmax(output, 1) gt_labels.append(label.cpu().data.numpy()) pred_labels.append(preds.cpu().data.numpy()) loss = criterion(output, label) val_loss += loss.item()*data.size(0) # 计算验证集的平均损失 val_loss = val_loss/len(test_loader.dataset) gt_labels, pred_labels = np.concatenate(gt_labels), np.concatenate(pred_labels) # 计算准确率 acc = np.sum(gt_labels==pred_labels)/len(pred_labels) print('Epoch: {} \tValidation Loss: {:.6f}, Accuracy: {:6f}'.format(epoch, val_loss, acc))

for epoch in range(1, epochs+1): train(epoch) val(epoch)

Epoch: 1Training Loss: 0.664049 Epoch: 1Validation Loss: 0.421500, Accuracy: 0.852400 Epoch: 2Training Loss: 0.417311 Epoch: 2Validation Loss: 0.349790, Accuracy: 0.871200 Epoch: 3Training Loss: 0.355448 Epoch: 3Validation Loss: 0.318987, Accuracy: 0.879500 Epoch: 4Training Loss: 0.323644 Epoch: 4Validation Loss: 0.290521, Accuracy: 0.893800 Epoch: 5Training Loss: 0.301900 Epoch: 5Validation Loss: 0.266420, Accuracy: 0.901300 Epoch: 6Training Loss: 0.286696 Epoch: 6Validation Loss: 0.246448, Accuracy: 0.909700 Epoch: 7Training Loss: 0.271441 Epoch: 7Validation Loss: 0.241845, Accuracy: 0.911200 Epoch: 8Training Loss: 0.260185 Epoch: 8Validation Loss: 0.243311, Accuracy: 0.910800 Epoch: 9Training Loss: 0.247986 Epoch: 9Validation Loss: 0.225896, Accuracy: 0.916200 Epoch: 10Training Loss: 0.240718 Epoch: 10Validation Loss: 0.227848, Accuracy: 0.914700 Epoch: 11Training Loss: 0.232358 Epoch: 11Validation Loss: 0.220180, Accuracy: 0.917500 Epoch: 12Training Loss: 0.223933 Epoch: 12Validation Loss: 0.215308, Accuracy: 0.919400 Epoch: 13Training Loss: 0.218354 Epoch: 13Validation Loss: 0.211890, Accuracy: 0.919300 Epoch: 14Training Loss: 0.210027 Epoch: 14Validation Loss: 0.209707, Accuracy: 0.922700 Epoch: 15Training Loss: 0.203024 Epoch: 15Validation Loss: 0.208233, Accuracy: 0.925600 Epoch: 16Training Loss: 0.196965 Epoch: 16Validation Loss: 0.208209, Accuracy: 0.921900 Epoch: 17Training Loss: 0.193155 Epoch: 17Validation Loss: 0.200000, Accuracy: 0.926100 Epoch: 18Training Loss: 0.184376 Epoch: 18Validation Loss: 0.197259, Accuracy: 0.926200 Epoch: 19Training Loss: 0.184272 Epoch: 19Validation Loss: 0.200259, Accuracy: 0.926000 Epoch: 20Training Loss: 0.172641 Epoch: 20Validation Loss: 0.200177, Accuracy: 0.927100

7.模型保存
save_path = "./FahionModel.pkl" torch.save(model, save_path)



    推荐阅读