(一)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.集合