我试图了解tf.assign 和赋值运算符(=(之间的区别。我有三组代码
首先,使用简单的 tf.assign
import tensorflow as tf
with tf.Graph().as_default():
a = tf.Variable(1, name="a")
assign_op = tf.assign(a, tf.add(a,1))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print sess.run(assign_op)
print a.eval()
print a.eval()
输出预期为
2
2
2
二、使用赋值运算符
import tensorflow as tf
with tf.Graph().as_default():
a = tf.Variable(1, name="a")
a = a + 1
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print sess.run(a)
print a.eval()
print a.eval()
结果仍然是 2、2、2。
第三,我同时使用 tf.assign 和赋值运算符
import tensorflow as tf
with tf.Graph().as_default():
a = tf.Variable(1, name="a")
a = tf.assign(a, tf.add(a,1))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print sess.run(a)
print a.eval()
print a.eval()
现在,输出变为 2、3、4。
我的问题是
在使用 (=( 的第二个代码段中,当我有 sess.run(a( 时,似乎我正在运行一个赋值操作。那么"a = a+1"是否在内部创建了一个像assign_op = tf.assign(a, a+1(这样的赋值操作?会话运行的操作真的只是assign_op吗?但是当我运行 a.eval(( 时,它不会继续递增 a,因此看起来 eval 正在评估一个"静态"变量。
我不确定如何解释第三个片段。为什么两个 eval 递增 a,而第二个代码段中的两个 eval 不增加?
谢谢。
这里的主要混淆是,执行a = a + 1
会将 Python 变量a
重新分配给加法运算的结果张量a + 1
。 另一方面,tf.assign
是用于设置 TensorFlow 变量值的操作。
a = tf.Variable(1, name="a")
a = a + 1
这相当于:
a = tf.add(tf.Variable(1, name="a"), 1)
考虑到这一点:
在使用 (=( 的第二个代码段中,当我有 sess.run(a( 时,似乎我正在运行一个赋值操作。那么"a = a+1"是否在内部创建了一个像assign_op = tf.assign(a, a+1(这样的赋值操作?[...]
它可能看起来如此,但不是真的。如上所述,这只会重新分配 Python 变量。如果没有tf.assign
或任何其他更改变量的操作,它将保持值 1。每次评估a
时,程序将始终计算a + 1 => 1 + 1
。
我不确定如何解释第三个片段。为什么两个 eval 递增 a,而第二个代码段中的两个 eval 不增加?
这是因为在第三个代码段中的赋值张量上调用eval()
也会触发变量赋值(请注意,这与对当前会话执行session.run(a)
没有太大区别(。
首先,anwser并不是很精确。IMO,python对象和tf对象之间没有区别。它们都是由python GC管理的内存对象。
如果将第二个a
更改为b
,并打印出变量,
In [2]: g = tf.Graph()
In [3]: with g.as_default():
...: a = tf.Variable(1, name='a')
...: b = a + 1
...:
In [4]: print(a)
<tf.Variable 'a:0' shape=() dtype=int32_ref>
In [5]: print(b)
Tensor("add:0", shape=(), dtype=int32)
In [6]: id(a)
Out[6]: 140253111576208
In [7]: id(b)
Out[7]: 140252306449616
a
和b
不会引用内存中的同一对象。
绘制计算图或内存图
一线,
# a = tf.Varaible(...
a -> var(a)
二线,
# b = a + 1
b -> add - var(a)
|
-- 1
现在,如果将其替换回b = a + 1
以a = a + 1
,则分配操作后的a
指向tf.add
对象,而不是递增 1 的变量a
。
当你运行sess.run
时,你正在通过该add
运算符获取结果,对原始a
变量没有副作用。
另一方面,tf.assign
将具有更新会话下图形状态的副作用。
对于片段 1:
with tf.Graph().as_default():
a = tf.Variable(1, name="a_var")
assign_op = tf.assign(a, tf.add(a,1,name='ADD'))
b = tf.Variable(112)
b = b.assign(a)
print(a)
print(b)
print(assign_op)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print (sess.run(a))
print ("assign_op : ",sess.run(assign_op))
print(" b :- ",b.eval())
print (sess.run(a))
print (sess.run(a))
print ("assign_op : ",sess.run(assign_op))
print (sess.run(a))
print (sess.run(a))
writer = tf.summary.FileWriter("/tmp/log", sess.graph)
writer.close()
此代码段 1 的 O/P:
<tf.Variable 'a_var:0' shape=() dtype=int32_ref>
Tensor("Assign_1:0", shape=(), dtype=int32_ref)
Tensor("Assign:0", shape=(), dtype=int32_ref)
1
assign_op : 2
b :- 2
2
2
assign_op : 3
3
3
看看TensorBoard的计算图
注意事项:
- 计算第一个变量"A",因此得到 O/P : 1
- next sess.run(assign_op(, executes => assign_op = tf.assign(a, tf.add(a,1,name='ADD'((,它具有更新变量 'a'(=2( 并创建 'assign_op' 的效果,这是对象的张量类型。
对于片段 2:请参阅计算图,你会明白 (请注意,没有用于赋值操作的节点(
with tf.Graph().as_default():
a = tf.Variable(1, name="Var_a")
just_a = a + 1
print(a)
print(just_a)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print (sess.run(a))
print (sess.run(a))
print ("just_a : ",sess.run(just_a))
print (sess.run(a))
print (sess.run(a))
print ("just_a : ",sess.run(just_a))
print (sess.run(a))
print (sess.run(a))
writer = tf.summary.FileWriter("/tmp/log", sess.graph)
writer.close()
代码段 2 的 O/P:
enter code here
<tf.Variable 'Var_a:0' shape=() dtype=int32_ref>
Tensor("add:0", shape=(), dtype=int32)
1
1
just_a : 2
1
1
just_a : 2
1
1
对于代码段 3:计算图
with tf.Graph().as_default():
a = tf.Variable(1, name="Var_name_a")
a = tf.assign(a, tf.add(a,5))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print (sess.run(a))
print (sess.run(a))
print (" a : ",sess.run(a))
print (sess.run(a))
print (sess.run(a))
print (" a : ",sess.run(a))
print (sess.run(a))
print (sess.run(a))
writer = tf.summary.FileWriter("/tmp/log", sess.graph)
writer.close()
代码段 3 的 O/P:
enter code here
6
11
a : 16
21
26
a : 31
36
41
现在,如果您查看此代码段的计算图,它看起来与代码段 1 的计算图相似/精确。但这里的问题是代码 a = tf.assign(a, tf.add(a,5((,不仅更新变量 'a',还再次创建另一个张量 'a'。
现在刚刚创建的"A"将被使用
print (sess.run(a))
这个 'a' 将是 a = tf.assign(a, tf.add(a,5((
来自 tf.add(a,5( 的"a"只不过是 'a'(=1( => a = tf。变量(1, 名称="Var_name_a"(...所以 5+1=6 被分配给原来的"a",这个原来的"a"被分配给新的"a"。
我还有一个例子一次解释这个概念
在此处查看图表
enter code here
with tf.Graph().as_default():
w = tf.Variable(10,name="VAR_W") #initial val = 2
init_op = tf.global_variables_initializer()
# Launch the graph in a session.
with tf.Session() as sess:
# Run the variable initializer.
sess.run(init_op)
print(w.eval())
print(w) #type of 'w' before assign operation
#CASE:1
w = w.assign(w + 50)#adding 100 to var w
print(w.eval())
print(w) #type of 'w' after assign operation
# now if u try => w = w.assign(w + 50), u will get error bcoz newly
created 'w' is considered here which don't have assign attribute
#CASE:2
w = tf.assign(w, w + 100) #adding 100 to var w
print(w.eval())
#CASE:3
w = tf.assign(w, w + 300) #adding 100 to var w
print(w.eval())
writer = tf.summary.FileWriter("/tmp/log", sess.graph)
writer.close()
上面代码段的 o/p:
10
<tf.Variable 'VAR_W:0' shape=() dtype=int32_ref>
60
Tensor("Assign:0", shape=(), dtype=int32_ref)
210
660