【问题解决】Tensorflow中run究竟运行了哪些节点?

我们都知道Tensorflow中是先定义图结构,再驱动节点进行运算。当构建完graph图后,需要在一个session会话中启动图,可以自定义创建一个对话,也可以使用默认对话。

其中典型的两个驱动节点的方法是session.run()tensor.eval(),调用tensor.eval()相当于调用session().run(tensor)。二者的区别在这篇文章中有了较为详细的解释:

下面针对run(self, fetches, feed_dict=None, options=None, run_metadata=None) 方法做出详细介绍:
其中常用的fetches和feed_dict就是常用的传入参数。fetches主要指从计算图中取回计算结果进行放回的那些placeholder和变量,而feed_dict则是将对应的数据传入计算图中占位符,它是字典数据结构只在调用方法内有效。

其中需要注意的一点是tensorflow并不是计算了整个图,只是计算了与想要fetch的值相关的部分,这一点在很多答案中给出了错误的解答,可以看一下官方注释,是 “running the necessary graph fragment”:

    '''
    This method runs one "step" of TensorFlow computation, by
    running the necessary graph fragment to execute every `Operation`
    and evaluate every `Tensor` in `fetches`, substituting the values in
    `feed_dict` for the corresponding input values.
    '''

这种类似预“用到什么才去计算什么”的感觉非常像拉式,这也说明了为什么定义了一个完整的网络,但有的时候传入X和y进行训练,有的时候只传入X来进行预测,因为没有用到相关参数的图节点,所以无需传入。

但是,其中有个例外,就是网络本身的层参数,看以下代码:

X = tf.placeholder(tf.float32, shape=[None, n_inputs])
cross_entropy_loss = NetWork_loss(X)
grads_and_vars = optimizer.compute_gradients(cross_entropy_loss)
# print(grads_and_vars)
gradients = [grad for grad, variable in grads_and_vars]
gradient_placeholders = []
grads_and_vars_feed = []
for grad, variable in grads_and_vars:
    gradient_placeholder = tf.placeholder(tf.float32)
    # gradient_placeholder = tf.placeholder(tf.float32, shape=grad.get_shape())
    gradient_placeholders.append(gradient_placeholder)
    grads_and_vars_feed.append((gradient_placeholder, variable))
    # training_op = optimizer.apply_gradients(grads_and_vars_feed)
training_op = grads_and_vars_feed

这个网络的定义将计算出的损失,也就是cross_entropy_loss传入优化器optimizer,进行梯度的计算。
这个梯度计算的方法会返回一个个的元组,分别代表的就是当层的梯度和参数。
后面那一大段是为了进行梯度的更新,不过这里使用的是 “策略梯度”,也就是强化学习中需要它执行过了若干步后再更新梯度。
这里的更新的梯度就不再是神经网络中直接计算出的导数了,而是和你强化学习的reward挂钩,不再细讲,总之就是通过一个循环,把每层计算出的梯度传出,再传入根据自己的策略计算出的新的梯度。

重点来了,当我使用下面这段代码进行执行的时候:

with tf.Session() as sess:
    init.run()
    feed_dict = {}
    for var_index, gradient_placeholder in enumerate(gradient_placeholders):
        feed_dict[gradient_placeholder] = [9.]
    a = sess.run(training_op, feed_dict=feed_dict)

居然没报错!我们明明看到要计算的 training_op 需要的是grads_and_vars_feed,而后面这个参数用到了variable,也就是最终需要的还是 cross_entropy_loss,这个loss又是根据传入的X计算出来的
那追本溯源下去,这个training_op用到了两个需要填充的地方,而我们仅仅传入了梯度,凭什么不传入X就可以执行?

经过我的一番探索,发现把variable变成grad就会报错需要传入X,可这两个明明是一个循环取出来的。

经过一步步断点调试,终于破案了,原来这个 variable 是网络参数,是定义的图结构中的一些成员变量,也就是在执行 init.run() 的时候已经被初始化了~图结构中会直接把这样的变量标记为“已计算”。而grad则需要通过X,也就是上面正常逻辑回溯一步一步计算过来,所以没传入X的时候这个变量会被标记为“未计算”,那在拉取的时候才会回溯到X。

所以tensorflow并不是计算了整个图,只是计算了与想要fetch的值相关的部分,而这个“相关的部分”指的是还没被标记为“已计算的部分”,尤其是对于网络参数这类“固有的”,虽然表面上看起来是通过一个个的函数得出,实际上则不然,很有误导性。

### 回答1: 下面是 TensorFlow 使用 session.run() 训练和预测的代码示例: 训练代码: ``` # 创建 TensorFlow session with tf.Session() as sess: # 初始化变量 sess.run(tf.global_variables_initializer()) for i in range(num_steps): # 获取训练数据 x_batch, y_batch = get_next_batch(batch_size) # 运行训练操作 sess.run(train_op, feed_dict={x: x_batch, y: y_batch}) if i % 100 == 0: # 计算损失 loss_value = sess.run(loss, feed_dict={x: x_batch, y: y_batch}) print("Step: %d, Loss: %f" % (i, loss_value)) ``` 预测代码: ``` # 创建 TensorFlow session with tf.Session() as sess: # 加载模型参数 saver.restore(sess, "path/to/model.ckpt") # 获取预测数据 x_test = get_test_data() # 运行预测操作 predictions = sess.run(pred, feed_dict={x: x_test}) ``` 注意:需要对于训练和预测的部分要先定义x,y,train_op,loss,pred,saver等变量或者操作 ### 回答2: 在TensorFlow,sess.run()是一个非常重要的函数,用于执行计算图节点。训练和预测过程都会涉及到sess.run()函数的使用。 在训练代码,我们首先需要定义一个优化器(如AdamOptimizer),并使用它来最小化我们的损失函数。然后,我们会创建一个会话(session),并使用sess.run()函数来初始化变量。接下来,我们会迭代训练数据,每次迭代都会使用sess.run()函数来计算一个或多个节点的值,并将其用于更新模型参数。最后,我们可以使用sess.run()函数来计算训练过程的评估指标。 在预测代码,我们也会创建一个会话,并使用sess.run()函数来初始化变量。接着,我们会将待预测的数据输入到模型,并使用sess.run()函数来计算输出节点的值。对于分类问题,我们可以通过sess.run()函数将输出节点的值转化为概率分布或预测结果。对于回归问题,我们可以直接使用sess.run()函数得到预测的结果。 需要注意的是,在sess.run()函数,我们可以指定要计算的节点,也可以同时计算多个节点的值。当使用sess.run()函数计算多个节点的值时,TensorFlow会自动处理节点之间的依赖关系,并按照正确的顺序计算它们。 总结起来,sess.run()函数在TensorFlow用于执行计算图节点,训练过程可以用来计算损失函数和评估指标,预测过程可以用来计算输出节点的值并进行结果的转化。 ### 回答3: 在使用tensorflow进行训练和预测时,我们通常会使用`sess.run()`函数来执行相应的操作。 在进行训练时,`sess.run()`函数通常会用来执行训练操作,例如`sess.run(train_op)`,其`train_op`表示训练操作,可以是优化器的`minimize`函数或其他自定义的训练操作。当执行`sess.run(train_op)`时,tensorflow会自动计算并更新变量的值,以使得模型能够逐渐收敛到最优解。这样,我们就可以利用`sess.run()`来进行模型的训练,通过多次调用这个函数,逐渐迭代参数,提升模型的性能。 而在进行预测时,`sess.run()`函数通常会用来执行模型的预测操作,例如`sess.run(y_pred, feed_dict={x: input_data})`,其`y_pred`表示模型的预测结果,`x`表示输入数据的占位符,`input_data`表示输入数据的实际值。通过在`feed_dict`参数提供实际的输入数据,`sess.run()`会根据模型的计算图和输入数据,运行并返回预测结果。这样,我们就可以利用`sess.run()`来获取模型的预测结果,并根据需要进行进一步的处理和分析。 总的来说,`sess.run()`是tensorflow非常重要的一个函数,通过它我们可以执行模型的训练操作和预测操作,根据需要获取模型的输出结果,并对其进行进一步处理。在使用`sess.run()`时,我们通常需要明确指定待执行的操作和提供相应的输入数据,以使得tensorflow能够正确地执行计算图定义的操作,获得所需的结果。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值