1 梯度爆炸

  • 原因:学习的过程中,梯度变得非常大,使得学习的过程偏离了正常的轨迹。
  • 症状:观察每次迭代的loss值,会发现loss明显增长,最后因为loss值太大以至于不能用浮点去表示,所以变成了Nan。
  • 可采取的措施:1 降低学习速率,2 如果模型中有多个loss层,就需要找到梯度爆炸的层,然后降低该层的loss weight。

2 学习率过高

  • 原因:过高的学习率乘上所有的梯度使得所有参数变成无效的值。
  • 症状:观察输出日志,会发现学习率变成nan
  • 可采取的措施:设置合适的学习速率

3 损失函数有误

  • 原因:损失函数的计算,如交叉熵损失函数的计算可能出现log(0),所以就会出现loss为Nan的情况
  • 症状: loss逐渐下降,突然出现Nan,或loss正常下降,突然出现Nan
  • 可采取的措施: 尝试重现该错误,打印损失层的值进行调试。对预测数据增加最小值偏移,避免0,例如:
y_pred = tf.clip_by_value(y_pred, 1e-15, 99999.)  # clip to avoid nan in cce

4 输入数据有误

  • 原因: 你的输入中存在Nan
  • 症状: loss逐渐下降,突然出现Nan
  • 可采取的措施: 逐步去定位错误数据,然后删掉这部分数据. 可以使用一个简单的网络去读取输入,如果有一个数据是错误的,这个网络的loss值也会出现Nan

5 Pooling层的步长大于核的尺寸

6 设置远距离的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 )

结果:

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

我的理解是,模型采用了交叉熵损失函数,当标签过于分散的时候,比方说标签为8000的数据,其概率分布值就会变成了比较小的数值,也就是会出现类似于log(0)这种情况,从而模型的loss为Nan.

修改自:模型训练中出现NaN Loss的原因及解决方法 - 知乎 (zhihu.com)

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐