【youcans的深度学习 05】PyTorch入门教程:快速入门

欢迎关注『youcans的深度学习』系列,持续更新中…
【youcans的深度学习 01】安装环境之 miniconda
【youcans的深度学习 02】PyTorch CPU版本安装与环境配置
【youcans的深度学习 03】PyTorch CPU版本安装与环境配置
【youcans的深度学习 04】PyTorch入门教程:基础知识
【youcans的深度学习 05】PyTorch入门教程:快速入门



1. 基本步骤和程序框架

1.1 基本步骤

使用 PyTorch 建立、训练和使用神经网络模型的基本步骤如下。

  1. 准备数据集(Prepare dataset)
  2. 创建网络模型(Design model using Class)
  3. 设置损失函数和优化器(Construct loss and optimizer)
  4. 模型训练(Trainning the model)
  5. 模型保存与加载(Saving and loading a model)
  6. 模型推理/预测(Inferring model)

1.2 程序框架

# torch02_v1.py

# (0) 导入 PyTorch

# Define a neural network model
class NeuralNetwork(nn.Module):
	...

# model trainning
def train(dataloader, model, loss_fn, optimizer):
	...

# model testing
def test(dataloader, model, loss_fn):
	...


if __name__ == "__main__":
    # (1) 下载数据集
    # Download training data from open datasets.
    # Download test data from open datasets.

    # (2) 创建数据加载器
    # batch size
    # Create data loaders.

    # (3) 创建神经网络模型
    # Get cpu or gpu device for training.
    # Creat a model instance

    # (4) 模型训练
    # Define loss function and optimizer
    # Train the model
   
    # (5) 保存模型

    # (6) 加载模型

    # (7) 模型推理

2. 程序实现的具体过程

2.1 数据处理

PyTorch 中有两个重要的数据处理的类:torch.utils.data.DataLoadertorch.uutils.data.dataset
dataset 存储样本及标签,DataLoader为数据集构造一个可迭代的加载器。

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 库。torchvision.datasets 模块包含了许多视觉任务数据集,如 MNIST、CIFAR、COCO、ImageNet 等。每个 TorchVision 数据集 Dataset 都包括两个参数:transform 和 target_transform,用于分别设置样本和标签。

在本教程中,我们使用FashionMNIST数据集。

# Download training data from open datasets.
training_data = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor(),
)

# Download test data from open datasets.
test_data = datasets.FashionMNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor(),
)

初次运行该程序时,如果 root 中没有该数据集,将自动从网络下载 FashionMNIST 数据集并保存到 root,需要花一点时间。再次运行该程序时,将自动读取 root 保存的数据集,不需要再从网络下载。

运行后该段例程后输出:

Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz
Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz to data/FashionMNIST/raw/train-images-idx3-ubyte.gz

接下来,我们将 Dataset 作为参数传递给 DataLoader,封装了一个可迭代的数据加载器,支持自动批处理、采样、混洗和多进程数据加载。

在这里,我们又定义了一个 batchsize=64 的批大小,即可迭代的数据加载器 DataLoader 每次都将返回一批 64 个样本和标签。

batch_size = 64

# Create data loaders.
train_dataloader = DataLoader(training_data, batch_size=batch_size)
test_dataloader = DataLoader(test_data, batch_size=batch_size)

for X, y in test_dataloader:
    print(f"Shape of X [N, C, H, W]: {
      
      X.shape}")
    print(f"Shape of y: {
      
      y.shape}, {
      
      y.dtype}")
    break

输出为:

Shape of X [N, C, H, W] : torch.Size([64, 1, 28, 28])
Shape of y : torch.Size([64]), torch.int64


2.2 创建模型

为了在 PyTorch 中定义神经网络,我们创建了一个继承自 nn.Module 的类。

我们在 __init__ 函数中定义网络的层,由此确定数据是如何经过网络前向传播的。为了加速神经网络的操作,可以将其移动到 GPU(如果可用)。

# Get cpu or gpu device for training.
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"Using {
      
      device} device")

# Define model
class NeuralNetwork(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, 512),
            nn.ReLU(),
            nn.Linear(512, 10)
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits

model = NeuralNetwork().to(device)
print(model)

输出为:

Using cuda device
NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear_relu_stack): Sequential(
    (0): Linear(in_features=784, out_features=512, bias=True)
    (1): ReLU()
    (2): Linear(in_features=512, out_features=512, bias=True)
    (3): ReLU()
    (4): Linear(in_features=512, out_features=10, bias=True)
  )
)

2.3 模型训练(模型参数优化)

为了训练模型,需要定义一个损失函数loss function和一个优化器optimizer

loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)

在训练中,DataLoader 向模型分批提供训练数据,一个批次(batch)的训练数据通过模型前向传播得到模型输出,再对误差进行反向传播,由此来调整模型的参数。

def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    model.train()
    for batch, (X, y) in enumerate(dataloader):
        X, y = X.to(device), y.to(device)

        # Compute prediction error
        pred = model(X)
        loss = loss_fn(pred, y)

        # Backpropagation
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if batch % 100 == 0:
            loss, current = loss.item(), (batch + 1) * len(X)
            print(f"loss: {
      
      loss:>7f}  [{
      
      current:>5d}/{
      
      size:>5d}]")

然后,我们还可以使用测试数据集来检测模型的性能。

def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {
      
      (100*correct):>0.1f}%, Avg loss: {
      
      test_loss:>8f} \n")

训练过程将进行多个轮次(epochs)。在每个轮次中,以损失函数下降为指标来优化模型参数,使模型能做出更好的预测。

在每个轮次的训练完成后,打印模型的准确度和损失函数值。我们希望随着训练轮次的增加,模型的准确度提高,而损失函数值减小。

epochs = 5
for t in range(epochs):
    print(f"Epoch {
      
      t+1}\n-------------------------------")
    train(train_dataloader, model, loss_fn, optimizer)
    test(test_dataloader, model, loss_fn)
print("Done!")

程序运行后的输出为:

Epoch 1
-------------------------------
loss: 2.285525  [   64/60000]
...
loss: 2.153531  [57664/60000]
Test Error:
 Accuracy: 39.1%, Avg loss: 2.137758

Epoch 2
 Accuracy: 50.9%, Avg loss: 1.864810

Epoch 3
 Accuracy: 58.5%, Avg loss: 1.501794

Epoch 4
 Accuracy: 62.4%, Avg loss: 1.246997

Epoch 5
 Accuracy: 64.2%, Avg loss: 1.089453

Done!

2.4 保存模型

PyTorch 使用 torch.save() 函数保存模型(包含模型参数),将序列化的对象保存到磁盘。

torch.save(model.state_dict(), "model.pth")
print("Saved PyTorch Model State to model.pth")

这段代码只存储模型中的参数,保存的模型格式为 .pth。该方法序列化一个用于前向传播的 pth 模型,保存模型的速度快,占用空间少。


2.5 加载模型

PyTorch 使用 torch.load() 函数加载模型。加载模型的过程包括重新创建模型结构,并加载 pth 模型文件中的状态字典(加载模型权值参数)。

model = NeuralNetwork()
model.load_state_dict(torch.load("model.pth"))
# <All keys matched successfully>

这个模型现在可以用来进行模型推理(根据输入数据计算模型输出)了。

classes = [
    "T-shirt/top",
    "Trouser",
    "Pullover",
    "Dress",
    "Coat",
    "Sandal",
    "Shirt",
    "Sneaker",
    "Bag",
    "Ankle boot"
]

model.eval()  # evaluation mode
x, y = test_data[0][0], test_data[0][1]
with torch.no_grad():
    pred = model(x)
    predicted, actual = classes[pred[0].argmax(0)], classes[y]
    print(f'Predicted: "{
      
      predicted}", Actual: "{
      
      actual}"')

运行这段程序的输出结果是:

Predicted: “Ankle boot”, Actual: “Ankle boot”


以上就是我们使用 PyTorch 创建模型、训练模型和模型推理的全部过程。


3. PyTorch 的工作流程

通过以上的基本例程,我们再次回顾一下使用 PyTorch 建立、训练和使用神经网络模型的基本步骤如下。

  1. 准备数据集(Prepare dataset)
  2. 创建网络模型(Design model using Class)
  3. 构造损失函数和优化器(Construct loss and optimizer)
  4. 模型训练(Trainning the model)
  5. 模型保存与加载(Saving and loading a model)
  6. 模型推断/预测(Inferring model)

将这些步骤进行抽象,下图显示了 PyTorch 典型的工作流程,及与之相关的重要模块。

在这里插入图片描述


4. 完整例程

完整例程如下。

# torch02_v1.py
# PyTorch QuickStart 快速入门
# PyTorch QuickStart
# This section runs through the API for common tasks in machine learning.
# https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html
# https://github.com/pytorch/tutorials/blob/main/beginner_source/basics/quickstart_tutorial.py
# Copyright: [email protected]
# Crated: Huang Shan, 2023/04/01

# (0) 导入 PyTorch
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor


# Define a neural network model
class NeuralNetwork(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, 512),
            nn.ReLU(),
            nn.Linear(512, 10)
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits


# model trainning
def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    model.train()
    for batch, (X, y) in enumerate(dataloader):
        X, y = X.to(device), y.to(device)

        # Compute prediction error
        pred = model(X)
        loss = loss_fn(pred, y)

        # Backpropagation
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if batch % 100 == 0:
            loss, current = loss.item(), (batch + 1) * len(X)
            print(f"loss: {
      
      loss:>7f}  [{
      
      current:>5d}/{
      
      size:>5d}]")


# model testing
def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {
      
      (100*correct):>0.1f}%, Avg loss: {
      
      test_loss:>8f} \n")


if __name__ == "__main__":
    # (1) 下载数据集 FashionMNIST
    # Download training data from open datasets.
    # Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz
    # Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz
    training_data = datasets.FashionMNIST(
        root="data",
        train=True,
        download=True,
        transform=ToTensor(),
    )

    # Download test data from open datasets.
    # Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz
    # Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz
    test_data = datasets.FashionMNIST(
        root="data",
        train=False,
        download=True,
        transform=ToTensor(),
    )

    # (2) 创建数据加载器
    batch_size = 64  # batch size
    # Create data loaders.
    train_dataloader = DataLoader(training_data, batch_size=batch_size)
    test_dataloader = DataLoader(test_data, batch_size=batch_size)
    imgs, labels = next(iter(train_dataloader))  # 创建生成器,用 next 返回一个批次的数据
    print(imgs.shape)  # torch.Size([64, 1, 28, 28])
    print(labels.shape)  # torch.Size([64])

    # (3) 创建神经网络模型
    # Get cpu or gpu device for training.
    device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
    print(f"Using {
      
      device} device")
    # Creat a model instance
    model = NeuralNetwork().to(device)  # 创建模型
    print(model)  # 打印模型结构

    # # (4) 模型训练
    # # Define loss function and optimizer
    # loss_fn = nn.CrossEntropyLoss()
    # optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
    #
    # # Train the model
    # epochs = 10
    # for t in range(epochs):
    #     print(f"Epoch {t+1}\n-------------------------------")
    #     train(train_dataloader, model, loss_fn, optimizer)
    #     test(test_dataloader, model, loss_fn)
    # print("Done!")

    # # (5) 保存模型
    # modelPath = "../model/model_demo1.pth"  # 训练集图像
    # torch.save(model.state_dict(), modelPath)
    # print("Saved PyTorch Model State to: ", modelPath)

    # (6) 加载模型
    modelPath = "../model/model_demo1.pth"  # 训练集图像
    # model = NeuralNetwork().to(device)  # 创建模型
    model = NeuralNetwork()
    model.load_state_dict(torch.load(modelPath))

    # (7) 模型推理
    classes = [
        "T-shirt/top",
        "Trouser",
        "Pullover",
        "Dress",
        "Coat",
        "Sandal",
        "Shirt",
        "Sneaker",
        "Bag",
        "Ankle boot"]

    model.eval()  # evaluation mode
    x, y = test_data[0][0], test_data[0][1]
    with torch.no_grad():
        pred = model(x)
        predicted, actual = classes[pred[0].argmax(0)], classes[y]
        print(f'Predicted: "{
      
      predicted}", Actual: "{
      
      actual}"')

参考文献:
【LearnOpenCV: Getting Started with PyTorch】https://learnopencv.com/getting-started-with-pytorch/
【PyTorch QuickStart】https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html

【本节完】


版权声明:
欢迎关注『youcans的深度学习』系列,转发请注明原文链接:
【youcans的深度学习 05】PyTorch入门教程:快速入门(https://youcans.blog.csdn.net/article/details/129908491)
Copyright 2023 youcans, XUPT
Crated:2023-04-02


猜你喜欢

转载自blog.csdn.net/youcans/article/details/129908491