训练模型时,需要使用变量(Variables)保存和更新参数。Variables是包含张量(tensor)的内存缓冲。变量必须要先被初始化(initialize),而且可以在训练时和训练后保存(save)到磁盘中。之后可以再恢复(restore)保存的变量值来训练和测试模型。
- 1、变量op能够持久化保存,普通张量不行
- 2、定义一个变量时,在会话中必须初始化
- 3、name参数:在tensorboard使用时显示名字,可以让相同op名字进行区分
变量的创建
创建当一个变量时,将你一个张量作为初始值传入构造函数Variable()。TensorFlow提供了一系列操作符来初始化张量,值初始的英文常量或是随机值。像任何一样Tensor,创建的变量Variable()可以用作图中其他操作的输入。此外,为Tensor该类重载的所有运算符都被转载到变量中,因此您也可以通过对变量进行算术来将节点添加到图形中。
x = tf.Variable(5.0,name="x")
weights = tf.Variable(tf.random_normal([784, 200], stddev=0.35),name="weights")
biases = tf.Variable(tf.zeros([200]), name="biases")
调用tf.Variable()向图中添加了以下几个操作:
- 一个variable op保存变量值。
- 初始化器op将变量设置为其初始值。这实际上是一个tf.assign操作。
- 初始值的ops,例如 示例中biases变量的zeros op 也被添加到图中。
变量的初始化
- 变量的初始化必须在模型的其它操作运行之前先明确地完成。最简单的方法就是添加一个给所有变量初始化的操作,并在使用模型之前首先运行那个操作。最常见的初始化模式是使用便利函数 initialize_all_variables()将Op添加到初始化所有变量的图形中。
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init_op)
- 还可以通过运行其初始化函数op来初始化变量,从保存文件还原变量,或者简单地运行assign向变量分配值的Op。实际上,变量初始化器op只是一个assignOp,它将变量的初始值赋给变量本身。assign是一个方法,后面方法的时候会提到
with tf.Session() as sess:
sess.run(w.initializer)
- 还可以通过另一个变量赋值
你有时候会需要用另一个变量的初始化值给当前变量初始化,由于tf.global_variables_initializer()初始化所有变量,所以需要注意这个方法的使用。就是将已初始化的变量的值赋值给另一个新变量!
weights = tf.Variable(tf.random_normal([784, 200], stddev=0.35),name="weights")
w2 = tf.Variable(weights.initialized_value(), name="w2")
w_twice = tf.Variable(weights.initialized_value() * 0.2, name="w_twice")
所有变量都会自动收集到创建它们的图形中。默认情况下,构造函数将新变量添加到图形集GraphKeys.GLOBAL_VARIABLES。方便函数 global_variables()返回该集合的内容。
变量的属性
Variable.name:返回变量的名字
weights = tf.Variable(tf.random_normal([784, 200], stddev=0.35),name="weights")
print(weights.name)
Variable.op:返回op
weights = tf.Variable(tf.random_normal([784, 200], stddev=0.35))
print(weights.op)
变量的方法
- assign:为变量分配一个新值。
w = tf.Variable(5.0,name="x")
w.assign(w + 1.0)
- eval:在会话中,计算并返回此变量的值。这不是一个图形构造方法,它不会向图形添加操作。方便打印结果。eval的作用和sess.run的作用相似
v = tf.Variable([1, 2])
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
# 指定会话
print(v.eval(sess))
# 使用默认会话
print(v.eval())
占位符--tf.placeholder()
只是一个占位符,占位符并没有初始值,只是在必要时分配内存,
在TensorFlow中,数据并不会保存为 integer, float, 或 string. 这些值都封装在 tensor 对象中,因此不能直接定义并使用一个变量例如x,因为你设计的模型可能需要受不同的数据集与不同的参数。所以TF使用placeholder()来传递一个tensor到session.run()中,并与feed_dict{}结合一起使用。
feed_dict{}是一个字典,在字典中需要给每一个用到的占位符取值。在训练神经网络时,需要大批量的训练样,如果每一次迭代选取的数据都需要常量表示,那么TensorFlow的计算图会非常大。因为每计算一个常量 ,TensorFlow会增加一个结点,所以说,拥有几百万次迭代的神经网络会拥有庞大的计算图,如果使用占位符的话,就可以很好的解决这一点,它只会拥有占位符这一个结点。
import tensorflow as tf
import numpy as np
x = tf.placeholder(tf.string)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
output = sess.run(x, feed_dict={x: 'Hello World'})
print(output)
变量的作用域
tensorflow提供了变量作用域和共享变量这样的概念,有几个重要的作用。
- 让模型代码更加清晰,作用分明
变量作用域
通过tf.variable_scope(<scope_name>)创建指定名字的变量作用域
with tf.variable_scope("itcast"):
print("----")
加上with语句就可以在整个itcast变量作用域下就行操作。
- 嵌套使用:变量作用域可以嵌套使用
with tf.variable_scope("itcast") as itcast:
with tf.variable_scope("python") as python:
print("----")
变量作用域下的变量
在同一个变量作用域下,如果定义了两个相同名称的变量(这里先用tf.Variable())会怎么样呢?
with tf.variable_scope("itcast") as scope:
a = tf.Variable([1.0,2.0],name="a")
b = tf.Variable([2.0,3.0],name="a")
我们通过tensoflow提供的计算图界面观察,如下图所示
我们发现尽管在代码中取了同样的名字,其实tensorflow并没有当作同一个,而是另外又增加了一个a_1,来表示b的图。
变量范围
当每次在一个变量作用域中创建变量的时候,会在变量的name前面加上变量作用域的名称。
with tf.variable_scope("itcast"):
a = tf.Variable(1.0,name="a")
b = tf.get_variable("b", [1])
print(a.name,b.name)
结果为:
(u'itcast/a:0', u'itcast/b:0')
对于嵌套的变量作用域来说
with tf.variable_scope("itcast"):
with tf.variable_scope("python"):
python3 = tf.get_variable("python3", [1])
assert python3.name == "itcast/python/python3:0"
var2 = tf.get_variable("var",[3,4],initializer=tf.constant_initializer(0.0))