深学南楠失败的原因

时间:2016-10-14 19:07:18

标签: python tensorflow machine-learning keras theano

问题可能过于笼统,但任何人都可以解释会导致卷积神经网络分歧的原因吗?

具体细节:

我正在使用Tensorflow的iris_training模型和我自己的一些数据并继续获取

  

错误:张量流:模型与损失= NaN分开。

     

...回溯

     

tensorflow.contrib.learn.python.learn.monitors.NanLossDuringTrainingError:培训期间NaN损失。

追溯源于行:

 tf.contrib.learn.DNNClassifier(feature_columns=feature_columns,
                                        hidden_units=[300, 300, 300],
                                        #optimizer=tf.train.ProximalAdagradOptimizer(learning_rate=0.001, l1_regularization_strength=0.00001),                                                          
                                        n_classes=11,
                                        model_dir="/tmp/iris_model")

我尝试调整优化器,使用零学习率,并且不使用优化器。任何有关网络层,数据大小等的见解都是值得赞赏的。

9 个答案:

答案 0 :(得分:62)

我看到很多事情让模型分歧。

  1. 学习率过高。如果损失开始增加然后发散到无穷大,您通常可以判断是否是这种情况。

  2. 我不熟悉DNNClassifier,但我猜它使用了分类交叉熵成本函数。这涉及在预测接近零时取得预测的对数。这就是为什么人们通常会在预测中添加一个小的epsilon值来防止这种分歧。我猜测DNNClassifier可能会这样做或使用tensorflow opp。可能不是问题。

  3. 其他数值稳定性问题可能存在,例如除以零,其中添加epsilon可以提供帮助。另一个不那么明显的一个,如果在处理有限精度数时,如果没有正确简化,那么导数的平方根可以发散。我再次怀疑这是DNNC分类器的问题。

  4. 输入数据可能存在问题。尝试在输入数据上调用assert not np.any(np.isnan(x))以确保您没有引入nan。还要确保所有目标值都有效。最后,确保数据已正确规范化。您可能希望像素在[-1,1]范围内而不是[0,255]。

  5. 标签必须在损失函数的范围内,因此如果使用基于对数的损失函数,则所有标签必须是非负的(如evan pu和下面的评论所述)。

答案 1 :(得分:8)

如果你正在训练交叉熵,你想在你的输出概率上添加一个像1e-8这样的小数字。

因为log(0)是负无穷大,当你的模型受到足够的训练时,输出分布会非常偏斜,例如说我做了4级输出,在开始时我的概率看起来像

0.25 0.25 0.25 0.25

但是到最后概率可能看起来像

1.0 0 0 0

你采用这种分布的交叉熵,一切都会爆炸。修复是人为地在所有术语中添加一个小数字以防止这种情况。

答案 2 :(得分:3)

就我而言,设置远距离整数LABEL时得到NAN。即:

  • 标记[0..100]培训还可以,
  • 标记[0..100]加上一个附加标签8000,然后我得到了NAN。

因此,请勿使用距离太远的标签。

编辑 您可以在以下简单代码中看到效果:

from keras.models import Sequential
from keras.layers import Dense, Activation
import numpy as np

X=np.random.random(size=(20,5))
y=np.random.randint(0,high=5, size=(20,1))

model = Sequential([
            Dense(10, input_dim=X.shape[1]),
            Activation('relu'),
            Dense(5),
            Activation('softmax')
            ])
model.compile(optimizer = "Adam", loss = "sparse_categorical_crossentropy", metrics = ["accuracy"] )

print('fit model with labels in range 0..5')
history = model.fit(X, y, epochs= 5 )

X = np.vstack( (X, np.random.random(size=(1,5))))
y = np.vstack( ( y, [[8000]]))
print('fit model with labels in range 0..5 plus 8000')
history = model.fit(X, y, epochs= 5 )

结果显示添加标签8000后的NAN:

fit model with labels in range 0..5
Epoch 1/5
20/20 [==============================] - 0s 25ms/step - loss: 1.8345 - acc: 0.1500
Epoch 2/5
20/20 [==============================] - 0s 150us/step - loss: 1.8312 - acc: 0.1500
Epoch 3/5
20/20 [==============================] - 0s 151us/step - loss: 1.8273 - acc: 0.1500
Epoch 4/5
20/20 [==============================] - 0s 198us/step - loss: 1.8233 - acc: 0.1500
Epoch 5/5
20/20 [==============================] - 0s 151us/step - loss: 1.8192 - acc: 0.1500
fit model with labels in range 0..5 plus 8000
Epoch 1/5
21/21 [==============================] - 0s 142us/step - loss: nan - acc: 0.1429
Epoch 2/5
21/21 [==============================] - 0s 238us/step - loss: nan - acc: 0.2381
Epoch 3/5
21/21 [==============================] - 0s 191us/step - loss: nan - acc: 0.2381
Epoch 4/5
21/21 [==============================] - 0s 191us/step - loss: nan - acc: 0.2381
Epoch 5/5
21/21 [==============================] - 0s 188us/step - loss: nan - acc: 0.2381

答案 3 :(得分:2)

如果使用整数作为目标,请确保它们在0处不对称。

即,不要使用-1,0,1类。改为使用0,1,2。

答案 4 :(得分:1)

如果您想收集有关错误的更多信息,并且如果在前几次迭代中发生错误,我建议您在仅CPU模式下运行实验(无GPU)。错误消息将更加具体。

来源:https://github.com/tensorflow/tensor2tensor/issues/574

答案 5 :(得分:0)

正规化可以提供帮助。对于分类器,无论是二进制分类器还是多分类器,都有很好的活动正则化条件。对于回归器,内核正则化可能更合适。

答案 6 :(得分:0)

我想插入一些我遇到的(浅)原因,如下所示:

  1. 我们可能已经更新了字典(用于NLP任务),但是模型和准备的数据使用了不同的字典。
  2. 我们可能已经重新处理了我们的数据(二进制tf_record),但是我们加载了旧模型。重新处理的数据可能与先前的数据冲突 一。
  3. 我们可能应该从头开始训练模型,但是我们忘记删除检查点,并且模型会自动加载最新参数。

希望有帮助。

答案 7 :(得分:0)

使用naninf-inf的原因通常是因为TensorFlow中的division by 0.0不会导致被零除。可能会产生naninf-inf“值”。在训练数据中,您可能有0.0,因此在损失函数中,有可能您执行了division by 0.0

a = tf.constant([2., 0., -2.])
b = tf.constant([0., 0., 0.])
c = tf.constant([1., 1., 1.])
print((a / b) + c)

输出是以下张量:

tf.Tensor([ inf  nan -inf], shape=(3,), dtype=float32)

添加一个小的eplison(例如1e-5)通常可以解决问题。此外,自TensorFlow 2起,定义了tf.math.division_no_nan

答案 8 :(得分:0)

尽管大多数要点已经讨论过。但我想再次强调缺少NaN的另一个原因。

tf.estimator.DNNClassifier(
    hidden_units, feature_columns, model_dir=None, n_classes=2, weight_column=None,
    label_vocabulary=None, optimizer='Adagrad', activation_fn=tf.nn.relu,
    dropout=None, config=None, warm_start_from=None,
    loss_reduction=losses_utils.ReductionV2.SUM_OVER_BATCH_SIZE, batch_norm=False
)

默认情况下,激活功能为“ Relu”。中间层可能会生成负值,而“ Relu”会将其转换为0。逐渐停止训练。

我观察到“ LeakyRelu”能够解决此类问题。