首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PyTorch入门,快速上手案例

PyTorch入门,快速上手案例

原创
作者头像
皮大大
发布2024-12-06 14:44:58
发布2024-12-06 14:44:58
40800
代码可运行
举报
文章被收录于专栏:PyTorchPyTorch
运行总次数:0
代码可运行

公众号:尤而小屋 编辑:Peter 作者:Peter

大家好,我是Peter~

PyTorch是一种开源的深度学习框架,主要用于自然语言处理和图像识别等机器学习任务,由Facebook(Meta)人工智能研究院(FAIR)开发。它提供了强大的GPU加速张量计算能力,并内置了自动微分系统。

PyTorch支持多种神经网络架构,从简单的线性回归到复杂的卷积神经网络和生成式转换器模型。它还提供了丰富的预配置(甚至预训练)模型库,使数据科学家能够构建和运行复杂的深度学习网络.

本文给大家分享一个PyTorch简易入门案例,采用的数据是内置的FashionMNIST数据集。

版本说明:

代码语言:python
代码运行次数:0
运行
复制
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及其他相关库:

代码语言:python
代码运行次数:0
运行
复制
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")
  1. torch: PyTorch的核心库,用于构建和训练神经网络。
  2. torch.nn: 包含所有神经网络模块(如线性层、卷积层等)。
  3. torch.utils.data: 提供数据加载器和数据集类。
  4. torchvision: 提供常用的数据集和图像变换工具

其中,torch.utils.data是Pytorh用于加载和预处理数据的两个重要模块,通常用下面的两个类来结合使用加载和处理数据:

  • torch.utils.data.DataLoader:用于加载数据,需要实例化后使用
  • torch.utils.data.Dataset:抽象类,只能用于继承

注意:numpy的版本一定要用1.X

导入数据集

PyTorch提供许多用于特定领域的数库,比如TorchText、TorchVisionTorchAudio,它们都包含数据集。

比如加载和预处理 FashionMNIST 数据集的。FashionMNIST 是一个流行的机器学习数据集,包含10个类别的灰度图像,每个类别有7000张训练图像和1000张测试图像。

第一次下载可能报错,多尝试运行几次代码:

参考:https://pytorch.ac.cn/tutorials/beginner/basics/data_tutorial.html

代码语言:python
代码运行次数:0
运行
复制
# 下载原始训练集train

training_data = datasets.FashionMNIST(  # 数据集的类:FashionMNIST类是datasets模块中的一个类
    root="data", # 指定数据集下载后存储的根目录
    train=True,  # 加载的是训练集而不是测试集。如果设置为 False,则会加载测试集
    download=True, # 如果数据集未下载,则从网上下载
    transform=ToTensor()  # 指定特征:使用 ToTensor() 将图像数据转换为 PyTorch 张量(tensor)
    #target_transfomr  # 指定标签
)
代码语言:python
代码运行次数:0
运行
复制
# 下载原始测试集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是宽度。

迭代和数据可视化

代码语言:python
代码运行次数:0
运行
复制
# 定义类别标签
labels_map = {0:"T-shirt",1:"Trouser",2:"Pullover",3:"Dress",4:"Coat",
              5:"Sandal",6:"Shirt",7:"Sneaker",8:"Bag",9:"Ankle Boot"}
代码语言:python
代码运行次数:0
运行
复制
torch.randint(1000, size=(1,))   # 在给定数值内随机选择一个整数

tensor(315)

代码语言:python
代码运行次数:0
运行
复制
torch.randint(1000, size=(1,)).item()  # 通过item()取出数据部分 

221

代码语言:python
代码运行次数:0
运行
复制
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()

使用DataLoader准备训练数据

Dataset 一次获取数据集的特征和标签。在训练模型时,我们通常希望以小批量的形式传递样本,在每个 epoch 中重新洗牌数据以减少模型过拟合,并使用 Python 的 multiprocessing 来加速数据检索。

将Dataset作为参数传递给DataLoader,包装成一个可迭代对象,并支持自动批处理、采样、洗牌和多进程数据加载:

代码语言:python
代码运行次数:0
运行
复制
# 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)
代码语言:python
代码运行次数:0
运行
复制
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>

代码语言:python
代码运行次数:0
运行
复制
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

前面我们已经将数据集加载到了DataLoader中,可以根据需要遍历该数据集。

下面的迭代过程都会返回一批train_features和train_label(分别包含batch_size=64个特征和标签)

代码语言:python
代码运行次数:0
运行
复制
# 关于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("生成器已耗尽")
代码语言:python
代码运行次数:0
运行
复制
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)

代码语言:python
代码运行次数:0
运行
复制
img = train_features[0].squeeze()
plt.imshow(img, cmap="gray")

print("label: ",label)
plt.show()

label: 6

创建模型

创建一个继承自nn.Module的类:在初始化函数init中定义网络的层,在forward函数中指定数据如何通过网络进行传递。

为了加速神经网络中的操作,可以指定使用GPU或者MPS。

代码语言:python
代码运行次数:0
运行
复制
device = ("cuda"  # 根据可用硬件选择设备
          if torch.cuda.is_available()
          else "mps"
          if torch.backends.mps.is_available()
          else "cpu"
         )

print("Using", device)

Using cpu

代码语言:python
代码运行次数:0
运行
复制
# 定义模型

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

模型的实例化运行:

代码语言:python
代码运行次数:0
运行
复制
model = NeuralNetwork().to(device)  # 将模型移动到可选设备上
model
代码语言:python
代码运行次数:0
运行
复制
    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)
      )
    )

优化模型参数

添加损失函数和优化器

代码语言:python
代码运行次数:0
运行
复制
# 使用交叉熵损失函数和随机梯度下降(SGD)优化器

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

定义训练函数train

在一个训练中,模型对训练数据集(以批次形式)进行预测,并将预测误差反向传播以调整模型的参数:

代码语言:python
代码运行次数:0
运行
复制
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}]")

定义测试函数test

代码语言:python
代码运行次数:0
运行
复制
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期间,模型学习参数做出更好的预测;同时打印模型的准确率和损失:

代码语言:python
代码运行次数:0
运行
复制
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")

显示结果:

代码语言:python
代码运行次数:0
运行
复制
    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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导入库
  • 导入数据集
  • 迭代和数据可视化
  • 使用DataLoader准备训练数据
  • 遍历DataLoader
  • 创建模型
  • 优化模型参数
    • 定义训练函数train
    • 定义测试函数test
  • 模型训练
  • 完整代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档