问题可能过于笼统,但任何人都可以解释会导致卷积神经网络分歧的原因吗?
具体细节:
我正在使用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")
我尝试调整优化器,使用零学习率,并且不使用优化器。任何有关网络层,数据大小等的见解都是值得赞赏的。
答案 0 :(得分:62)
我看到很多事情让模型分歧。
学习率过高。如果损失开始增加然后发散到无穷大,您通常可以判断是否是这种情况。
我不熟悉DNNClassifier,但我猜它使用了分类交叉熵成本函数。这涉及在预测接近零时取得预测的对数。这就是为什么人们通常会在预测中添加一个小的epsilon值来防止这种分歧。我猜测DNNClassifier可能会这样做或使用tensorflow opp。可能不是问题。
其他数值稳定性问题可能存在,例如除以零,其中添加epsilon可以提供帮助。另一个不那么明显的一个,如果在处理有限精度数时,如果没有正确简化,那么导数的平方根可以发散。我再次怀疑这是DNNC分类器的问题。
输入数据可能存在问题。尝试在输入数据上调用assert not np.any(np.isnan(x))
以确保您没有引入nan。还要确保所有目标值都有效。最后,确保数据已正确规范化。您可能希望像素在[-1,1]范围内而不是[0,255]。
标签必须在损失函数的范围内,因此如果使用基于对数的损失函数,则所有标签必须是非负的(如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。即:
因此,请勿使用距离太远的标签。
编辑 您可以在以下简单代码中看到效果:
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)。错误消息将更加具体。
答案 5 :(得分:0)
正规化可以提供帮助。对于分类器,无论是二进制分类器还是多分类器,都有很好的活动正则化条件。对于回归器,内核正则化可能更合适。
答案 6 :(得分:0)
我想插入一些我遇到的(浅)原因,如下所示:
希望有帮助。
答案 7 :(得分:0)
使用nan
,inf
或-inf
的原因通常是因为TensorFlow中的division by 0.0
不会导致被零除。可能会产生nan
,inf
或-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”能够解决此类问题。