Tensorflow:如果对同一输入执行多个独立操作,则操作员结果会更改

时间:2017-12-27 10:03:04

标签: python tensorflow

[编辑如下]

我遇到了来自tensorflow的一些意外行为:如果我先执行另一个独立运算符,则运算符的结果会发生变化。

我已将项目剥离到下面的最小代码示例。如果" h_chrdP "输出将会改变。 line是(un)注释,但该行不应对输出产生任何影响!

我把头发拉到这个上面。任何人都可以解释一下是什么错误吗?

import tensorflow as tf
import numpy as np   

def ch_redux_layer(input, in_ch, out_ch):
    W = tf.Variable(tf.truncated_normal([1, 1, in_ch, out_ch]))
    conv = tf.nn.conv2d(input, W, strides=[1, 1, 1, 1], padding='VALID')
    #x = tf.shape([1,1])      # uncomment THIS one for different results, too...
    return tf.nn.relu(conv)


def create_network(graph):
    with graph.as_default():
        state = tf.placeholder(tf.float32,
                    shape=[None, 2, 2, 4],
                    name='state')

        h_chrdP = ch_redux_layer(state, 4, 2)  #(un)comment this line for different results
        h_chrdV = ch_redux_layer(state, 4, 1)

        tf.add_to_collection('state', state)
        tf.add_to_collection('dbg', h_chrdV)


# --------------------------------------------------------------
if __name__ == "__main__":
    state = np.array([[[ 0., 0., -0.2, 0.], [ 0., 0., 0.8, 0.]], [[ 0., 1., 0., 0.], [ 0., 1., 0., 0.]]])

    graph = tf.Graph()
    with tf.Session(graph=graph) as session:
        tf.set_random_seed(66)
        np.random.seed(66)

        create_network(session.graph)
        session.run(tf.global_variables_initializer())
        n_state = graph.get_collection('state')[0]

        chV = graph.get_collection('dbg')[0]
        print(session.run(chV, feed_dict={n_state: [state]}))

编辑:

@Lior,谢谢!我永远不会想到随机播种,但即使种子没有被分割也是完全合乎逻辑的,因为第二次调用会产生不同的随机数。

似乎我的例子减少了太多;我现在加入了一行。如果我取消对完全荒谬的" x = tf.shape()"" x = tf.shape()"代码中的一行,但只有当我同时保留 ch_redux_layer()行?

1 个答案:

答案 0 :(得分:2)

要理解差异,您需要了解随机数生成器种子在TensorFlow中的工作原理。

假设您将种子设置为值66,然后添加两个具有随机性的ops(= operations),例如tf.truncated_normal()。让我们调用这些操作op1op2。然后每个op获得自己的“私人”种子。 op1将获得种子(66,1),而op2将获得种子(66,2)。如你所见,私人种子由“全球”种子和柜台组合而成。每次添加op到图表时,计数器都会增加。

结果是,当您的行被评论时,当您运行第h_chrdV = ...行时,它会调用W = tf.Variable(tf.truncated_normal([1, 1, in_ch, out_ch]))。由于这是第一个添加到图形中的操作(让我们假设它是第一个),它将具有种子(66,1)。但是当你的专栏没有评论时,调用h_chrdV = ...将是你第二次添加操作(因为你已经通过调用h_chrdP=...添加了一个),因此种子将是(66,2) 。然后,当你session.run时,你得到不同的随机数。

您可以验证,如果您在行h_chrdP=...h_chrdV=...之间切换顺序,则对前者进行评论不会更改结果。

根据documentation,术语是“操作种子”和“图形级种子”(而不是“全局”和“私有”)