TensorFlow float16支持被破坏

时间:2017-02-06 10:00:45

标签: tensorflow

最近我尝试使用float16训练TF中的CNN。令我惊讶的是,即使TF声称支持它一段时间,它仍以各种方式被打破。例如,无论网络如何,float16优化都会在第二步中导致NaN丢失。

import tensorflow as tf
import numpy as np

slim = tf.contrib.slim

dtype = tf.float16
shape = (4, 16, 16, 3)

inpt = tf.placeholder(dtype, shape, name='input')
net = slim.conv2d(inpt, 16, [3, 3], scope='conv',
        weights_initializer=tf.zeros_initializer(),
        # normalizer_fn=slim.batch_norm
        )
loss = tf.reduce_mean(net)
opt = tf.train.AdamOptimizer(1e-3)
train_op = slim.learning.create_train_op(loss, opt)

val = np.zeros(shape)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(2):
        print(sess.run(train_op, feed_dict={inpt: val}))

据我所知,这显然是一个错误:我在零输入上应用零卷积,我应该得到零梯度,不会改变零损失。它只是不能分歧。如果dtype是float32就行了。在CPU和GPU版本上都会发生NaN损失。

然而,我被解雇了GH问题,一个随机的家伙关闭了这个问题,说它是预期的行为:https://github.com/tensorflow/tensorflow/issues/7226

如果你用BN取消注释该线,它将在图形构建时间中断,因为BN假设移动平均线(和beta,gamma)总是float32并且不能正确地投射它们。这个问题也已关闭,显然被忽略了:https://github.com/tensorflow/tensorflow/issues/7164

我觉得我正在与ISP的第一线IT支持人员交谈。

当这样一个简单的“网络”失败时,有人可以解释我应该如何用float16训练吗?现在报告错误的推荐方法是什么?

1 个答案:

答案 0 :(得分:13)

看起来你需要一个略大的epsilon以避免在AdamOptimizer中零时刻的数值不稳定(默认值为1e-8)。这适用于我的float16:

opt = tf.train.AdamOptimizer(1e-3, epsilon=1e-4)

请求基于dtype设置epsilon是合理的(并且可能是这样的请求,或者更好的是拉取请求,将在GitHub上遇到更积极的响应)。请注意,GradientDescentOptimizer没有此类问题。