深学楠失落的原因

也许这个问题太笼统了,但有谁能解释一下,是什么导致了卷积神经网络的分歧?

详情:

我正在使用 Tensorflow 的 iris _ training 模型和我自己的一些数据,并不断得到

误差: 张量流: 模型偏离损失 = NaN。

回溯。

在训练过程中丢失。

追溯起源于 line:

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

我试过调整优化器,学习率为零,没有使用优化器。对网络层、数据大小等的任何见解都是值得赞赏的。

197642 次浏览

我见过很多事情使模型发生分歧。

  1. 学习速度太快了。如果损失开始增加,然后发散到无穷远,你通常可以判断是否是这种情况。

  2. 我不太熟悉 DNN 分类器,但我猜它使用的是绝对交叉熵成本函数。这涉及到取预测值的日志,当预测值接近零时发生偏离。这就是为什么人们通常在预测中加入一个小的 ε 值来防止这种分歧。我猜测 DNN 分类器可能做到这一点或使用张量流操作。也许不是问题所在。

  3. 其他的数值稳定性问题也可能存在,比如除以零,在这种情况下,加入 epsilon 会有所帮助。另一个不太明显的例子是,当处理有限精度数时,如果没有适当简化,导数可以发散的平方根。我再次怀疑这是问题的情况下,DNN 分类器。

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

  5. 标签必须在损失函数的领域,所以如果使用对数为基础的损失函数,所有的标签必须是非负的(正如 Evan pu 和下面的评论所指出的)。

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

也就是说,不要使用 -1,0,1类,而是使用0,1,2类。

如果你正在进行交叉熵的训练,你需要在输出概率上增加一个小数,比如1e-8。

因为 log (0)是负无穷大,当你的模型训练得足够好的时候,输出分布会非常倾斜,例如,假设我正在做一个4类的输出,一开始我的概率是这样的

0.25 0.25 0.25 0.25

但到最后,这种可能性可能看起来像

1.0 0 0 0

取这个分布的交叉熵,一切都会爆炸。解决办法是在所有术语中人为地添加一个小数字,以防止出现这种情况。

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

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

在我的例子中,我在设置远程整数标签时得到了 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后,NANs:

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

正规化会有所帮助。对于分类器来说,无论是二进制分类器还是多类分类器,活动正则化都是一个很好的例子。对于回归器,内核正则化可能更合适。

我想插入一些我经历过的(浅层次的)原因如下:

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

希望能帮上忙。

产生 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

虽然大部分观点已经讨论过了。但我想再次强调 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”能够解决这样的问题。

我发现了一些有趣的事情,除了上面的答案,当你的数据标签像下面的应用洗牌数据可能会有所帮助:

y=[0,0,0,0,0,0,0....,0,0,0,1,1,1,1,1....,1,1,1,1,1,1,1,2,2,2,2,2,......,2,2,2,2,2]


from sklearn.utils import shuffle
x, y = shuffle(x, y)

我也有同样的问题。我的标签是享受等级[1,3,5]。我读了所有的答案,它们对我面临的问题没有多大意义。我把标签改成了[012] ,成功了。不知道怎么会这样。

TensorFlow 在某些情况下使用标签作为张量中的位置,因此它们必须是0,1,... ,L-1。负数、非整数等会导致损失为 NaN。

原因也可能是使用了非常小的值(比如1e9)。 试着用以下代替:

tf.float32.min

或者(如果手动更改 tf.keras.backend.floatx) :

tf.float16.min