Pytorch框架
PyTorch是一个开源的深度学习框架,由Facebook的AI研究团队(FAIR)开发。它广泛应用于机器学习和人工智能的研究和应用中。PyTorch的核心特点包括:
- 动态计算图:PyTorch采用动态计算图(Define-by-Run),这意味着计算图在每次前向传播时都被即时创建和更新。这使得模型的调试更加灵活和直观。
- 强大的GPU支持:PyTorch原生支持GPU加速,可以通过CUDA快速进行张量计算。这使得在大规模数据和复杂神经网络训练时,能够显著提升计算效率。
- 易用性和灵活性:PyTorch拥有与NumPy相似的API,且其张量操作非常直观。它允许开发者更容易进行模型的实验、调试和修改。
- 深度学习模块:PyTorch包含一个丰富的深度学习模块——
torch.nn
,它提供了构建神经网络所需的各种功能,包括层、损失函数、优化器等。 - 自动微分:PyTorch的
autograd
模块实现了自动微分,可以轻松计算模型训练中的梯度,支持反向传播算法,是训练神经网络的重要工具。 - 广泛的社区支持和生态系统:PyTorch有一个活跃的开发者和研究者社区,不仅提供了许多高质量的教程和文档,还有大量预训练模型和开源项目,可以快速进行迁移学习或进行模型重构。
- 与Python兼容性强:由于PyTorch是用Python编写的,它与Python生态系统中的其他库(如NumPy、SciPy等)兼容,并且能够轻松集成到现有的Python项目中。
一、基本数据类型Tensor
在 PyTorch 中,张量(Tensor)是框架的核心数据类型。它类似于 NumPy 的多维数组,但具有以下核心优势:
- GPU 加速计算:支持将张量转移到 GPU 上进行高性能计算。
- 自动微分:通过
autograd
模块自动计算梯度,简化神经网络训练。 - 动态计算图:与静态图框架不同,PyTorch 的计算图在运行时动态构建,更灵活。
1. Tensor 的基本概念
维度与形状
张量的维度决定了其数据的结构:
- 0维张量(标量):单个数值,如
torch.tensor(5)
。 - 1维张量(向量):一维数组,如
torch.tensor([1, 2, 3])
。 - 2维张量(矩阵):二维数组,如
torch.tensor([[1, 2], [3, 4]])
。 - 3维及以上张量:例如图像数据通常表示为
[批次大小, 通道数, 高度, 宽度]
。
# 示例:不同维度的张量
scalar = torch.tensor(3.14) # 标量(0维)
vector = torch.tensor([1, 2, 3]) # 向量(1维)
matrix = torch.tensor([[1, 2], [3, 4]]) # 矩阵(2维)
image_batch = torch.randn(32, 3, 224, 224) # 4维张量(批次图像数据)
2. Tensor 的创建方法
2.1 从数据创建
-
直接通过 Python 列表或 NumPy 数组创建:
data = [[1, 2], [3, 4]] tensor = torch.tensor(data)
2.2 通过函数创建
-
初始化全值张量:
zeros_tensor = torch.zeros(2, 3) # 2x3 零矩阵 ones_tensor = torch.ones(2, 3) # 2x3 单位矩阵 eye_matrix = torch.eye(3) # 3x3 单位矩阵 full_tensor = torch.full((2, 3), 5.0) # 2x3 填充值为5的矩阵
-
生成序列:
range_tensor = torch.arange(0, 10, 2) # tensor([0, 2, 4, 6, 8]) linspace_tensor = torch.linspace(0, 1, 5) # tensor([0.0, 0.25, 0.5, 0.75, 1.0])
-
随机初始化:
uniform_tensor = torch.rand(2, 3) # 均匀分布 [0, 1) normal_tensor = torch.randn(2, 3) # 标准正态分布 randint_tensor = torch.randint(0, 10, (2, 3)) # 0~9的随机整数
-
基于已有张量创建:
x = torch.tensor([[1, 2], [3, 4]]) x_like = torch.zeros_like(x) # 形状和数据类型与x相同的零张量
3. Tensor 的属性
属性 | 说明 | 示例 |
---|---|---|
tensor.shape | 张量的维度形状 | torch.Size([2, 3]) |
tensor.dtype | 数据类型(如 float32 , int64 ) | torch.float32 |
tensor.device | 所在设备(CPU 或 GPU) | device(type='cuda:0') |
tensor.requires_grad | 是否启用梯度追踪 | True 或 False |
tensor.grad | 梯度值(反向传播后更新) | tensor([0.5, -0.2]) |
tensor.grad_fn | 创建该张量的函数(用于计算图) | <AddBackward0 at 0x...> |
# 示例:查看属性
x = torch.randn(2, 3, requires_grad=True)
print("Shape:", x.shape) # 输出: torch.Size([2, 3])
print("Data type:", x.dtype) # 输出: torch.float32
print("Device:", x.device) # 输出: cpu
print("Requires grad:", x.requires_grad) # 输出: True
4. Tensor 的操作
4.1 数学运算
-
逐元素运算:
a = torch.tensor([1, 2, 3]) b = torch.tensor([4, 5, 6]) c = a + b # tensor([5, 7, 9]) d = torch.sin(a) # tensor([0.8415, 0.9093, 0.1411])
-
矩阵乘法:
x = torch.tensor([[1, 2], [3, 4]]) y = torch.tensor([[5, 6], [7, 8]]) z = x @ y # 或 torch.matmul(x, y) # 输出: tensor([[19, 22], [43, 50]])
-
广播机制:
a = torch.tensor([[1, 2], [3, 4]]) b = torch.tensor([10]) c = a + b # 广播后的结果:[[11, 12], [13, 14]]
4.2 形状操作
-
调整形状:
x = torch.arange(6) y = x.view(2, 3) # 调整为2x3(共享内存) z = x.reshape(2, 3) # 同上,但更灵活(可能复制内存)
-
压缩/扩展维度:
x = torch.randn(3, 1, 4) y = x.squeeze() # 移除所有大小为1的维度 → [3, 4] z = y.unsqueeze(0) # 在第0维增加维度 → [1, 3, 4]
-
拼接与分割:
a = torch.tensor([[1, 2], [3, 4]]) b = torch.tensor([[5, 6]]) c = torch.cat([a, b], dim=0) # 沿行拼接 → 3x2矩阵 chunks = torch.chunk(c, 3, dim=0) # 分割为3个张量
4.3 索引与切片
-
基本索引:
x = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(x[0, :]) # 第一行 → tensor([1, 2, 3]) print(x[:, 1]) # 第二列 → tensor([2, 5, 8]) print(x[1:, 0:2]) # 行1~2,列0~1 → [[4,5], [7,8]]
-
布尔索引:
mask = x > 5 print(x[mask]) # 输出所有大于5的元素 → tensor([6, 7, 8, 9])
4.4 聚合操作
x = torch.tensor([[1, 2], [3, 4]])
print(torch.sum(x)) # 所有元素求和 → 10
print(torch.mean(x.float())) # 平均值 → 2.5
print(torch.max(x)) # 最大值 → 4
print(torch.argmax(x)) # 最大值的索引 → 3(展平后)
5. Tensor 的设备管理
-
CPU 与 GPU 互转:
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") x = torch.tensor([1, 2, 3]) x_gpu = x.to(device) # 转移到GPU x_cpu = x_gpu.cpu() # 转回CPU
-
多 GPU 操作(需分布式训练支持):
if torch.cuda.device_count() > 1: model = torch.nn.DataParallel(model) # 数据并行
6. 自动求导(Autograd)
6.1 基础示例
# 创建需要梯度的张量
x = torch.tensor(2.0, requires_grad=True)
y = x ** 2 + 3 * x
# 反向传播计算梯度
y.backward() # dy/dx = 2x + 3 → 在x=2时梯度为7
print(x.grad) # 输出: tensor(7.)
6.2 梯度清零与禁用梯度
-
梯度清零(训练循环中必须):
optimizer = torch.optim.SGD(model.parameters(), lr=0.01) optimizer.zero_grad() # 清空历史梯度 loss.backward() optimizer.step()
-
禁用梯度计算(推理时节省内存):
with torch.no_grad(): inference_output = model(input_data)
6.3 实战案例:线性回归
# 生成数据
X = torch.linspace(0, 10, 100).reshape(-1, 1)
Y = 3 * X + 5 + torch.randn(100, 1) * 2
# 定义模型和优化器
model = torch.nn.Linear(1, 1)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# 训练循环
for epoch in range(100):
optimizer.zero_grad()
outputs = model(X)
loss = criterion(outputs, Y)
loss.backward()
optimizer.step()
if (epoch+1) % 10 == 0:
print(f'Epoch {epoch+1}, Loss: {loss.item():.4f}')
7. 张量与 NumPy 的互操作
-
Tensor → NumPy(共享内存):
tensor = torch.tensor([1, 2, 3]) numpy_array = tensor.numpy() # 修改其中一个会影响另一个
-
NumPy → Tensor:
import numpy as np numpy_array = np.array([4, 5, 6]) tensor = torch.from_numpy(numpy_array) # 共享内存
8. 张量的序列化
-
保存与加载:
# 保存张量 torch.save(tensor, 'tensor.pt') # 加载张量 loaded_tensor = torch.load('tensor.pt')