-QuQ-
Articles10
Tags4
Categories0

Archive

PyTorch基础

PyTorch基础

一些记录

来自课程link

张量

总览

  • 创建
    • torch.tensor(data, dtype, devide, requires_grad) - 创建
    • torch.rand(size) - 根据size随机创建
    • torch.zeros(size) - 全零
    • torch.ones(size) - 全一
    • torch.arange(start, end, step) - 根据[start, end)范围创建
  • 属性
    • a_tensor.ndim - 维数,即中括号嵌套层数
    • a_tensor.shape - 形状,即从外到内,该层级中括号中元素个数
    • a_tensor.dtype - 数据类型
  • 方法
    • a_tensor.item() - 获取Python内置类型数据
    • a_tensor.size() - 效果与a_tensor.shape相同
    • 最值,均值,求和
      • torch.min(), torch.max(), torch.mean() # 需要torch.float32类型, torch.sum()
      • torch.argmin(), torch.argmax() - 返回最值索引
    • 数学运算
      • * - 点乘
      • torch.matmul(t_a, t_b)torch.mm(a, b)@ - 矩阵乘法
    • 张量操作
      • a_tensor.reshape(size) - reshape为指定size
      • a_tensor.view(size) - 返回指定size的视图(内存共享)
      • a_tensor.stack(tensors, dim) - 按第dim维堆叠
      • a_tensor.hstack(tensors) - 水平堆叠(没搞明白)
      • a_tensor.vstack(tensors) - 垂直堆叠(dim=0)
      • a_tensor.squeeze() - 删除所有只有一个元素的维度
      • a_tensor.unsqueeze(dim) - 在指定维数unsqueeze
      • a_tensor.permute(order, of, index) - 按照原来维度索引重新排列
      • 索引与切片 - 与python相同
      • 张量与NumPy数组
        • torch.from_numpy(ndarray) - NumPy to Tensor 注意numpy默认类型 float64, 而 tensor 为 float32
        • a_tensor.numpy() - Tensor to NumPy

再现性(reproducibility)与设备

总览

  • reproducibility
    • torch.manual_seed(seed) - 设置随机种子
  • 设备
    • torch.cuda.is_available() - 含义正如其名
    • torch.cuda.device_count()
    • a_tensor().to(device) - 将张量移动到指定设备
    • tensor_on_gpu.cpu().numpy() - NumPy数组在cpu上,所以要先转换为cpu张量

PyTorh工作流

总览

  • 模型:构建(继承自torch.nn.Module)
    • model.state_dict() - 返回参数列表
    • model(input) - 返回模型输出
    • torch.inference_mode() - 上下文管理器,开启推理模式
  • 模型:训练
    • 损失函数
      • nn.L1Loss - MAE Mean Absolute Error
    • torch.optim - 优化器
      • SGD - Stocastic Gradient Descent
    • 训练循环
      1. Call model.train()
      2. Do the forward pass
      3. Calculate the loss
      4. optimizer.zero_grad() - 优化器梯度清零
      5. loss.backward()
      6. optimizer.step()
    • 测试循环
      1. Call model.eval()
      2. with torch.inference_mode()
      3. Do the forward pass
      4. Calculate the loss
      5. Print out the result
  • 模型:保存与加载
    • torch.save(model.state_dict(), path)
    • torch.load(model_path) - 将状态字典从磁盘加载到内存
    • model.load_state_dict(torch.load(model_path)) - 将加载到内存的状态字典应用到模型

数据

训练模型最重要的就是数据。数据处理中一个重要步骤就是将数据切分为训练集与测试集(可能还有验证集)

分割 用途 数据量 是否使用
训练集 模型从这些数据中学习(上课) ~60-80% 经常
验证集 模型从这些数据中调整(课后作业) ~10-20% 较多
测试集 模型从这些数据得到评估(期末考试) ~10-20% 经常

模型:构建

首先是模型定义:

一般将模型放在一个类中,该类继承自torch.nn.Module

然后是重写forward()方法,以便进行前向传播

1
2
3
4
5
6
7
8
9
10
11
12
import torch
from torch import nn

class YourModel(nn.Module):
  def __init__(self):
    super().__init__()

    # layer definitions

  def forward(self, input: torch.Tensor)-> torch.Tensor:
    # Computaions and layers
    return #something

模型:训练

训练循环与测试循环。有一首魔性歌曲…link

训练需要先设置损失函数与优化器

训练与测试代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# An epoch is one loop through data
epochs = 200

epoch_count = []
loss_values = []
test_loss_values = []

### Traning
# 0. Loop through the data
for epoch in range(epochs):
    # set the model to training mode
    model_0.train() # Traing mode sets all parameters that require gradients to require gradients

    # 1. Forward pass
    Y_pred = model_0(X_train)

    # 2. Calc the loss
    loss = loss_fn(Y_pred, Y_train)

    # 3. Optimizer zero grad
    optimizer.zero_grad()

    # 4. Perform back propagation on the loss with respect to the parameters of the model
    loss.backward()

    # 5. Step the optimizer (perform gradient descent)
    optimizer.step() # The changes will accumulate through the loop, so we have to zero the grad in step 3 for the next iteration


    ### Testing
    model_0.eval() # turns off different settings in model not needed for evaluation/testing
    with torch.inference_mode(): # turns off gradient tracking & more things behind the scenes
        # 1. Do the forward pass
        test_pred = model_0(X_test)

        # 2. Calc the loss
        test_loss = loss_fn(test_pred, Y_test)

    if epoch % 10 == 0:
        epoch_count.append(epoch)
        loss_values.append(loss)
        test_loss_values.append(test_loss)

        print(f"Epoch: {epoch} | Loss: {loss} | Test loss: {test_loss}")

        print(loss, model_0.state_dict())

模型:保存与加载

  1. torch.save() - 以Python的pickle格式保存
  2. torch.load() - 加载PyTorch对象
  3. torch.nn.Moduel.load_state_dict() - 加载模型的状态字典

模型加载与保存一般与pathlib共同使用

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pathlib import Path

MODEL_PATH = Path("./models")
MODEL_PATH.mkdir(parents=True, exist_ok=True)

MODEL_NAME = "model.pth"
MODEL_SAVE_PATH = MODEL_PATH / MODEL_NAME

# Save
torch.save(obj=model.state_dict(), f=MODEL_SAVE_PATH)

# Load
model = YourModel()
model.load_state_dict(torch.load(MODEL_SAVE_PATH))

Classification

分类(classification)是机器学习的重要算法之一

种类 是什么 例子
Binary classification 正如其名 是否为xxx
Multi-class classification 正如其名 xxx是yyy种类别中的哪一种
Multi-label classification 正如其名 xxx中存在yyy种类别中的哪几种

分类神经网络基本架构:

超参数 Binary Classification Multiclass classification
输入shape (in_features) 与输入特征个数相同 与 binary classification 相同
隐藏层 与具体问题相关, 最小 = 1, 最大无限制 与 binary classification 相同
每一个隐藏层神经元个数 与具体问题相关, 通常是 10 到 512 与 binary classification 相同
输出shape (out_features) 1 (单类) 每一类一个
隐藏层激活函数 常用 ReLU (rectified linear unit) 但 也可以是其他 与 binary classification 相同
输出激活函数 Sigmoid (torch.sigmoid) Softmax (torch.softmax)
损失函数 Binary crossentropy (torch.nn.BCELoss in PyTorch) Cross entropy (torch.nn.CrossEntropyLoss)
优化器 SGD (stochastic gradient descent), Adam (see torch.optim for more options) 与 binary classification 相同

模型构建与训练详见上一章

Author:-QuQ-
Link:http://172.207.131.165/2024/08/14/PyTorch%E5%9F%BA%E7%A1%80/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可