• tf.identity 与 tf.control_dependencies


    先来看看官方解释

    def identity(input, name=None):  # pylint: disable=redefined-builtin
      r"""Return a tensor with the same shape and contents as input.

    返回一个和输入 相同形状和内容 的 Tensor;

    我们来分析一下:

    1. 形状和内容都相同,那不就是等于吗?为什么还要这个函数呢?

    2. 返回一个 Tensor,说明 tf.identity 是一个 op,因为 Tensor 是 op 的输入输出;

    3. 也就是说,tf.identity 接受任意的 input,都强制输出 Tensor;

    下面我们来验证一下

    首先,以 constant 为例

    ##### constant 本身是个操作, 它的 = 也是操作
    c = tf.constant(1.)
    print(c)        # Tensor("Const:0", shape=(), dtype=float32)
    d = tf.identity(c, name='d')
    print(d)        # Tensor("d:0", shape=(), dtype=float32)
    e = c
    print(e)        # Tensor("Const:0", shape=(), dtype=float32)

    tf.identity 和 = 没什么差别,只是加了个名字,然后我们可以不加的啊,不加名字,一模一样

    接着,以 Variable 为例

    ##### Variable 本身不是操作,它的 = 不是操作
    v = tf.Variable(2.)
    print(v)        # <tf.Variable 'Variable:0' shape=() dtype=float32_ref>
    no_name = tf.identity(v) print(no_name) # Tensor("Identity:0", shape=(), dtype=float32) x = tf.identity(v, name='x') print(x) # Tensor("x:0", shape=(), dtype=float32)
    y = v print(y) # <tf.Variable 'Variable:0' shape=() dtype=float32_ref>

    tf.identity 是个 op,而 = 不是 op;

    此时,我们可以得出这样的结论:

    tf.identity 是一个操作,把任意输入强制转换成 Tensor,如果 输入就是 Tensor,那他就等价于 =;

    而 = 不是操作,只是内存拷贝;

    然而这玩意有什么用呢? 

    这就要提到另一个方法 tf.control_dependencies,它只对其内部的操作起作用,

    我们以一个累加的例子来说明

    ##### test1
    x = tf.Variable(1.0)
    print(x)                            # <tf.Variable 'Variable:0' shape=() dtype=float32_ref>
    x_plus_1 = tf.assign_add(x, 1)      ### 返回一个op
    
    # control_dependencies的意义是:
    # 在执行with包含的内容(y = x)前,先执行 control_dependencies 参数中的内容(x_plus_1),这里的解释不准确,先接着看。。。
    with tf.control_dependencies([x_plus_1]):
        y = x
        print(y)            # <tf.Variable 'Variable_6:0' shape=() dtype=float32_ref>       ### y 只是个变量,不是 op
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init)
        for i in range(5):
            print(sess.run(y))      # 1 1 1 1 1

    先执行 with 包含的内容的前提是 ,该内容是个 操作,然而 y=x 不是操作,那么 control_dependencies 的参数 x_plus_1 没有执行,x 就还是 1, y=x 自然也是1,故输出 5 个 1

    修改如下

    ##### test2
    x = tf.Variable(1.0)
    x_plus_1 = tf.assign_add(x, 1)
    
    with tf.control_dependencies([x_plus_1]):
        y = x + 0.0
        print(y)        # Tensor("add:0", shape=(), dtype=float32)      ### y 变成 add op
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init)
        for i in range(5):
            print(sess.run(y))      # 2 3 4 5 6

    with 内是个操作,x_plus_1 先执行,输出符合预期;

    只是这样写有点别扭,y=x 和 y=x+0 产生了截然不同的结果;

    继续修改

    ##### test3
    x = tf.Variable(1.0)
    x_plus_1 = tf.assign_add(x, 1)
    
    with tf.control_dependencies([x_plus_1]):
        y = tf.identity(x, name='x')
        print(y)                # Tensor("x:0", shape=(), dtype=float32)        ### y 变成 add op
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init)
        for i in range(5):
            print(sess.run(y))          # 2 3 4 5 6

    tf.identity 登场了,他把 y=x 变成了一个 操作,结果符合预期;

    当然也可以这样写

    ##### test4
    x = tf.Variable(1.0)
    x = tf.assign_add(x, 1)
    
    with tf.control_dependencies([x]):
        y = x                   ### 等价于 y = tf.assign_add(x, 1)
        print(y)                # Tensor("AssignAdd_3:0", shape=(), dtype=float32_ref)
    init = tf.initialize_all_variables()
    with tf.Session() as session:
        init.run()
        for i in range(5):
            print(y.eval())     # 2 3 4 5 6         ### 相当于sess.run(y)

    总结:对于 control_dependencies 这个管理器,只有当里面的操作是一个 op 时,才会生效,也就是先执行传入的参数 op,再执行里面的 op;

    而 y=x 仅仅是 一个简单赋值,不是 op,在 graph 中不会形成一个节点,这样该管理器就失效了;

    tf.identity 是返回一个一模一样新的 tensor 的 op,这会增加一个新节点到 gragh 中,这时 control_dependencies 就会生效了

    参考资料:

    https://blog.csdn.net/hu_guan_jie/article/details/78495297

    https://yq.aliyun.com/articles/487737

    https://www.360kuai.com/pc/935e0f65c4a884856?cota=4&kuai_so=1&tj_url=so_rec&sign=360_57c3bbd1&refer_scene=so_1

  • 相关阅读:
    洛谷P1434 滑雪
    P1855 榨取kkksc03
    C#中将表示颜色的string转换成Color
    DevExpress的对话框XtraMessageBox的使用
    Winform中怎样根据Name获取同窗体的控件
    Winform中使用代码编写Button按钮的点击事件
    SqlServer 2014还原数据库时提示:无法在已有的""上还原文件,请重新发出RESTORE语句,用WITH REPLACE来覆盖原先存在的文件
    SqlServer 2014 还原数据库时提示:操作系统返回了错误5,,拒绝访问
    Windows 7 上怎样打开SQL Server 配置管理器
    SqlServer2014怎样还原数据库
  • 原文地址:https://www.cnblogs.com/yanshw/p/12371034.html
Copyright © 2020-2023  润新知