写在前面
tensorflow的命名问题断断续续接触了又忘记,干脆写一篇博来记录一下好啦。其实极客学院里面也回答的挺清楚的了:极客学院:共享变量, 但它考虑了更多种情况,自己还是想以更简单的方式去记忆。
tf.Variable:创建变量
这个是最简单粗暴的创建变量方式,如果不停地调用它,是会产生不同的变量的。举个更简单的例子:
import tensorflow as tf
#tf.Variable创建变量
def geta():
a = tf.Variable([1],name='a')
return a
a = geta() # 得到<tf.Variable 'a:0' shape=(1,) dtype=int32_ref>
a1 = geta() # 得到与a不同的变量:<tf.Variable 'a_1:0' shape=(1,) dtype=int32_ref>
调用geta(),会得到 <tf.Variable ‘a:0’ shape=(1,) dtype=int32_ref>,再调用geta(),则得到<tf.Variable ‘a_1:0’ shape=(1,) dtype=int32_ref>。可以看到此时两次调用得到两个不同的变量。
但在实际中,我们很可能需要多次调用而使用同一个变量,比如极客学院中提到的,我们可能需要定义一个图片的滤波器函数,然后对不同图片使用同一个滤波器,这时候就需要所谓的共享变量,可以用到下面的tf.get_variable大招啦。
tf.get_variable: 创建或获取变量
一般与tf.variable_scope搭配使用。
reuse=True?False?
首先先说说reuse,每次跑别人tensorflow代码debug时总是会弹出来令我头疼的:
ValueError: Variable xxx already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope?
其实reuse说简单也很简单,一句话就是:如果你想用get_variable创建变量,你就用reuse=False;如果想用get_variable获取变量,就用reuse=True。 反过来会有问题,比如如果该变量还没有创建就用reuse=True,get_variable会告诉你它找不到这个变量;如果该变量已经创建过了还用reuse=False,get_variable就会弹出上面那一串ValueError,告诉你变量已经存在了。没错,它就是这么挑剔,所以一定要选对它的值。
示例1:
def geta():
with tf.variable_scope('A',reuse=False):
a = tf.get_variable('a',[1])
return a
a = geta() # <tf.Variable 'A/a:0' shape=(1,) dtype=float32_ref>
a1 = geta() # 会报错
此时a为<tf.Variable ‘A/a:0’ shape=(1,) dtype=float32_ref>,创建成功。但再次调用geta()的时候就会报出上面的ValueError错误,因为不能重用。
示例2:
def geta():
with tf.variable_scope('AA',reuse=True):
a = tf.get_variable('a',[1])
return a
a = geta() # 会报错
此时调用geta()会报错(注意此时scope的域我改为了AA,而不是A了,所以属于一个新的域,我们还没往这个域里面定义变量):Variable AA/a does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=tf.AUTO_REUSE in VarScope? 因为我们还没有创建过这个变量。
想先创建,后获取?
于是问题来了:如果我想定义一个函数,第一次调用的时候创建,第二次调用的时候获取,怎么办?
方法一:极客学院:共享变量中提到的,用scope.reuse_variables()解决。即在另一个域里面先调用一次函数,然后用scope.reuse_variables()设置为重用,再调用一次函数:
def getb():
with tf.variable_scope('B'):
b = tf.get_variable('b',[1])
return b
with tf.variable_scope('main_scope') as scope:
b1 = getb()
scope.reuse_variables()
b2 = getb()
assert b1==b2 #不会报错,两个都是<tf.Variable 'main_scope/B/b:0' shape=(1,) dtype=float32_ref>
此时b1和b2都是<tf.Variable ‘main_scope/B/b:0’ shape=(1,) dtype=float32_ref>。
方法二:但其实我自己更喜欢这种方法,因为无需再多定义一个scope。即只需要在函数中多加一个reuse的标志,第一次调用的时候设置reuse为None或False,第二次调用的时候设置为True即可。
def getc(reuse=None):
with tf.variable_scope('C',reuse=reuse):
c = tf.get_variable('c',[1])
return c
c1=getc()
c2=getc(True)
assert c1==c2 # 不会报错,两者都是<tf.Variable 'C/c:0' shape=(1,) dtype=float32_ref>
此时c1和c2都是<tf.Variable ‘C/c:0’ shape=(1,) dtype=float32_ref>。
END
目前关于变量域的先学习到这么多,如果在之后的使用中还有遇到什么经验,再来更新~