Variable

  • 注意:
  1. 请不要直接调用 Variable 的构造函数,因为这会造成严重的错误发生!

  2. 在静态图形模式下:请使用 Block.create_var 创建一个静态的 Variable ,该静态的 Variable 在使用 Executor 执行前是没有实际数据的。

  3. Dygraph 模式下:请使用 to_variable 创建一个拥有实际数据的 Variable

在Fluid中,OP的每个输入和输出都是 Variable 。多数情况下, Variable 用于保存不同种类的数据或训练标签。

Variable 总是属于某一个 Block 。所有 Variable 都有其自己的 name ,不同 Block 中的两个 Variable 可以具有相同的名称。如果使用的 不是 Dygraph 模式,那么同一个 Block 中的两个或更多 Variable 拥有相同 name 将意味着他们会共享相同的内容。通常我们使用这种方式来实现 参数共享

Variable 有很多种。它们每种都有自己的属性和用法。请参考 framework.proto 以获得详细信息。 Variable 的大多数成员变量可以设置为 None。它的意思是它不可用或稍后指定。

如果您希望创建一个 Variable 那么可以参考如下示例:

示例代码:

  • 在静态图形模式下:
  1. import paddle.fluid as fluid
  2. cur_program = fluid.Program()
  3. cur_block = cur_program.current_block()
  4. new_variable = cur_block.create_var(name="X",
  5. shape=[-1, 23, 48],
  6. dtype='float32')
  1. import paddle.fluid as fluid
  2. import numpy as np
  3. with fluid.dygraph.guard():
  4. new_variable = fluid.dygraph.to_variable(np.arange(10))
  • detach()

注意:

1. 该API只在 Dygraph 模式下生效

2. detach 后的 Variable 将会成为临时变量

产生一个新的,和当前计算图分离的,但是拥有当前 Variable 其内容的临时变量

返回:一个新的,和当前计算图分离的,但是拥有当前 Variable 其内容的临时 Variable

返回类型:(Variable | 和输入的 Dtype 一致)

  • 示例代码
  1. import paddle.fluid as fluid
  2. from paddle.fluid.dygraph.base import to_variable
  3. from paddle.fluid.dygraph import Linear
  4. import numpy as np
  5.  
  6. data = np.random.uniform(-1, 1, [30, 10, 32]).astype('float32')
  7. with fluid.dygraph.guard():
  8. linear = Linear(32, 64)
  9. data = to_variable(data)
  10. x = linear(data)
  11. y = x.detach()
  • numpy()

注意:

1. 该API只在 Dygraph 模式下生效

返回一个 ndarray 来表示当前 Variable 的值

返回:numpy 的数组,表示当前 Variable 的实际值

返回类型:ndarray,dtype 和输入的 dtype 一致

  • 示例代码
  1. import paddle.fluid as fluid
  2. from paddle.fluid.dygraph.base import to_variable
  3. from paddle.fluid.dygraph import Linear
  4. import numpy as np
  5.  
  6. data = np.random.uniform(-1, 1, [30, 10, 32]).astype('float32')
  7. with fluid.dygraph.guard():
  8. linear = Linear(32, 64)
  9. data = to_variable(data)
  10. x = linear(data)
  11. print(x.numpy())
  • set_value()

注意:

1. 该API只在 Dygraph 模式下生效

为此 Variable 设置一个新的值。

参数:

返回:无

抛出异常: ValueError - 当要赋于的新值的 shape 和此 Variable 原有的 shape 不同时,抛出 ValueError

  • 示例代码
  1. import paddle.fluid as fluid
  2. from paddle.fluid.dygraph.base import to_variable
  3. from paddle.fluid.dygraph import Linear
  4. import numpy as np
  5.  
  6. data = np.ones([3, 1024], dtype='float32')
  7. with fluid.dygraph.guard():
  8. linear = fluid.dygraph.Linear(1024, 4)
  9. t = to_variable(data)
  10. linear(t) # 使用默认参数值调用前向
  11. custom_weight = np.random.randn(1024, 4).astype("float32")
  12. linear.weight.set_value(custom_weight) # 将参数修改为自定义的值
  13. out = linear(t) # 使用新的参数值调用前向
  • backward()

注意:

1. 该API只在 Dygraph 模式下生效

2. 由于如果该 Variable 以上没有任何地方需要梯度,那么仅仅设置该 Variable 的梯度为 1 是没有意义的。因此,这种情况下,为了节省一些计算,我们不去产生该 Variable 的梯度

从该节点开始执行反向

参数:

返回:无

  • 示例代码
  1. import paddle.fluid as fluid
  2. import numpy as np
  3.  
  4. x = np.ones([2, 2], np.float32)
  5. with fluid.dygraph.guard():
  6. inputs2 = []
  7. for _ in range(10):
  8. tmp = fluid.dygraph.base.to_variable(x)
  9. # 如果这里我们不为输入tmp设置stop_gradient=False,那么后面loss2也将因为这个链路都不需要梯度
  10. # 而不产生梯度
  11. tmp.stop_gradient=False
  12. inputs2.append(tmp)
  13. ret2 = fluid.layers.sums(inputs2)
  14. loss2 = fluid.layers.reduce_sum(ret2)
  15. backward_strategy = fluid.dygraph.BackwardStrategy()
  16. backward_strategy.sort_sum_gradient = True
  17. loss2.backward(backward_strategy)
  • gradient()

注意:

1. 该API只在 Dygraph 模式下生效

2. 由于如果该 Variable 以上没有任何地方需要梯度,那么仅仅设置该 Variable 的梯度为 1 是没有意义的。因此,这种情况下,为了节省一些计算,我们不去产生该 Variable 的梯度

获取该 Variable 的梯度值

返回:如果 Variable 的类型是LoDTensor(参见 LoDTensor ),返回该 Variable 类型为 ndarray 的梯度值;如果 Variable 的类型是SelectedRows,返回该 Variable 类型为 ndarray 的梯度值和类型为 ndarray 的词id组成的tuple。

返回类型:ndarray 或者 tuple of ndarray , 返回类型 tuple of ndarray 仅在 Embedding 层稀疏更新时产生。

  • 示例代码
  1. import paddle.fluid as fluid
  2. import numpy as np
  3.  
  4. # example1: 返回ndarray
  5. x = np.ones([2, 2], np.float32)
  6. with fluid.dygraph.guard():
  7. inputs2 = []
  8. for _ in range(10):
  9. tmp = fluid.dygraph.base.to_variable(x)
  10. tmp.stop_gradient=False
  11. inputs2.append(tmp)
  12. ret2 = fluid.layers.sums(inputs2)
  13. loss2 = fluid.layers.reduce_sum(ret2)
  14. backward_strategy = fluid.dygraph.BackwardStrategy()
  15. backward_strategy.sort_sum_gradient = True
  16. loss2.backward(backward_strategy)
  17. print(loss2.gradient())
  18.  
  19. # example2: 返回tuple of ndarray
  20. with fluid.dygraph.guard():
  21. embedding = fluid.dygraph.Embedding(
  22. size=[20, 32],
  23. param_attr='emb.w',
  24. is_sparse=True)
  25. x_data = np.arange(12).reshape(4, 3).astype('int64')
  26. x_data = x_data.reshape((-1, 3, 1))
  27. x = fluid.dygraph.base.to_variable(x_data)
  28. out = embedding(x)
  29. out.backward()
  30. print(embedding.weight.gradient())
  • clear_gradient()

注意:

1. 该API只在 Dygraph 模式下生效

2. 只有当该 Variable 有梯度时才可调用,通常我们都会为参数调用这个方法,因为临时变量的梯度将会在其离开作用域时被 python 自动清除

设置该 Variable 的梯度为零

返回:无

  • 示例代码
  1. import paddle.fluid as fluid
  2. import numpy as np
  3.  
  4. x = np.ones([2, 2], np.float32)
  5. with fluid.dygraph.guard():
  6. inputs2 = []
  7. for _ in range(10):
  8. tmp = fluid.dygraph.base.to_variable(x)
  9. tmp.stop_gradient=False
  10. inputs2.append(tmp)
  11. ret2 = fluid.layers.sums(inputs2)
  12. loss2 = fluid.layers.reduce_sum(ret2)
  13. backward_strategy = fluid.dygraph.BackwardStrategy()
  14. backward_strategy.sort_sum_gradient = True
  15. loss2.backward(backward_strategy)
  16. print(loss2.gradient())
  17. loss2.clear_gradient()
  18. print("After clear {}".format(loss2.gradient()))
  • to_string()

注意:

1. 该API只在非 Dygraph 模式下生效

获取该 Variable 的静态描述字符串

  • 参数:(仅在非 Dygraph 模式下生效)
    • throw_on_error (bool) - 是否在没有设置必需字段时抛出异常。
    • with_details (bool) - 值为true时,打印更多关于 Variable 的信息,如 error_clip , stop_gradient

返回:用于静态描述该 Variable 的字符串

返回: 将Program转换为字符串

返回类型: str

抛出异常: ValueError - 当 throw_on_error == true ,当没有设置任何必需的字段时,抛出 ValueError

  • 示例代码
  1. import paddle.fluid as fluid
  2.  
  3. cur_program = fluid.Program()
  4. cur_block = cur_program.current_block()
  5. new_variable = cur_block.create_var(name="X",
  6. shape=[-1, 23, 48],
  7. dtype='float32')
  8. print(new_variable.to_string(True))
  9. print("\n=============with detail===============\n")
  10. print(new_variable.to_string(True, True))
  • astype(self, dtype)

将该 Variable 中的数据转换成目标 Dtype

  • 参数:
    • self ( Variable ) - 当前 Variable , 用户不需要传入。
    • dtype (int | float | float64) - 希望转换成的 Dtype

返回:一个全新的转换了 DtypeVariable

返回类型: Variable

示例代码

  • 在静态图模式下:
  1. import paddle.fluid as fluid
  2.  
  3. startup_prog = fluid.Program()
  4. main_prog = fluid.Program()
  5. with fluid.program_guard(startup_prog, main_prog):
  6. original_variable = fluid.data(name = "new_variable", shape=[2,2], dtype='float32')
  7. new_variable = original_variable.astype('int64')
  8. print("new var's dtype is: {}".format(new_variable.dtype))
  1. import paddle.fluid as fluid
  2. import numpy as np
  3.  
  4. x = np.ones([2, 2], np.float32)
  5. with fluid.dygraph.guard():
  6. original_variable = fluid.dygraph.to_variable(x)
  7. print("original var's dtype is: {}, numpy dtype is {}".format(original_variable.dtype, original_variable.numpy().dtype))
  8. new_variable = original_variable.astype('int64')
  9. print("new var's dtype is: {}, numpy dtype is {}".format(new_variable.dtype, new_variable.numpy().dtype))

属性

  • stop_gradient

注意:该属性在 Dygraph 模式下除参数以外默认值为 True ,而参数的该属性默认值为 False 。在静态图下所有的 Variable 该属性默认值都为 False

是否从此 Variable 开始,之前的相关部分都停止梯度计算

  • 示例代码
  1. import paddle.fluid as fluid
  2.  
  3. with fluid.dygraph.guard():
  4. value0 = np.arange(26).reshape(2, 13).astype("float32")
  5. value1 = np.arange(6).reshape(2, 3).astype("float32")
  6. value2 = np.arange(10).reshape(2, 5).astype("float32")
  7. linear = fluid.Linear(13, 5, dtype="float32")
  8. linear2 = fluid.Linear(3, 3, dtype="float32")
  9. a = fluid.dygraph.to_variable(value0)
  10. b = fluid.dygraph.to_variable(value1)
  11. c = fluid.dygraph.to_variable(value2)
  12. out1 = linear(a)
  13. out2 = linear2(b)
  14. out1.stop_gradient = True
  15. out = fluid.layers.concat(input=[out1, out2, c], axis=1)
  16. out.backward()
  17. # 可以发现这里linear的参数变成了
  18. assert (linear.weight.gradient() == 0).all()
  19. assert (out1.gradient() == 0).all()
  • persistable

注意:该属性我们即将废弃,此介绍仅为了帮助用户理解概念, 1.6版本后用户可以不再关心该属性

1. 该属性除参数以外默认值为 False ,而参数的该属性默认值为 True

2. 该属性在 Dygraph 模式下一经初始化即不能修改,这是由于在动态执行时, Variable 的生命周期将由 Python 自行控制不再需要通过该属性来修改

Variable 是否是长期存活的 Variable

  • name

注意:在非 Dygraph 模式下,那么同一个 Block 中的两个或更多 Variable 拥有相同 name 将意味着他们会共享相同的内容。通常我们使用这种方式来实现参数共享

Variable 的名字(str)

  • shape

注意:该属性是只读属性

Variable 的维度

  • dtype

注意:该属性是只读属性

Variable 的实际数据类型

  • lod_level

注意:

1. 该属性是只读属性

2. Dygraph 模式下,不支持该属性,该值为零

VariableLoD 信息,关于 LoD 可以参考 api_fluid_LoDTensor 相关内容

  • type

注意:该属性是只读属性

Variable 的内存模型,例如是:api_fluid_LoDTensor, 或者SelectedRows