tensorflow学习笔记--tf.make_template与tf.global_variables_initializer()

2019.9.21

关于tf.make_template与tf.global_variables_initializer()

 

一、tf.global_variables_initializer()要点:

a.只会初始化之前定义了的变量,从实验3中注释了initialize之后无法运行可以看出

b.这里有个疑问是实验中z w两个变量的创建似乎没有进入到函数中,sess.run()时也没有进入其中?参看实验 4 

c.关于b,在随后检查输出后发现,在最上方有print(1)和print(var1)的输出,粘贴的时候省略tf建立计算图的一堆提示,没有注意最上方的输出。

d.只有在建立计算图时会进入函数,sess.run()时只用计算图,不会调用函数

 

二、tf.make_template()要点:

a.参看实验6,其作用正如官方文档中的解释

Given an arbitrary function, wrap it so that it does variable sharing.

给定一个任意函数,将其包装,以便它进行变量共享.

b.重用时注意函数的名称需要完全一致,参看实验4 5 

c.变量重用还可以在name_scope.reuse_variables()的方法下实现,参看实验8

 

三、具体实验

1.初始代码:

import tensorflow as tf

def my_op(x, scalar_name, scalar):
  var1 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(var1)
  return x * var1

with tf.compat.v1.variable_scope('scope') as vs:
  scale_by_y = tf.compat.v1.make_template('scale_by_y', my_op,
  scalar_name='y',scalar=3)
  z = scale_by_y(tf.constant(2,dtype=tf.float32))
  w = scale_by_y(tf.constant(5.))


with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z))
	print(sess.run(w))

with tf.compat.v1.variable_scope('c', reuse=False):
  scale_by_y2 = tf.compat.v1.make_template('scale_by_y', my_op,
  scalar_name='x', scalar=4)
  z2 = scale_by_y2(tf.constant(3.))
  w2 = scale_by_y2(tf.constant(4.))

with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z2))
	print(sess.run(w2))

代码输出:

6.0
15.0

   
12.0
16.0

可见scale_by_y函数并没有打印变量var1,猜测是没有initialize的原因,而在scale_by_y2函数调用时打印了其中的var1

真正的输出:



#此处省略一堆tf的提示
6.0
15.0

  
#此处省略两行tf的提示 
12.0
16.0

因此只有在最初建立计算图时会进入函数,sess.run()时只会使用计算图,而不会再次调用函数。

另外之后的所有输出都不再修改,阅读请注意这点。

2.添加一行之后

import tensorflow as tf

def my_op(x, scalar_name, scalar):
  var1 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(var1)
  return x * var1

with tf.compat.v1.variable_scope('scope') as vs:
  scale_by_y = tf.compat.v1.make_template('scale_by_y', my_op,
  scalar_name='y',scalar=3)
  z = scale_by_y(tf.constant(2,dtype=tf.float32))
  w = scale_by_y(tf.constant(5.))


with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	# z = scale_by_y(tf.constant(2,dtype=tf.float32))
	# w = scale_by_y(tf.constant(5.))
	print(sess.run(z))
	print(sess.run(w))

with tf.compat.v1.variable_scope('c', reuse=False):
  scale_by_y2 = tf.compat.v1.make_template('scale_by_y', my_op,
  scalar_name='x', scalar=4)
# 此处为添加代码
  z = scale_by_y(tf.constant(2,dtype=tf.float32)) 
# 上方为添加代码
  z2 = scale_by_y2(tf.constant(3.))
  w2 = scale_by_y2(tf.constant(4.))

with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z2))
	print(sess.run(w2))

此时输出为:

6.0
15.0


   
12.0
16.0

3.随后将第二处的 sess.run(tf.global_variables_initializer()) 注释掉,同时z2 w2的variable_scope改为vs,无法运行

import tensorflow as tf

def my_op(x, scalar_name, scalar):
  var1 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(var1)
  return x * var1

with tf.compat.v1.variable_scope('scope') as vs:
  scale_by_y = tf.compat.v1.make_template('scale_by_y', my_op,
  scalar_name='y',scalar=3)
  z = scale_by_y(tf.constant(2,dtype=tf.float32))
  w = scale_by_y(tf.constant(5.))


with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z))
	print(sess.run(w))

with tf.compat.v1.variable_scope(vs, reuse=False):
  scale_by_y2 = tf.compat.v1.make_template('scale_by_y', my_op,
  scalar_name='x', scalar=4)
  z = scale_by_y(tf.constant(2,dtype=tf.float32))
  z2 = scale_by_y2(tf.constant(3.))
  w2 = scale_by_y2(tf.constant(4.))

with tf.Session() as sess:
	# sess.run(tf.global_variables_initializer())
	print(sess.run(z2))
	print(sess.run(w2))

4.对my_op进行修改,添加一行输出

import tensorflow as tf

def my_op(x, scalar_name, scalar):
  var1 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(1)
  print(var1)
  return x * var1

with tf.compat.v1.variable_scope('scope') as vs:
  scale_by_y = tf.compat.v1.make_template('scale_by_y', my_op,
  scalar_name='y',scalar=3)
  z = scale_by_y(tf.constant(2,dtype=tf.float32))
  w = scale_by_y(tf.constant(5.))


with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z))
	print(sess.run(w))

with tf.compat.v1.variable_scope(vs, reuse=False):
  scale_by_y2 = tf.compat.v1.make_template('scale_by_y2', my_op,
  scalar_name='x', scalar=4)
  z2 = scale_by_y2(tf.constant(3.))
  w2 = scale_by_y2(tf.constant(4.))

with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z2))
	print(sess.run(w2))

输出为

6.0
15.0
1

1
     
12.0
16.0

似乎z w两个变量在创建时根本没有进入my_op函数,在sess.run()时也没有,反而是在z2 w2定义时进入了函数,但在run时同样没有进入函数,那么函数对于tensorflow而言主要是向计算图中添加节点,run时不会调用

5.关于reuse=True,这段代码中必须scalar_name, func_name, variable_scope完全一致,这也是不出预料的,即变量的名字必须完全相同,reuse才可以,这是重新定义的值是无效的

import tensorflow as tf

def my_op(x, scalar_name, scalar):
  var1 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(1)
  print(var1)
  return x * var1

with tf.compat.v1.variable_scope('scope') as vs:
  scale_by_y = tf.compat.v1.make_template('scale_by_y', my_op,
  scalar_name='y',scalar=3)
  z = scale_by_y(tf.constant(2,dtype=tf.float32))
  w = scale_by_y(tf.constant(5.))


with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z))
	print(sess.run(w))

with tf.compat.v1.variable_scope(vs, reuse=True):
  scale_by_y2 = tf.compat.v1.make_template('scale_by_y', my_op,
  scalar_name='y', scalar=4)
  z2 = scale_by_y2(tf.constant(3.))
  w2 = scale_by_y2(tf.constant(4.))

with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z2))
	print(sess.run(w2))

输出为

6.0
15.0
1

1
   
9.0
12.0

scalar_by_y2的倍数值是3,而非传入的4,即reuse生效,重用了之前scalar_by_y定义的倍数

5. 关于make_template的作用

import tensorflow as tf

def my_op(x, scalar_name, scalar):
  var1 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(1)
  print(var1)
  return x * var1

def my_op2(x, scalar_name, scalar):
  var2 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(1)
  print(var2)
  return x + var2

with tf.compat.v1.variable_scope('scope') as vs:
  scale_by_y = tf.compat.v1.make_template('scale_by_y', my_op,
  scalar_name='y',scalar=3)
  z = scale_by_y(tf.constant(2,dtype=tf.float32))
  w = scale_by_y(tf.constant(5.))


with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z))
	print(sess.run(w))

with tf.compat.v1.variable_scope(vs, reuse=True):
  scale_by_y2 = tf.compat.v1.make_template('scale_by_y', my_op2,
  scalar_name='y', scalar=4)
  z2 = scale_by_y2(tf.constant(3.))
  w2 = scale_by_y2(tf.constant(4.))

with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z2))
	print(sess.run(w2))

输出为

6.0
15.0
1

1
    
6.0
7.0

及时重新定义了函数my_op2,以及其中的变量名var2,但对于计算图而言,其名称还是 scope/scale_by_y/y:0 ,因此可以重用

 

6.关注make_template的作用

import tensorflow as tf

def my_op(x, scalar_name, scalar):
  var2 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(1)
  print(var2)
  return x * var2

with tf.compat.v1.variable_scope('scope') as vs:
  z = my_op(tf.constant(2,dtype=tf.float32),'y',3)



with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z))

这时有正常输出:

6.0

7.添加定义w之后,程序报错

import tensorflow as tf

def my_op(x, scalar_name, scalar):
  var2 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(1)
  print(var2)
  return x * var2

with tf.compat.v1.variable_scope('scope') as vs:
  z = my_op(tf.constant(2,dtype=tf.float32),'y',3)
  w = my_op(tf.constant(5.),'y',3)


with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z))
	# print(sess.run(w))

这里print(sess.run(w))被注释掉了,同时输出中给出的错误提示也是在z的定义处,因此直接使用my_op无法进行变量共享

7.将定义w的变量改名为x,正常输出

import tensorflow as tf

def my_op(x, scalar_name, scalar):
  var2 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(1)
  print(var2)
  return x * var2

with tf.compat.v1.variable_scope('scope') as vs:
  z = my_op(tf.constant(2,dtype=tf.float32),'y',3)
  w = my_op(tf.constant(5.),'x',4)


with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z))
	print(sess.run(w))

输出为:

6.0
20.0

8.变量重用还可以在variable_scope的框架下进行,通过reuse_variables()方法可以重用变量

import tensorflow as tf

def my_op(x, scalar_name, scalar):
  var2 = tf.compat.v1.get_variable(scalar_name,
                         shape=[],
                         initializer=tf.compat.v1.constant_initializer(scalar))
  print(1)
  print(var2)
  return x * var2

with tf.compat.v1.variable_scope('scope') as vs:
  z = my_op(tf.constant(2,dtype=tf.float32),'y',3)
  vs.reuse_variables()
  w = my_op(tf.constant(5.),'y',4)


with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	print(sess.run(z))
	print(sess.run(w))

输出为

6.0
15.0

可见重新定义的var1=4没有生效,而是重用了之前定义的值3

你可能感兴趣的:(tensorflow学习笔记,tensorflow)