『跟着雨哥学AI』系列之三:详解飞桨框架模型训练

 

课程简介:

“跟着雨哥学AI”是百度飞桨开源框架近期针对高层API推出的系列课。本课程由多位资深飞桨工程师精心打造,不仅提供了从数据处理、到模型组网、模型训练、模型评估和推理部署全流程讲解;还提供了丰富的趣味案例,旨在帮助开发者更全面清晰地掌握百度飞桨框架的用法,并能够举一反三、灵活使用飞桨框架进行深度学习实践。

图片

1. 什么是模型训练?

在深度学习领域,我们经常听到「模型训练」这一关键词,上节课中我们详细的解释了什么是模型以及模型是如何组建的,这节课我们需要考虑「什么是模型训练?」「为什么要进行模型训练?」「我们如何进行模型的训练?」, 甚至我们还会好奇「模型训练的结果是什么?」 。

 

以识别任务为例,如下图所示,面对大量的数据和素材,我们的目的就是使用我们设计并组建的模型(算法)能够实现对目标进行准确的识别。那么这一目标也就是我们进行模型训练的原动力,为了达到这一目标,我们需要有一个好的算法,而算法对应的就是我们上节课讲述的模型,这套算法里面包含若干的关键权重信息,用于指导每个模型(算法)节点如何对输入数据做特征提取,在刚建设好模型的时候,这些权重信息会随机设置,效果很差,无法直接用于我们的任务使用,我们就需要为算法找到一组最合适的权重参数,这组权重参数就是我们模型训练后得到的结果。

 

总的来说,模型训练其实就是我们使用大量的数据「调教」模型(算法)找出最优权重参数的过程。

图片

那么如何才能进行模型训练呢?

 

2. 模型训练详解

 

以往我们实现模型训练时常常需要面对非常繁杂的代码,要写好多步骤,才能正确的使程序运行起来。这些代码里面包含比较多的概念和接口使用,刚刚上手的同学们一般需要花比较多的时间和精力来弄明白相关的知识和使用方法,使得许多开发者望而却步。

为了解决这种问题,同时满足新手开发者和资深开发者,既能够减少入门的难度,提升开发的效率,又能拥有较好的定制化能力。飞桨框架提供了两种模型训练的方法:一种是基于基础API的常规训练方式;另一种是用paddle.Model对组建好的模型进行封装,通过高层API完成模型的训练与预测,可以在3-5行内,完成模型的训练。前者适合框架经验比较多的资深开发者,而后者极大的简化了学习和开发的代码量,对初学者用户非常友好。

 

接下来我们就进行到详细的讲解环节吧。

 

Note: 高层API实现的模型训练与预测API都可以通过基础API实现,本文着重介绍高层API的训练方式,然后会将高层API拆解为基础API,方便同学们对比学习。

2.1 模型训练配置

 

什么是模型训练配置呢?

 

这里是我们做的一个概念抽象,在模型训练的时候我们需要选用和指定我们要使用的梯度优化器、损失函数计算方法和模型评估指标计算方法,那么我们可以在正式启动训练之前对这些所需的必备内容做一个统一配置。

 

那么如何进行模型训练配置呢?

 

第一步就是我们需要使用paddle.Model接口完成对模型的封装,将网络结构组合成一个可快速使用高层API进行训练和预测的类。完成模型的封装以后,我们便可以使用model.prepare接口实现模型的配置。

 

为了完整的实现这个过程,我们就一起回忆一下前几节课的内容,进行数据的处理和加载、模型组建、模型的封装以及模型配置吧。

 

数据的处理与加载

In [1]
import paddle
import paddle.nn as nn

paddle.__version__
'2.0.0-rc1'
In [2]
import paddle.vision.transforms as T
from paddle.vision.datasets import MNIST


# 数据预处理,这里用到了随机调整亮度、对比度和饱和度
transform = T.Normalize(mean=[127.5], std=[127.5])

# 数据加载,在训练集上应用数据预处理的操作
train_dataset = MNIST(mode='train', transform=transform)
test_dataset = MNIST(mode='test', transform=transform)
Cache file /home/aistudio/.cache/paddle/dataset/mnist/train-images-idx3-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/train-images-idx3-ubyte.gz
Begin to download

Download finished
Cache file /home/aistudio/.cache/paddle/dataset/mnist/train-labels-idx1-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/train-labels-idx1-ubyte.gz
Begin to download
........
Download finished
Cache file /home/aistudio/.cache/paddle/dataset/mnist/t10k-images-idx3-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/t10k-images-idx3-ubyte.gz
Begin to download

Download finished
Cache file /home/aistudio/.cache/paddle/dataset/mnist/t10k-labels-idx1-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/t10k-labels-idx1-ubyte.gz
Begin to download
..
Download finished  
模型的组建
In [3]
# 模型的组建
mnist = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 512),
nn.ReLU(),
nn.Linear(512, 10))
模型的封装
In [5]
# 将网络结构用 Model类封装成为模型
model = paddle.Model(mnist)
模型训练配置
In [6]
# 为模型训练做准备,参数optimizer设置优化器,参数loss损失函数,参数metrics设置精度计算方式
model.prepare(optimizer=paddle.optimizer.Adam(parameters=model.parameters()),
loss=paddle.nn.CrossEntropyLoss(),
metrics=paddle.metric.Accuracy())

2.2 模型训练

完成模型的配置工作以后,我们可以正式进入模型训练环节。那么如何进行模型训练呢?

飞桨框架进行模型训练有3种方式来完成:

  1. 全流程的训练启动,包含轮次迭代,数据集迭代,模型评估等,我们可以使用高层APImodel.fit接口来完成;

  2. 对于一些单轮训练内部定制化训练计算过程可以自己手写轮次和数据集迭代,通过高层APImodel.train_batch来实现单个批次数据的训练操作,比如训练GAN类型的网络,需要同时训练生成器和辨别器两个网络;

  3. 如果每个计算细节都想自定义来完成,我们也可以直接使用基础API来实现整个训练过程。

接下来我们就给大家展示下3种方式的使用示例代码来具体了解一下接口的使用方式。

 

2.2.1 全流程模型训练model.fit接口

In [7]
# 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式
model.fit(train_dataset, epochs=5, batch_size=64, verbose=1)
The loss value printed in the log is the current step, and the metric is the average value of previous step.
Epoch 1/5
step  10/938 [..............................] - loss: 0.9135 - acc: 0.3906 - ETA: 26s - 29ms/step
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/layers/utils.py:77: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
return (isinstance(seq, collections.Sequence) and

step  20/938 [..............................] - loss: 0.6332 - acc: 0.5844 - ETA: 20s - 22ms/step
step 938/938 [==============================] - loss: 0.2774 - acc: 0.9140 - 9ms/step
Epoch 2/5
step 938/938 [==============================] - loss: 0.0598 - acc: 0.9598 - 9ms/step
Epoch 3/5
step 938/938 [==============================] - loss: 0.0467 - acc: 0.9688 - 9ms/step
Epoch 4/5
step 938/938 [==============================] - loss: 0.0051 - acc: 0.9734 - 10ms/step
Epoch 5/5
step 938/938 [==============================] - loss: 0.0877 - acc: 0.9775 - 9ms/step

2.2.2 单批次模型训练model.train_batch接口

那么我们如果使用train_batch来实现整个训练过程代码是如何编写呢,下面我们为大家展示一下。

In [8]
epoch_num = 5
train_loader = paddle.io.DataLoader(train_dataset, batch_size=64, shuffle=True, drop_last=True)
model_2 = paddle.Model(mnist)
model_2.prepare(optimizer=paddle.optimizer.Adam(parameters=model.parameters()),
loss=paddle.nn.CrossEntropyLoss(),
metrics=paddle.metric.Accuracy())

for epoch in range(epoch_num):
    for batch_id, batch_data in enumerate(train_loader):
        inputs = batch_data[0]
        labels = batch_data[1]

        out = model_2.train_batch([inputs], [labels])

        if batch_id % 100 == 0:
            print('epoch: {}, batch: {}, loss: {}, acc: {}'.format(epoch, batch_id, out[0], out[1]))
epoch: 0, batch: 0, loss: [array([0.03247563], dtype=float32)], acc: [0.984375]
epoch: 0, batch: 100, loss: [array([0.07372712], dtype=float32)], acc: [0.984375]
epoch: 0, batch: 200, loss: [array([0.01235867], dtype=float32)], acc: [1.0]
epoch: 0, batch: 300, loss: [array([0.0119832], dtype=float32)], acc: [1.0]
epoch: 0, batch: 400, loss: [array([0.06045506], dtype=float32)], acc: [0.96875]
epoch: 0, batch: 500, loss: [array([0.14250125], dtype=float32)], acc: [0.953125]
epoch: 0, batch: 600, loss: [array([0.1298923], dtype=float32)], acc: [0.984375]
epoch: 0, batch: 700, loss: [array([0.23071991], dtype=float32)], acc: [0.96875]
epoch: 0, batch: 800, loss: [array([0.01316315], dtype=float32)], acc: [1.0]
epoch: 0, batch: 900, loss: [array([0.04338323], dtype=float32)], acc: [0.984375]
epoch: 1, batch: 0, loss: [array([0.02602096], dtype=float32)], acc: [1.0]
epoch: 1, batch: 100, loss: [array([0.04736591], dtype=float32)], acc: [0.984375]
epoch: 1, batch: 200, loss: [array([0.02717919], dtype=float32)], acc: [1.0]
epoch: 1, batch: 300, loss: [array([0.0559457], dtype=float32)], acc: [0.984375]
epoch: 1, batch: 400, loss: [array([0.07509188], dtype=float32)], acc: [0.96875]
epoch: 1, batch: 500, loss: [array([0.02436191], dtype=float32)], acc: [0.984375]
epoch: 1, batch: 600, loss: [array([0.04190612], dtype=float32)], acc: [0.984375]
epoch: 1, batch: 700, loss: [array([0.07679007], dtype=float32)], acc: [0.953125]
epoch: 1, batch: 800, loss: [array([0.08825812], dtype=float32)], acc: [0.984375]
epoch: 1, batch: 900, loss: [array([0.18007225], dtype=float32)], acc: [0.953125]
epoch: 2, batch: 0, loss: [array([0.01614574], dtype=float32)], acc: [1.0]
epoch: 2, batch: 100, loss: [array([0.08536448], dtype=float32)], acc: [0.953125]
epoch: 2, batch: 200, loss: [array([0.00554189], dtype=float32)], acc: [1.0]
epoch: 2, batch: 300, loss: [array([0.07758754], dtype=float32)], acc: [0.96875]
epoch: 2, batch: 400, loss: [array([0.14692244], dtype=float32)], acc: [0.953125]
epoch: 2, batch: 500, loss: [array([0.00391791], dtype=float32)], acc: [1.0]
epoch: 2, batch: 600, loss: [array([0.10242598], dtype=float32)], acc: [0.953125]
epoch: 2, batch: 700, loss: [array([0.02423085], dtype=float32)], acc: [1.0]
epoch: 2, batch: 800, loss: [array([0.01023059], dtype=float32)], acc: [1.0]
epoch: 2, batch: 900, loss: [array([0.02060814], dtype=float32)], acc: [0.984375]
epoch: 3, batch: 0, loss: [array([0.02141282], dtype=float32)], acc: [0.984375]
epoch: 3, batch: 100, loss: [array([0.02560318], dtype=float32)], acc: [0.984375]
epoch: 3, batch: 200, loss: [array([0.0649575], dtype=float32)], acc: [0.984375]
epoch: 3, batch: 300, loss: [array([0.05790395], dtype=float32)], acc: [0.984375]
epoch: 3, batch: 400, loss: [array([0.00305776], dtype=float32)], acc: [1.0]
epoch: 3, batch: 500, loss: [array([0.01016137], dtype=float32)], acc: [1.0]
epoch: 3, batch: 600, loss: [array([0.03847548], dtype=float32)], acc: [0.984375]
epoch: 3, batch: 700, loss: [array([0.03043737], dtype=float32)], acc: [1.0]
epoch: 3, batch: 800, loss: [array([0.05468608], dtype=float32)], acc: [0.984375]
epoch: 3, batch: 900, loss: [array([0.07398543], dtype=float32)], acc: [0.984375]
epoch: 4, batch: 0, loss: [array([0.02614518], dtype=float32)], acc: [1.0]
epoch: 4, batch: 100, loss: [array([0.13249119], dtype=float32)], acc: [0.984375]
epoch: 4, batch: 200, loss: [array([0.05901051], dtype=float32)], acc: [0.96875]
epoch: 4, batch: 300, loss: [array([0.00670905], dtype=float32)], acc: [1.0]
epoch: 4, batch: 400, loss: [array([0.01490758], dtype=float32)], acc: [1.0]
epoch: 4, batch: 500, loss: [array([0.03787259], dtype=float32)], acc: [0.984375]
epoch: 4, batch: 600, loss: [array([0.02870828], dtype=float32)], acc: [0.984375]
epoch: 4, batch: 700, loss: [array([0.05344635], dtype=float32)], acc: [0.96875]
epoch: 4, batch: 800, loss: [array([0.01395352], dtype=float32)], acc: [1.0]
epoch: 4, batch: 900, loss: [array([0.00741577], dtype=float32)], acc: [1.0]

2.2.3 基础API实现模型训练

使用高层API实现模型训练只需要一行代码就可以搞定,比较方便。有的时候我们的任务比较复杂,整个训练过程发现高层API的封装无法来达到预期目标,这个时候我们也可以将上述用高层API实现的过程拆解成用基础API的实现。

In [9]
# dataset与mnist网络结构的定义与第一部分内容一致

# 用 DataLoader 实现数据加载
train_loader = paddle.io.DataLoader(train_dataset, batch_size=64, shuffle=True, drop_last=True)

mnist.train()

# 设置迭代次数
epoch_num = 5

# 设置优化器
optim = paddle.optimizer.Adam(parameters=model.parameters())

# 设置损失函数
loss_fn = paddle.nn.CrossEntropyLoss()

for epoch in range(epoch_num):
    for batch_id, data in enumerate(train_loader):
        inputs = data[0]            # 训练数据
        labels = data[1]            # 训练数据标签
        predicts = mnist(inputs)    # 预测结果

        # 计算损失 等价于 prepare 中loss的设置
        loss = loss_fn(predicts, labels)
    
        # 计算准确率 等价于 prepare 中metrics的设置
        acc = paddle.metric.accuracy(predicts, labels)

        # 反向传播
        loss.backward()

        if batch_id % 100 == 0:
            print("epoch: {}, batch_id: {}, loss is: {}, acc is: {}".format(epoch, batch_id, loss.numpy(), acc.numpy()))

        # 更新参数
        optim.step()

        # 梯度清零
        optim.clear_grad()
epoch: 0, batch_id: 0, loss is: [0.0035142], acc is: [1.]
epoch: 0, batch_id: 100, loss is: [0.05046262], acc is: [0.96875]
epoch: 0, batch_id: 200, loss is: [0.05871505], acc is: [0.953125]
epoch: 0, batch_id: 300, loss is: [0.0398513], acc is: [0.984375]
epoch: 0, batch_id: 400, loss is: [0.02114001], acc is: [0.984375]
epoch: 0, batch_id: 500, loss is: [0.03265548], acc is: [0.984375]
epoch: 0, batch_id: 600, loss is: [0.02440762], acc is: [0.984375]
epoch: 0, batch_id: 700, loss is: [0.01399789], acc is: [1.]
epoch: 0, batch_id: 800, loss is: [0.00720934], acc is: [1.]
epoch: 0, batch_id: 900, loss is: [0.03644863], acc is: [0.96875]
epoch: 1, batch_id: 0, loss is: [0.04353006], acc is: [0.984375]
epoch: 1, batch_id: 100, loss is: [0.05608448], acc is: [0.96875]
epoch: 1, batch_id: 200, loss is: [0.01647361], acc is: [1.]
epoch: 1, batch_id: 300, loss is: [0.01115488], acc is: [1.]
epoch: 1, batch_id: 400, loss is: [0.0112262], acc is: [1.]
epoch: 1, batch_id: 500, loss is: [0.03933069], acc is: [0.984375]
epoch: 1, batch_id: 600, loss is: [0.02522848], acc is: [1.]
epoch: 1, batch_id: 700, loss is: [0.00357857], acc is: [1.]
epoch: 1, batch_id: 800, loss is: [0.02319109], acc is: [1.]
epoch: 1, batch_id: 900, loss is: [0.0019039], acc is: [1.]
epoch: 2, batch_id: 0, loss is: [0.02895336], acc is: [0.984375]
epoch: 2, batch_id: 100, loss is: [0.00558926], acc is: [1.]
epoch: 2, batch_id: 200, loss is: [0.01878058], acc is: [1.]
epoch: 2, batch_id: 300, loss is: [0.10249343], acc is: [0.96875]
epoch: 2, batch_id: 400, loss is: [0.00268026], acc is: [1.]
epoch: 2, batch_id: 500, loss is: [0.03055108], acc is: [0.984375]
epoch: 2, batch_id: 600, loss is: [0.0162295], acc is: [1.]
epoch: 2, batch_id: 700, loss is: [0.00872635], acc is: [1.]
epoch: 2, batch_id: 800, loss is: [0.00212811], acc is: [1.]
epoch: 2, batch_id: 900, loss is: [0.00818303], acc is: [1.]
epoch: 3, batch_id: 0, loss is: [0.0039459], acc is: [1.]
epoch: 3, batch_id: 100, loss is: [0.08966698], acc is: [0.953125]
epoch: 3, batch_id: 200, loss is: [0.01709959], acc is: [1.]
epoch: 3, batch_id: 300, loss is: [0.08004878], acc is: [0.984375]
epoch: 3, batch_id: 400, loss is: [0.14321736], acc is: [0.96875]
epoch: 3, batch_id: 500, loss is: [0.00930889], acc is: [1.]
epoch: 3, batch_id: 600, loss is: [0.0018653], acc is: [1.]
epoch: 3, batch_id: 700, loss is: [0.11423732], acc is: [0.953125]
epoch: 3, batch_id: 800, loss is: [0.00624554], acc is: [1.]
epoch: 3, batch_id: 900, loss is: [0.00426558], acc is: [1.]
epoch: 4, batch_id: 0, loss is: [0.00100102], acc is: [1.]
epoch: 4, batch_id: 100, loss is: [0.01645062], acc is: [1.]
epoch: 4, batch_id: 200, loss is: [0.00757009], acc is: [1.]
epoch: 4, batch_id: 300, loss is: [0.08349247], acc is: [0.984375]
epoch: 4, batch_id: 400, loss is: [0.00622703], acc is: [1.]
epoch: 4, batch_id: 500, loss is: [0.01024241], acc is: [1.]
epoch: 4, batch_id: 600, loss is: [0.06242872], acc is: [0.96875]
epoch: 4, batch_id: 700, loss is: [0.00065227], acc is: [1.]
epoch: 4, batch_id: 800, loss is: [0.00531822], acc is: [1.]
epoch: 4, batch_id: 900, loss is: [0.07632213], acc is: [0.984375]

2.3 模型评估

模型训练结束后,我们得到了一组精度看起来还不错的模型参数,但是这组参数到底好还是不好还需要我们去具体做下评估。

 

那么何为模型评估呢?

模型评估其实就是使用我们预留的验证数据放到所得到的模型中进行实际的预测并基于标签进行校验,来看模型在验证集上的精度表现,模型的好坏直接影响我们的目标任务是否可以实现。模型评估的代码实现在高层API中也非常地简单,我们事先定义好用于评估使用的数据集后,可以简单的调用飞桨高层API提供的model.evaluate接口或model.eval_batch接口完成模型评估操作,其中model.eval_batch接口是在一个批次的数据上进行评估测试。

 

操作结束后会根据prepare接口配置的loss和metric来进行相关指标计算返回。

 

2.3.1 全流程评估model.evaluate接口

In [10]
# 用 model.evaluate 在测试集上对模型进行验证
eval_result = model.evaluate(test_dataset, verbose=1)
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 10000/10000 [==============================] - loss: 0.0000e+00 - acc: 0.9766 - 2ms/step
Eval samples: 10000

 

2.3.2 单批次model.eval_batch接口

In [11]
# 用 model.eval_batch 在测试集一个批次的数据上进行验证

eval_loader = paddle.io.DataLoader(test_dataset, batch_size=64, drop_last=True)

for batch_id, batch_data in enumerate(eval_loader):
    inputs = batch_data[0]
    labels = batch_data[1]
    out = model.eval_batch([inputs],[labels])

    if batch_id % 100 == 0:
        print('batch_id: {}, loss: {}, acc: {}'.format(batch_id, out[0], out[1]))
batch_id: 0, loss: [array([0.00120578], dtype=float32)], acc: [1.0]
batch_id: 100, loss: [array([0.00050124], dtype=float32)], acc: [1.0]

2.3.3 基础API实现模型评估

类似地,我们来了解一下使用基础API如何实现模型评估功能。如下代码所示,和模型训练功能相似,使用基础API实现模型评估需要数据的加载和读取,损失函数和精度的定义,需要十几行代码,使用高层API只需要一行代码就可以完成模型的评估。

In [12]
# 加载测试数据集
test_loader = paddle.io.DataLoader(test_dataset, batch_size=64, drop_last=True)
loss_fn = paddle.nn.CrossEntropyLoss()

mnist.eval()

for batch_id, data in enumerate(test_loader()):
    inputs = data[0]            # 测试数据
    labels = data[1]            # 测试数据标签
    predicts = mnist(inputs)    # 预测结果

    # 计算损失与精度
    loss = loss_fn(predicts, labels)
    acc = paddle.metric.accuracy(predicts, labels)

    # 打印信息
    if batch_id % 100 == 0:
        print("batch_id: {}, loss is: {}, acc is: {}".format(batch_id, loss.numpy(), acc.numpy()))
batch_id: 0, loss is: [0.00120578], acc is: [1.]
batch_id: 100, loss is: [0.00050124], acc is: [1.]

2.4 模型预测

从数据的处理到模型的组建再到模型的训练,其实我们的终极任务是希望我们的模型可以真正的用起来。如果是模型评估的结果符合我们的期望,我们就模型就可以真正的使用了,那就是模型预测。那么如何进行模型预测呢?飞桨高层API中提供了model.predict接口和model.predict_batch接口来方便用户对训练好的模型进行预测验证,只需要基于训练好的模型将需要进行预测测试的数据放到接口中进行计算即可,接口会把模型计算得到的预测结果返回,从而完成我们的任务。

 

2.4.1 使用高层API全流程预测接口 model.predict

 

In [13]
# 用 predict 在测试集上对模型进行测试
test_result = model.predict(test_dataset)

# 可以在后面继续加上自己对于预测数据的处理
Predict begin...
step 10000/10000 [==============================] - 2ms/step
Predict samples: 10000

 

2.4.2 使用高层API单批次预测接口 model.predict_batch

In [14]
# 用 predict_batch 在测试集一个批次的数据上进行测试
predict_loader = paddle.io.DataLoader(test_dataset, batch_size=64)

for batch_id, batch_data in enumerate(predict_loader):
    inputs = batch_data[0]
    test_result = model.predict_batch([inputs])
    # 可以在后面继续加上自己对于预测数据的处理
    print("predict finished")
    predict finished

 

2.4.3 使用基础API来完成模型预测

如果将高层API的实现拆解,使用基础API来操作的话,那么对应的代码如下:

In [15]
# 定义测试数据集加载器
test_loader = paddle.io.DataLoader(test_dataset, batch_size=64)

# 将网络结构的模式变成评估
mnist.eval()

# 加载数据进行迭代预测
for batch_id, batch_data in enumerate(test_loader):
    inputs = data[0]
    predicts = mnist(inputs)
    # 可以在后面继续加上自己对于预测数据的处理

    print("predict finished")
    predict finished    

总结

本节课首先为大家详细的讲解了什么是模型训练以及为什么要进行模型训练。然后和同学们一起学习了如何进行模型训练,并且在学习过程中,我们还复习了数据的预处理和加载以及模型组建等前面所学的课程,详细介绍了飞桨框架提供的4个模型训练的功能,且将高层API的代码实现拆解成基础API,方便同学们对比学习。到这里,同学们已经基本掌握了模型训练的一整套流程了,课后同学们一定要多练习,自己完成一个小项目。为了让同学们的学习节奏变的紧凑,下周我们将会发布两篇高层API的高阶用法的内容,大家如果有什么希望实现的模型或者感兴趣的趣味案例都可以在评论区留言,我们将会在后续的课程中给大家安排上哈,今天的课程到这里就结束了,我是雨哥,下节课见~

 

回顾往期:

第一篇:『跟着雨哥学AI』系列:详解飞桨框架数据管道

第二篇:『跟着雨哥学AI』系列之二:详解飞桨框架模型组网

 

有任何问题可以在本项目中评论或到飞桨Github仓库(链接)提交Issue。

同时欢迎扫码加入飞桨框架高层API技术交流群

图片

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值