我有一个存储的张量模型,我想确定性地评估最终预测。恢复模型和运行预测时,网络流中有一个点,张量值是以非确定性方式计算的。
这是有问题的点:
self.h0 = tf.concat([self.q_weighted, self.x_weighted], 1, name='h0')
self.h1 = tf.layers.dense(inputs=self.h0, units=512, activation=tf.nn.relu, name='h1',kernel_initializer=self.kernel_initializer, bias_initializer=self.bias_initializer)
其中:
self.kernel_initializer = tf.glorot_uniform_initializer()
self.bias_initializer = tf.truncated_normal_initializer(mean=0.011, stddev=0.005)
将多个执行与相同输入进行比较,H0的结果值是一致的,而H1的值则变化。
我构建图形并还原模型的方式:
- 建筑模型图(例如,上面提到的两个变量(。我创建init op(tf.global_variables_initializer(((,但在这里(只有在训练时( 才能运行它
- 初始化会话
- 加载训练的模型
- 运行操作以获取预测
代码:
// building network graph
// ...
// restoring trained model
self.saver = tf.train.Saver(max_to_keep=2)
self.sess = tf.Session()
self.saver.restore(self.sess, model_path)
// running network ops (without running tf.global_variables_initializer)
self.sess.run([...])
我在两个单独的执行中手动检查了H0和H1的恢复重量(内核和偏置(,并且从检查点还原后它们是相同的。
有什么想法会导致这呢?或如何处理此操作,以使执行是确定性的?
P.S-我还试图设置一个恒定的全局张量和Numpy种子。这无济于事。
**编辑**
在网络层上系统地进行操作,我发现第一个非确定性OP是redus_sum。具体而言,这条代码线:
self.x_weighted = tf.reduce_sum(tf.multiply(tf.expand_dims(self.x_weights_norm, -1), x_outputs), axis=1, name="x_weighted")
我看到这是一个已知的问题 - 请参阅此处和此处。然而,这种行为在单个CPU上复制,而将线程数限制为1,例如:
config = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1, allow_soft_placement=True, device_count={'CPU': 1})
self.sess = tf.Session(config=config)
现在,我想知道是否有另一部分设置不正确,例如导致随机性,或者即使使用这种配置也会发生redy_sum非确定性。
解决了问题。随机性是由于使用Python Hash函数的使用,应用于网络的输入。通过修复Pythonhashseed环境变量,输出已在不同的执行中变得一致。