PyTorch 简单入门指南

只是做个记录,以备不时之需

1. 安装 Torch

可以使用 pip 来安装最新版本的 PyTorch。访问 PyTorch 官网以获取针对您系统的正确命令。

例如,对于 CPU 版本:

1
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu

对于 GPU 版本(CUDA 支持):

1
pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cuXXX

(将 cuXXX 替换为所需的 CUDA 版本,如 cu118)

2. 基础概念

张量(Tensor)

  • 定义:张量是多维数组,是 torch 中的核心数据结构。
  • 优点:
    • 高效的数值运算。
    • 自动求导支持。
    • 显著优于 NumPy 数组的地方在于其对 GPU 的良好支持。

自动求导(Autograd)

  • 定义:autograd 模块实现了所有张量操作的历史记录,并允许执行反向传播以计算梯度。
  • 关键类:
    • Variable: 已经废弃,现在所有的张量默认都具有追踪属性。
    • Function: 执行向前和向后的计算步骤。

3. 创建和操作张量

创建张量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import torch

# 创建一个空的二维张量
empty_tensor = torch.empty(2, 3)
print(empty_tensor)

# 创建一个全零的三维张量
zeros_tensor = torch.zeros(2, 3, dtype=torch.float32)
print(zeros_tensor)

# 创建一个单位矩阵
identity_matrix = torch.eye(3)
print(identity_matrix)

# 从列表创建张量
list_data = [[1, 2], [3, 4]]
tensor_from_list = torch.tensor(list_data)
print(tensor_from_list)

# 使用现有的张量克隆新的张量
cloned_tensor = tensor_from_list.clone().fill_(5)
print(cloned_tensor)

张量形状操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看张量形状
shape = tensor_from_list.shape
print(shape) # Output: torch.Size([2, 2])

# 修改张量形状
reshaped_tensor = tensor_from_list.view(-1, 4)
print(reshaped_tensor)

# 展平张量
flattened_tensor = tensor_from_list.flatten()
print(flattened_tensor)

# 转置张量
transposed_tensor = tensor_from_list.t()
print(transposed_tensor)

索引和切片

1
2
3
4
5
6
7
8
9
10
11
12
# 单个元素访问
element = tensor_from_list[0][1] # 或者 tensor_from_list[0, 1]
print(element)

# 切片操作
slice_tensor = tensor_from_list[:, 1:]
print(slice_tensor)

# 使用布尔掩码
mask = tensor_from_list > 2
masked_elements = tensor_from_list[mask]
print(masked_elements)

4. 张量运算

基本运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 加法
add_result = tensor_from_list + cloned_tensor
print(add_result)

# 减法
sub_result = tensor_from_list - cloned_tensor
print(sub_result)

# 元素-wise 乘法
mul_elementwise = tensor_from_list * cloned_tensor
print(mul_elementwise)

# 点积
dot_product = torch.dot(tensor_from_list.reshape(-1), flattened_tensor)
print(dot_product)

# 矩阵乘法
mat_mul = torch.mm(tensor_from_list, transposed_tensor)
print(mat_mul)

聚合操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 最大值
max_value, max_index = tensor_from_list.max(dim=1)
print(max_value, max_index)

# 最小值
min_value, min_index = tensor_from_list.min(dim=1)
print(min_value, min_index)

# 各种汇总操作
mean_val = tensor_from_list.mean()
sum_val = tensor_from_list.sum()
std_dev = tensor_from_list.std()

print(mean_val, sum_val, std_dev)

5. 自动求导与优化

启用跟踪

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 默认情况下,requires_grad 设置为 False
x = torch.ones(2, requires_grad=True)
print(x.requires_grad) # Output: True

# 进行一些操作
y = x + 2
z = y * y * 3
out = z.mean()

# 计算梯度
out.backward()

# 查看 grad
print(x.grad) # d(out)/dx
禁用跟踪
有时不需要跟踪某个变量的梯度,可以临时关闭:

with torch.no_grad():
print((x ** 2).requires_grad) # Output: False
或者永久设置:

w = torch.rand(2, 2, requires_grad=True)
v = w.detach()
print(v.requires_grad) # Output: False

优化器

通常使用 optim 模块中的优化器来更新模型参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import torch.optim as optim

# 初始化模型参数
params = torch.randn(4, requires_grad=True)

# 创建优化器
optimizer = optim.SGD(params, lr=0.01)

# 训练循环的一部分
for epoch in range(10):
optimizer.zero_grad() # 清除之前的梯度

output = model(input_data)
loss = criterion(output, target)

loss.backward() # 反向传播计算梯度
optimizer.step() # 更新参数

6. 构建神经网络

自定义模型

继承 nn.Module 类并定义前向传播逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import torch.nn as nn
import torch.nn.functional as F

class SimpleNet(nn.Module):
def __init__(self):
super(SimpleNet, self).__init__()
self.fc1 = nn.Linear(in_features=784, out_features=128)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(in_features=128, out_features=10)

def forward(self, x):
x = x.view(-1, 784) # Flatten the input
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x

# 实例化模型
model = SimpleNet()
print(model)

使用预训练模型

torchvision.models 提供了许多常用的预训练模型。

1
2
3
4
5
import torchvision.models as models

# 加载 ResNet-18 预训练模型
resnet_model = models.resnet18(pretrained=True)
print(resnet_model)

7. 数据加载与处理

Dataset 和 DataLoader

torch.utils.data 模块提供了方便的数据管理工具。

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
from torch.utils.data import Dataset, DataLoader

# 自定义 Dataset
class CustomDataset(Dataset):
def __init__(self, data, labels):
self.data = data
self.labels = labels

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

def __getitem__(self, idx):
sample = {'data': self.data[idx], 'labels': self.labels[idx]}
return sample

# 示例数据
data_samples = torch.randn(100, 784)
labels = torch.randint(low=0, high=10, size=(100,))
custom_dataset = CustomDataset(data=data_samples, labels=labels)

# 创建 DataLoader
dataloader = DataLoader(custom_dataset, batch_size=10, shuffle=True)

# 遍历 DataLoader
for i_batch, sample_batched in enumerate(dataloader):
inputs, targets = sample_batched['data'], sample_batched['labels']
break
Transformations
使用 transforms 对数据进行预处理。

from torchvision import transforms

transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])

# 应用 Transformations
transformed_sample = transform(sample_batched['data'])

8. 训练和评估模型

完整的训练流程

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
import torch.optim as optim
# 定义设备
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)

# 训练循环
num_epochs = 5
for epoch in range(num_epochs):
running_loss = 0.0
for i, data in enumerate(dataloader, 0):
inputs, labels = data['data'].to(device), data['labels'].to(device)

# 清除之前的梯度
optimizer.zero_grad()

# 前向传播
outputs = model(inputs)
loss = criterion(outputs, labels)

# 反向传播和优化
loss.backward()