函数:run(fetches, feed_dict=none, options=none, run_metadata=none)
当构建完图后,需要在一个session会话中启动图,第一步是创建一个session对象。
为了取回(fetch)操作的输出内容, 可以在使用 session 对象的 run()调用执行图时,传入一些 tensor, 这些 tensor 会帮助你取回结果。
在python语言中,返回的tensor是numpy ndarray对象。
import tensorflow as tf
#创建一个变量。在默认的图中创建节点,这个节点是一个变量,命名为“counter”
state = tf.variable(0, name="counter")
#创建一个常量
one = tf.constant(1)
#创建一个op。对常量与变量进行简单的加法操作,这点需要说明的是: 在tensoorflow中,
#所有的操作op和变量都视为节点,tf.add() 的意思就是在tf的默认图中添加一个op,这个op是用来做加法操作的。
new_value = tf.add(state,one)
#赋值操作。将new_value的值赋值给update变量
update = tf.assign(state,new_value)
#此处用于初始化变量。但是这句话仍然不会立即执行。需要通过sess来将数据流动起来 。如果有variable,一定需要写这句话
init = tf.initialize_all_variables()
#启动图,运行op
with tf.session() as sess:
#对变量进行初始化,真正的赋值操作
sess.run(init)
#循环3次,并且打印输出。
for _ in range(3):
sess.run(update)
# 打印变量时也需要用sess.run
print(sess.run(state))
1.执行sess.run()时,tensorflow是否计算了整个图
我们在编写代码的时候,总是要先定义好整个图,然后才调用sess.run()。那么调用sess.run()的时候,程序是否执行了整个图
import tensorflow as tf
state = tf.variable(0.0,dtype=tf.float32)
one = tf.constant(1.0,dtype=tf.float32)
new_val = tf.add(state, one)
update = tf.assign(state, new_val) #返回tensor, 值为new_val
update2 = tf.assign(state, 10000) #没有fetch,便没有执行
init = tf.initialize_all_variables()
with tf.session() as sess:
sess.run(init)
for _ in range(3):
print sess.run(update)
我们仅仅是fetch “update”,输出是1.0 , 2.0, 3.0,可以看出,tensorflow并没有计算整个图,只是计算了与想要fetch 的值相关的部分。
2.sess.run() 中的feed_dict
features_, labels_, indexs_ = sess.run([features, labels, indexs])
feed_dict参数的作用是替换图中的某个tensor的值或设置graph的输入值。
(1)是否需要进行传参feed_dict
需要看features, labels, indexs这3个变量的产生是否存在于“一个需要传参的函数中”,如果产生features, labels, indexs这3个变量的函数的形式像下面这样
def xxx():
x = tf.placeholder(dtype=tf.float32, shape=([50,93]))
y = tf.placeholder(dtype=tf.int32, shape=([50]))
z = tf.placeholder(dtype=tf.int32, shape=([50]))
...
return features, labels, indexs
features, labels, indexs = xxx()
那么这时候features_, labels_, indexs_ = sess.run([features, labels, indexs]),就需要写成下面这样
features_, labels_, indexs_ = sess.run([features, labels, indexs], feed_dict={x:features_, y:labels_, z:indexs_})
并且要注意feed_dict不接受tensor格式的数据,所以features_需要是普通格式,比如numpy,但是传参进去后,会自动进行类型的转化,在xxx()函数中,他们就变成tensor格式
(2)是否执行一次sess.run函数,代码里的“数据迭代生成器”就会更新一次batch
那要取决于sess.run函数里面的参数是否与“数据迭代生成器”有关
假如features, labels, indexs = input_fn(),input_fn()函数每执行一次,就生成一个batch的数据,那么这种sess.run([features, labels, indexs])每每执行一次 就会更新一个batch的数据
举个反面的例子,也就是即使执行了2000次sess.run(),也不会更新batch的数据
pred_new_2 = sess.run([pred_new_1], feed_dict={x:features_, y:labels_, z:indexs_})。这里pred_new_1的产生函数 就必须要传进来3个参数,所以有feed_dict传参
当前pred_new_1并不是和“数据迭代生成器”有关,而是另外一个函数的返回结果,那么就符合我的举例
(3)sess.run()可以将tensor格式转成numpy格式
可以用来很方便的将一些tensor格式的数据,进行数据具体内容查看,也就是将tensor格式转成numpy格式,上面的所有例子都是这种作用
(4)feed 只在调用它的方法内有效
我们都知道feed_dict的作用是给使用placeholder创建出来的tensor赋值。其实,他的作用更加广泛:feed 使用一个值临时替换一个 op 的输出结果. 你可以提供 feed 数据作为 run() 调用的参数. feed 只在调用它的方法内有效, 方法结束, feed 就会消失。
import tensorflow as tf
y = tf.variable(1)
b = tf.identity(y)
with tf.session() as sess:
tf.global_variables_initializer().run()
print(sess.run(b,feed_dict={y:3})) #使用3 替换掉
#tf.variable(1)的输出结果,所以打印出来3
#feed_dict{y.name:3} 和上面写法等价
print(sess.run(b)) #由于feed只在调用他的方法范围内有效,所以这个打印的结果是 1
3.用sess.run()有两种情况:
(1)想要获取某个变量的时候:
(2)执行某种操作的时候,这个操作不是一个变量,没有值,如下图n这个更新操作,还包括神经网络训练的时候的optimizer:
4.其他:
(1)tensorflow与我们正常的编程思维略有不同:tensorflow中的语句不会立即执行;而是等到开启会话session的时候,才会执行session.run()中的语句。如果run中涉及到其他的节点,也会执行到。
(2)tesorflow模型中的所有的节点都是可以视为运算操作op或tensor