Tensorflow 变量机制

最近一直在跟着《TensorFlow:实战google深度学习框架》学习Tensorflow,学到第5.3节变量管理以及5.4节模型持久化的时候忽然发现基础好像学的还是不够扎实,被变量的使用搞得一脸懵逼。书中讲的还是很详细的,我针对一些有疑问的定义进行了实验,这里总结一下。

问题1:tf.Variable中不指定name参数会怎样?

运行以下程序

a=tf.Variable(tf.constant(1.0,shape=[1]))
b=tf.Variable(tf.constant(1.0,shape=[1]))
print(a)
print(b)

输出

<tf.Variable 'Variable:0' shape=(1,) dtype=float32_ref>
<tf.Variable 'Variable_1:0' shape=(1,) dtype=float32_ref>

可见程序中a定义的第一个变量被自动命名为Variable,由于重名而把b定义的第二个变量自动命名为Variable_1

补充:tf.get_variable的name参数是不能重名的

运行以下程序

a = tf.get_variable(name='a1',shape=[1,2])
b = tf.get_variable(name='a1',shape=[3,4])
print(a)
print(b)

报了如下错

ValueError: Variable a1 already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope?

因此在使用tf.get_variable要注意name参数是不能相同的

 

问题2:变量名指的究竟是什么?

a = tf.get_variable( 'b' , [1] , initializer = tf.constant_initializer(1.0) ) 

该语句定义了一个名为“b”的节点,并且书中的变量名指的也应该是‘b’(即tf.Variable中的name参数)

print(a)后输出Tensor("b:0", shape=(2,), dtype=float32),其中“b:0”表示该张量计算节点“b”输出的第一个结果

print(a.name)后输出b:0

注:tf.get_variable与tf.Variable最大不同就是tf.get_variable中name参数是一个必填的参数,而在tf.Variable中是可选的。tf.get_variable就是根据这一参数来创建和命名变量

那么该语句中的a是指什么呢?

运行下面两个程序

code1

a = tf.get_variable(name='a1',shape=[1,2])
a = tf.get_variable(name='a1',shape=[1,2])
print(a)

code2

a=tf.Variable(tf.constant(1.0,shape=[1]))
a=tf.Variable(tf.constant(1.0,shape=[1]))
print(a)

code1的运行结果为

ValueError: Variable a1 already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope?

code2的运行结果为

<tf.Variable 'Variable_1:0' shape=(1,) dtype=float32_ref>

通过上述两个程序比较,可以看出,每个程序中相同语句执行了两次,因此可以将这个‘a’理解为用来指代程序中操作的结果的标识(也就是python中的变量名指向了一个新的内存地址)(此处有问题可能是混淆了C与python变量名的意义,可以参考https://www.jianshu.com/p/3289be65c76d

 

问题3:tf.variable_scope的作用范围?

一开始我对tf.variable_scope的理解有问题,所有对以下代码有个疑惑,就是为什么在scope('layer2')中也可以直接用在scope('layer1')中定义的layer1

#训练时会创建变量,测试时会通过保存的模型加载变量v          
def get_weight_variable(shape,regularizer):                           
weights=tf.get_variable("weights",shape,initializer=tf.truncated_normal_initializer(stddev=0.1))
    if regularizer !=None :
        #将张量加入自定义集合losses中
        tf.add_to_collection('losses',regularizer(weights))
    return weights

#dnn前向传播
def inference(input_tensor,regularizer):
    #第一层变量
    with tf.variable_scope('layer1'):
        weights=get_weight_variable([INPUT_NODE,LAYER1_NODE],regularizer)
        biases=tf.get_variable("biases",[LAYER1_NODE],initializer=tf.constant_initializer(0.0))
        layer1=tf.nn.relu(tf.matmul(input_tensor,weights)+biases)

    #第二层变量
    with tf.variable_scope('layer2'):
        weights=get_weight_variable([LAYER1_NODE,OUTPUT_NODE],regularizer)
        biases=tf.get_variable("biases",[OUTPUT_NODE],initializer=tf.constant_initializer(0.0))
        layer2=tf.nn.relu(tf.matmul(layer1,weights)+biases)

因为scope只对name参数中的变量名起作用而不对程序中定义的变量名起作用,程序中定义的变量名仍是起到一个指示的作用。这里tf.variable_scope('XXX')语句是用来在name参数指定的变量名前添加命名空间的,可以将每次执行 with tf.variable_scope('XXX'):理解为打开了一个名为XXX的文件夹(variable_scope的命名空间也可以嵌套,类似绝对地址)

下列两个代码执行结果是一样的

with tf.variable_scope('layer1'):
    biases=tf.get_variable("biases1",[1],initializer=tf.constant_initializer(0.0))

with tf.variable_scope('layer2'):
    biases=tf.get_variable("biases2",[1],initializer=tf.constant_initializer(0.0))

print(biases.name)
with tf.variable_scope('layer1'):
    biases=tf.get_variable("biases1",[1],initializer=tf.constant_initializer(0.0))

with tf.variable_scope('layer2'):
    biases=tf.get_variable("biases2",[1],initializer=tf.constant_initializer(0.0))
    print(biases.name)

均为

layer2/biases2:0

(还是对python中变量名理解的问题T T)

 

问题4:保存或加载指定变量时,tf.train.saver列表中提供的变量是哪一个?

如在加载模型时只加载一个变量则应该使用如下代码定义一个Saver类

saver=tf.train.Saver([v1])

那么这个v1到底是name参数还是程序中定义的变量名呢

分别执行以下两段代码(只声明了一个Saver类,没有执行具体操作的代码)

code1

v=tf.Variable(tf.constant(1.0,shape=[1]),name='v1')
saver=tf.train.Saver([v1])

code2

v1=tf.Variable(tf.constant(1.0,shape=[1]),name='v')
saver=tf.train.Saver([v1])

code1报错如下错,而code2可以执行

NameError: name 'v1' is not defined

因此列表中指定的变量应该是在程序中定义的变量,此时可以将它当做普通python程序理解,毕竟只有程序中定义了的变量才能被列表使用

 

问题5:tf.train.Saver在保存或者加载变量时给变量重命名,字典中的key-value分别对应什么?

如在保存模型时为v1,v2重命名,则应该使用如下代码定义一个Saver类

 

那这个字典中key,value是什么含义呢?继续做一个实验。

首先执行了

a=tf.Variable(tf.constant(1.0,shape=[1]),name='a1')
saver=tf.train.Saver({"a":a2})

报错

NameError: name 'a2' is not defined

这说明key应该是这个变量在被保存的模型里的名称,value应该是a或者a1,根据问题4我们可以推测value应该是a(在程序中定义了的变量)

接着执行

a=tf.Variable(tf.constant(1.0,shape=[1]),name='a1')
saver=tf.train.Saver({"a2":a})

程序没有报错,说明value应该对应程序中定义了的变量,为了证明使用name参数作为value是错误的,再执行以下程序

a=tf.Variable(tf.constant(1.0,shape=[1]),name='a1')
saver=tf.train.Saver({"a2":a1})

程序报错

NameError: name 'a1' is not defined

综上所述,定义用来重命名的Saver类时,使用的字典的key应该是在被保存的模型中的名称,value是程序中定义的变量名称。在加载重命名时是将名为key的变量重命名并加载到当前程序名为value的变量中;在保存重命名时是将当前程序名为value的变量重命名为key再保存。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值