pytorch基础api

部署运行你感兴趣的模型镜像

PyTorch 是一个基于 Python 的开源深度学习框架,以其动态计算图和易用性著称。以下是 PyTorch 的核心 API 分类及自定义模型的详细指南:

一、PyTorch 核心 API 分类

1. 张量操作 (Tensor Operations)

1.1核心对象

        `torch.Tensor`

  • 定义: PyTorch 中的 Tensor 是多维数组(类似 NumPy 的 ndarray),支持 GPU 加速计算和自动微分。

  • 与 NumPy 的关系:

    • Tensor 的设计受 NumPy 启发,但支持 GPU 和自动梯度。

    • 可通过 tensor.numpy() 和 torch.from_numpy() 与 NumPy 数组互相转换。

1.2创建张量
# 从数据创建
data = [[1, 2], [3, 4]]
tensor = torch.tensor(data)  # dtype 自动推断(默认 float32)

# 指定数据类型
tensor = torch.tensor(data, dtype=torch.float64)

# 特殊初始化
zeros = torch.zeros((2, 3))      # 全零张量
ones = torch.ones((2, 3))        # 全一张量
rand = torch.rand((2, 3))         # [0,1) 均匀分布
randn = torch.randn((2, 3))       # 标准正态分布
arange = torch.arange(0, 10, 2)  # 类似 range 的序列

1.3数学运算
a = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])

# 逐元素运算
c = a + b          # 等价于 torch.add(a, b),结果为tensor([5, 7, 9])
c = a * b          # 逐元素乘法,等价于torch.mul(a,b),结果为tensor([ 4, 10, 18])
c = a.pow(2)       # 平方,结果为tensor([1, 4, 9])

# 广播机制
a = torch.ones((2, 3))
b = torch.tensor([1, 2, 3])
c = a + b          # b 被广播到 (2,3),结果为tensor([[2., 3., 4.], [2., 3., 4.]])

# 矩阵乘法
mat1 = torch.randn(3, 4)
mat2 = torch.randn(4, 5)
result = torch.matmul(mat1, mat2)  # 等价于 mat1 @ mat2,
                   # 结果为tensor([[ 0.2384,  2.6001, -1.7793,  1.7267, -1.5907],
                   #              [-0.0654,  1.0599, -0.5975,  1.4739, -1.6811],
                   #              [ 0.0711,  0.9760, -1.2212,  3.3302, -2.7632]])
1.4原地操作
a = torch.tensor([1., 2., 3.])
a.add_(5)     # 对原张量操作 a+=5, 结果为tensor([6., 7., 8.])
b = a.sqrt_() # 带下划线的操作符表示原地操作
torch.equal(a,b) # 判断a和b是否相同,返回为True

1.5形状操作

tensor.view(shape)和tensor.reshape(shpe)

返回一个对原张量tensor的所有元素创建按照shape重新组合的张量,shape输出的数据数量需要与原张量相同。view()方法和reshape()方法达到的效果相同,但是view方法处理的是连续张量,reshape方法可以处理不连续张量。对于不连续张量,tensor.contiguous().view()等同于tensor.reshape()。

tensor.transpose(dim0,dim1)和tensor.permute(dims)

transpose方法返回一个对原张量tensor的dim0和dim1进行交换的张量,只能对两个维度进行操作。permute方法返回一个按照dims中给出的维度角标重组后的张量。两种方法均会调整张量中元素的位置,因此对一个张量调用此方法后,新张量会变成不连续的。

a = torch.arange(24).reshape(1, 2, 3, 4)
>>> a = tensor([[[[ 0,  1,  2,  3],
                  [ 4,  5,  6,  7],
                  [ 8,  9, 10, 11]],

                 [[12, 13, 14, 15],
                  [16, 17, 18, 19],
                  [20, 21, 22, 23]]]])

b = a.transpose(1, 2)      # 对a的第二维和第三维进行交换
c = a.view(1, 3, 2, 4)     # 对a的第二维和第三维进行重组
d = a.permute(1, 3, 0, 2)  # 对a按照输入的维度角标重新排列维度
>>> b : tensor([[[[ 0,  1,  2,  3],
                  [12, 13, 14, 15]],

                 [[ 4,  5,  6,  7],
                  [16, 17, 18, 19]],

                 [[ 8,  9, 10, 11],
                  [20, 21, 22, 23]]]]) 

>>> c : tensor([[[[ 0,  1,  2,  3],
                  [ 4,  5,  6,  7]],

                 [[ 8,  9, 10, 11],
                  [12, 13, 14, 15]],

                 [[16, 17, 18, 19],
                  [20, 21, 22, 23]]]])

print(d.shape)
>>> torch.Size([2, 4, 1, 3])

torch.cat(tensors, dim=0)

  • 作用: 沿指定维度 dim 将多个张量拼接成一个连续的新张量。

  • 输入:

    • tensors (sequence of Tensors): 要拼接的张量序列(列表或元组)。

    • dim (int, optional): 拼接的维度,默认为 0

  • 输出: 拼接后的新张量。

  • 形状一致性要求:

    • 除 dim 维度外,其他所有维度的形状必须完全相同

    • 例如:若 dim=1,则所有张量的第 023 等维度必须相等。

  • 拼接结果形状:

    • dim 维度的大小为所有输入张量在该维度大小的总和。

    • 其他维度大小保持不变。

# 沿 dim=1 拼接(水平拼接)
d = torch.cat([a, b], dim=1)
print(d)
"""
输出:
tensor([[ 1,  2,  3,  7,  8,  9],
        [ 4,  5,  6, 10, 11, 12]])
形状:(2, 6)
"""

torch.stack(tensors, dim=0)

  • 作用:将多个形状相同的张量沿着新的维度堆叠,生成一个更高维度的张量。

  • 输入

    • tensors (sequence of Tensors):要堆叠的张量序列(列表或元组)。

    • dim (int, optional):指定新维度的位置(默认 dim=0)。

  • 输出:堆叠后的新张量,维度数比输入张量多一维。

  • 所有输入张量的形状必须完全相同

a = torch.tensor([[1, 2, 3], [4, 5, 6]])  # 形状 (2, 3)
b = torch.tensor([[7, 8, 9], [10, 11, 12]])

# 沿新维度 dim=0 堆叠
c = torch.stack([a, b], dim=0)
print(c)
"""
输出:
tensor([[[ 1,  2,  3],
         [ 4,  5,  6]],

        [[ 7,  8,  9],
         [10, 11, 12]]])
形状:(2, 2, 3)
"""

2. 自动微分 (Autograd)

2.1梯度跟踪开关
  • requires_grad 属性:

    • 所有依赖该张量的计算都会被跟踪,形成动态计算图。

    • 默认值:创建张量时默认为 False(如 torch.tensor([1.0]))。

tensor.requires_grad = True  # 启用梯度跟踪
tensor.requires_grad_(True)  # 原地修改方法(推荐)

2.2梯度计算
  • .backward() 方法:

    • 计算所有参与计算图的张量的梯度,结果存储在 .grad 属性中。

    • 仅限标量输出:默认只能对标量(如 loss)调用 .backward(),非标量需传递 gradient 参数。

loss.backward()  # 标量损失反向传播
output.backward(gradient=torch.ones_like(output))  # 非标量输出需指定梯度权重

2.3梯度累积与清零
  • 梯度累积:每次调用 .backward() 会累加梯度到 .grad

  • 梯度清零

optimizer.zero_grad()  # 优化器清零梯度(推荐)
model.zero_grad()      # 模型所有参数梯度清零
tensor.grad.zero_()    # 手动清零特定张量梯度

2.4高阶梯度计算
  • create_graph=True:保留计算图以支持高阶导数。

x = torch.tensor(2.0, requires_grad=True)
y = x**3
dy_dx = torch.autograd.grad(y, x, create_graph=True)[0]  # 一阶导: 3x²
d2y_dx2 = torch.autograd.grad(dy_dx, x)[0]               # 二阶导: 6x

2.5梯度截断
  • 梯度裁剪

torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)

2.6禁用梯度:
  • torch.no_grad() :

with torch.no_grad():
    y = model(x)  # 不跟踪计算图,节省内存

2.7自定义反向传播
  • torch.autograd.Function

class MyFunction(torch.autograd.Function):
    @staticmethod
    def forward(ctx, input):
        ctx.save_for_backward(input)
        return input.clamp(min=0)
    
    @staticmethod
    def backward(ctx, grad_output):
        input, = ctx.saved_tensors
        grad_input = grad_output.clone()
        grad_input[input < 0] = 0
        return grad_input

3. 数据加载与处理 (Data Utilities)

3.1核心模块与类

PyTorch 数据处理的基石是 torch.utils.data 模块,主要包含以下类:

  • Dataset: 数据集的抽象类,定义数据访问接口。

  • DataLoader: 数据加载器,实现批量加载、多进程加速等功能。

  • Sampler: 控制数据采样策略(如顺序、随机、加权采样)。

  • Transform: 数据预处理与增强(通过 torchvision.transforms 或自定义)。

3.2数据集类的使用

必须实现 __len__ 和 __getitem__ 方法

from torch.utils.data import Dataset

class CustomDataset(Dataset):
    def __init__(self, data, labels, transform=None):
        self.data = data
        self.labels = labels
        self.transform = transform

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        sample = self.data[idx]
        label = self.labels[idx]
        if self.transform:
            sample = self.transform(sample)
        return sample, label

# 假设 data 和 labels 是已加载的原始数据
dataset = CustomDataset(data, labels, transform=my_transform)

3.3数据加载器
from torch.utils.data import DataLoader

dataloader = DataLoader(
    dataset,          # 数据集对象
    batch_size=32,    # 每批数据量
    shuffle=True,     # 是否打乱数据(训练时建议开启)
    num_workers=4,    # 并行加载的进程数(建议设为 CPU 核心数)
    pin_memory=True,  # 数据直接加载到 GPU 内存(加速 GPU 训练)
    drop_last=False,  # 是否丢弃最后不足一个 batch 的数据
    collate_fn=None   # 自定义批次组装函数(处理不同长度样本)
)

3.4数据增强
from torchvision import transforms

# 组合多个变换
transform = transforms.Compose([
    transforms.Resize(256),          # 调整大小
    transforms.RandomCrop(224),      # 随机裁剪
    transforms.RandomHorizontalFlip(),  # 随机水平翻转
    transforms.ToTensor(),           # 转为 Tensor (范围 [0,1])
    transforms.Normalize(            # 标准化 (均值, 标准差)
        mean=[0.485, 0.456, 0.406],
        std=[0.229, 0.224, 0.225]
    )
])

 3.5内置数据集与工具

使用 torchvision 内置数据集

from torchvision.datasets import MNIST
from torchvision.transforms import ToTensor

# 下载并加载 MNIST 数据集
train_data = MNIST(
    root="data",          # 数据存储路径
    train=True,           # 训练集
    download=True,        # 自动下载
    transform=ToTensor()  # 转换到 Tensor
)

数据集分割

from torch.utils.data import random_split

# 按比例分割数据集
train_size = int(0.8 * len(dataset))
val_size = len(dataset) - train_size
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])

快速封装数据

from torch.utils.data import TensorDataset

# 将数据和标签封装为 Dataset
data_tensor = torch.tensor(data)
labels_tensor = torch.tensor(labels)
dataset = TensorDataset(data_tensor, labels_tensor)

3.6高级功能

自定义采样器

from torch.utils.data import WeightedRandomSampler

# 处理类别不平衡:为每个样本指定采样权重
weights = [0.9 if label == 0 else 0.1 for label in labels]
sampler = WeightedRandomSampler(weights, num_samples=1000, replacement=True)

dataloader = DataLoader(dataset, batch_size=32, sampler=sampler)

自定义批次组装

处理边长序列(如文本)

def collate_padded(batch):
    # batch 是 [(data1, label1), (data2, label2), ...]
    inputs = [item[0] for item in batch]
    labels = torch.tensor([item[1] for item in batch])
    
    # 填充到相同长度
    inputs_padded = torch.nn.utils.rnn.pad_sequence(inputs, batch_first=True)
    return inputs_padded, labels

dataloader = DataLoader(dataset, collate_fn=collate_padded)

3.7最佳实践与注意事项
  1. 加速数据加载:

    • 设置 num_workers=4~8(根据 CPU 核心数调整)。

    • 启用 pin_memory=True(搭配 GPU 时)。

    • 使用 SSD 硬盘存储数据。

  2. 内存管理:

    • 大规模数据集使用 IterableDataset 流式加载。

    • 避免在 __getitem__ 中执行耗时操作。

  3. 数据增强:

    • 训练集开启增强(如旋转、裁剪),验证集关闭。

  4. 调试技巧:

# 检查单个样本
sample, label = dataset[0]
print(sample.shape, label)

# 可视化批次数据
import matplotlib.pyplot as plt
batch = next(iter(dataloader))
plt.imshow(batch[0][0].permute(1,2,0))

4. 神经网络模块 (torch.nn)

4.1核心组件概览

`torch.nn` 提供了构建神经网络所需的所有基础模块,主要分为以下类别:
        层类型(Layers): 如全连接层、卷积层、循环层等。
        容器(Containers): 如 `Sequential`、`ModuleList` 用于组合层。
        激活函数(Activation Functions): 如 `ReLU`、`Sigmoid`。
        损失函数(Loss Functions): 如 `CrossEntropyLoss`、`MSELoss`。
        实用工具(Utilities): 如参数初始化、归一化层。

4.2层类型


全连接层(Linear Layer)

import torch.nn as nn

# 输入特征数 784,输出特征数 128
fc = nn.Linear(in_features=784, out_features=128, bias=True)  

卷积层
2D 卷积(图像处理):

# 输入通道数 3,输出通道数 64,3x3 卷积核
conv = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1)


1D 卷积(时序数据):
 

conv1d = nn.Conv1d(in_channels=16, out_channels=32, kernel_size=3)

循环神经网络层
长短期记忆(LSTM):

# 输入特征数 100,隐藏层特征数 256,2 层堆叠
lstm = nn.LSTM(input_size=100, hidden_size=256, num_layers=2, batch_first=True)


门控制单元(GRU):

gru = nn.GRU(input_size=100, hidden_size=256, bidirectional=True)  # 双向 GRU

其他常用层
池化层:

max_pool = nn.MaxPool2d(kernel_size=2)  # 最大池化
avg_pool = nn.AvgPool2d(kernel_size=2)  # 平均池化


归一化层:

batch_norm = nn.BatchNorm2d(num_features=64)  # 批量归一化
layer_norm = nn.LayerNorm(normalized_shape=128)  # 层归一化


嵌入层(用于 NLP):

embed = nn.Embedding(num_embeddings=10000, embedding_dim=300)  # 词嵌入

4.3容器

 `nn.Sequential`
按顺序堆叠层:

model = nn.Sequential(
    nn.Linear(784, 128),
    nn.ReLU(),
    nn.Linear(128, 10)
)

 `nn.ModuleList`
动态管理层列表(适用于可变层数):

class DynamicModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.layers = nn.ModuleList([
            nn.Linear(784, 256),
            nn.Linear(256, 128)
        ])
    
    def forward(self, x):
        for layer in self.layers:
            x = layer(x)
        return x

 `nn.ModuleDict`**  
通过字典管理子模块:

model_dict = nn.ModuleDict({
    'conv': nn.Conv2d(3, 64, 3),
    'pool': nn.MaxPool2d(2)
})

4.4激活函数

 常用激活函数

relu = nn.ReLU()          # 整流线性单元
sigmoid = nn.Sigmoid()    # 输出范围 (0,1)
tanh = nn.Tanh()          # 输出范围 (-1,1)
softmax = nn.Softmax(dim=1)  # 沿指定维度归一化
leaky_relu = nn.LeakyReLU(negative_slope=0.1)  # 带泄漏的 ReLU

使用方式

x = torch.randn(2, 128)
x = relu(x)  # 直接应用

4.5损失函数

分类任务

# 交叉熵损失(输入为 logits,无需手动 softmax)
ce_loss = nn.CrossEntropyLoss()
loss = ce_loss(outputs, labels)  # outputs: (B, C), labels: (B)

# 二元分类(输入为概率)
bce_loss = nn.BCELoss()
loss = bce_loss(predictions, labels)

回归任务

mse_loss = nn.MSELoss()          # 均方误差
mae_loss = nn.L1Loss()           # 平均绝对误差
smooth_l1 = nn.SmoothL1Loss()    # Huber 损失

自定义损失函数

class CustomLoss(nn.Module):
    def __init__(self):
        super().__init__()
    
    def forward(self, pred, target):
        return (pred - target).abs().mean()  # MAE 的等价实现

loss_fn = CustomLoss()

4.6优化器

 常用优化器

from torch.optim import SGD, Adam, RMSprop

# 随机梯度下降(带动量)
optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)

# Adam 优化器(自适应学习率)
optimizer = Adam(model.parameters(), lr=1e-3, weight_decay=1e-4)

# RMSprop
optimizer = RMSprop(model.parameters(), lr=0.01, alpha=0.99)

学习率调度器

from torch.optim.lr_scheduler import StepLR

scheduler = StepLR(optimizer, step_size=30, gamma=0.1)  # 每 30 个 epoch 学习率 ×0.1

4.7模型保存与加载

保存模型参数

torch.save(model.state_dict(), 'model.pth')

加载模型参数

model = MyModel()
model.load_state_dict(torch.load('model.pth'))
model.eval()  # 切换到评估模式(关闭 Dropout/BatchNorm)

保存模型参数、优化器状态、epoch 等信息,便于恢复训练

# 保存检查点
checkpoint = {
    'epoch': 10,
    'model_state_dict': model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
    'loss': loss,
}
torch.save(checkpoint, 'checkpoint.pth')

# 加载检查点
checkpoint = torch.load('checkpoint.pth')
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
epoch = checkpoint['epoch']
loss = checkpoint['loss']

4.8自定义模型

 继承 `nn.Module`

class MyModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 64, 3)
        self.fc = nn.Linear(64 * 28 * 28, 10)
    
    def forward(self, x):
        x = self.conv1(x)
        x = x.view(x.size(0), -1)  # 展平
        x = self.fc(x)
        return x

参数初始化

def init_weights(m):
    if isinstance(m, nn.Linear):
        nn.init.xavier_uniform_(m.weight)
        m.bias.data.fill_(0.01)

model.apply(init_weights)  # 递归应用初始化函数

4.9高级功能

参数共享**

shared_layer = nn.Linear(128, 64)
model = nn.Sequential(
    shared_layer,
    nn.ReLU(),
    shared_layer  # 重复使用同一层(参数共享)
)

4.10应用场景示例

图像分类(CNN)

class CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 64, 3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(64, 128, 3),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        self.classifier = nn.Linear(128 * 6 * 6, 10)
    
    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        x = self.classifier(x)
        return x

序列建模(RNN)

class RNN(nn.Module):
    def __init__(self, vocab_size, embed_dim, hidden_size):
        super().__init__()
        self.embed = nn.Embedding(vocab_size, embed_dim)
        self.rnn = nn.GRU(embed_dim, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, 1)  # 二分类
    
    def forward(self, x):
        x = self.embed(x)
        _, h_n = self.rnn(x)
        output = self.fc(h_n.squeeze(0))
        return output

4.11注意事项


设备管理: 确保模型和数据在同一设备(CPU/GPU)。

model = model.to('cuda')
inputs = inputs.to('cuda')


训练模式切换: 训练时 `model.train()`,评估时 `model.eval()`。
梯度清零: 每个 batch 前调用 `optimizer.zero_grad()`。
参数访问: 使用 `model.parameters()` 获取所有可训练参数。

 5. 设备管理 (Device Management)

5.1设备选择与初始化

设备对象 (`torch.device`)
        创建设备对象:指定目标设备类型(CPU 或 CUDA)。

device_cpu = torch.device('cpu')  # CPU 设备
device_gpu = torch.device('cuda')  # 默认 GPU(索引 0)
device_gpu1 = torch.device('cuda:1')  # 指定 GPU 索引

检查 CUDA 可用性

if torch.cuda.is_available():
    print(f"可用 GPU 数量: {torch.cuda.device_count()}")
    print(f"当前 GPU 索引: {torch.cuda.current_device()}")
    print(f"GPU 名称: {torch.cuda.get_device_name(0)}")
else:
    print("CUDA 不可用")

5.2张量与模型的设备移动

将张量移动到指定设备
        使用 `to()` 方法:

tensor = torch.randn(3, 3)
tensor_gpu = tensor.to(device_gpu)  # 移动到 GPU
tensor_cpu = tensor_gpu.to('cpu')   # 移回 CPU

 
  
        直接创建在目标设备:

tensor_on_gpu = torch.randn(3, 3, device=device_gpu)

将模型移动到指定设备

model = MyModel()
model.to(device_gpu)  # 所有模型参数移至 GPU

# 前向传播时,输入数据需在同一设备
inputs = inputs.to(device_gpu)
outputs = model(inputs)

5.3多 GPU 训练

 数据并行 (`DataParallel`) 
        单机多卡,自动分割数据到不同 GPU:

model = nn.DataParallel(model, device_ids=[0, 1])  # 使用 GPU 0 和 1
outputs = model(inputs)  # inputs 自动分配到各 GPU
loss.backward()          # 梯度自动聚合

 分布式数据并行 (`DistributedDataParallel`)  
        适用于多机多卡,效率更高:

import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel as DDP

# 初始化进程组
dist.init_process_group(backend='nccl', rank=rank, world_size=world_size)

# 包装模型
model = DDP(model, device_ids=[local_rank])

5.4设备相关错误处理

设备不匹配错误

# 错误示例:张量位于不同设备
a = torch.tensor([1.0], device='cuda')
b = torch.tensor([2.0], device='cpu')
c = a + b  # RuntimeError: Expected all tensors to be on the same device

# 修复:统一设备
b = b.to('cuda')
c = a + b  # 正常执行

加载模型时的设备映射

# 从 GPU 保存的模型加载到 CPU
model.load_state_dict(
    torch.load('model_gpu.pth', map_location=torch.device('cpu'))

5.5内存管理

清空 GPU 缓存

torch.cuda.empty_cache()  # 释放未使用的显存(不影响张量持有的内存)

监控显存使用

print(torch.cuda.memory_allocated())  # 当前已分配显存(字节)
print(torch.cuda.max_memory_allocated())  # 最大分配显存

5.6设备无关的代码编写

动态选择设备

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)
inputs = inputs.to(device)

 通用代码模板

class MyModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.layer = nn.Linear(10, 5)
    
    def forward(self, x):
        return self.layer(x)

model = MyModel().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

for batch in dataloader:
    inputs, labels = batch
    inputs, labels = inputs.to(device), labels.to(device)
    
    outputs = model(inputs)
    loss = criterion(outputs, labels)
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

5.7最佳实践

        统一设备:确保所有张量和模型在同一设备上。
        高效数据传输:尽量减少 CPU 和 GPU 之间的数据拷贝。
        多 GPU 选择:小规模训练用 `DataParallel`,大规模分布式用 `DDP`。
        显存优化:
                   - 使用 `with torch.no_grad():` 减少中间变量存储。
                   - 混合精度训练 (`torch.cuda.amp`) 减少显存占用。

二、自定义模型开发指南

1.模型开发基础

1.1 继承 `nn.Module` 类

        所有自定义模型必须继承 `nn.Module`,并实现 `__init__` 和 `forward` 方法:

import torch.nn as nn

class CustomModel(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super().__init__()  # 必须调用父类初始化
        self.layer1 = nn.Linear(input_dim, hidden_dim)
        self.act = nn.ReLU()
        self.layer2 = nn.Linear(hidden_dim, output_dim)
    
    def forward(self, x):
        x = self.layer1(x)
        x = self.act(x)
        x = self.layer2(x)
        return x

1.2模型实例化与设备管理
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = CustomModel(input_dim=784, hidden_dim=128, output_dim=10).to(device)

2.模型结构设计

2.1层组合策略

`nn.Sequential`**(顺序结构):

self.features = nn.Sequential(
    nn.Conv2d(3, 64, 3),
    nn.BatchNorm2d(64),
    nn.ReLU(),
    nn.MaxPool2d(2)
)


`nn.ModuleList`(动态层管理):

self.layers = nn.ModuleList([nn.Linear(10, 10) for _ in range(5)])


`nn.ModuleDict`(字典式管理):

self.blocks = nn.ModuleDict({
    'conv': nn.Conv2d(3, 64, 3),
    'pool': nn.MaxPool2d(2)
})

2.2分支结构实现
class MultiBranchModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.branch1 = nn.Sequential(...)
        self.branch2 = nn.Sequential(...)
    
    def forward(self, x):
        out1 = self.branch1(x)
        out2 = self.branch2(x)
        return torch.cat([out1, out2], dim=1)

3.参数管理

3.1参数初始化

def init_weights(m):
    if isinstance(m, nn.Linear):
        nn.init.xavier_normal_(m.weight)
        nn.init.constant_(m.bias, 0.1)

model.apply(init_weights)  # 递归应用初始化

3.2冻结部分参数

for name, param in model.named_parameters():
    if 'layer1' in name:
        param.requires_grad_(False)  # 冻结 layer1 的参数

4.输入输出处理


4.1输入维度适配
def forward(self, x):
    # 处理图像输入 (B,C,H,W) → 展平为 (B, C*H*W)
    x = x.view(x.size(0), -1)  
    x = self.fc_layers(x)
    return x

4.2多模态输入处理
def forward(self, img, text):
    img_feat = self.img_encoder(img)
    text_feat = self.text_encoder(text)
    return torch.cat([img_feat, text_feat], dim=1)

5.调试与优化

5.1模型结构可视化
from torchsummary import summary
summary(model, input_size=(3, 224, 224))  # 输出各层维度信息

5.2 梯度监控
# 注册梯度钩子
def grad_hook(grad):
    print(f"Gradient norm: {grad.norm().item()}")

for name, param in model.named_parameters():
    if 'weight' in name:
        param.register_hook(grad_hook)

5.3混合精度训练

scaler = torch.cuda.amp.GradScaler()

with torch.cuda.amp.autocast():
    outputs = model(inputs)
    loss = criterion(outputs, labels)

scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()

6.高级功能扩展

6.1 自定义层开发
class CustomLayer(nn.Module):
    def __init__(self, in_features, out_features):
        super().__init__()
        self.weight = nn.Parameter(torch.randn(out_features, in_features))
    
    def forward(self, x):
        return x @ self.weight.t()

# 在模型中使用
self.custom_layer = CustomLayer(128, 64)

6.2模型融合技巧
class HybridModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.cnn = torchvision.models.resnet18(pretrained=True)
        self.rnn = nn.LSTM(input_size=512, hidden_size=128)
    
    def forward(self, img, seq):
        img_feat = self.cnn(img)          # CNN 提取图像特征
        seq_feat, _ = self.rnn(seq)       # RNN 处理序列
        return img_feat + seq_feat[:, -1] # 特征融合

7.模型部署准备

7.1TorchScript 导出
script_model = torch.jit.script(model)  # 转换为脚本模型
script_model.save("model_scripted.pt")

7.2 ONNX 格式导出
dummy_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(
    model, 
    dummy_input,
    "model.onnx",
    input_names=["input"],
    output_names=["output"]
)

8.最佳实践


8.1设备一致性

        确保模型和输入数据位于同一设备

inputs = inputs.to(next(model.parameters()).device)
   
8.2模式切换
model.train()  # 训练模式(启用 Dropout/BatchNorm)
model.eval()   # 评估模式(关闭随机层)
 
8.3检查点管理

        定期保存完整训练状态

torch.save({
    'epoch': epoch,
    'model_state': model.state_dict(),
    'optim_state': optimizer.state_dict(),
}, f"checkpoint_epoch{epoch}.pt")

9.常见问题解决

9.1维度不匹配错误

        - 症状:`RuntimeError: size mismatch`
        - 调试:在 `forward()` 中添加 `print(x.shape)` 跟踪数据流

9.2 梯度消失/爆炸

        - 解决:
          - 使用梯度裁剪:`nn.utils.clip_grad_norm_(model.parameters(), 1.0)`
          - 调整初始化策略

9.3模型加载失败

        - 错误:`Missing key(s) in state_dict`
        - 处理:

model.load_state_dict(torch.load(path), strict=False)  # 忽略未知键

三、调试与优化技巧

1·调试技巧

1.1张量形状跟踪

- 在 `forward()` 中打印形状:

def forward(self, x):
    print("Input shape:", x.shape)  # 跟踪输入
    x = self.conv1(x)
    print("After conv1:", x.shape)
    x = self.pool(x)
    ...
    return x


- 使用 `torchsummary`:

from torchsummary import summary
summary(model, input_size=(3, 224, 224))  # 输出各层维度信息

1.2 梯度监控

- 检查梯度是否存在:

for name, param in model.named_parameters():
    if param.grad is None:
        print(f"参数 {name} 无梯度!")


- 注册梯度钩子:

def grad_hook(grad):
    print(f"梯度均值: {grad.mean().item()}, 最大值: {grad.max().item()}")

for param in model.parameters():
    param.register_hook(grad_hook)

1.3设备一致性检查

# 确保所有张量在同一设备
assert inputs.device == next(model.parameters()).device, "设备不匹配!"

1.4 NaN/Inf 检测

if torch.isnan(outputs).any():
    raise ValueError("输出包含 NaN!")

# 或使用自动调试模式
torch.autograd.set_detect_anomaly(True)  # 在反向传播时检测异常

2.性能优化技巧


2.1计算图优化


- 禁用梯度计算:

with torch.no_grad():  # 推理阶段使用
    outputs = model(inputs)


- 使用 `detach()` 截断计算图:

hidden = rnn_output.detach()  # 阻止梯度回传至 RNN

2.2内存优化

- 混合精度训练:

from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()

with autocast():
    outputs = model(inputs)
    loss = criterion(outputs, labels)

scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()


- 激活检查点(Checkpointing):

from torch.utils.checkpoint import checkpoint

def forward(self, x):
    # 分段保存中间结果,减少内存占用
    x = checkpoint(self.layer1, x)
    x = checkpoint(self.layer2, x)
    return x

2.3 批量处理优化

- 增大 `batch_size`:在显存允许下最大化批次。
- 梯度累积: 

for i, (inputs, labels) in enumerate(dataloader):
    outputs = model(inputs)
    loss = criterion(outputs, labels)
    loss = loss / accumulation_steps  # 梯度累积步数
    loss.backward()
    
    if (i+1) % accumulation_steps == 0:
        optimizer.step()
        optimizer.zero_grad()

3.分布式训练优化

3.1数据并行加速
model = nn.DataParallel(model, device_ids=[0, 1])  # 多 GPU 并行

3.2分布式训练(DDP)
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel as DDP

# 初始化进程组
dist.init_process_group(backend='nccl')
model = DDP(model, device_ids=[local_rank])

4.可视化工具

4.1TensorBoard 集成
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter()
writer.add_graph(model, inputs)  # 可视化计算图
writer.add_scalar('Loss/train', loss.item(), epoch)

4.2 使用 `torchviz` 绘制计算图
from torchviz import make_dot

outputs = model(inputs)
make_dot(outputs, params=dict(model.named_parameters())).render("model_graph", format="png")

5.常见错误与修复

5.1CUDA 内存不足

- 症状:`RuntimeError: CUDA out of memory`
- 解决方案:
  - 减小 `batch_size`
  - 使用混合精度训练 (`amp`)
  - 启用激活检查点 (`checkpoint`)

5.2梯度爆炸/消失

- 症状:损失值剧烈波动或停滞
- 解决方案:

# 梯度裁剪
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)

# 调整初始化策略
nn.init.xavier_uniform_(layer.weight)

5.3 张量设备不匹配

- 症状:`RuntimeError: Expected all tensors to be on the same device`
- 修复方案:

model = model.to(device)
inputs = inputs.to(device)

6.最佳实践总结


- 调试优先:先确保模型能运行,再优化性能。
- 增量测试:从简单数据(如单个样本)开始验证模型。
- 版本控制:记录 PyTorch 版本和硬件环境。
- 性能分析:使用 `torch.profiler` 定位瓶颈:

with torch.profiler.profile(activities=[torch.profiler.ProfilerActivity.CUDA]) as prof:
    model(inputs)
print(prof.key_averages().table(sort_by="cuda_time_total"))

四、扩展资源

官方文档:

        英文版 https://pytorch.org/docs/stable/index.html

        中文版 主页 - PyTorch中文文档

教程推荐:

  - PyTorch 官方 Tutorials

  - 《Deep Learning with PyTorch》 - Eli Stevens等著

  - Kaggle 上的 PyTorch 实战 Notebook

您可能感兴趣的与本文相关的镜像

PyTorch 2.9

PyTorch 2.9

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值