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.