深度学习的工业标准框架,灵活、Pythonic、可调试
PyTorch是Meta(Facebook)开源的深度学习框架,以动态计算图和Pythonic设计著称,是2024年学术界和工业界最流行的深度学习框架。
| 特性 | PyTorch | TensorFlow | JAX |
|---|---|---|---|
| 计算图 | 动态 | 动态/静态 | 函数式 |
| 调试 | ✅ 原生Python | ⚠️ 较难 | ✅ 原生 |
| GPU加速 | CUDA | CUDA/TPU | TPU优先 |
| 部署 | TorchScript/ONNX | TF Serving/TF Lite | 有限 |
| 学术采用率 | 80%+ | 15% | 5% |
Tensor是PyTorch的核心数据结构,类似NumPy的ndarray,但支持GPU加速和自动微分。
import torch
import numpy as np
print(f"PyTorch版本: {torch.__version__}")
print(f"CUDA可用: {torch.cuda.is_available()}")
# ===== 创建Tensor =====
# 从Python数据
a = torch.tensor([1.0, 2.0, 3.0])
# 从范围
b = torch.arange(0, 12).reshape(3, 4).float()
# 随机
c = torch.randn(3, 3) # 标准正态
d = torch.zeros(2, 3) # 全零
e = torch.ones(2, 3) # 全一
f = torch.linspace(0, 1, 5) # 等间距
print(f"向量: {a}")
print(f"矩阵形状: {b.shape}")
print(f"等间距: {f}")
# ===== 运算 =====
x = torch.tensor([1.0, 2.0, 3.0])
y = torch.tensor([4.0, 5.0, 6.0])
print(f"\n加法: {x + y}")
print(f"点积: {torch.dot(x, y)}") # 32.0
print(f"外积形状: {torch.outer(x, y).shape}") # (3, 3)
# 矩阵乘法
A = torch.randn(3, 4)
B = torch.randn(4, 2)
C = A @ B # 或 torch.matmul(A, B)
print(f"\n矩阵乘法: (3,4) @ (4,2) = {C.shape}")
# 广播机制
a2 = torch.randn(3, 1)
b2 = torch.randn(1, 4)
c2 = a2 + b2 # (3,1) + (1,4) → (3,4)
print(f"广播: (3,1) + (1,4) = {c2.shape}")
# ===== NumPy互转 =====
np_arr = np.array([1, 2, 3])
t_from_np = torch.from_numpy(np_arr) # 共享内存!
t_to_np = t_from_np.numpy() # 共享内存!
print(f"\nNumPy→Tensor: {t_from_np}")
print(f"Tensor→NumPy: {t_to_np}")
| 创建方式 | 代码 | 说明 |
|---|---|---|
| 从列表 | torch.tensor([1,2,3]) | 自动推断类型 |
| 全零 | torch.zeros(3,4) | 指定形状 |
| 全一 | torch.ones(3,4) | 指定形状 |
| 随机正态 | torch.randn(3,4) | N(0,1) |
| 范围 | torch.arange(0,10) | 类似range |
| 等间距 | torch.linspace(0,1,5) | 含端点 |
| 从NumPy | torch.from_numpy(arr) | 共享内存 |
Autograd是PyTorch的灵魂——自动计算梯度,无需手写反向传播!只需设置requires_grad=True,PyTorch会自动追踪所有运算并构建计算图。
# ===== 标量求导 =====
x = torch.tensor(2.0, requires_grad=True)
y = x**2 + 3*x + 1 # y = x² + 3x + 1
y.backward()
print(f"y = x² + 3x + 1, x=2")
print(f"dy/dx = 2x + 3 = {x.grad} (应为7)")
# ===== 向量求导 =====
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
w = torch.tensor([0.5, 0.3, 0.2], requires_grad=True)
y = (x * w).sum() # y = Σ(xᵢ·wᵢ)
y.backward()
print(f"\ny = Σ(x*w)")
print(f"∂y/∂w = x = {w.grad}")
print(f"∂y/∂x = w = {x.grad}")
# ===== 高阶导数 =====
x = torch.tensor(3.0, requires_grad=True)
y = x**3 # y = x³
y.backward(retain_graph=True)
print(f"\ny=x³, dy/dx = 3x² = {x.grad} (应为27)")
x.grad.zero_() # 清除梯度
y.backward()
print(f"再次: dy/dx = {x.grad}")
# ===== 梯度控制 =====
x = torch.tensor([1.0, 2.0], requires_grad=True)
# 方式1: no_grad上下文
with torch.no_grad():
y = x * 2
print(f"\nno_grad内: y.requires_grad = {y.requires_grad}")
# 方式2: detach分离
z = (x * 3).detach()
print(f"detach后: z.requires_grad = {z.requires_grad}")
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
import numpy as np
np.random.seed(42)
X, y = make_moons(n_samples=500, noise=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 转为Tensor
X_t = torch.tensor(X_train, dtype=torch.float32)
y_t = torch.tensor(y_train, dtype=torch.float32).unsqueeze(1)
X_test_t = torch.tensor(X_test, dtype=torch.float32)
y_test_t = torch.tensor(y_test, dtype=torch.float32).unsqueeze(1)
# ===== 定义模型 (Sequential方式) =====
model = torch.nn.Sequential(
torch.nn.Linear(2, 16),
torch.nn.ReLU(),
torch.nn.Linear(16, 8),
torch.nn.ReLU(),
torch.nn.Linear(8, 1),
torch.nn.Sigmoid()
)
# 损失函数 + 优化器
criterion = torch.nn.BCELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
# ===== 训练循环 =====
for epoch in range(500):
optimizer.zero_grad() # 1. 清零梯度
output = model(X_t) # 2. 前向传播
loss = criterion(output, y_t) # 3. 计算损失
loss.backward() # 4. 反向传播
optimizer.step() # 5. 更新参数
if epoch % 100 == 0:
pred = (output >= 0.5).float()
acc = (pred == y_t).float().mean()
print(f"Epoch {epoch}: loss={loss.item():.4f}, acc={acc.item():.4f}")
# 测试
with torch.no_grad():
test_pred = (model(X_test_t) >= 0.5).float()
test_acc = (test_pred == y_test_t).float().mean()
print(f"\n测试集准确率: {test_acc.item():.4f}")
# 查看模型参数
total_params = sum(p.numel() for p in model.parameters())
print(f"模型总参数量: {total_params}")
# 更灵活的方式:自定义Module
class MoonClassifier(torch.nn.Module):
def __init__(self, hidden_dim=16):
super().__init__()
self.fc1 = torch.nn.Linear(2, hidden_dim)
self.fc2 = torch.nn.Linear(hidden_dim, hidden_dim // 2)
self.fc3 = torch.nn.Linear(hidden_dim // 2, 1)
self.relu = torch.nn.ReLU()
self.sigmoid = torch.nn.Sigmoid()
def forward(self, x):
x = self.relu(self.fc1(x))
x = self.relu(self.fc2(x))
x = self.sigmoid(self.fc3(x))
return x
model2 = MoonClassifier(hidden_dim=32)
print(f"自定义模型结构:\n{model2}")
# 参数量统计
for name, param in model2.named_parameters():
print(f" {name}: shape={param.shape}, params={param.numel()}")
# 保存/加载模型
torch.save(model2.state_dict(), 'model_weights.pth')
model2.load_state_dict(torch.load('model_weights.pth', weights_only=True))
print("\n模型保存和加载成功 ✅")
| 优化器 | 公式核心 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|---|
| SGD | w -= η·∇L | 简单,泛化好 | 收敛慢 | CV大模型 |
| SGD+Momentum | v = βv + ∇L | 加速收敛 | 需调β | ResNet等 |
| Adam | 自适应学习率 | 收敛快,少调参 | 可能泛化差 | NLP/默认 |
| AdamW | Adam+解耦正则 | 比Adam更好 | 稍复杂 | Transformer |
| LAMB | 大批量Adam | 支持大批量 | 小数据无优势 | BERT预训练 |
# 不同优化器对比
optimizers = {
'SGD': torch.optim.SGD(model.parameters(), lr=0.1),
'SGD+Momentum': torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9),
'Adam': torch.optim.Adam(model.parameters(), lr=0.01),
'AdamW': torch.optim.AdamW(model.parameters(), lr=0.01, weight_decay=0.01),
}
# 实践中: Adam/AdamW 是最安全的首选