tensorflow里面的变量的定义必须使用xxx = tf.Variable(),才能使xxx成为一个变量,它的作用就是保存和更新神经网络中的参数,对Variable的设置好之后,就规定了它的名字和形状,变量的初始值可以设置为随机数,常数或者是通过其他变量的初始值计算得到。
import tensorflow as tf
state = tf.Variable(0,name='counter')
one = tf.constant(1)
new_value = tf.add(state,one)
update = tf.assign(state,new_value)
init = tf.global_variables_initializer() #must have if define variable
with tf.Session() as sess:
sess.run(init)
for _ in range(3):
sess.run(update)
print(sess.run(state))
这是一个小例子,这个例子里面对state规定了初始值和名字,之后的更新update就是所说必须利用assign来对他的值进行改动。
然后要使这些变量的运行,或者说激活,那么就得利用这一句
init = tf.global_variables_initializer()
之前不这么用,之前是tf.initialize_all_variables(),可能在旧的教材或者视频资料里面会看到这样子,得改过来。反正设置了变量就得对变量进行激活,不过这还不算激活,真正的激活是在后面的sess.run(init),这之后才算真正的激活。
一个神经网络的实例:
import tensorflow as tf
#声明w1、w2两个变量。这里还通过seed参数设定了随机种子
#这样可以保证每次运行得到的结果都是意义的。
w1 = tf.Variable(tf.random_normal((2,3),stddev = 1,seed = 1))
w2 = tf.Variable(tf.random_normal((3,1),stddev = 1,seed = 1))
#暂时将输入的特征向量定义为一个常量值,这里的x是一个1*2的矩阵
x = tf.constant([[0.7,0.9]])
#通过前向传播算法获得神经网络的输出
a = tf.matmul(x,w1)
y = tf.matmul(a,w2)
sess = tf.Session()
#这里不能直接通过sess.run(y)来获取y的取值
#因为这里的w1,w2都没有运行初始化过程,以下两行分别初始化了w1,w2两个变量
sess.run(w1.initializer) #初始化w1
sess.run(w2.initializer) #初始化w2
#输出[[3.957578]]
print(sess.run(y))
sess.close()
从整个程序来看,首先是对w1,w2的定义确定神经网络的前向传播过程并得到中间结果a和最后答案y。这也是Tensorflow程序的第一步,定义计算图中所有的计算。但是这些计算在第一步中不会真正地运行,当需要运行这些计算时,需要进行第二部,就是会话部分。但是会话部分的运行必须对前面声明的变量进行初始化,这里一个一个地进行初始化,当然也可以用上面的方法对所有的变量都初始化。
Tensorflow的核心概念是张量,那么变量和张量的关系是什么呢:在tensorflow中变量声明函数tf.Variable是一个运算,这个运算的输出结果是一个张量,但是这个张量也可以看作一个变量。所以变量只是一种特殊的张量。
变量的维度和类型在定义好之后名义上是不可改动的,但是通过assign是可以改变变量的维度,但是变量的类型在定义好之后就确定了,无法更改,维度的更改需要通过设置参数validate_shape = False
w1 = tf.Variable(tf.random_normal([2,3],stddev = 1),name = "w1")
w2 = tf.Variable(tf.random_normal([2,2],stddev = 1),name = "w2")
#下面这句话会报维度不匹配的错误:
#ValueError:Dimension 1 in both shapes must be equal,but are 3 and 2
#for 'Assign_1' (op: 'Assign') with input shapes: [2,3], [2,2].
tf.assign(w1,w2)
#这一句被成功执行
tf.assign(w1,w2, validate_shape = False)
虽然tensorflow支持更改变量的维度,但是在实践中很少见