【问题标题】:What's the difference between `tf.random_normal` and `tf.random_normal_initializer`?`tf.random_normal` 和 `tf.random_normal_initializer` 有什么区别?
【发布时间】:2018-01-10 07:03:44
【问题描述】:

使用这两个函数似乎得到了相同的结果。

t4 = tf.get_variable('t4', initializer=tf.random_normal((2,), seed=0))
t5 = tf.get_variable('t5', shape=(2,), initializer=tf.random_normal_initializer(seed=0))

我发现里面random_normal_initializer()也用random_normal()

我隐隐约约地意识到它们之间的区别。 random_normal 将返回一个常量张量,但 random_normal_initializer 将在初始化后返回值。

我想更多地了解如何在正确的时间使用这两个功能。

它是否使用random_normal 来初始化一个变量实际上会初始化两次(在初始化变量之后)?换句话说,如果它们之间存在性能问题。

【问题讨论】:

    标签: variables random tensorflow initialization


    【解决方案1】:

    Maxim 对这个问题的回答非常好,但我想回答一个更简单的问题(有几个例子),OP 可能会问:

    最基本的答案tf.random_normalTensor;但是tf.random_normal_initializerRandomNormal不是 Tensor。我认为简单的代码最能阐明这两者之间的区别:

    # Simple examples to clarify tf.random_normal from tf.random_normal_initializer
    tf.reset_default_graph()
    # OP's code
    t4 = tf.get_variable('t4', initializer=tf.random_normal((2,), seed=0))
    t5 = tf.get_variable('t5', shape=(2,), initializer=tf.random_normal_initializer(seed=0))
    # clarifying Tensor vs Initializer outside the context of get_variable.
    t6 = tf.random_normal((2,),seed=0)
    t7 = tf.random_normal_initializer(seed=0)
    # types
    print(type(t6)) # <class 'tensorflow.python.framework.ops.Tensor'>
    print(type(t7)) # <class 'tensorflow.python.ops.init_ops.RandomNormal'>
    # run the graph...
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        # OP's code
        print(sess.run(t4)) #[-0.39915761  2.10443926]
        print(sess.run(t5)) #[-0.39915761  2.10443926]
        # tf.random_normal is a Tensor
        print(sess.run(t6)) #[-0.39915761  2.10443926]
        # tf.random_normal_initializer returns a tf.RandomNormal, not a Tensor or Op, so can't be sess.run()!
        try:
            print(sess.run(t7)) # Exception!
        except:
            print("Exception!")
        # But notice that you don't need to initialize an initializer, just a variable.
        t8 = tf.random_normal_initializer(seed=0)
        t9 = tf.get_variable('t9',shape=(2,), initializer=t8)
        sess.run(t9.initializer)  # still need to initialize the variable
        print(sess.run(t9)) #[-0.39915761  2.10443926]
    

    在您的设置中:现在,就您调用的代码而言,没有真正的区别; initializer 关键字被重载以接受两者,并将按照 Maxim 的指示运行。来自the tf/ops/variable_scope docs

    if initializer is None:
              init, initializing_from_value = self._get_default_initializer(
                  name=name, shape=shape, dtype=dtype)
              if initializing_from_value:
                init_shape = None
              else:
                init_shape = var_shape
            elif callable(initializer):
              init = initializer
              init_shape = var_shape
            elif isinstance(initializer, ops.Tensor):
              init = array_ops.slice(initializer, var_offset, var_shape)
              # Use the dtype of the given tensor.
              dtype = init.dtype.base_dtype
              init_shape = None
            else:
              init = ops.convert_to_tensor(initializer, dtype=dtype)
              init = array_ops.slice(init, var_offset, var_shape)
              init_shape = None
    

    【讨论】:

      【解决方案2】:

      tf.random_normal 返回由随机正常值填充的指定形状的 张量。此外,它还创建了许多底层操作来计算值:

      random_normal/shape
      random_normal/mean
      random_normal/stddev
      random_normal/RandomStandardNormal
      random_normal/mul
      

      在运行时,此张量的连续评估会产生一个新值,但不会添加其他节点。


      tf.random_normal_initializer 是一个Initializer instance,它在调用时调用tf.random_normal。所以tf.random_normal_initializertf.random_normal之间没有太大区别。即使您两次调用 init,它们都不会向图中添加新节点。但两者都在编译中添加了 6 个额外的节点。


      另一种选择(在某些情况下可能更有效)是使用 numpy.random.normal 数组进行初始化,如下所示:

      t1 = tf.Variable(name='t1', initial_value=np.random.normal(size=(2,)))
      

      这种方式不会将random_normal 节点添加到图中,无论是在编译还是在运行时。

      UPD:在这种情况下,tensorflow 添加了 const op .../initial_value,整个 numpy 数组将出现在图中,如果数组很大,这可能会出现问题。

      【讨论】:

      • 请注意,第三种选择,使用numpy.random.normal(),如果尺寸很大,效率会很低,因为它会在尺寸与数组维度的乘积。 tf.random_uniform()/tf.random_uniform_initializer() 方法在图中使用常量空间。 (由于初始化程序通常只在训练开始时运行一次,因此在任何一种情况下运行时影响都可以忽略不计。)
      • 谢谢!我没有在 tensorboard 中检查它,但我没有注意到 tf.get_default_graph().get_operations() 中的任何其他节点 - 我正在专门寻找那里是否有 const op。是initial_value吗?
      • 是的,我认为这将是名为“/initial_value:0”的张量,创建here
      猜你喜欢
      • 2017-06-01
      • 2010-10-02
      • 2011-12-12
      • 2010-09-16
      • 2012-03-14
      • 2012-02-06
      • 2011-02-25
      • 2011-11-22
      • 2015-03-26
      相关资源
      最近更新 更多