tensorflow变量操作相关函数

(一)tensorflow的变量类型与使用

(1)tf.costant函数

tf里面常量的含义不是其他编程语言里的常量不能改变,而是在神经网络训练的过程中,即在Optimizer操作过程中,不会更新。

def constant( value, dtype=None, shape=None, name="Const", verify_shape=False) //创建一个常量
value:初始值,必须是一个张量(1或[1,2,3]或[[1,2,3],[2,2,3]]或......)
dtype:数据类型,默认为value的数据类型,传入参数为tensorflow下的枚举值(float32,float64.......)
shape:数据形状,默认为value的shape,设置时不得比value小,可以比value阶数、维度更高,超过部分按广播运算的方式复制补充。
name:常量名,选填,默认值不重复,根据创建顺序为(Const,Const_1,Const_2.......)
verify_shape:是否验证value的shape和指定shape相符,若设为True则进行验证,不相符时会抛出异常。
return:一个常量tensor

示例如下:

​
import tensorflow as tf
cons1 = tf.constant([1, 2, 3], shape=[2, 3])
cons2 = tf.zeros([2,3])
print(cons1)
print(cons2)
#error
#cons3 = tf.constant([1, 2, 3], shape=[2, 3],verify_shape=True)
with tf.Session() as sess:
    print(sess.run(cons1))

result:

Tensor("Const_68:0", shape=(2, 3), dtype=int32)
Tensor("zeros_8:0", shape=(2, 3), dtype=float32)
[[1 2 3]
 [3 3 3]]

​

tf.ones, tf.random_normal系列操作得到的都是常量,使用前不需要初始化,也不会存到本地。

tf.Variable为一个类,它的初始化函数为:

def __init__(self,  
               initial_value=None,# 初始值,必填,张量或可以转换为张量的Python对象。初始值必须有指定一个形状,除非`validate_shape`设置为False。

               trainable=True,# 如果`True`,则默认值也将变量添加到图形中集合`GraphKeys.TRAINABLE_VARIABLES`。这个集合用作“Optimizer”类使用的默认变量列表

               collections=None, # 图表集合键的列表。新的变量被添加到这些集合。默认为`[GraphKeys.GLOBAL_VARIABLES]`。

               validate_shape=True,# 如果`False`,允许变量用初始化未知形状的值。如果“True”,默认的形状`initial_value`必须是已知的。

               caching_device=None, # 可选设备字符串,描述变量的位置应该被缓存以供阅读。默认为变量的设备。如果不是“None”,则缓存在另一个设备上。典型的用途是缓存在使用变量的Ops所在的设备上进行重复数据删除复制`Switch`和其他条件语句。

               name=None, # 变量的可选名称。默认为“Variable”并获取自动去重(Variable_1,Variable_2....)。
               variable_def=None,# `VariableDef`协议缓冲区。如果不是“无”,则重新创建变量对象及其内容,引用变量的节点在图中,必须已经存在。图形没有改变。`variable_def`和其他参数是互斥的。
               dtype=None,# 如果设置,initial_value将被转换为给定的类型。如果`None',数据类型将被保存(如果`initial_value`是一个张量),或者“convert_to_tensor”来决定。
               expected_shape=None,# 张量的Shape。如果设置,initial_value需要符合这个形状。
               import_scope=None,# 可选的字符串。名称范围添加到`Variable.`仅在从协议缓冲区初始化时使用。
               constraint=None,
               use_resource=None,
               synchronization=VariableSynchronization.AUTO,
               aggregation=VariableAggregation.NONE):

示例代码:

import tensorflow as tf

v1 = tf.Variable([2,3], name="v1",trainable=False)
v2 = tf.Variable(tf.zeros([1,2]), name="v2")

#tf.GraphKeys.LOCAL_VARIABLES
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    print(sess.run(v1))
    print(sess.run(v2))
    #这几个集合的区别
    variable_names = [v.name for v in tf.global_variables()]
    print(variable_names)
    variable_names = [v.name for v in tf.trainable_variables()]
    print(variable_names)
    variable_names = [v.name for v in tf.local_variables()]
    print(variable_names)

result:

[2 3]
[[0. 0.]]
['v1:0', 'v2:0']
['v2:0']
[]

变量必须要初始化后才能使用。若没有初始化就使用着会报错:Attempting to use uninitialized value

Variable和Tensor之间的区别:
1. Variable是可更改的,可训练的参数,而Tensor是不可更改的。
2. Variable用于存储网络中的权重矩阵等变量,而Tensor更多的是中间结果等。
3. Variable是会显示分配内存空间的,需要初始化操作(assign一个tensor),由Session管理,可以进行存储、读取、更改等操作。相反地,诸如Const, Zeros等操作创造的Tensor,是记录在Graph中,所以没有单独的内存空间;而其他未知的由其他Tensor操作得来的Tensor则是只会在程序运行中间出现。
4. Tensor可以使用的地方,几乎都可以使用Variable。

(二)占位符

placeholder是TensorFlow的占位符节点,由placeholder方法创建,其也是一种常量,但是由用户在调用run方法是传递的,也可以将placeholder理解为一种形参。即其不像constant那样直接可以使用,需要用户传递常数值。

def placeholder(dtype, shape=None, name=None)
dtype:数据类型,必填,默认为value的数据类型,传入参数为tensorflow下的枚举值(float32,float64.......)
shape:数据形状,选填,不填则随传入数据的形状自行变动,可以在多次调用中传入不同形状的数据
name:常量名,选填,默认值不重复,根据创建顺序为(Placeholder,Placeholder_1,Placeholder_2.......)

示例代码,占位符传入参数是,可以时python数组,初始化后的tensorflow变量或常量。

import tensorflow as tf

input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = input1 * input2
cons1 = tf.constant([1,2])
v1 = tf.Variable([2,3])
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    #The value of a feed cannot be a tf.Tensor object. Acceptable feed values include Python scalars, 
    #strings, lists, numpy ndarrays, or TensorHandles.
    #print(sess.run(output, feed_dict={input1:cons1, input2:[2,4]}))
    print(sess.run(output, feed_dict={input1:sess.run(cons1), input2:[2,4]}))
    print(sess.run(output, feed_dict={input1:sess.run(cons1), input2:sess.run(v1)}))

(三)变量作用域

除了tf.Variable函数,Tensorflow还提供了tf.get_variable函数来创建或者获取变量。当变量作用域里面有该变量时,get_variable获取该变量。当变量作用域没有该变量时,get_variable用于创建变量时,它和tf.Variable的功能是基本等价的。

def get_variable(name, #待创建和待获取变量的名字
                 shape=None,#待创建和待获取变量的形状
                 dtype=None,#待创建和待获取变量的数据类型 默认为float32
                 initializer=None,#新建变量提供的初始化方法
                 regularizer=None,#创建新变量时候提供的正则化方法,若不为空,添加到tf.GraphKeys.REGULARIZATION_LOSSES集合,regularization运算使用。
                 trainable=None,#如果`True`,将变量添加到图形中集合GraphKeys.TRAINABLE_VARIABLES。
                 collections=None,#新的变量被添加到这些集合。默认为`[GraphKeys.GLOBAL_VARIABLES]`。
                 caching_device=None, # 可选设备字符串,描述变量的位置应该被缓存以供阅读。默认为变量的设备。如果不是“None”,则缓存在另一个设备上。典型的用途是缓存在使用变量的Ops所在的设备上进行重复数据删除复制`Switch`和其他条件语句。
                 partitioner=None,
                 validate_shape=True,#如果`False`,允许变量用初始化未知形状的值。如果“True”,默认的形状`initial_value`必须是已知的。
                 use_resource=None,
                 custom_getter=None,
                 constraint=None,
                 synchronization=VariableSynchronization.AUTO,
                 aggregation=VariableAggregation.NONE):

示例代码:

import tensorflow as tf

#error shape应该明确定义
#v1 = tf.get_variable("v1",initializer=tf.constant_initializer([1,2]))
v1 = tf.get_variable("v1",shape=[2,1],initializer=tf.constant_initializer([1,2]))
v2 = tf.Variable([1,2],name="v2")
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    print(sess.run(v1))
    print(sess.run(v2))
    variable_names = [v.name for v in tf.global_variables()]
    print(variable_names)
    variable_names = [v.name for v in tf.trainable_variables()]
    print(variable_names)
    variable_names = [v.name for v in tf.local_variables()]
    print(variable_names)

result:

[[1.]
 [2.]]
[1 2]
['v1:0', 'v2:0']
['v1:0', 'v2:0']
[]

tf.get_variable在使用时要明确指出shape,不然就会抛出错误。使用tf.get_variable创建新变量时,默认情况下与tf.Variable生成的变量无区别,都加入了TRAINABLE_VARIABLES 与 GLOBAL_VARIABLES_VARIABLES这两个集合,如是指定regularizer方法,会加入到相关集合。

初始化的方法有以下几种:

tf.constant_initializer:常量初始化函数
tf.random_normal_initializer:正态分布
tf.truncated_normal_initializer:截取的正态分布
tf.random_uniform_initializer:均匀分布
tf.zeros_initializer:全部是0
tf.ones_initializer:全是1
tf.uniform_unit_scaling_initializer:满足均匀分布,但不影响输出数量级的随机值

import tensorflow as tf

v1 = tf.get_variable(name='v1', shape=[2, 3], initializer=tf.random_normal_initializer(mean=0,stddev=1))
v2 = tf.get_variable(name='v2', shape=[1], initializer=tf.constant_initializer(1))
v3 = tf.get_variable(name='v3', shape=[2, 3], initializer=tf.ones_initializer())
print(v1)
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    print(sess.run(v1))
    print(sess.run(v2))
    print(sess.run(v3))

result:

<tf.Variable 'v1:0' shape=(2, 3) dtype=float32_ref>
[[ 1.2977121  0.7859428  1.0332977]
 [-1.6809679  0.9055225  2.3012352]]
[1.]
[[1. 1. 1.]
 [1. 1. 1.]]

用tf.variable_scope来控制tf.get_variable是获取变量还是新建变量。

tf.variable_scope类初始化函数如下:

def __init__(self,
               name_or_scope,#作用域名称
               default_name=None,
               values=None,
               initializer=None,
               regularizer=None,
               caching_device=None,
               partitioner=None,
               custom_getter=None,
               reuse=None,#是否为获取
               dtype=None,
               use_resource=None,
               constraint=None,
               auxiliary_name_scope=True):

在使用tf.variable_scope变量作用域时,主要使用了name_or_scope, reuse两个参数。如果tf.variable_scope函数使用参数 reuse=None 或者reuse=False创建上下文管理器,tf.get_variable操作将创建新的变量,如果同名的变量已经存在,则tf.get_variable函数将报错。另外,Tensorflow中tf.variable_scope函数是可以嵌套的。如果tf.variable_scope函数使用参数 reuse=True 生成上下文管理器时,该上下文管理器中的所有 tf.get_variable 函数会直接获取已经创建的变量,如果变量不存在,将会报错。

示例代码如下:

import tensorflow as tf

sess = tf.InteractiveSession()
#在名字为foo的命名空间内创建名字为v的变量
with tf.variable_scope("foo"):
    v = tf.get_variable("v",[1],initializer=tf.constant_initializer(1.0))
    print(sess.run(v))
"""
#因为在命名空间foo已经存在名字为v的变量,所有下面的代码将会报错:
#Attempting to use uninitialized value foo/v[[{{node _retval_foo/v_0_0}}]]
with tf.variable_scope("foo"):
    v = tf.get_variable("v",[1])
    sess.run(v)
"""
#在生成上下文管理器时,将参数reuse设置为True。这样tf.get_variable函数将直接获取已经生成的变量
with tf.variable_scope("foo",reuse=True):
    v = tf.get_variable("v",[1])
    print(sess.run(v))   
"""
#将参数reuse设置为True时,tf.variable_scope将只能获取已经创建的变量,因为在命名空间bar中还没有创建变量v,所以下面的代码将会报错:
with tf.variable_scope("bar",reuse=True):
  v = tf.get_variable("v",[1])
   print(sess.run(v))
"""

4.集合


版权声明:本文为u012580657原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。