Paddle 在训练过程中评测模型

模型的测试评价与训练的 fluid.Program 不同。在测试评价中:

  1. 测试评价不进行反向传播,不优化更新参数。

  2. 测试评价执行的操作可以不同。

    • 例如 BatchNorm 操作,在训练和测试时执行不同的算法。

    • 测试评价模型与训练模型可以是完全不同的模型。

生成测试 fluid.Program

Paddle 提供两种生成测试 fluid.Program 的方式,分别对应不同的使用场景。

通过克隆训练 fluid.Program 生成测试 fluid.Program

可以直接通过一句克隆命令复制训练 fluid.Program 生成测试 fluid.Program

1
2
3
4
5
6
7
8
9
model = network()
loss = model.loss
acc = model.acc

train_prog = fluid.default_main_program()
test_prog = train_prog.clone(for_test=True)

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

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

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

如果训练程序和测试程序相差较大时,也可以通过完全定义两个不同的 fluid.Program,分别进行训练和测试。但是当新建用于测试的模型的时候,默认情况下模型参数会初始化为不同的名字,将无法与训练模型共享参数。因此,使用 fluid.unique_name.guard 来保证多次调用某些函数初始化得到相同的参数名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
train_prog = fluid.Program()
train_startup = fluid.Program()
with fluid.program_guard(train_prog, train_startup):
with fluid.unique_name.guard():
train_model = network()
train_loss = train_model.loss
train_acc = train_model.acc
adam = fluid.optimizer.Adam(learning_rate=0.001)
adam.minimize(train_loss)

test_prog = fluid.Program()
test_startup = fluid.Program()
with fluid.program_guard(test_prog, test_startup):
with fluid.unique_name.guard():
test_model = network()
test_loss = test_model.loss
test_acc = test_model.acc

执行训练与测试

使用 CompiledProgram 执行

fluid.CompiledProgram 针对计算图优化,并利用 with_data_parallel 提供数据并行能力。

1
2
3
4
5
6
7
8
9
10
11
12
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(train_startup)
exe.run(test_startup)

compiled_train_prog = fluid.CompiledProgram(train_prog).with_data_parallel(loss_name=train_loss.name)
compiled_test_prog = fluid.CompiledProgram(test_prog).with_data_parallel(share_vars_from=compiled_train_prog)

train_cur_loss, train_cur_acc = exe.run(program=compiled_train_prog, feed=train_data,
fetch_list=[train_loss.name, train_acc.name])
test_cur_loss, test_cur_acc = exe.run(program=compiled_test_prog, feed=test_data,
fetch_list=[test_loss.name, test_acc.name])

使用 ParallelExecutor 执行

fluid.ParallelExecutor 提供数据并行能力。可以新建一个测试 ParallelExecutor,与训练 ParallelExecutor 共享参数,再使用测试 ParallelExecutor.run 来执行测试。

1
2
3
4
5
6
7
train_pexe = fluid.ParallelExecutor(use_cuda=True, loss_name=train_loss.name, main_program=train_prog)
test_pexe = fluid.ParallelExecutor(use_cuda=True, share_vars_from=train_pexe,
main_program=test_prog)

train_cur_loss, train_cur_acc = train_pexe.run(fetch_list=[train_loss.name, train_acc.name],
feed=train_data)
test_cur_acc, = test_exec.run(fetch_list=[test_acc.name], feed=test_data)