概述
前面几篇文章一直使用动态图底层训练循环:
python
logits = model(batch_x)
loss = F.cross_entropy(logits, batch_y)
loss.backward()
optimizer.step()
optimizer.clear_grad()
这种写法最适合理解训练机制。但当模型、数据和训练流程稳定后,Paddle 还提供了更高层的训练封装:paddle.Model。
paddle.Model 可以帮助你组织:
- 模型训练。
- 模型评估。
- 模型预测。
- 优化器和损失函数配置。
- 指标管理。
- 训练日志输出。
- 模型保存。
读完本文,你应该知道何时使用 paddle.Model,并能用它完成 prepare -> fit -> evaluate -> predict 的基本流程。
底层循环与高层 API 的区别
| 写法 | 优势 | 适合场景 |
|---|---|---|
| 手写训练循环 | 灵活、透明、方便调试 | 学习原理、自定义复杂训练 |
paddle.Model |
简洁、流程统一、少写模板代码 | 标准训练、快速实验、教学演示 |
手写循环像手动驾驶:
text
你控制每一步 backward、step、clear_grad
paddle.Model 像框架帮你封装常规流程:
text
prepare 配置训练组件
fit 执行训练
evaluate 执行评估
predict 执行预测
如果你刚学训练原理,先写底层循环;如果任务流程稳定,可以用 paddle.Model 提高开发效率。
基本流程:prepare、fit、evaluate、predict
高层 API 常见流程:
python
model = paddle.Model(network)
model.prepare(optimizer, loss, metrics)
model.fit(train_data, eval_data, epochs, batch_size)
model.evaluate(test_data, batch_size)
model.predict(test_data, batch_size)
可以理解为:
text
network:定义神经网络结构
Model:包装训练流程
prepare:配置优化器、损失、指标
fit:训练
evaluate:评估
predict:预测
准备网络:仍然使用 nn.Layer
paddle.Model 不是替代 nn.Layer,而是包装它。
python
import paddle
import paddle.nn as nn
class Classifier(nn.Layer):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
nn.Linear(2, 32),
nn.ReLU(),
nn.Linear(32, 16),
nn.ReLU(),
nn.Linear(16, 2),
)
def forward(self, x):
return self.net(x)
网络结构仍然由 paddle.nn 定义。
准备 Dataset
使用前面同样的圆形数据集:
python
class CircleDataset(paddle.io.Dataset):
def __init__(self, num_samples, seed):
super().__init__()
paddle.seed(seed)
self.x = paddle.rand([num_samples, 2], dtype="float32") * 4.0 - 2.0
radius_square = paddle.sum(self.x ** 2, axis=1)
self.y = (radius_square > 1.0).astype("int64")
def __len__(self):
return self.y.shape[0]
def __getitem__(self, index):
return self.x[index], self.y[index]
创建数据:
python
train_dataset = CircleDataset(2048, seed=2026)
val_dataset = CircleDataset(512, seed=2027)
test_dataset = CircleDataset(512, seed=2028)
paddle.Model.fit() 可以直接接收 Dataset,并通过 batch_size 参数组织 batch。
使用 prepare 配置训练组件
创建高层模型:
python
network = Classifier()
model = paddle.Model(network)
配置优化器、损失函数、指标:
python
optimizer = paddle.optimizer.Adam(
learning_rate=0.01,
parameters=network.parameters(),
)
model.prepare(
optimizer=optimizer,
loss=paddle.nn.CrossEntropyLoss(),
metrics=paddle.metric.Accuracy(),
)
这里有三个组件:
optimizer:更新参数。loss:计算训练损失。metrics:计算训练和评估指标。
注意:优化器的 parameters 仍然来自底层网络:
python
parameters=network.parameters()
使用 fit 训练模型
训练:
python
model.fit(
train_data=train_dataset,
eval_data=val_dataset,
epochs=10,
batch_size=64,
verbose=1,
)
fit 会帮你完成常规训练流程:
text
读取 batch
前向计算
计算 loss
反向传播
优化器更新
指标统计
验证集评估
日志输出
这也是高层 API 最大的价值:减少重复模板代码。
使用 evaluate 评估模型
训练后评估测试集:
python
result = model.evaluate(
test_data,
batch_size=64,
verbose=1,
)
print(result)
返回结果通常包含 loss 和 metrics。具体格式可根据 Paddle 版本和配置略有差异。
评估阶段由 paddle.Model 管理,不需要你手写 model.eval() 和 paddle.no_grad()。
使用 predict 做预测
预测:
python
predictions = model.predict(
test_dataset,
batch_size=64,
)
对于分类任务,预测结果通常是 logits 或模型输出。你可以进一步处理:
python
logits = predictions[0]
实际输出结构可能与版本、数据输入方式有关,使用时建议先打印:
python
print(type(predictions))
print(len(predictions))
如果希望完全控制预测结果处理,手写动态图推理仍然更直接。
完整脚本:paddle.Model 训练分类模型
python
import paddle
import paddle.nn as nn
class CircleDataset(paddle.io.Dataset):
def __init__(self, num_samples, seed):
super().__init__()
paddle.seed(seed)
self.x = paddle.rand([num_samples, 2], dtype="float32") * 4.0 - 2.0
radius_square = paddle.sum(self.x ** 2, axis=1)
self.y = (radius_square > 1.0).astype("int64")
def __len__(self):
return self.y.shape[0]
def __getitem__(self, index):
return self.x[index], self.y[index]
class Classifier(nn.Layer):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
nn.Linear(2, 32),
nn.ReLU(),
nn.Linear(32, 16),
nn.ReLU(),
nn.Linear(16, 2),
)
def forward(self, x):
return self.net(x)
def main():
paddle.seed(2026)
train_dataset = CircleDataset(2048, seed=2026)
val_dataset = CircleDataset(512, seed=2027)
test_dataset = CircleDataset(512, seed=2028)
network = Classifier()
model = paddle.Model(network)
optimizer = paddle.optimizer.Adam(
learning_rate=0.01,
parameters=network.parameters(),
)
model.prepare(
optimizer=optimizer,
loss=nn.CrossEntropyLoss(),
metrics=paddle.metric.Accuracy(),
)
model.fit(
train_data=train_dataset,
eval_data=val_dataset,
epochs=10,
batch_size=64,
verbose=1,
)
result = model.evaluate(
test_dataset,
batch_size=64,
verbose=1,
)
print("test result:", result)
if __name__ == "__main__":
main()
这段代码比手写循环短很多,但训练流程更"框架化"。
保存和加载 paddle.Model
paddle.Model 支持保存训练模型:
python
model.save("circle_model")
加载时需要先创建同样网络和 paddle.Model:
python
network = Classifier()
model = paddle.Model(network)
model.load("circle_model")
实际项目中,也可以继续使用底层方式保存:
python
paddle.save(network.state_dict(), "circle_model.pdparams")
如果你需要更细粒度控制,底层 state_dict 更透明;如果走高层流程,model.save() 更方便。
高层 API 的优势
paddle.Model 适合:
- 快速训练标准模型。
- 教学和演示。
- 统一训练、评估、预测流程。
- 减少手写训练循环模板。
- 配合 Paddle 高层生态组件。
它让代码更短,也减少一些重复错误,比如忘记切换评估模式、忘记关闭梯度等。
高层 API 的边界
不适合完全依赖 paddle.Model 的情况:
- 训练过程有多个优化器。
- 需要复杂自定义 loss。
- 每个 batch 有特殊控制流。
- GAN、强化学习、多任务训练等复杂范式。
- 需要手动控制梯度裁剪、混合精度、梯度累积细节。
这些场景更适合手写训练循环。
判断标准:
text
训练流程标准,用 paddle.Model
训练流程特殊,手写循环
与手写训练循环对照
手写循环:
python
for batch_x, batch_y in loader:
logits = network(batch_x)
loss = F.cross_entropy(logits, batch_y)
loss.backward()
optimizer.step()
optimizer.clear_grad()
高层 API:
python
model.prepare(optimizer, loss, metrics)
model.fit(train_dataset, val_dataset, epochs=10, batch_size=64)
高层 API 并没有改变训练本质,只是把常规步骤封装起来。
常见错误
错误一:optimizer 绑定了错误参数
优化器应使用底层网络参数:
python
parameters=network.parameters()
错误二:prepare 没有配置 loss
训练分类模型需要配置:
python
loss=nn.CrossEntropyLoss()
错误三:metrics 与任务不匹配
分类任务可以用:
python
metrics=paddle.metric.Accuracy()
回归任务则不适合 Accuracy。
错误四:predict 输出结构没有先检查
不同输入方式下,预测输出可能是嵌套结构。先打印类型和长度,再处理。
错误五:复杂训练强行塞进高层 API
如果你发现大量逻辑绕不开 fit 的默认流程,说明应该回到底层训练循环。
建议练习:对比两种训练方式
- 用手写训练循环训练同一个
Classifier。 - 用
paddle.Model训练同一个Classifier。 - 对比两种方式的代码长度。
- 对比最终测试准确率。
- 使用
model.save()保存模型。 - 使用
model.evaluate()评估测试集。 - 修改 metrics,观察日志输出变化。
总结
这一篇介绍了 Paddle 高层 API:
paddle.Model(network)包装nn.Layer。prepare配置优化器、损失函数和指标。fit执行训练和验证。evaluate执行评估。predict执行预测。save/load可保存和加载高层模型。- 标准任务适合高层 API,复杂训练更适合手写循环。
如果只能记住一句话,那就是:
paddle.Model 不改变训练原理,它只是把常规训练、评估和预测流程封装得更简洁。