tensorflow中使用张量tensor数据结构来代表所有的数据,在计算图中操作间传递的数据都是tensor。可以把tensor看为是一个n维数组或者列表,每个tensor都包含了类型(type)、阶(rank)和形状(shape)。
阶指的是维度,但是张量的阶主要看有几层中括号,这与矩阵的阶不同。
张量的相关操作主要包括类型转换、数值操作、形状变换和数据操作。
np.shape与tf.shape的区别:
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
import numpy as np
t=[[1,2],[22,3]]
print(np.shape(t))
tshape=tf.shape(t)
tshape2=tf.shape(tshape)
with tf.Session() as sess:
print(sess.run(tshape))
print(sess.run(tshape2))
运行后得到的结果如下所示:
可以从结果看出,np.shape返回的是张量形状对应的元组,而tf.shape返回的是一个张量即列表。
tf.expand_dims(input,dim,name=None)
该函数的作用是增加张量input在原dim维度的维度值,这种描述不好理解,下面通过一个小例子去理解:
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
import numpy as np
t=[[2,3,4],[1,2,3]]
t1=tf.expand_dims(t,0)
t2=tf.expand_dims(t,1)
t3=tf.expand_dims(t,2)
t4=tf.expand_dims(t,-1)
with tf.Session() as sess:
print(sess.run(t1))
print(sess.run(t2))
print(sess.run(t3))
print(sess.run(t4))
运行结果为:
可以通过运行结果得出,当dim为0时,在最外层括号的层级上加括号;当dim为1时,在次外层的括号的层级上分别加一个括号...最终得到的t1,t2,t3的形状分别为(1,2,3),(2,1,3),(2,3,1)。需要注意的是,当dim为-1时,相当于最内层的层级。在本例中,就是说相当于dim为2。
共享变量
在构建每一个模型时,都需要使用tf.Variable来创建一个变量。但是在某种情况下,一个模型的训练需要使用其他模型创建的变量,两个模型一起训练。为了使得两个或多个模型对应一套权重,引入get_variable方法,实现共享变量来解决这个问题。get_variable一般会配合variable_scope一起使用,以实现共享变量。variabel_scope的意思是变量作用域,在某一作用域中的变量可以被设置成共享的方式,被其他网络模型使用。get_variable的函数定义如下:
tf.get_variable(name,shape,initializer)
使用get_variable生成的变量以指定的name属性为唯一标识,并不是定义的变量名称。使用时一般通过name属性定位到具体变量,并将其共享到其他模型中。
在特定的作用域下获取变量:
使用get_variable创建两个同样名字的变量是行不通的,如下代码会报错:
var1=tf.get_variable('firstvar',shape=[1],dtype=tf.float32)
var2=tf.get_variable('firstvar',shape=[1].dtype=tf.float32)
如果想要实现上述功能,可以使用variable_scope将它们隔开,在不同的变量域中创建同样名字的两个不同变量,还支持嵌套,代码如下:
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
with tf.variable_scope('test1',):
var1=tf.get_variable('first',shape=[1],dtype=tf.float32)
with tf.variable_scope('test2',):
var2=tf.get_variable('first',shape=[1],dtype=tf.float32)
print('var1:',var1.name)
print('var2:',var2.name)
实现共享变量功能
varibale_scope里面的参数reuse=True时,表示使用已经定义过的变量。此时,get_variable将不会再创建新的变量,而是去图中get_variable所创建过的变量中找与name相同的变量。
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
with tf.variable_scope('test1',):
var1=tf.get_variable('first',shape=[1],dtype=tf.float32)
with tf.variable_scope('test2',):
var2=tf.get_variable('first',shape=[1],dtype=tf.float32)
with tf.variable_scope('test1',reuse=True):
var3=tf.get_variable('first',shape=[1],dtype=tf.float32)
with tf.variable_scope('test2',reuse=True):
var4=tf.get_variable('first',shape=[1],dtype=tf.float32)
print('var1:',var1.name)
print('var2:',var2.name)
print('var3',var3.name)
print('var4:',var4.name)
从结果可以看出,var1和var3共用了一个变量,var2和var4也共用了一个变量。在实际应用中,可以把var1和var2放到一个网络模型中去训练,把var3和var4放到另一个模型里去训练,而这两个模型的训练结果都会作用于一个模型的学习参数中。
初始化共享变量的作用域
variable_scope和get_variable都有初始化的功能。在初始化时,如果没有对当前变量初始化,则tensorflow会默认使用作用域的初始化方法对其初始化,并且作用域的初始化方法也有继承功能。用下面的代码演示:
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
with tf.variable_scope('test1',initializer=tf.constant_initializer(0.4)):
var1=tf.get_variable('first',shape=[3],dtype=tf.float32)
with tf.variable_scope('test2'):
var2=tf.get_variable('first',shape=[2],dtype=tf.float32)
var3=tf.get_variable('xixi',shape=[1],dtype=tf.float32,initializer=tf.constant_initializer(0.3))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print('var1:',var1.eval())
print('var2:',var2.eval())
print('var3:',var3.eval())