公众号:尤而小屋 编辑:Peter 作者:Peter
大家好,我是Peter~
PyTorch是一种开源的深度学习框架,主要用于自然语言处理和图像识别等机器学习任务,由Facebook(Meta)人工智能研究院(FAIR)开发。它提供了强大的GPU加速张量计算能力,并内置了自动微分系统。
PyTorch支持多种神经网络架构,从简单的线性回归到复杂的卷积神经网络和生成式转换器模型。它还提供了丰富的预配置(甚至预训练)模型库,使数据科学家能够构建和运行复杂的深度学习网络.
本文给大家分享一个PyTorch简易入门案例,采用的数据是内置的FashionMNIST数据集。
版本说明:
notebook 6.5.6
numpy 1.26.0
pandas 2.2.3
torch 2.0.1
torchaudio 2.0.2
torchvision 0.15.2
导入我们需要的PyTorch及其他相关库:
import torch
from torch import nn
from torch.utils.data import DataLoader,Dataset # utils是工具包
from torchvision import datasets
from torchvision.transforms import ToTensor
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings("ignore")
其中,torch.utils.data
是Pytorh用于加载和预处理数据的两个重要模块,通常用下面的两个类来结合使用加载和处理数据:
注意:numpy的版本一定要用1.X
PyTorch提供许多用于特定领域的数库,比如TorchText、TorchVision
和 TorchAudio
,它们都包含数据集。
比如加载和预处理 FashionMNIST 数据集的。FashionMNIST 是一个流行的机器学习数据集,包含10个类别的灰度图像,每个类别有7000张训练图像和1000张测试图像。
第一次下载可能报错,多尝试运行几次代码:
参考:https://pytorch.ac.cn/tutorials/beginner/basics/data_tutorial.html
# 下载原始训练集train
training_data = datasets.FashionMNIST( # 数据集的类:FashionMNIST类是datasets模块中的一个类
root="data", # 指定数据集下载后存储的根目录
train=True, # 加载的是训练集而不是测试集。如果设置为 False,则会加载测试集
download=True, # 如果数据集未下载,则从网上下载
transform=ToTensor() # 指定特征:使用 ToTensor() 将图像数据转换为 PyTorch 张量(tensor)
#target_transfomr # 指定标签
)
# 下载原始测试集test
testing_data = datasets.FashionMNIST(
root="data",
train=False,
download=True,
transform=ToTensor()
)
ToTensor()
是torchvision.transforms
模块中的一个函数,它将PIL
图像或numpy
数组转换成形状为[C,H,W]
的浮点数张量,其中C是通道数(对于灰度图像是1),H是高度,W是宽度。
# 定义类别标签
labels_map = {0:"T-shirt",1:"Trouser",2:"Pullover",3:"Dress",4:"Coat",
5:"Sandal",6:"Shirt",7:"Sneaker",8:"Bag",9:"Ankle Boot"}
torch.randint(1000, size=(1,)) # 在给定数值内随机选择一个整数
tensor(315)
torch.randint(1000, size=(1,)).item() # 通过item()取出数据部分
221
fig = plt.figure(figsize=(8,8))
cols, rows = 3, 3
for i in range(1, cols * rows + 1):
# 随机取数:基于pytorch
#sample_index = torch.randint(len(training_data), size=(1,)).item() # 随机选择一个图
# 随机取数:基于numpy
sample_index = np.random.randint(len(training_data))
img, label = training_data[sample_index] # 取出样本的特征和标签部分
#type(img) # <class 'torch.Tensor'>
#type(label) # <class 'int'>
fig.add_subplot(rows,cols,i)
plt.title(labels_map[label])
plt.axis("off")
# torch.squeeze() 用法:对Tensor进行降维,去掉维数为1的维度。如果输入形状为 (A×1×B×C×1),那么返回的形状则为 (A×B×C)
plt.imshow(img.squeeze(), cmap="gray")
plt.show()
Dataset 一次获取数据集的特征和标签。在训练模型时,我们通常希望以小批量
的形式传递样本,在每个 epoch 中重新洗牌数据以减少模型过拟合,并使用 Python 的 multiprocessing 来加速数据检索。
将Dataset作为参数传递给DataLoader,包装成一个可迭代对象,并支持自动批处理、采样、洗牌和多进程数据加载:
# https://pytorch.org/docs/stable/data.html
DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,
batch_sampler=None, num_workers=0, collate_fn=None,
pin_memory=False, drop_last=False, timeout=0,
worker_init_fn=None, *, prefetch_factor=2,
persistent_workers=False)
batch_size = 64 # 每个批次64个样本
# 用于批量加载数据,并支持打乱顺序shuffle=True
train_dataloader = DataLoader(training_data, batch_size=batch_size,shuffle=True)
test_dataloader = DataLoader(testing_data, batch_size=batch_size,shuffle=True)
test_dataloader
<torch.utils.data.dataloader.DataLoader at 0x23a4285ead0>
for X, y in test_dataloader:
print(f"shape of X [N,C,H,W]: {X.shape}") # numpy的版本用1.X;否则报错
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
前面我们已经将数据集加载到了DataLoader中,可以根据需要遍历该数据集。
下面的迭代过程都会返回一批train_features和train_label(分别包含batch_size=64个特征和标签)
# 关于next函数的使用
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
print(next(gen)) # 输出: 1
print(next(gen)) # 输出: 2
print(next(gen)) # 输出: 3
# 再次调用 next() 会引发 StopIteration 异常
try:
print(next(gen))
except StopIteration:
print("生成器已耗尽")
train_features, train_label = next(iter(train_dataloader)) # next函数迭代元素
print(train_features.size())
print(train_label.size())
torch.Size(64, 1, 28, 28)
torch.Size(64)
img = train_features[0].squeeze()
plt.imshow(img, cmap="gray")
print("label: ",label)
plt.show()
label: 6
创建一个继承自nn.Module的类:在初始化函数init中定义网络的层,在forward函数中指定数据如何通过网络进行传递。
为了加速神经网络中的操作,可以指定使用GPU或者MPS。
device = ("cuda" # 根据可用硬件选择设备
if torch.cuda.is_available()
else "mps"
if torch.backends.mps.is_available()
else "cpu"
)
print("Using", device)
Using cpu
# 定义模型
class NeuralNetwork(nn.Module):
"""
定义全连接神经网络:2个隐藏层和1个输出层
"""
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)
logtis = self.linear_relu_stack(x)
return logtis
模型的实例化运行:
model = NeuralNetwork().to(device) # 将模型移动到可选设备上
model
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)
)
)
添加损失函数和优化器
# 使用交叉熵损失函数和随机梯度下降(SGD)优化器
loss_fun = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
在一个训练中,模型对训练数据集(以批次形式)进行预测,并将预测误差反向传播以调整模型的参数:
def train(dataloader, model, loss_fun, optimizer):
size = len(dataloader.dataset)
model.train() # 设置模型为训练模式
for batch, (X,y) in enumerate(dataloader): # 遍历加载数据中的批次
X,y = X.to(device), y.to(device)
# 预测并计算误差
pred = model(X)
loss = loss_fun(pred, y)
# 基于反向传播进行参数优化
loss.backward() # 反向传播计算梯度
optimizer.step() # 更新模型参数
optimizer.zero_grad() # 梯度清零
if batch % 100 == 0: # 每100个批次打印一个损失值
loss, current = loss.item(), (batch + 1) * len(X)
print(f"loss: {loss:>7f} [{current:>5d} / {size:>5d}]")
def test(dataloader, model, loss_fun):
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)
#test_loss和correct记录测试损失和正确预测的数量
pred = model(X)
test_loss += loss_fun(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。在每个epoch期间,模型学习参数做出更好的预测;同时打印模型的准确率和损失:
epochs = 5
for i in range(epochs):
print(f"Epoch {i+1}\n-----------------------------------")
train(train_dataloader, model, loss_fun, optimizer)
test(test_dataloader, model, loss_fun)
print("End")
显示结果:
Epoch 1
-----------------------------------
loss: 2.304864 [ 64 / 60000]
loss: 2.297977 [ 6464 / 60000]
loss: 2.285217 [12864 / 60000]
loss: 2.272212 [19264 / 60000]
loss: 2.231185 [25664 / 60000]
loss: 2.232408 [32064 / 60000]
loss: 2.210726 [38464 / 60000]
loss: 2.205886 [44864 / 60000]
loss: 2.168824 [51264 / 60000]
loss: 2.152246 [57664 / 60000]
Test Error:
Accuracy: 41.6%, Avg loss: 2.153291
Epoch 2
-----------------------------------
loss: 2.149517 [ 64 / 60000]
loss: 2.142866 [ 6464 / 60000]
loss: 2.108011 [12864 / 60000]
loss: 2.119373 [19264 / 60000]
loss: 2.020631 [25664 / 60000]
loss: 2.023993 [32064 / 60000]
loss: 2.030735 [38464 / 60000]
loss: 1.936665 [44864 / 60000]
loss: 1.935420 [51264 / 60000]
loss: 1.896548 [57664 / 60000]
Test Error:
Accuracy: 55.1%, Avg loss: 1.880378
Epoch 3
-----------------------------------
loss: 1.856415 [ 64 / 60000]
loss: 1.841119 [ 6464 / 60000]
loss: 1.797163 [12864 / 60000]
loss: 1.785939 [19264 / 60000]
loss: 1.828926 [25664 / 60000]
loss: 1.616563 [32064 / 60000]
loss: 1.635652 [38464 / 60000]
loss: 1.639792 [44864 / 60000]
loss: 1.512122 [51264 / 60000]
loss: 1.473193 [57664 / 60000]
Test Error:
Accuracy: 62.0%, Avg loss: 1.508694
Epoch 4
-----------------------------------
loss: 1.602649 [ 64 / 60000]
loss: 1.463723 [ 6464 / 60000]
loss: 1.400202 [12864 / 60000]
loss: 1.339562 [19264 / 60000]
loss: 1.326941 [25664 / 60000]
loss: 1.354389 [32064 / 60000]
loss: 1.306382 [38464 / 60000]
loss: 1.221228 [44864 / 60000]
loss: 1.357533 [51264 / 60000]
loss: 1.220939 [57664 / 60000]
Test Error:
Accuracy: 63.2%, Avg loss: 1.242424
Epoch 5
-----------------------------------
loss: 1.177626 [ 64 / 60000]
loss: 1.236755 [ 6464 / 60000]
loss: 1.124333 [12864 / 60000]
loss: 1.107375 [19264 / 60000]
loss: 1.158336 [25664 / 60000]
loss: 1.118539 [32064 / 60000]
loss: 1.102393 [38464 / 60000]
loss: 1.034745 [44864 / 60000]
loss: 1.044187 [51264 / 60000]
loss: 1.107361 [57664 / 60000]
Test Error:
Accuracy: 64.4%, Avg loss: 1.080261
End
从运行结果来看,模型的loss损失是呈现降低趋势;准确率accuracy呈现上升趋势。
最后提供完整代码,多多coding:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。