使用这两个函数似乎得到了相同的结果。
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
初始化变量实际上会初始化两次(在初始化变量之后)?换句话说,如果它们之间存在性能问题。
答案 0 :(得分:3)
Maxim对这个问题的回答非常好,但我想回答OP可能会问的一个稍微简单的问题(有几个例子):
最基本的答案:Tensor
是tf.random_normal_initializer
;但RandomNormal
是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
在您的设置中:现在,就您所呼叫的代码而言,没有真正的区别; 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("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVQ4EaVTO26DQBD1ohQWaS2lg9JybZ+AK7hNwx2oIoVf4UPQ0Lj1FdKktevIpel8AKNUkDcWMxpgSaIEaTVv3sx7uztiTdu2s/98DywOw3Dued4Who/M2aIx5lZV1aEsy0+qiwHELyi+Ytl0PQ69SxAxkWIA4RMRTdNsKE59juMcuZd6xIAFeZ6fGCdJ8kY4y7KAuTRNGd7jyEBXsdOPE3a0QGPsniOnnYMO67LgSQN9T41F2QGrQRRFCwyzoIF2qyBuKKbcOgPXdVeY9rMWgNsjf9ccYesJhk3f5dYT1HX9gR0LLQR30TnjkUEcx2uIuS4RnI+aj6sJR0AM8AaumPaM/rRehyWhXqbFAA9kh3/8/NvHxAYGAsZ/il8IalkCLBfNVAAAAABJRU5ErkJggg=="); 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_initializer
是Initializer
实例,在调用时会调用tf.random_normal
。因此tf.random_normal_initializer
和tf.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数组将出现在图中,如果数组很大,这可能是个问题。