当前位置: 首页>>技术问答>>正文


python - 深度学习Loss Nan的原因

技术问答 , , , , , , 去评论

在深度学习中Loss出现Nan的可能原因有哪些?

也许这个问题太笼统,但是谁能大致解释下导致卷积神经网络发散的原因呢?

问题细节:

我正在使用Tensorflow的iris_training模型以及一些我自己的数据,老是出现以下报错:

ERROR:tensorflow:Model diverged with loss = NaN.

Traceback...

tensorflow.contrib.learn.python.learn.monitors.NanLossDuringTrainingError: NaN loss during training.

Traceback问题源于以下行:

 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")

我尝试过调整优化器,将学习率设置为零,并且不使用优化器,然并卵。

 

最佳回答

常见的导致模型发散(Nan问题)原因:

  1. 学习率太高。损失是否开始增加然后发散到无穷大。
  2. 我对DNNClassifier不熟悉,但是我猜想它使用了分类交叉熵代价函数。这涉及获取预测的对数,该对数随着预测接近零而发散。这就是为什么人们通常在预测中添加较小的ε值以防止这种差异。我猜测DNNClassifier可能会这样做或使用tensorflow opp。
  3. 也可能存在其他数值稳定性问题,例如零除,在其中添加epsilon可能会有所帮助。一种不那么明显的情况是,如果在处理有限精度数时未适当简化,则导数的平方根可能发散。我再次怀疑这是DNNClassifier的问题。
  4. 还可能是输入数据有问题。尝试对输入数据调用assert not np.any(np.isnan(x)),以确保您没有引入nan。还要确保所有目标值(样本Label)均有效。最后,确保数据正确归一化。您可能希望像素在[-1,1]而不是[0,255]范围内。
  5. 另外,标签(样本Label)必须在损失函数值的域(范围)中。例如,如果使用基于对数的损失函数,则所有标签都必须是非负的。

 

次佳回答

如果您正在训练交叉熵,则需要在输出概率中添加一个小数,例如1e-8。

因为log(0)是负无穷大,所以当您的模型经过足够的训练后,输出分布将非常偏斜,例如说我正在执行4类输出,一开始我的概率类似下面这样:

0.25 0.25 0.25 0.25

但到最后,可能看起来像

1.0 0 0 0
如果对该分布进行交叉熵分解,问题就来了。解决方法是人为地在所有项中添加很小的数字,以防止出现这种情况。

 

第三种回答

调试NaN可能很棘手,尤其是在您拥有大型网络的情况下。可以用 tf.add_check_numerics_ops()将ops添加到图中,以声明图中的每个浮点张量不包含任何NaN值(默认情况下是不运行这些检查的)。参考:tensorflow Nan调试


train_op = ...
check_op = tf.add_check_numerics_ops()

sess = tf.Session()
sess.run([train_op, check_op])  # Runs training and checks for NaNs

第四种回答

就我而言,设置远距离整数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


第五种回答

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

即,请勿使用-1、0、1类。而应使用0、1、2类。


loss nan

参考资料

 

本文由《纯净天空》出品。文章地址: https://vimsky.com/article/4341.html,未经允许,请勿转载。