Program
- class
paddle.fluid.
Program
[源代码]
注意:默认情况下,Paddle Fluid内部默认含有 default_startup_program 和 default_main_program ,它们共享参数。 default_startup_program 只运行一次来初始化参数, default_main_program 在每个mini batch中运行并更新权重。
Program是Paddle Fluid对于计算图的一种静态描述,使用Program的构造函数可以创建一个Program。Program中包括至少一个 Block ,当 Block 中存在条件选择的控制流OP(例如 While 等)时,该Program将会含有嵌套着的 Block 即控制流外部的 Block 将包含着控制流内部的 Block ,而嵌套的 Block 的元素访问控制将由具体的控制流OP来决定。关于Program具体的结构和包含的类型请参阅 framework.proto 。
一个Program的集合通常包含初始化程序(startup_program)与主程序(main_program),初始化程序是一个包含一些初始化工作的Program,主程序将会包含用来训练的网络结构和变量,在使用同一个 执行引擎 执行时他们会共享初始化工作的结果,例如初始化的参数。一个Program的集合可以被用来测试或者训练,被用来训练时, Paddle Fluid
将会利用所有用户使用的OP和变量来搭建一个训练网络,被用来测试时, 可以通过调用Program相关的接口例如:clone 剪去一些与测试无关的OP和变量,比如反向传播的OP和变量。
返回:创建的空的Program
返回值类型:Program
代码示例
- import paddle.fluid as fluid
- main_program = fluid.Program()
- startup_program = fluid.Program()
- with fluid.program_guard(main_program=main_program, startup_program=startup_program):
- x = fluid.layers.data(name="x", shape=[-1, 784], dtype='float32')
- y = fluid.layers.data(name="y", shape=[-1, 1], dtype='int32')
- z = fluid.layers.fc(name="fc", input=x, size=10, act="relu")
- # start_up program here will share fc's weight with main program
- print("main program is: {}".format(main_program))
- print("start up program is: {}".format(startup_program))
to_string
(throw_on_error, with_details=False)
将Program转换为字符串
- 参数:
- throw_on_error (bool) - 是否在没有设置必需字段时抛出异常。
- with_details (bool) - 值为true时,打印更多关于变量和参数的信息,如trainable, optimize_attr等
返回: 将Program转换为字符串
返回类型: str
抛出异常: ValueError
- 当 throw_on_error == true
,当没有设置任何必需的字段时,抛出 ValueError
。
代码示例
- import paddle.fluid as fluid
- prog = fluid.default_main_program()
- a = fluid.layers.data(name="X", shape=[2,3], dtype="float32", append_batch_size=False)
- c = fluid.layers.fc(a, size=3)
- prog_string = prog.to_string(throw_on_error=True, with_details=False)
- prog_string_with_details = prog.to_string(throw_on_error=False, with_details=True)
- print(prog_string)
- print("\n =============== with_details =============== \n")
- print(prog_string_with_details)
clone
(for_test=False)
- 注意:
Program.clone()
方法不会克隆例如 DataLoader 这样的数据读取相关的部分,这可能会造成的数据读取部分在克隆后丢失此API当
for_test=True
时将会裁剪部分OP和变量。为防止错误的裁剪,推荐在 append_backward 和执行优化器之前使用clone(for_test=True)
。
当 for_test=True
时创建一个新的、仅包含当前Program前向内容的Program。否则创建一个新的,和当前Program完全相同的Program
有些OP,在训练和测试之间的行为是不同的,比如 batch_norm 。它们有一个属性 is_test
来控制行为。当 for_test=True
时,此方法将把它们的 is_test
属性更改为True。
- 克隆Program用于训练时,将
for_test
设置为False。 - 克隆Program用于测试时,将
for_test
设置为True。虽然在这种情况下,如果在使用了优化器之后调用clone
我们依旧会对Program当中反向执行以及优化器相关的内容进行自动裁剪,但是,我们强烈建议在使用优化器之前使用clone
例如如果使用的是 Momentum 可以这样去使用:
代码示例
- import paddle.fluid as fluid
- ## 我们推荐在使用 Optimizer前使用clone()接口
- test_program = fluid.default_main_program().clone(for_test=True)
- optimizer = fluid.optimizer.Momentum(learning_rate=0.01, momentum=0.9)
- optimizer.minimize()
- 参数:
- for_test (bool) – 取值为True时,clone方法内部会把operator的属性
is_test
设置为 True, 并裁剪反向OP和参数优化OP
- for_test (bool) – 取值为True时,clone方法内部会把operator的属性
返回:当 for_test=True
时返回一个新的、仅包含当前Program前向内容的Program。否则返回一个新的,和当前Program完全相同的Program
返回类型: Program
代码示例
注意,Program在clone后的顺序可能不同,这不会影响的训练或测试进程。在下面的示例中,我们提供了一个简单的方法print_prog(Program)来打印程序描述,以确保clone后仍能得到同样的打印结果:
- import paddle.fluid as fluid
- import six
- def print_prog(prog):
- for name, value in sorted(six.iteritems(prog.block(0).vars)):
- print(value)
- for op in prog.block(0).ops:
- print("op type is {}".format(op.type))
- print("op inputs are {}".format(op.input_arg_names))
- print("op outputs are {}".format(op.output_arg_names))
- for key, value in sorted(six.iteritems(op.all_attrs())):
- if key not in ['op_callstack', 'op_role_var']:
- print(" [ attrs: {}: {} ]".format(key, value))
1.克隆一个Program,示例代码如下。
- import paddle.fluid as fluid
- import six
- def print_prog(prog):
- for name, value in sorted(six.iteritems(prog.block(0).vars)):
- print(value)
- for op in prog.block(0).ops:
- print("op type is {}".format(op.type))
- print("op inputs are {}".format(op.input_arg_names))
- print("op outputs are {}".format(op.output_arg_names))
- for key, value in sorted(six.iteritems(op.all_attrs())):
- if key not in ['op_callstack', 'op_role_var']:
- print(" [ attrs: {}: {} ]".format(key, value))
- train_program = fluid.Program()
- startup_program = fluid.Program()
- # ``startup_program`` 被用来执行一些参数初始化工作
- # ``main_program`` 被用来容纳网络
- with fluid.program_guard(train_program, startup_program):
- with fluid.unique_name.guard():
- img = fluid.layers.data(name='image', shape=[784])
- hidden = fluid.layers.fc(input=img, size=200, act='relu')
- hidden = fluid.layers.dropout(hidden, dropout_prob=0.5)
- loss = fluid.layers.cross_entropy(
- input=fluid.layers.fc(hidden, size=10, act='softmax'),
- label=fluid.layers.data(name='label', shape=[1], dtype='int64'))
- avg_loss = fluid.layers.mean(loss)
- test_program = train_program.clone(for_test=False)
- print_prog(test_program)
- # 由于需要使训练和测试参数共享,我们需要使用训练的 ``startup_program``
- # 来代替测试用的 ``startup_program``, 尽管测试的 ``startup_program`` 里面什么也没有。
- # 在Paddle Fluid中我们会通过同样的变量名来共享权重.
- # 训练和测试程序的所有参数将会拥有同样的名字,这将会使训练和测试程序实现参数的共享,
- # 所以我们使用训练程序的 ``startup_program`` .并且由于测试的 ``startup_program`` 什么也没有,
- # 因此它是一个新的程序.
- with fluid.program_guard(train_program, startup_program):
- with fluid.unique_name.guard():
- sgd = fluid.optimizer.SGD(learning_rate=1e-3)
- sgd.minimize(avg_loss)
2.如果分别运行 train Program 和 test Program,则可以不使用clone。
- import paddle.fluid as fluid
- import six
- def print_prog(prog):
- for name, value in sorted(six.iteritems(prog.block(0).vars)):
- print(value)
- for op in prog.block(0).ops:
- print("op type is {}".format(op.type))
- print("op inputs are {}".format(op.input_arg_names))
- print("op outputs are {}".format(op.output_arg_names))
- for key, value in sorted(six.iteritems(op.all_attrs())):
- if key not in ['op_callstack', 'op_role_var']:
- print(" [ attrs: {}: {} ]".format(key, value))
- def network(is_test):
- img = fluid.layers.data(name='image', shape=[784])
- hidden = fluid.layers.fc(input=img, size=200, act='relu')
- hidden = fluid.layers.dropout(hidden, dropout_prob=0.5)
- loss = fluid.layers.cross_entropy(
- input=fluid.layers.fc(hidden, size=10, act='softmax'),
- label=fluid.layers.data(name='label', shape=[1], dtype='int64'))
- avg_loss = fluid.layers.mean(loss)
- return avg_loss
- train_program_2 = fluid.Program()
- startup_program_2 = fluid.Program()
- test_program_2 = fluid.Program()
- with fluid.program_guard(train_program_2, startup_program_2):
- with fluid.unique_name.guard():
- sgd = fluid.optimizer.SGD(learning_rate=1e-3)
- sgd.minimize(avg_loss)
- # 不使用测试阶段的启动程序
- with fluid.program_guard(test_program_2, fluid.Program()):
- with fluid.unique_name.guard():
- loss = network(is_test=True)
- print(test_program_2)
上边两个代码片段生成和打印的Program是一样的。
- static
parse_from_string
(binary_str)
通过对 protobuf 的反序列化,转换成Program
- 参数:
- binary_str_type (str) – protobuf 二进制字符串
返回:反序列化后的 Program
返回类型:Program
代码示例
- import paddle.fluid as fluid
- startup_prog = fluid.Program()
- main_prog = fluid.Program()
- with fluid.program_guard(startup_prog, main_prog):
- x = fluid.layers.data(
- name='X', shape=[1000, 784], dtype='float32', append_batch_size=False)
- y = fluid.layers.data(
- name='Y', shape=[784, 100], dtype='float32', append_batch_size=False)
- z = fluid.layers.mul(x=x, y=y)
- binary_str = fluid.default_main_program().desc.serialize_to_string()
- prog_restored = fluid.default_main_program().parse_from_string(binary_str)
- print(fluid.default_main_program())
- print(prog_restored)
- # 这里打印出的两个Program应该是一模一样的
num_blocks
该Program中的 Block 的个数
返回: 该Program中的 Block 的个数
返回类型:int
代码示例
- import paddle.fluid as fluid
- prog = fluid.default_main_program()
- num_blocks = prog.num_blocks
- print(num_blocks)
- ## 1
- ## 当前Program中只有一个Block,即全局的Block
random_seed
注意:必须在相关OP被添加之前设置。例如
代码示例
- import paddle.fluid as fluid
- prog = fluid.default_main_program()
- random_seed = prog.random_seed
- x_var = fluid.layers.data(name="X", shape=[3,3], dtype="float32", append_batch_size=False)
- # 这里我们必须要在fluid.layers.dropout之前设置random_seed
- print(random_seed)
- prog.random_seed = 1
- z_var = fluid.layers.dropout(x_var, 0.7)
- print(prog.random_seed)
程序中随机运算符的默认随机种子。0意味着随机生成随机种子。
返回:该Program中当前正在使用的random seed
返回类型:int64
代码示例
- import paddle.fluid as fluid
- prog = fluid.default_main_program()
- random_seed = prog.random_seed
- print(random_seed)
- prog.random_seed = 1
- print(prog.random_seed)
- ## 0
- ## 默认的random seed是 0
- ## 1
- ## 修改后random seed变成了 1
global_block
()
获取该Program的第一个 Block 。
返回:该Program的第一个 Block
返回类型:Block
代码示例
- import paddle.fluid as fluid
- prog = fluid.default_main_program()
- gb_block = prog.global_block()
- print(gb_block)
- ##
- ## idx: 0
- ## parent_idx: -1
- ## 打印出了当前全局Block的描述
block
(index)
返回该Program中 , index
指定的 Block 。 index
类型为int
- 参数:
- index (int) - 需要获取的 Block 的index
返回: 该Program中index对应的那个 Block
返回类型: Block
代码示例
- import paddle.fluid as fluid
- prog = fluid.default_main_program()
- block_0 = prog.block(0)
- print(block_0)
- ##
- ## idx: 0
- ## parent_idx: -1
- ## 打印出了0号Block的描述
current_block
()
获取当前 Block 。当前 Block 是用来添加OP的。
返回: 该Program中用户当前所在的 Block
返回类型: Block
代码示例
- import paddle.fluid as fluid
- prog = fluid.default_main_program()
- current_blk = prog.current_block()
- print(current_blk)
- ##
- ## idx: 0
- ## parent_idx: -1
- ## 打印出了当前Block的描述
list_vars
()
获取当前Program中所有变量。返回值是一个可迭代对象(iterable object)。
返回: Generator 会yield每个Program中的变量
返回类型: iterable 的 Variable
代码示例
- import paddle.fluid as fluid
- prog = fluid.default_main_program()
- img = fluid.layers.data(name='img', shape=[1,28,28], dtype='float32')
- label = fluid.layers.data(name='label', shape=[128,1], dtype='int64')
- for var in prog.list_vars():
- print(var)
- # 这里将会打印出当前Program中所有的Variable
all_parameters
()
获取当前Program中所有的 模型参数 。返回值是一个列表。
返回: 一个包含当前Program中所有参数的列表。
返回类型: list[ 模型参数 ]
代码示例
- import paddle.fluid as fluid
- program = fluid.default_main_program()
- data = fluid.data(name='x', shape=[None, 13], dtype='float32')
- hidden = fluid.layers.fc(input=data, size=10)
- loss = fluid.layers.mean(hidden)
- fluid.optimizer.SGD(learning_rate=0.01).minimize(loss)
- for param in program.all_parameters():
- print(param)
- # 这里将会打印出当前Program中所有的Parameters,在本例中,输出结果是:
- #
- # name: "fc_0.w_0"
- # type {
- # type: LOD_TENSOR
- # lod_tensor {
- # tensor {
- # data_type: FP32
- # dims: 13
- # dims: 10
- # }
- # }
- # }
- #
- # persistable: true
- # name: "fc_0.b_0"
- # type {
- # type: LOD_TENSOR
- # lod_tensor {
- # tensor {
- # data_type: FP32
- # dims: 10
- # }
- # }
- # }
- # persistable: true
- #
- # 这里print(param)将会打印出一个参数所有的属性,包括name,type和persistable,
- # 你可以访问一个参数的指定属性,例如param.name,param.type