如何为 TensorFlow 变量赋值?
Posted
技术标签:
【中文标题】如何为 TensorFlow 变量赋值?【英文标题】:How to assign a value to a TensorFlow variable? 【发布时间】:2016-03-17 04:32:01 【问题描述】:我正在尝试为 python 中的 tensorflow 变量分配一个新值。
import tensorflow as tf
import numpy as np
x = tf.Variable(0)
init = tf.initialize_all_variables()
sess = tf.InteractiveSession()
sess.run(init)
print(x.eval())
x.assign(1)
print(x.eval())
但我得到的输出是
0
0
所以值没有改变。我错过了什么?
【问题讨论】:
【参考方案1】:在 TF1 中,语句 x.assign(1)
实际上并没有将值 1
分配给 x
,而是创建了一个 tf.Operation
,您必须显式地运行 来更新该变量。 * 调用Operation.run()
或Session.run()
可用于运行操作:
assign_op = x.assign(1)
sess.run(assign_op) # or `assign_op.op.run()`
print(x.eval())
# ==> 1
(*其实是返回一个tf.Tensor
,对应变量的更新值,方便链式赋值。)
不过,在 TF2 中,x.assign(1)
现在会急切地赋值:
x.assign(1)
print(x.numpy())
# ==> 1
【讨论】:
谢谢! assign_op.run() 给出错误:AttributeError: 'Tensor' object has no attribute 'run'。但是 sess.run(assign_op) 运行得非常好。 在这个例子中,Variable
x
在运行 assign
操作/可变张量之前存储在内存中的数据是被覆盖了,还是创建了一个新的张量来存储更新的值?
assign()
的当前实现覆盖了现有值。
有没有一种方法可以为Variable
分配一个新值,而无需在图中创建任何额外的操作?似乎每个变量都已经为其创建了一个赋值操作,但是调用my_var.assign()
或tf.assign()
会创建一个新操作而不是使用现有的操作。
我认为这与这里无关,但是您可以给assign
一个张量参数,例如数学运算。并以这种方式创建一个计数器,每次评估分配操作时都会更新该计数器:op = t.assign(tf.add(t, 1))
.【参考方案2】:
有一个更简单的方法:
x = tf.Variable(0)
x = x + 1
print x.eval()
【讨论】:
操作正在检查tf.assign
的用法,而不是添加。【参考方案3】:
首先,您可以将值分配给变量/常量,只需将值输入到它们中,就像使用占位符一样。所以这是完全合法的:
import tensorflow as tf
x = tf.Variable(0)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print sess.run(x, feed_dict=x: 3)
关于您对tf.assign() 运算符的混淆。在 TF 中,在会话中运行之前不会执行任何操作。所以你总是必须做这样的事情:op_name = tf.some_function_that_create_op(params)
,然后在会话内部运行sess.run(op_name)
。以 assign 为例,您将执行以下操作:
import tensorflow as tf
x = tf.Variable(0)
y = tf.assign(x, 1)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print sess.run(x)
print sess.run(y)
print sess.run(x)
【讨论】:
@RobinDinse,确实如此。在上面的例子中,你得到 0,1,1 作为你的标准输出。 请注意,通过feed_dict
提供值不会将该值永久分配给变量,而仅适用于特定的运行调用。
@RobinDinse 如何永久分配该值?如果可以,请在此处查看我的问题***.com/questions/53141762/…【参考方案4】:
另外,需要注意的是,如果您使用的是your_tensor.assign()
,则无需显式调用tf.global_variables_initializer
,因为分配操作会在后台为您完成。
例子:
In [212]: w = tf.Variable(12)
In [213]: w_new = w.assign(34)
In [214]: with tf.Session() as sess:
...: sess.run(w_new)
...: print(w_new.eval())
# output
34
但是,这不会初始化所有变量,而只会初始化执行assign
的变量。
【讨论】:
【参考方案5】:您还可以为tf.Variable
分配一个新值,而无需向图形添加操作:tf.Variable.load(value, session)
。此功能还可以在您从图表外部分配值时避免添加占位符,并且在图表完成时很有用。
import tensorflow as tf
x = tf.Variable(0)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
print(sess.run(x)) # Prints 0.
x.load(1, sess)
print(sess.run(x)) # Prints 1.
更新:这在 TF2 中已被弃用,因为默认执行是急切,图表为 no longer exposed in the user-facing API。
【讨论】:
警告:您不能使用与变量初始值形状不同的数组来加载它! Variable.load(来自 tensorflow.python.ops.variables)已被弃用,将在未来版本中删除。更新说明:首选在 2.X 中具有等效行为的 Variable.assign。不确定如何在不向图中添加操作的情况下更改 Tensorflow 2.0 中变量的值【参考方案6】:这是完整的工作示例:
import numpy as np
import tensorflow as tf
w= tf.Variable(0, dtype=tf.float32) #good practice to set the type of the variable
cost = 10 + 5*w + w*w
train = tf.train.GradientDescentOptimizer(0.01).minimize(cost)
init = tf.global_variables_initializer()
session = tf.Session()
session.run(init)
print(session.run(w))
session.run(train)
print(session.run(w)) # runs one step of gradient descent
for i in range(10000):
session.run(train)
print(session.run(w))
注意输出将是:
0.0
-0.049999997
-2.499994
这意味着一开始变量为 0,正如定义的那样,然后在梯度下降仅一步后,变量为 -0.049999997,再经过 10.000 步后,我们达到 -2.499994(基于我们的成本函数)。
注意:您最初使用的是交互式会话。当需要在同一个脚本中运行多个不同的会话时,交互式会话很有用。不过,为了简单起见,我使用了非交互式会话。
【讨论】:
【参考方案7】:使用最新的 TensorFlow Eager Execution 模式。
import tensorflow as tf
tf.enable_eager_execution()
my_int_variable = tf.get_variable("my_int_variable", [1, 2, 3])
print(my_int_variable)
【讨论】:
【参考方案8】:所以我有一个不同的情况,我需要在运行会话之前分配值,所以这是最简单的方法:
other_variable = tf.get_variable("other_variable", dtype=tf.int32,
initializer=tf.constant([23, 42]))
我在这里创建一个变量并同时为其赋值
【讨论】:
【参考方案9】:我回答了一个类似的问题here。我查看了很多总是产生同样问题的地方。基本上,我不想为权重分配值,而只是更改权重。上述答案的简短版本是:
tf.keras.backend.set_value(tf_var, numpy_weights)
【讨论】:
以上是关于如何为 TensorFlow 变量赋值?的主要内容,如果未能解决你的问题,请参考以下文章