pytorch

pytorch指南

目录

[TOC]

思维导图

pytorch

container处分类笔误

细节

一、张量 (Tensors)

1. 创建 (Creation)

1
2
3
4
5
6
7
8
9
10
import torch

x = torch.tensor([1, 2, 3]) # 从列表创建
x = torch.zeros(2, 3) # 全0张量
x = torch.ones(2, 3) # 全1张量
x = torch.randn(2, 3) # 标准正态分布
x = torch.rand(2, 3) # 均匀分布 [0,1)
x = torch.arange(0, 10, 2) # 序列 [0,2,4,6,8]
x = torch.linspace(0, 1, 5) # 等间距5个点 [0,0.25,0.5,0.75,1]
x = torch.eye(3) # 单位矩阵

2. 属性 (Attributes)

1
2
3
4
5
x.shape          # 形状 (2,3)
x.dtype # 数据类型 (torch.float32)
x.device # 设备 ('cpu' 或 'cuda:0')
x.ndim # 维度数量 (2)
x.size() # 同 shape

3. 操作 (Operations)

1
2
3
4
5
6
7
8
9
10
11
# 算术运算
x + y, x - y, x * y, x / y, x ** y # 逐元素运算
torch.matmul(x, y) # 矩阵乘法 (或 x @ y)
torch.sum(x), torch.mean(x) # 求和、均值
torch.max(x), torch.min(x) # 最大值、最小值

# 数学函数
torch.sin(x), torch.cos(x), torch.exp(x), torch.log(x)

# 逻辑运算
x > y, x == y, torch.logical_and(x, y)

4. 重塑 (Reshaping)

1
2
3
4
5
6
x.view(2, 3)          # 改变形状(需内存连续)
x.reshape(2, 3) # 改变形状(更通用)
x.flatten() # 展平为1维
x.squeeze() # 去除维度为1的维度
x.unsqueeze(1) # 在第1维增加维度
x.permute(1, 0) # 维度置换(转置)

5. 索引与切片 (Indexing/Slicing)

1
2
3
4
x[0, :]               # 第0行所有列
x[:, 1] # 所有行第1列
x[x > 0] # 布尔索引
x[[0, 2], [1, 3]] # 花式索引

6. 拼接与拆分 (Concatenation/Splitting)

1
2
3
torch.cat([x, y], dim=0)    # 按行拼接
torch.stack([x, y], dim=1) # 新增维度拼接
torch.split(x, 2, dim=0) # 按大小拆分

7. 类型转换与设备移动

1
2
3
4
5
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
x.to(torch.float64) # 数据类型转换
x.to(device) # 移动到指定设备
x.cpu() # 移动到CPU
x.detach() # 截断梯度

二、自动微分与计算图 (Autograd & Computational Graph)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 启用梯度追踪
x = torch.tensor([1.0, 2.0], requires_grad=True)

# 前向传播
y = x * 2 + 1
z = y.mean()

# 反向传播(计算梯度)
z.backward()
print(x.grad) # 输出 tensor([1., 1.])

# 计算特定变量的梯度(不使用 backward)
grads = torch.autograd.grad(outputs=z, inputs=x)
print(grads[0])

# 禁用梯度计算(评估/推理时用)
with torch.no_grad():
y = x * 2

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

# 清空梯度
x.grad.zero_()

三、数据加载 (Data Loading)

1. 自定义 Dataset

1
2
3
4
5
6
7
8
9
10
11
12
from torch.utils.data import Dataset

class MyDataset(Dataset):
def __init__(self, data, labels):
self.data = data
self.labels = labels

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

def __getitem__(self, idx):
return self.data[idx], self.labels[idx]

2. DataLoader

1
2
3
4
5
6
7
8
9
from torch.utils.data import DataLoader

dataloader = DataLoader(
dataset,
batch_size=32,
shuffle=True,
num_workers=4,
drop_last=True
)

3. 数据预处理 (Transforms)

1
2
3
4
5
6
7
8
9
10
11
12
from torchvision import transforms
from torchvision.datasets import ImageFolder

transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.5], std=[0.5]),
transforms.Resize((224, 224)),
transforms.RandomHorizontalFlip()
])

# 按文件夹加载图像数据集
dataset = ImageFolder(root='./data/train', transform=transform)

四、神经网络 (Neural Networks - torch.nn)

1. 定义模型(完整示例)

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
import torch.nn as nn
import torch.nn.functional as F

class MyModel(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 256)
self.bn1 = nn.BatchNorm1d(256)
self.dropout = nn.Dropout(0.5)
self.fc2 = nn.Linear(256, 10)

def forward(self, x):
x = self.fc1(x)
x = self.bn1(x)
x = F.relu(x)
x = self.dropout(x)
x = self.fc2(x)
return x

# 快速定义模型(Sequential)
model = nn.Sequential(
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10)
)

2. 常用层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 线性层/全连接层
nn.Linear(in_features, out_features)

# 卷积层
nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=1)

# 池化层
nn.MaxPool2d(kernel_size=2)
nn.AvgPool2d(kernel_size=2)

# 循环层
nn.LSTM(input_size, hidden_size, num_layers)
nn.GRU(input_size, hidden_size, num_layers)

# 嵌入层(NLP常用)
nn.Embedding(num_embeddings=10000, embedding_dim=128)

# 激活函数
nn.ReLU(), nn.Sigmoid(), nn.Tanh(), nn.LeakyReLU()

# 损失函数
nn.MSELoss() # 均方误差(回归)
nn.CrossEntropyLoss() # 交叉熵(多分类)
nn.BCELoss() # 二分类交叉熵

3. 模型微调(冻结部分参数)

1
2
3
4
5
6
7
8
9
10
# 冻结前几层
for name, param in model.named_parameters():
if 'fc1' in name:
param.requires_grad = False

# 优化器仅更新需要梯度的参数
optimizer = optim.Adam(
filter(lambda p: p.requires_grad, model.parameters()),
lr=0.001
)

五、优化器 (Optimization - torch.optim)

1
2
3
4
5
6
7
8
9
10
11
import torch.optim as optim

# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
optimizer = optim.Adam(model.parameters(), lr=0.001)
optimizer = optim.RMSprop(model.parameters(), lr=0.001)

# 学习率调度器
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', patience=5)
scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=50)

六、完整训练循环 (Training Loop)

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
47
48
49
50
51
52
# 1. 准备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scaler = torch.cuda.amp.GradScaler() # 混合精度缩放器

# 2. 训练循环
for epoch in range(10):
model.train()
running_loss = 0.0

for inputs, labels in dataloader:
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()

# 混合精度前向传播
with torch.cuda.amp.autocast():
outputs = model(inputs)
loss = criterion(outputs, labels)

# 混合精度反向传播与优化
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()

running_loss += loss.item()

scheduler.step()

# 3. 验证循环
model.eval()
correct = 0
total = 0

with torch.no_grad():
for inputs, labels in val_dataloader:
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()

print(f'Epoch {epoch+1}, Loss: {running_loss/len(dataloader):.4f}, '
f'Val Accuracy: {100*correct/total:.2f}%')

# 4. 模型保存与加载
torch.save(model.state_dict(), 'model.pth')
model.load_state_dict(torch.load('model.pth', map_location=device))

torch.save(model, 'full_model.pth')
model = torch.load('full_model.pth', map_location=device)

七、补充:模型评估 (Evaluations)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.metrics import accuracy_score, f1_score

y_true = []
y_pred = []

model.eval()
with torch.no_grad():
for inputs, labels in test_dataloader:
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
y_true.extend(labels.numpy())
y_pred.extend(preds.numpy())

print(f'Accuracy: {accuracy_score(y_true, y_pred):.4f}')
print(f'F1 Score: {f1_score(y_true, y_pred, average="macro"):.4f}')