paddlepaddle配置简单网络和训练

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gentelyang/article/details/85046714

要进行paddlepaddle Fluid单机训练,需要准备数据和配置简单网络。当配置简单的网络完毕后,可以得到两个fluid.Program,startup_program和main_program。默认情况下,可以使用fluid.default_startup_program()与fluid.default_main_program()获取全局的fluid.Program。

1:定义网络简单模型

import paddle.fluid as fluid
image=fluid.layers.data(name="image",shape=[784])
label=fluid.layers.data(name="label",shape=[1])
hidden=fluid.layers.fc(input=image,size=100,act='relu')
prediction=fluid.layers.fc(input=hidden,size=10,act='softmax')
loss=fluid.layers.mean(
    fluid.layers.cross_entropy(
        input=prediction,
        label=label
    )
)
sgd=fluid.optimizer.SGD(learning_rate=0.001).minimize(loss)
exe=fluid.Executor(fluid.CUDAPlace(0))
exe.run(program=fluid.default_startup_program())
#如果使用多GPU训练,参数需要在GPU0上初始化,再由fluid.ParalleExecutor
#分发到多显卡上。

2:初始化参数

2.1 参数随机初始化

用户配置完模型后,参数初始化操作会被写入到fluid.default_startup_program() 中。使用 fluid.Executor() 运行 这一程序,即可在全局 fluid.global_scope() 中随机初始化参数。例如:

exe=fluid.Executor(fluid.CUDAPlace(0))

exe.run(program=fluid.default_satrt_program())

如果使用多GPU训练,参数需要在GPU0上初始化,再经由fluid.ParallelExecutor分发到多张显卡上。

2.2 载入预定义参数

在神经网络训练过程中,经常会需要载入预定义模型,进而继续训练。如何载入预定义参数进行预训练,即载入预定义模型。

2.2.1保存与载入模型变量

paddlepaddle fluid中,所欲模型变量都用fluid.Variable()作为基类进行表示。模型变量可以分为以下几种类别:

模型变量包括:模型参数、长期变量和临时变量。

2.2.1.1: 模型参数:

模型参数是深度学习中被训练和学习变量,在训练过程中,训练框架根据反向传播算法计算出每个模型参数当前的梯度,并用优化器根据梯度对参数进行更新。模型的训练过程本质上可以看作是模型参数不断迭代更新的过程。在paddlepaddle fluid中,模型参数使用fluid.framwork.Parameter来表示,这是一个fluid.Variable()的派生类,除了fluid.Variable()具有的各项性质之外,fluid.framework.parameter还可以配置自身的初始化方法、更新率等属性。

2.2.1.2 长期变量

长期变量指的是在整个训练过程中持续存在、不会因为一个迭代的结束而被销毁的变量,例如动态调节的全局学习率等。在paddlepaddle fluid中,长期变量通过将fluid.Variable()的persistable属性设置为true来表示。

2.2.1.3 临时变量

不属于上面两个类别的所有模型变量都是临时变量,这种类型的变量只在一个训练迭代中存在,在每一个迭代结束后, 所有的临时变量都会被销毁,然后在下一个迭代开始之前,又会先构造出新的临时变量供本轮迭代使用。 一般情况下模型中的大部分变量都属于这一类别,例如输入的训练数据、一个普通的layer的输出等等。

2.2.2 如何保存模型变量

根据用途的不同,我们需要保存的模型变量也不同的。例如,如果我们只想保存模型用来进行以后的预测,那么只保存模型就足够了。单如果我们需要保存一个checkpoint以备将来恢复模型训练,那么我们应该将各种长期变量都保存下来,甚至还需要基类当前epoch和step的id。因为一些模型变量虽然不是参数,但是对于模型训练依然必不可少。

因此根据需求的不同,有两套分别进行模型的参数和checkpoint的保存。

2.2.2.1保存模型用于对新样本的预测

import paddle.fluid as fluid
exe=fluid.Executor(fluid.CPUPlace())
param_path="./my_paddle_model"
prog=fluid.default_main_program()
fluid.io.save_params(executor=exe,dirname=param_path,main_program=None)

上面的例子中使用fluid.io.save_params函数,paddlepadlle Fluid会对默认fluid.program也就是prog中所有模型变量进行扫描,筛选出其中 所有的模型参数,并将这些参数保存到指定的param_path之中。

2.2.2.2保存checkpoint用于恢复训练

在训练过程中,我们可能希望在一些节点上将当前的训练状态保存下来, 以便在将来需要的时候恢复训练环境继续进行训练。这一般被称作“checkpoint”。 想要保存checkpoint,可以使用 fluid.io.save_checkpiont() 接口。

path="./checkpoints"
prog=fluid.default_main_program()
trainer_args={"epoch_id":200,
              "step_id":20
              }
fluid.io.save_checkpoint(executor=exe,
                         checkpoint_dir=path,
                         trainer_args=trainer_args,
                         main_progrm=prog,
                         max_num_checkpoints=3
                         )

上面的例子中,通过调用 fluid.io.save_checkpoint 函数,PaddlePaddle Fluid会对默认 fluid.Program 也就是 prog 中的所有模型变量进行扫描, 根据一系列内置的规则自动筛选出其中所有需要保存的变量,并将他们保存到指定的 path 目录下。

fluid.io.save_checkpoint 的各个参数中, trainer_id 在单机情况下设置为0即可; trainer_args 为一个Python dict,用于给定当前的epoch_id和step_id; max_num_checkpoints 用于表示的最大checkpoint数量, 如果目录中已经存在的checkpoint数量超过这个值,那最早的checkpoint将被删除。

2.2.3 如何载入模型变量

与模型变量保存相对应,有两套分别载入模型的参数和载入模型的checkpoint。

2.2.3.1载入模型用于对新样本的预测

对于通过fluid.io.save_params保存的模型,可以使用fluid.io.load_params来进行载入。

例如:

import paddle.fluid as fluid
exe=fluid.Executor(fluid.CPUPlace())
param_path="./my_paddle_model"
prog=fluid.default_main_program()
fluid.io.load_params(executor=exe,dirname=param_path,
                     mian_program=prog)

通过使用fluid.io.load_params函数,paddlepaddle fluid会对屏prog中的所有模型变量进行扫描,筛选出其中所有模型参数,并尝试从param_path只用读取加载它们。需要格外注意的是,这里的 prog 必须和调用 fluid.io.save_params 时所用的 prog 中的前向部分完全一致,且不能包含任何参数更新的操作。如果两者存在不一致, 那么可能会导致一些变量未被正确加载;如果错误地包含了参数更新操作,那可能会导致正常预测过程中参数被更改。 这两个 fluid.Program 之间的关系类似于训练 fluid.Program 和测试 fluid.Program 之间。

生成测试 fluid.Program

通过clone克隆训练fluid.Program,生成测试fluid.program。

program.clone()方法可以复制出新的fluid.program。通过设置Program.clone(for_test=True)复制含有用于测试操作Program。

import paddle.fluid as fluid

img = fluid.layers.data(name="image", shape=[784])
prediction = fluid.layers.fc(
  input=fluid.layers.fc(input=img, size=100, act='relu'),
  size=10,
  act='softmax'
)
label = fluid.layers.data(name="label", shape=[1], dtype="int64")
loss = fluid.layers.mean(fluid.layers.cross_entropy(input=prediction, label=label))
acc = fluid.layers.accuracy(input=prediction, label=label)

test_program = fluid.default_main_program().clone(for_test=True)

adam = fluid.optimizer.Adam(learning_rate=0.001)
adam.minimize(loss)

在使用 Optimizer 之前,将 fluid.default_main_program() 复制成一个 test_program 。之后使用测试数据运行 test_program,就可以做到运行测试程序,而不影响训练结果。

分别配置训练fluid.Program 和测试fluid.program

如果训练程序和测试程序相差较大时,用户也可以通过完全定义两个不同的 fluid.Program,分别进行训练和测试。在PaddlePaddle Fluid中,所有的参数都有名字。如果两个不同的操作,甚至两个不同的网络使用了同样名字的参数,那么他们的值和内存空间都是共享的。

PaddlePaddle Fluid中使用 fluid.unique_name 包来随机初始化用户未定义的参数名称。通过 fluid.unique_name.guard 可以确保多次调用某函数参数初始化的名称一致。

import paddle.fluid as fluid

def network(is_test):
    file_obj = fluid.layers.open_files(filenames=["test.recordio"] if is_test else ["train.recordio"], ...)
    img, label = fluid.layers.read_file(file_obj)
    hidden = fluid.layers.fc(input=img, size=100, act="relu")
    hidden = fluid.layers.batch_norm(input=hidden, is_test=is_test)
    ...
    return loss

with fluid.unique_name.guard():
    train_loss = network(is_test=False)
    sgd = fluid.optimizer.SGD(0.001)
    sgd.minimize(train_loss)

test_program = fluid.Program()
with fluid.unique_name.guard():
    with fluid.program_gurad(test_program, fluid.Program()):
        test_loss = network(is_test=True)

2.2.3.2载入checkpoint用于恢复训练

对于通过fluid.io.save_checkpoint保存的模型,可以使用fluid.io.load_checkpoint来进行载入

import paddle.fluid as fluid

exe = fluid.Executor(fluid.CPUPlace())
path = "./checkpoints"
prog = fluid.default_main_program()
fluid.io.load_checkpoint(executor=exe, checkpoint_dir=path,
                         serial=9, main_program=prog)

2.3 训练

神经网络训练过程中,经常需要载入预定义模型,进而继续进行训练。下面介绍单卡和多卡上模型训练过程

2.3.1单卡训练

执行单卡训练可以使用 fluid.Executor() 中的 run() 方法,运行训练fluid.Program 即可。在运行的时候,用户可以通过 run(feed=...)参数传入数据;用户可以通过 run(fetch=...) 获取持久的数据。例如:

loss = fluid.layers.mean(...)

exe = fluid.Executor(...)
# the result is an numpy array
result = exe.run(feed={"image": ..., "label": ...}, fetch_list=[loss])

2.3.2 多卡训练

执行多卡训练使用fluid.ParalleExecutor运行训练fluid.Program。例如:

train_exe = fluid.ParallelExecutor(use_cuda=True, loss_name=loss.name,
                             main_program=fluid.default_main_program())
train_exe.run(fetch_list=[loss.name], feed={...})

这里有几点注意事项:

  1. ParallelExecutor 的构造函数需要指明要执行的 fluid.Program , 并在执行过程中不能修改。默认值是 fluid.default_main_program()
  2. ParallelExecutor 需要明确指定是否使用 CUDA 显卡进行训练。在显卡训练模式下会占用全部显卡。用户可以配置 CUDA_VISIBLE_DEVICES 来修改占用的显卡。

猜你喜欢

转载自blog.csdn.net/gentelyang/article/details/85046714