| name | paddlepaddle-dev |
| description | PaddlePaddle 飞桨开发 — 环境搭建、模型训练、API 使用。涵盖高层 API (paddle.Model)、低层 API 踩坑、WSL GPU 配置、Context7 文档查询。触发词:飞桨、PaddlePaddle、paddle、MNIST、LeNet、paddle.Model。 |
| tags | ["paddlepaddle","deep-learning","cv","nlp","wsl","gpu"] |
| category | mlops |
PaddlePaddle 飞桨开发
核心理念
起步用高层 API (paddle.Model),不要手写训练循环。 高层 API 自动处理 labels 格式、accuracy 计算等细节,避免踩坑。
环境搭建
WSL2 + GPU(笔记本/单机)
uv venv --python 3.12 .venv
source .venv/bin/activate
uv pip install paddlepaddle==3.3.0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/
uv pip install paddlepaddle-gpu==3.3.0 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/
export LD_LIBRARY_PATH="/usr/lib/wsl/lib:$LD_LIBRARY_PATH"
验证
import paddle
print(paddle.__version__)
print(paddle.is_compiled_with_cuda())
print(paddle.device.cuda.device_count())
paddle.utils.run_check()
依赖安装(PyPI 超时备用)
uv pip install matplotlib pillow -i https://pypi.tuna.tsinghua.edu.cn/simple
matplotlib 中文字体(图表中文显示为方块)
默认 DejaVu Sans 字体不含 CJK 字符,训练脚本生成的图表中文会变成方块(Glyph missing from font(s) 警告)。
一次性修复:
fc-list :lang=zh | head -3
import matplotlib.font_manager as fm
fm.fontManager.addfont('/path/to/simhei.ttf')
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
批量为现有脚本打补丁:在每个脚本的 import matplotlib.pyplot 前插入上述 5 行。字体路径通过 fc-list :lang=zh 确认。
开始前:先查文档,再写代码
读本 skill ≠ 不用查文档。 本 skill 提供踩坑经验和常用片段,
具体 API 细节务必先查 Context7(/websites/paddlepaddle_cn_zh),
尤其是 3.x 版本间的行为差异。避免凭记忆写代码导致反复调试。
正确的 Hello Paddle(高层 API)
import paddle
from paddle.vision.transforms import ToTensor
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=ToTensor())
test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=ToTensor())
lenet = paddle.vision.models.LeNet()
model = paddle.Model(lenet)
model.prepare(
paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters()),
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy(),
)
model.fit(train_dataset, epochs=5, batch_size=64, verbose=1)
model.evaluate(test_dataset, verbose=1)
paddle.save(model.state_dict(), 'output/mnist.pdparams')
高层 API 自动处理:
- label shape(不需要手动 squeeze)
- accuracy 计算(不需要手动 argmax)
- train/eval 模式切换
- 进度条 + 日志
低层 API 踩坑(仅当必须手写训练循环时参考)
坑 1:MNIST labels 是 (batch, 1) 不是 (batch,)
现象:argmax(1) == labels 比较结果异常,准确率 >100%
原因:Paddle 3.3 的 MNIST 返回 labels.shape = (64, 1) 而非 (64,)
修复:
labels = labels.squeeze()
坑 2:.numpy() 返回标量(仅 loss 类)
现象:loss.numpy()[0] → IndexError: too many indices
原因:3.x 中 loss.numpy() 返回 0 维标量,不是 1 维数组
修复:
loss.numpy().item()
float(loss.numpy())
loss.numpy()[0]
注意:model.weight.numpy()[0][0] 仍然正常——weight 是 Parameter,shape 为 (1,1) 的 2D 数组,[0][0] 访问元素没问题。只有 loss 等标量结果 受影响。
坑 3:.astype('int') 行为变更
model.weight 照常:
w = model.weight.numpy()[0][0] # ✅ (2D array → 正常索引)
### 坑 3:.astype('int') 行为变更
**现象**:`astype('int')` 后 sum 的值不对
**修复**:用 `'int64'` 明确类型
```python
(logits.argmax(1) == labels).astype('int64').sum().numpy()
或用 paddle.metric.accuracy() 代替手动计算。
Context7 文档查询
两个最佳 Library ID:
| ID | 内容 | Snippets | 用途 |
|---|
/websites/paddlepaddle_cn_zh | 中文官方文档 | 8060 | 快速开始、数据加载、模型训练 |
/paddlepaddle/paddle | GitHub 源码 | 2649 | API 细节、Release Notes |
查询示例:
Context7 query /websites/paddlepaddle_cn_zh "高层API paddle.Model fit MNIST"
Context7 query /paddlepaddle/paddle "paddle.metric.accuracy API"
常用代码片段
Normalize 正确写法
transform = ToTensor()
transform = Normalize(mean=[127.5], std=[127.5], data_format="CHW")
DataLoader 迭代
loader = paddle.io.DataLoader(dataset, batch_size=64, shuffle=True)
for batch_id, data in enumerate(loader()):
images, labels = data
labels = labels.squeeze()
模型保存/加载
paddle.save(model.state_dict(), 'model.pdparams')
model.set_state_dict(paddle.load('model.pdparams'))
GPU 选型
| CUDA 版本 | 飞桨源 | 适用 GPU |
|---|
| CUDA 12.6 | .../cu126/ | RTX 30/40 系列,A10 |
| CUDA 11.8 | .../cu118/ | 旧卡保守选择 |
| CUDA 12.9 | .../cu129/ | H100, Blackwell |
驱动要求:nvidia-smi 显示的 Driver Version ≥ 545.23.06(CUDA 12.6)。
Paddle 与 PyTorch API 差异(迁移代码必读)
从 PyTorch 代码迁移到 Paddle 时,以下差异最容易踩坑:
差异 1:nn.Linear.weight.shape 顺序相反
| 框架 | weight shape | in_features | out_features |
|---|
| PyTorch | [out_features, in_features] | shape[1] | shape[0] |
| Paddle | [in_features, out_features] | shape[0] | shape[1] |
踩坑场景:替换预训练模型的分类头时:
feature_dim = backbone.fc.weight.shape[1]
feature_dim = backbone.fc.weight.shape[0]
backbone.fc = nn.Linear(feature_dim, NUM_CLASSES)
差异 2:parameters(filter=...) 不支持
PyTorch 的 model.parameters(filter=lambda p: p.requires_grad) 在 Paddle 中不存在。
optimizer = paddle.optimizer.Adam(
parameters=model.parameters(filter=lambda p: not p.stop_gradient)
)
optimizer = paddle.optimizer.Adam(
parameters=[p for p in model.parameters() if not p.stop_gradient]
)
差异 3:import paddle 作用域问题
paddle 在函数内部 import 后,外部类/函数无法访问。确保模块级 import:
def get_system_info():
import paddle
import paddle
import paddle.nn as nn
差异 4:MobileNetV3 的 classifier 结构
Paddle 的 mobilenet_v3_small 的 classifier 是 nn.Sequential:
Sequential(
Linear(576, 1024), # ← 取第一层 Linear 的输入维度
Hardsigmoid(),
Dropout(),
Linear(1024, 1000), # ← 不是最后一层!
)
替换时取第一个 Linear 层(不是最后一个)的输入维度:
if isinstance(old_cls, nn.Sequential):
for layer in old_cls:
if isinstance(layer, nn.Linear):
in_features = layer.weight.shape[0]
break
mobilenet.classifier = nn.Linear(in_features, 4)
差异 5:自定义模型必须实现 __call__
非 nn.Layer 子类的自定义模型不会自动获得 __call__ 方法。如果类只有 forward() 方法,model(tensor) 会报 not callable:
class DummyTerrainModel:
def __init__(self): pass
def forward(self, x):
return paddle.randn([x.shape[0], 4])
model = DummyTerrainModel()
output = model(input)
class DummyTerrainModel:
def __init__(self): pass
def __call__(self, x):
return self.forward(x)
def forward(self, x):
return paddle.randn([x.shape[0], 4])
参考