精析 神经语言模型实验:tf.identity()的作用

先来看TensorFlow中对identity的定义:

####################################################################################################

def identity(input, name=None):  # pylint: disable=redefined-builtin
  r"""Return a tensor with the same shape and contents as input.
  Args:
    input: A `Tensor`.
    name: A name for the operation (optional).
  Returns:
    A `Tensor`. Has the same type as `input`.
  """
  if context.in_graph_mode():
    return gen_array_ops.identity(input, name=name)
  else:
    if context.context().device_name != input.device:
      return input._copy()  # pylint: disable=protected-access
    return input

####################################################################################################

它返回一个和输入的 tensor 大小和数值都一样的 tensor ,类似于 y=x 操作,我们通常可以查到以下使用示例:

import tensorflow as tf
 
g = tf.Graph()
with g.as_default():
    x = tf.Variable(1.0, name='x')
    x_plus_1 = tf.assign_add(x, 1, name='x_plus')
 
    with tf.control_dependencies([x_plus_1]):
        y = x
        z=tf.identity(x,name='z_added')
 
    init = tf.global_variables_initializer()
 
    with tf.Session() as sess:
        sess.run(init)
        for i in range(5):
            print(sess.run(z))
            # 输出 2,3,4,5,6
 
        # 如果改为输出 print(sess.run(y)) ,则结果为 1,1,1,1,1
但是所有的博客资料都没有详细说明为什么会这样,以及在 Graph 的构建中,这个方法应该怎么使用。

起初一看,这个方法好像并没有什么用,只是把输入原样复制了一遍,但是实际上,tf.identity在计算图内部创建了两个节点,send / recv节点,用来发送和接受两个变量,如果两个变量在不同的设备上,比如 CPU 和 GPU,那么将会复制变量,如果在一个设备上,将会只是一个引用。

之所以会出现上面代码的情况,就是因为 y = x 并没有在计算图中占有一席之地,所以每次sess.run(y) 的时候都没有进行它的上一步 tf.control_dependencies 的操作,而 z 的计算则不同,它是计算图内部的节点,所以每次sess.run(z) 的时候都会进行 tf.control_dependencies 的操作,所以它输出的值每次都会更新; 并且,我们可以想见,如果我们同时输出 y 和 z,那么 y 的值也会同步更新为2,3,4,5,6。

我们打印该计算图内部所有的 OP,可以看到也是没有 y 这样一个计算节点存在的:

[<tf.Operation 'x/initial_value' type=Const>, <tf.Operation 'x' type=VariableV2>, <tf.Operation 'x/Assign' type=Assign>, <tf.Operation 'x/read' type=Identity>, <tf.Operation 'x_plus/value' type=Const>, <tf.Operation 'x_plus' type=AssignAdd>, <tf.Operation 'z_added' type=Identity>, <tf.Operation 'init' type=NoOp>]
那么在什么时候使用这个方法呢?

它是通过在计算图内部创建 send / recv节点来引用或复制变量的,最主要的用途就是更好的控制在不同设备间传递变量的值;

另外,它还有一种常见的用途,就是用来作为一个虚拟节点来控制流程操作,比如我们希望强制先执行loss_averages_op或updata_op,然后更新相关变量。这可以实现为:

with tf.control_dependencies([loss_averages_op]):
  total_loss = tf.identity(total_loss)
或者:

with tf.control_dependencies([updata_op]):
  train_tensor = tf.identity(total_loss,name='train_op')
在这里,tf.identity除了在执行 loss_averages_op之后标记total_loss张量被执行之外没有做任何有用的事情。
--------------------- 
作者:周卫林 
来源:CSDN 
原文:https://blog.csdn.net/qq_23981335/article/details/81361748 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值