`tf.random_normal`和`tf.random_normal_initializer`之间的区别是什么?

时间:2018-01-10 07:03:45

标签: variables random tensorflow initialization

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

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将在init之后返回值。

我想了解更多关于如何在合适的时间使用这两个功能的信息。

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

2 个答案:

答案 0 :(得分:3)

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

最基本的答案Tensortf.random_normal_initializer;但RandomNormalTensor# 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

在您的设置中:现在,就您所呼叫的代码而言,没有真正的区别; 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 关键字被重载以接受两者,并且将按照Maxim指示的方式运行。来自the tf/ops/variable_scope docs

<input autofocus="autofocus" data-bind="product.title" data-bind-event-click="Shopify.AddProductFunnel.clickProductTitle()" id="product-name" placeholder="Short Sleeve T-Shirt" class="next-input" size="30" type="text" name="product[title]" style="background-image: url(&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVQ4EaVTO26DQBD1ohQWaS2lg9JybZ+AK7hNwx2oIoVf4UPQ0Lj1FdKktevIpel8AKNUkDcWMxpgSaIEaTVv3sx7uztiTdu2s/98DywOw3Dued4Who/M2aIx5lZV1aEsy0+qiwHELyi+Ytl0PQ69SxAxkWIA4RMRTdNsKE59juMcuZd6xIAFeZ6fGCdJ8kY4y7KAuTRNGd7jyEBXsdOPE3a0QGPsniOnnYMO67LgSQN9T41F2QGrQRRFCwyzoIF2qyBuKKbcOgPXdVeY9rMWgNsjf9ccYesJhk3f5dYT1HX9gR0LLQR30TnjkUEcx2uIuS4RnI+aj6sJR0AM8AaumPaM/rRehyWhXqbFAA9kh3/8/NvHxAYGAsZ/il8IalkCLBfNVAAAAABJRU5ErkJggg==&quot;); background-repeat: no-repeat; background-attachment: scroll; background-size: 16px 18px; background-position: 98% 50%; cursor: auto;">

答案 1 :(得分:2)

tf.random_normal返回填充了随机正常值的指定形状的 tensor 。此外,它还会创建一些计算值的底层操作:

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

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

tf.random_normal_initializerInitializer 实例,在调用时会调用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数组将出现在图中,如果数组很大,这可能是个问题。