欢迎关注『youcans的深度学习』系列,持续更新中…
【youcans的深度学习 01】安装环境之 miniconda
【youcans的深度学习 02】PyTorch CPU版本安装与环境配置
【youcans的深度学习 03】PyTorch CPU版本安装与环境配置
【youcans的深度学习 04】PyTorch入门教程:基础知识
【youcans的深度学习 05】PyTorch入门教程:快速入门
使用 PyTorch 建立、训练和使用神经网络模型的基本步骤如下。
# 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) 模型推理
PyTorch 中有两个重要的数据处理的类:torch.utils.data.DataLoader
和 torch.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
为了在 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)
)
)
为了训练模型,需要定义一个损失函数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!
PyTorch 使用 torch.save()
函数保存模型(包含模型参数),将序列化的对象保存到磁盘。
torch.save(model.state_dict(), "model.pth")
print("Saved PyTorch Model State to model.pth")
这段代码只存储模型中的参数,保存的模型格式为 .pth
。该方法序列化一个用于前向传播的 pth 模型,保存模型的速度快,占用空间少。
PyTorch 使用 torch.load()
函数加载模型。加载模型的过程包括重新创建模型结构,并加载 pth 模型文件中的状态字典(加载模型权值参数)。
model = NeuralNetwork()
model.load_state_dict(torch.load("model.pth"))
#
这个模型现在可以用来进行模型推理(根据输入数据计算模型输出)了。
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 创建模型、训练模型和模型推理的全部过程。
通过以上的基本例程,我们再次回顾一下使用 PyTorch 建立、训练和使用神经网络模型的基本步骤如下。
将这些步骤进行抽象,下图显示了 PyTorch 典型的工作流程,及与之相关的重要模块。
完整例程如下。
# 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: youcans@qq.com
# 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