菜鸟笔记
提升您的技术认知

sess.run()

函数: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