赞
踩
目录
2、使用 paddle.Model 高层 API 训练、评估与推理
3.1 模型训练(拆解 Model.prepare、Model.fit)
模型训练时,需要用到 CPU、 GPU 等计算处理器资源,由于飞桨框架的安装包是区分处理器类型的,默认情况下飞桨框架会根据所安装的版本自动选择对应硬件,比如安装的 GPU 版本的飞桨,则自动使用 GPU 训练模型,无需手动指定。因此一般情况下,无需执行此步骤。
但是如果安装的 GPU 版本的飞桨框架,想切换到 CPU 上训练,则可通过 paddle.device.set_device 修改。如果本机有多个 GPU 卡,也可以通过该 API 选择指定的卡进行训练,不指定的情况下则默认使用 'gpu:0'。
- import paddle
-
- # 指定在 CPU 上训练
- paddle.device.set_device('cpu')
-
- # 指定在 GPU 第 0 号卡上训练
- paddle.device.set_device('gpu:0')
模型训练前,需要先完成数据集的加载和模型组网,以 MNIST 手写数字识别任务为例,代码示例如下:
- from paddle.vision.transforms import Normalize
-
- transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
- # 加载 MNIST 训练集和测试集
- train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
- test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)
-
- # 模型组网,构建并初始化一个模型 mnist
- mnist = paddle.nn.Sequential(
- paddle.nn.Flatten(1, -1),
- paddle.nn.Linear(784, 512),
- paddle.nn.ReLU(),
- paddle.nn.Dropout(0.2),
- paddle.nn.Linear(512, 10)
- )
paddle.Model 封装模型
Model.prepare 配置训练准备参数
Model.fit 训练模型
Model.evaluate 评估模型
Model.predict 执行推理
- # 封装模型为一个 model 实例,便于进行后续的训练、评估和推理
- model = paddle.Model(mnist)
用 paddle.Model
完成模型的封装后,需通过 Model.prepare 进行训练前的配置准备工作,包括设置优化算法、Loss 计算方法、评价指标计算方法:
优化器(optimizer):即寻找最优解的方法,可计算和更新梯度,并根据梯度更新模型参数。飞桨框架在 paddle.optimizer 下提供了优化器相关 API。并且需要为优化器设置合适的学习率,或者指定合适的学习率策略,飞桨框架在 paddle.optimizer.lr 下提供了学习率策略相关的 API。
损失函数(loss):用于评估模型的预测值和真实值的差距,模型训练过程即取得尽可能小的 loss 的过程。飞桨框架在 paddle.nn Loss层 提供了适用不同深度学习任务的损失函数相关 API。
评价指标(metrics):用于评估模型的好坏,不同的任务通常有不同的评价指标。飞桨框架在 paddle.metric 下提供了评价指标相关 API。
- # 为模型训练做准备,设置优化器及其学习率,并将网络的参数传入优化器,设置损失函数和精度计算方式
- model.prepare(optimizer=paddle.optimizer.Adam(learning_rate=0.001,parameters=model.parameters()),
- loss=paddle.nn.CrossEntropyLoss(),
- metrics=paddle.metric.Accuracy())
需要指定至少三个关键参数:训练数据集,训练轮次和每批次大小:
训练数据集:传入之前定义好的训练数据集。
训练轮次(epoch):训练时遍历数据集的次数,即外循环轮次。
批次大小(batch_size):内循环中每个批次的训练样本数。
- # 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式
- model.fit(train_dataset,
- epochs=5,
- batch_size=64,
- verbose=1)
使用 Model.evaluate 接口完成模型评估操作,结束后根据在 Model.prepare 中定义的 loss
和 metric
计算并返回相关评估结果。
返回格式是一个字典:
只包含loss, {'loss': xxx}
包含loss和一个评估指标, {'loss': xxx, 'metric name': xxx}
包含loss和多个评估指标, {'loss': xxx, 'metric name1': xxx, 'metric name2': xxx}
- # 用 evaluate 在测试集上对模型进行验证
- eval_result = model.evaluate(test_dataset, verbose=1)
- print(eval_result)
只需传入待执行推理验证的样本数据,即可计算并返回推理结果。
返回格式是一个列表:
模型是单一输出:[(numpy_ndarray_1, numpy_ndarray_2, …, numpy_ndarray_n)]
模型是多输出:[(numpy_ndarray_1, numpy_ndarray_2, …, numpy_ndarray_n), (numpy_ndarray_1, numpy_ndarray_2, …, numpy_ndarray_n), …]
- # 用 predict 在测试集上对模型进行推理
- test_result = model.predict(test_dataset)
-
- print(test_result[0][0])
-
- # 打印推理结果,这里的argmax函数用于取出预测值中概率最高的一个的下标,作为预测标签
- pred_label = test_result[0][0].argmax()
- print('true label: {}, pred label: {}'.format(label[0], pred_label))
[[ -6.512169 -6.7076845 0.5048795 1.6733919 -9.670526 -1.6352568 -15.833721 13.87411 -8.215239 1.5966017]] true label: 7, pred label: 7
经过模型的计算得到一个数组 [[ -6.5593615 -6.4680595 -1.4708003 2.1043894 -11.743436 -4.4516582 -14.733968 12.036645 -6.582403 -1.8672216]],取其中最大的值(12.036645)的下标(对应 label 7),即得到该样本数据的预测结果(pred label: 7),可视化该样本图像(true label: 7),与预测结果一致,说明模型准确预测了样本图像上的数字。
完整代码
- from paddle.vision.transforms import Normalize
-
-
- ######################数据准备########################################
- #####################################################################
- transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
- # 加载 MNIST 训练集和测试集
- train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
- test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)
- ######################模型组网########################################
- #####################################################################
- # 模型组网,构建并初始化一个模型 mnist
- mnist = paddle.nn.Sequential(
- paddle.nn.Flatten(1, -1),
- paddle.nn.Linear(784, 512),
- paddle.nn.ReLU(),
- paddle.nn.Dropout(0.2),
- paddle.nn.Linear(512, 10)
- )
- ######################封装模型########################################
- ######################!paddle.Model!################################
- # 封装模型为一个 model 实例,便于进行后续的训练、评估和推理
- model = paddle.Model(mnist)
- ######################配置训练准备参数#################################
- ######################!Model.prepare!###############################
- # 为模型训练做准备,设置优化器及其学习率,并将网络的参数传入优化器,设置损失函数和精度计算方式
- model.prepare(optimizer=paddle.optimizer.Adam(learning_rate=0.001,parameters=model.parameters()),
- loss=paddle.nn.CrossEntropyLoss(),
- metrics=paddle.metric.Accuracy())
- ######################训练模型#######################################
- #####################!Model.fit!###################################
- # 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式
- model.fit(train_dataset,
- epochs=5, #循环次数
- batch_size=64,#每批次的数量
- verbose=1)#日志
-
- ######################评估模型#######################################
- #####################!Model.evaluate!##############################
- # 用 evaluate 在测试集上对模型进行验证
- eval_result = model.evaluate(test_dataset, verbose=1)
- print(eval_result)
- ######################执行推理#######################################
- #####################!Model.predict!##############################
-
- # 用 predict 在测试集上对模型进行推理
- ###############
- ###############
- test_result = model.predict(test_dataset)
- ###############
- ###############
- # 由于模型是单一输出,test_result的形状为[1, 10000],10000是测试数据集的数据量。这里打印第一个数据的结果,这个数组表示每个数字的预测概率
- print(len(test_result))
- print(test_result[0][0])
-
- # 从测试集中取出一张图片
- img, label = test_dataset[0]
-
- # 打印推理结果,这里的argmax函数用于取出预测值中概率最高的一个的下标,作为预测标签
- pred_label = test_result[0][0].argmax()
- print('true label: {}, pred label: {}'.format(label[0], pred_label))
- # 使用matplotlib库,可视化图片
- from matplotlib import pyplot as plt
- plt.imshow(img[0])

飞桨框架通过基础 API 对模型进行训练,对应高层 API 的 Model.prepare
与 Model.fit
,一般包括如下几个步骤:
加载训练数据集、声明模型、设置模型实例为 train
模式
设置优化器、损失函数与各个超参数
设置模型训练的二层循环嵌套,并在内层循环嵌套中设置如下内容
3.1 从数据读取器 DataLoader 获取一批次训练数据
3.2 执行一次预测,即经过模型计算获得输入数据的预测值
3.3 计算预测值与数据集标签的损失
3.4 计算预测值与数据集标签的准确率
3.5 将损失进行反向传播
3.6 打印模型的轮数、批次、损失值、准确率等信息
3.7 执行一次优化器步骤,即按照选择的优化算法,根据当前批次数据的梯度更新传入优化器的参数
3.8 将优化器的梯度进行清零
- from paddle.vision.transforms import Normalize
-
- transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
- # 加载 MNIST 训练集和测试集
- train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
- test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)
-
- # 模型组网,构建并初始化一个模型 mnist
- mnist = paddle.nn.Sequential(
- paddle.nn.Flatten(1, -1),
- paddle.nn.Linear(784, 512),
- paddle.nn.ReLU(),
- paddle.nn.Dropout(0.2),
- paddle.nn.Linear(512, 10)
- )
- #########################################
- #########################################
- # dataset与mnist的定义与使用高层API的内容一致
- # 用 DataLoader 实现数据加载
- train_loader = paddle.io.DataLoader(train_dataset,batch_size=64,shuffle=True)
-
- # 将mnist模型及其所有子层设置为训练模式。这只会影响某些模块,如Dropout和BatchNorm。
- mnist.train()
-
- # 设置迭代次数
- epochs = 5
-
- # 设置优化器
- optim = paddle.optimizer.Adam(parameters=mnist.parameters())
- # 设置损失函数
- loss_fn = paddle.nn.CrossEntropyLoss()
- for epoch in range(epochs):
- for batch_id, data in enumerate(train_loader()):
-
- x_data = data[0] # 训练数据
- y_data = data[1] # 训练数据标签
- predicts = mnist(x_data) # 预测结果
-
- # 计算损失 等价于 prepare 中loss的设置
- loss = loss_fn(predicts, y_data)
-
- # 计算准确率 等价于 prepare 中metrics的设置
- acc = paddle.metric.accuracy(predicts, y_data)
-
- # 下面的反向传播、打印训练信息、更新参数、梯度清零都被封装到 Model.fit() 中
- # 反向传播
- loss.backward()
-
- if (batch_id+1) % 900 == 0:
- print("epoch: {}, batch_id: {}, loss is: {}, acc is: {}".format(epoch, batch_id+1, loss.numpy(), acc.numpy()))
- # 更新参数
- optim.step()
- # 梯度清零
- optim.clear_grad()
-
-

飞桨框架通过基础 API 对训练好的模型进行评估,对应高层 API 的 Model.evaluate
。与模型训练相比,模型评估的流程有如下几点不同之处:
加载的数据从训练数据集改为测试数据集
模型实例从 train
模式改为 eval
模式
不需要反向传播、优化器参数更新和优化器梯度清零
- # 加载测试数据集
- test_loader = paddle.io.DataLoader(test_dataset, batch_size=64, drop_last=True)
- # 设置损失函数
- loss_fn = paddle.nn.CrossEntropyLoss()
- # 将该模型及其所有子层设置为预测模式。这只会影响某些模块,如Dropout和BatchNorm
- mnist.eval()
- # 禁用动态图梯度计算
- for batch_id, data in enumerate(test_loader()):
-
- x_data = data[0] # 测试数据
- y_data = data[1] # 测试数据标签
- predicts = mnist(x_data) # 预测结果
-
- # 计算损失与精度
- loss = loss_fn(predicts, y_data)
- acc = paddle.metric.accuracy(predicts, y_data)
-
- # 打印信息
- if (batch_id+1) % 30 == 0:
- print("batch_id: {}, loss is: {}, acc is: {}".format(batch_id+1, loss.numpy(), acc.numpy()))

飞桨框架通过基础 API 对训练好的模型执行推理,对应高层 API 的 Model.predict
。模型的推理过程相对独立,是在模型训练与评估之后单独进行的步骤。只需要执行如下步骤:
加载待执行推理的测试数据,并将模型设置为 eval
模式
读取测试数据并获得预测结果
对预测结果进行后处理
- # 加载测试数据集
- test_loader = paddle.io.DataLoader(test_dataset, batch_size=64, drop_last=True)
- # 将该模型及其所有子层设置为预测模式
- mnist.eval()
- for batch_id, data in enumerate(test_loader()):
- # 取出测试数据
- x_data = data[0]
- # 获取预测结果
- predicts = mnist(x_data)
- print("predict finished")
-
- # 从测试集中取出一组数据
- img, label = test_loader().next()
-
- # 执行推理并打印结果
- pred_label = mnist(img)[0].argmax()
- print('true label: {}, pred label: {}'.format(label[0].item(), pred_label[0].item()))
- # 可视化图片
- from matplotlib import pyplot as plt
- plt.imshow(img[0][0])

完整代码
- from paddle.vision.transforms import Normalize
-
- ########################数据加载########################################
- #######################################################################
- transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
- # 加载 MNIST 训练集和测试集
- train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
- test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)
- #########################模型组网#######################################
- #######################################################################
- # 模型组网,构建并初始化一个模型 mnist
- mnist = paddle.nn.Sequential(
- paddle.nn.Flatten(1, -1),
- paddle.nn.Linear(784, 512),
- paddle.nn.ReLU(),
- paddle.nn.Dropout(0.2),
- paddle.nn.Linear(512, 10)
- )
- #########################模型训练#######################################
- #######################################################################
- # dataset与mnist的定义与使用高层API的内容一致
- # 用 DataLoader 实现数据加载
- train_loader = paddle.io.DataLoader(train_dataset, batch_size=64, shuffle=True)
-
- # 将mnist模型及其所有子层设置为训练模式。这只会影响某些模块,如Dropout和BatchNorm。
- #####################
- #####################
- mnist.train()
- #####################
- #####################
- # 设置迭代次数
- epochs = 5
-
- # 设置优化器
- optim = paddle.optimizer.Adam(parameters=mnist.parameters())
- # 设置损失函数
- loss_fn = paddle.nn.CrossEntropyLoss()
- #####################
- #####################
- for epoch in range(epochs):
- for batch_id, data in enumerate(train_loader()):
-
- x_data = data[0] # 训练数据
- y_data = data[1] # 训练数据标签
- predicts = mnist(x_data) # 预测结果
-
- # 计算损失 等价于 prepare 中loss的设置
- loss = loss_fn(predicts, y_data)
-
- # 计算准确率 等价于 prepare 中metrics的设置
- acc = paddle.metric.accuracy(predicts, y_data)
-
- # 下面的反向传播、打印训练信息、更新参数、梯度清零都被封装到 Model.fit() 中
- # 反向传播
- loss.backward()
-
- if (batch_id+1) % 900 == 0:
- print("epoch: {}, batch_id: {}, loss is: {}, acc is: {}".format(epoch, batch_id+1, loss.numpy(), acc.numpy()))
- # 更新参数
- optim.step()
- # 梯度清零
- optim.clear_grad()
- #########################模型评估#######################################
- #######################################################################
-
- # 加载测试数据集
- test_loader = paddle.io.DataLoader(test_dataset, batch_size=64, drop_last=True)
- # 设置损失函数
- loss_fn = paddle.nn.CrossEntropyLoss()
-
- # 将该模型及其所有子层设置为预测模式。这只会影响某些模块,如Dropout和BatchNorm
- #####################
- #####################
- mnist.eval()
- #####################
- #####################
- # 禁用动态图梯度计算
- for batch_id, data in enumerate(test_loader()):
-
- x_data = data[0] # 测试数据
- y_data = data[1] # 测试数据标签
- predicts = mnist(x_data) # 预测结果
-
- # 计算损失与精度
- loss = loss_fn(predicts, y_data)
- acc = paddle.metric.accuracy(predicts, y_data)
-
- # 打印信息
- if (batch_id+1) % 30 == 0:
- print("batch_id: {}, loss is: {}, acc is: {}".format(batch_id+1, loss.numpy(), acc.numpy()))
- #########################模型推理#######################################
- #######################################################################
- # 加载测试数据集
- # 将该模型及其所有子层设置为预测模式
-
- for batch_id, data in enumerate(test_loader()):
- # 取出测试数据
- x_data = data[0]
- # 获取预测结果
- predicts = mnist(x_data)
- print("predict finished")
-
- # 从测试集中取出一组数据
- img, label = test_loader().next()
-
- # 执行推理并打印结果
- pred_label = mnist(img)[0].argmax()
- print('true label: {}, pred label: {}'.format(label[0].item(), pred_label[0].item()))
- # 可视化图片
- from matplotlib import pyplot as plt
- plt.imshow(img[0][0])

同时,飞桨的高层 API 和基础 API 可以组合使用,并不是完全割裂开的,这样有助于开发者更便捷地完成算法迭代。示例代码如下:
- from paddle.vision.models import LeNet
-
- class FaceNet(paddle.nn.Layer):
- def __init__(self):
- super().__init__()
- # 使用高层API组网
- #######################
- self.backbone = LeNet()
- #######################
- # 使用基础API组网
- #######################
- self.outLayer1 = paddle.nn.Sequential(
- paddle.nn.Linear(10, 512),
- paddle.nn.ReLU(),
- paddle.nn.Dropout(0.2)
- )
- #######################
- self.outLayer2 = paddle.nn.Linear(512, 10)
- #######################
- #######################
- #######################
- def forward(self, inputs):
- out = self.backbone(inputs)
- out = self.outLayer1(out)
- out = self.outLayer2(out)
- #######################
- #######################
- return out
- # 使用高层API封装网络
- model = paddle.Model(FaceNet())
- # 使用基础API定义优化器
- optim = paddle.optimizer.Adam(learning_rate=1e-3, parameters=model.parameters())
- # 使用高层API封装优化器和损失函数
- model.prepare(optim, paddle.nn.CrossEntropyLoss(), metrics=paddle.metric.Accuracy())
- # 使用高层API训练网络
- model.fit(train_dataset, test_dataset, epochs=5, batch_size=64, verbose=1)

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。