1. 程式人生 > >tf.control_dependencies與tf.identity組合詳解

tf.control_dependencies與tf.identity組合詳解

引言

我們在實現神經網路的時候經常會看到tf.control_dependencies的使用,但是這個函式究竟是什麼作用,我們應該在什麼情況下使用呢?今天我們就來一探究竟。

理解

其實從字面上看,control_dependencies 是控制依賴的意思,我們可以大致推測出來,這個函式應該使用來控制就算圖節點之間的依賴的。其實正是如此,tf.control_dependencies()是用來控制計算流圖的,給圖中的某些節點指定計算的順序。

原型分析

tf.control_dependencies(self, control_inputs)
 arguments:control_inputs: A list of `Operation` or `Tensor` objects 
which must be executed or computed before running the operations 
defined in the context. (注意這裡control_inputs是list)
return:  A context manager that specifies control dependencies 
for all operations constructed within the context.

通過以上的解釋,我們可以知道,該函式接受的引數control_inputs,是Operation或者Tensor構成的list。返回的是一個上下文管理器,該上下文管理器用來控制在該上下文中的操作的依賴。也就是說,上下文管理器下定義的操作是依賴control_inputs中的操作的,control_dependencies用來控制control_inputs中操作執行後,才執行上下文管理器中定義的操作。

例子

如果我們想要確保獲取更新後的引數,name我們可以這樣組織我們的程式碼。

opt = tf.train.Optimizer().minize(loss)

with tf.control_dependencies([opt]): #先執行opt
  updated_weight = tf.identity(weight)  #再執行該操作

with tf.Session() as sess:
  tf.global_variables_initializer().run()
  sess.run(updated_weight, feed_dict={...}) # 這樣每次得到的都是更新後的weight

可以看到以上的例子用到了,tf.identity(),至於為什麼要使用tf.identity(),我在下一篇部落格:名字中有詳細的解釋,不懂的可以移步瞭解。

control_flow_ops.with_dependencies

除了常用tf.control_dependencies()我們還會看到,control_flow_ops.with_dependencies(),其實連個函式都可以實現依賴的控制,只是實現的方式不太一樣。

with_dependencies(dependencies, output_tensor, name=None)
Produces the content of `output_tensor` only after `dependencies`.
所有的依賴操作完成後,計算output_tensor並返回
  In some cases, a user may want the output of an operation to be
  consumed externally only after some other dependencies have run
  first. This function ensures returns `output_tensor`, but only after all
  operations in `dependencies` have run. Note that this means that there is
  no guarantee that `output_tensor` will be evaluated after any `dependencies`
  have run.

  See also @{tf.tuple$tuple} and @{tf.group$group}.

  Args:
    dependencies: Iterable of operations to run before this op finishes.
    output_tensor: A `Tensor` or `IndexedSlices` that will be returned.
    name: (Optional) A name for this operation.

  Returns:
    Same as `output_tensor`.

  Raises:
    TypeError: if `output_tensor` is not a `Tensor` or `IndexedSlices`. 

 

參考連結:

http://blog.csdn.net/m0_37041325/article/details/76943364

https://stackoverflow.com/questions/34877523/in-tensorflow-what-is-tf-identity-used-for

tf.control_dependencies(self, control_inputs)

arguments:control_inputs: A list of `Operation` or `Tensor` objects which must be executed or computed before running the operations defined in the context. (注意這裡control_inputs是list)
return:  A context manager that specifies control dependencies for all operations constructed within the context.(返回所有在環境中的控制依賴的上下文管理器)

該方法可以控制操作(op)執行的順序,不能為tensor

tf.identity(input, name=None) 

Args:
input: A Tensor.
name: A name for the operation (optional).

Returns:A tensor with the same shape and contents as the input tensor or value.

源於StackOverFlow有個關於兩者使用的例子:

x = tf.Variable(0.0)
x_plus_1 = tf.assign_add(x, 1)

with tf.control_dependencies([x_plus_1]):
    y = x
init = tf.global_variables_initializer()

with tf.Session() as session:
    init.run()
    for i in range(5):
        print(y.eval())


針對此程式,輸出結果為:0.0 0.0 0.0 0.0 0.0
輸出變數x,結果也為0.0

說明x_plus_1操作並沒有被執行,我認為雖然tf.control_dependencies引數中的op列表會在with包含的操作op執行之前先執行,但是y=x這個語句並不是一個op,而是一個tensor,所以執行y=x時,並不會執行tf.control_dependencies引數中的操作op。

所以可以將  y=x 修改為 y=tf.identity(x),此時這個語句就是一個操作op,要先執行tf.control_dependencies引數中的op列表,再執行y=tf.identity(x)操作,最終輸出結果為1.0 2.0 3.0 4.0 5.0,最終變數x的結果也為5.0,完整程式如下:

x = tf.Variable(0.0)
x_plus_1 = tf.assign_add(x, 1)

with tf.control_dependencies([x_plus_1]):
    y = tf.identity(x)
init = tf.global_variables_initializer()
with tf.Session() as session:
    init.run()
    for i in range(5):
        print(y.eval())
    print(x.eval())