PyTorch 基础:张量、自动求导、你的第一个神经网络
把 L1 全部的数学和 Python 武器组合起来——这是你的"AI 工程师"入门仪式。
L1 学到这里,你已经懂:
- 矩阵和梯度(L1-02, L1-03)
- 损失函数(L1-04, L1-05)
- 反向传播(L1-06)
- Python + NumPy + Pandas(L1-07/08/09)
该跑你的第一个神经网络了。
我们用 PyTorch——目前学术界和工业界最主流的深度学习框架,2026 年生态已经远超 TensorFlow。
第一站:安装
PyTorch 已经预装在 Google Colab——直接用就行。
本地装:
pip install torch
GPU 版本:如果你有 NVIDIA 显卡,访问 pytorch.org 选对应 CUDA 版本。但本篇所有代码 CPU 就够跑。
第二站:张量(Tensor)
Tensor 是 PyTorch 的核心数据结构——本质上就是带 GPU 加速 + 自动求导的 NumPy 数组。
import torch
# 创建 tensor(和 NumPy 几乎一样)
a = torch.tensor([1, 2, 3, 4])
print(a) # tensor([1, 2, 3, 4])
print(a.shape) # torch.Size([4])
print(a.dtype) # torch.int64
# 浮点(神经网络常用)
b = torch.tensor([1.0, 2.0, 3.0])
print(b.dtype) # torch.float32
# 从 NumPy 来
import numpy as np
arr = np.array([1, 2, 3])
t = torch.from_numpy(arr)
# 反过来
t.numpy()
# 常用创建
torch.zeros(3, 4)
torch.ones(2, 3)
torch.randn(2, 3) # 标准正态
torch.arange(10)
torch.linspace(0, 1, 5)
第三站:张量运算
和 NumPy 99% 一样:
a = torch.tensor([[1.0, 2.0],
[3.0, 4.0]])
b = torch.tensor([[5.0, 6.0],
[7.0, 8.0]])
# 算术
a + b
a * b # 元素相乘
a @ b # 矩阵乘法
# 形状操作
a.shape # torch.Size([2, 2])
a.reshape(4, 1)
a.T # 转置
# 聚合
a.sum()
a.mean(dim=0) # 注意是 dim 不是 axis
a.argmax(dim=1)
# 索引
a[0, 1]
a[:, 0]
a[a > 2] # 布尔索引
关键差异:PyTorch 用 dim 不是 axis。
第四站:GPU 加速
# 检查 GPU
torch.cuda.is_available() # True/False
# 把 tensor 搬到 GPU
device = 'cuda' if torch.cuda.is_available() else 'cpu'
a = a.to(device)
b = b.to(device)
# 之后所有运算都在 GPU 上
c = a @ b # GPU 运算
# 搬回 CPU 查看
c.cpu().numpy()
为什么 GPU 快:矩阵运算可以并行——一次算几千个元素。CPU 一次算 1 个,GPU 一次几千个。神经网络几乎全是矩阵运算,所以训练必须 GPU。
第五站:自动求导(autograd)
这是 PyTorch 比 NumPy 强的地方——自动算导数。
# 让 PyTorch 追踪一个 tensor
x = torch.tensor(2.0, requires_grad=True)
# 做一些运算
y = x ** 2 + 3 * x + 1
# 一行算梯度
y.backward()
# 查看
print(x.grad) # tensor(7.) — dy/dx = 2x + 3,x=2 时为 7
回想 L1-06 我们手算的 2 层网络反向传播——PyTorch 直接帮你做了。
一个完整的反向传播例子
# 参数(要训练的)
w = torch.tensor(3.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)
# 数据
x = torch.tensor(2.0)
target = torch.tensor(5.0)
# 前向
y = w * x + b
loss = (y - target) ** 2
# 反向(一行)
loss.backward()
# 查看每个参数的梯度
print(f"dw = {w.grad}") # ≈ 4
print(f"db = {b.grad}") # ≈ 2
这取代了 L1-06 我们手算的几页推导。
第六站:第一个神经网络
让我们用 PyTorch 实现 L1-06 那个 2 层网络:
import torch
import torch.nn as nn
# 定义网络
class TinyNet(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(1, 8) # 输入 1 维,输出 8 维
self.fc2 = nn.Linear(8, 1) # 输入 8 维,输出 1 维
def forward(self, x):
x = self.fc1(x)
x = torch.relu(x)
x = self.fc2(x)
return x
model = TinyNet()
print(model)
# TinyNet(
# (fc1): Linear(in_features=1, out_features=8, bias=True)
# (fc2): Linear(in_features=8, out_features=1, bias=True)
# )
# 看一下有多少参数
total_params = sum(p.numel() for p in model.parameters())
print(f"参数总数: {total_params}") # 25
第七站:完整训练循环
让我们用这个网络拟合 :
import torch
import torch.nn as nn
import torch.optim as optim
# 1. 数据
X = torch.linspace(-5, 5, 100).reshape(-1, 1)
y = X ** 2 + torch.randn_like(X) * 0.1 # 加点噪声
# 2. 模型
model = nn.Sequential(
nn.Linear(1, 32),
nn.ReLU(),
nn.Linear(32, 32),
nn.ReLU(),
nn.Linear(32, 1)
)
# 3. 损失函数和优化器
loss_fn = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)
# 4. 训练循环
for epoch in range(500):
# 前向
y_pred = model(X)
loss = loss_fn(y_pred, y)
# 反向 + 更新(这三行是 PyTorch 训练的"咒语")
optimizer.zero_grad() # 清零上一轮梯度
loss.backward() # 反向传播
optimizer.step() # 更新参数
if epoch % 100 == 0:
print(f"epoch {epoch:3d} | loss {loss.item():.4f}")
# 5. 看预测
with torch.no_grad(): # 推理时不需要梯度
test_x = torch.tensor([[3.0]])
test_y = model(test_x)
print(f"\nf(3) ≈ {test_y.item():.2f} (真实 9.0)")
跑一下,你会看到 loss 一路下降,最终预测 。
optimizer.zero_grad()
loss.backward()
optimizer.step()
这三行你会在每个 PyTorch 训练代码里都看到。它就是:
- 清掉上轮残留的梯度
- 算这轮的梯度
- 用梯度更新参数
第八站:批训练 + DataLoader
实际训练几百万样本,不能一次全塞进去——分批:
from torch.utils.data import DataLoader, TensorDataset
# 包装数据
dataset = TensorDataset(X, y)
loader = DataLoader(dataset, batch_size=16, shuffle=True)
# 训练
for epoch in range(20):
for batch_X, batch_y in loader:
# 每个 batch 单独做前向 + 反向
y_pred = model(batch_X)
loss = loss_fn(y_pred, batch_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
Mini-batch SGD 是工业训练的标配——比一次全量训练快,比单个样本训练稳。
第九站:模型存取
# 保存
torch.save(model.state_dict(), 'model.pth')
# 加载(必须先定义同样结构的模型)
model = nn.Sequential(...) # 同样结构
model.load_state_dict(torch.load('model.pth'))
model.eval() # 切到推理模式
state_dict 只存参数(不存网络结构)——这是最佳实践。
第十站:常见错误
错误 1:忘了 zero_grad
# ❌ 不清零,梯度会累积
loss.backward()
optimizer.step()
# ✅
optimizer.zero_grad()
loss.backward()
optimizer.step()
错误 2:训练 vs 推理模式
model.train() # 训练模式(dropout 开)
model.eval() # 推理模式(dropout 关)
# 推理时还要这样:
with torch.no_grad():
pred = model(x) # 不计算梯度,省一半显存
错误 3:shape 不匹配
PyTorch 报错最多的就是 shape——养成”先 print shape” 的习惯。
print(x.shape, y.shape) # debug 神器
一个完整的”端到端”项目
把 L1 全部学的东西串起来——预测房价:
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.preprocessing import StandardScaler
from torch.utils.data import DataLoader, TensorDataset
# 1. 加载数据(用 Pandas)
df = pd.read_csv('housing.csv')
X = df[['rooms', 'age', 'distance']].values
y = df['price'].values
# 2. 标准化
scaler = StandardScaler()
X = scaler.fit_transform(X)
# 3. 转 tensor
X = torch.FloatTensor(X)
y = torch.FloatTensor(y).reshape(-1, 1)
# 4. 数据加载器
dataset = TensorDataset(X, y)
loader = DataLoader(dataset, batch_size=32, shuffle=True)
# 5. 模型
model = nn.Sequential(
nn.Linear(3, 64),
nn.ReLU(),
nn.Linear(64, 64),
nn.ReLU(),
nn.Linear(64, 1)
)
# 6. 训练
optimizer = optim.Adam(model.parameters(), lr=0.001)
loss_fn = nn.MSELoss()
for epoch in range(50):
total_loss = 0
for bx, by in loader:
pred = model(bx)
loss = loss_fn(pred, by)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch:02d} | Loss: {total_loss/len(loader):.4f}")
这就是一个真实的 ML 项目结构——L1 学完,你已经能写出来了。
读完 L1-10,你已经掌握了:
- 完整 ML 数学(线代 / 微积分 / 概率 / 信息论 / 反向传播)
- Python + NumPy + Pandas
- PyTorch 基础 + 训练神经网络
你现在已经能跟 ML 工程师对话了。
下一步:
- L2 经典机器学习(决策树、SVM、聚类等)
- L3 深度学习核心(CNN、Transformer 等)
- L4 LLM 与生成式(最热的方向)
按兴趣选。
读到这里说明你认真在学 🎯
订阅每周精选 —— 下一篇新文章 / 新可视化第一时间送到邮箱。
讨论区
· 用 GitHub 账号登录评论src/components/Comments.astro 顶部填入
仓库 ID 和分类 ID(见组件注释里的配置步骤)。