ChatGPT解决这个技术问题 Extra ChatGPT

训练回归网络时的 NaN 损失

我有一个具有 260,000 行和 35 列的“单热编码”(全一和零)数据矩阵。我正在使用 Keras 训练一个简单的神经网络来预测一个连续变量。制作网络的代码如下:

model = Sequential()
model.add(Dense(1024, input_shape=(n_train,)))
model.add(Activation('relu'))
model.add(Dropout(0.1))

model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.1))

model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.1))
model.add(Dense(1))

sgd = SGD(lr=0.01, nesterov=True);
#rms = RMSprop()
#model.compile(loss='categorical_crossentropy', optimizer=rms, metrics=['accuracy'])
model.compile(loss='mean_absolute_error', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_epoch=3, verbose=1, validation_data=(X_test,Y_test), callbacks=[EarlyStopping(monitor='val_loss', patience=4)] )

然而,在训练过程中,我看到损失很好地减少了,但是在第二个 epoch 的中间,它变成了 nan:

Train on 260000 samples, validate on 64905 samples
Epoch 1/3
260000/260000 [==============================] - 254s - loss: 16.2775 - val_loss:
 13.4925
Epoch 2/3
 88448/260000 [=========>....................] - ETA: 161s - loss: nan

我尝试使用 RMSProp 而不是 SGD,我尝试使用 tanh 而不是 relu,我尝试使用和不使用 dropout,但均无济于事。我尝试了一个较小的模型,即只有一个隐藏层,同样的问题(它在不同的点变成了 nan)。然而,它确实适用于较少的特征,即如果只有 5 列,并且给出了相当好的预测。似乎有某种溢出,但我无法想象为什么——损失一点也不大。

Python 版本 2.7.11,在 linux 机器上运行,仅 CPU。我用最新版本的 Theano 测试了一下,也得到了 Nans,所以我尝试去 Theano 0.8.2 也遇到了同样的问题。用最新版的 Keras 也有同样的问题,而且用的是 0.3.2 版本。

尝试 loss='mean_squared_error', optimizer='adam' 与单个隐藏层 - 还是 nans?
@1'' 将上述模型与 Adam 优化器一起使用时,我得到了 nans。只有一层,它不会在三个训练周期中给出 nans。
对于未来的读者,这里是一个相关的 keras 线程。 github.com/keras-team/keras/issues/2134 通过结合此处提到的所有建议,我取得了一些成功。例如添加batchnorm,改变学习率,优化器,添加clip_by_value,clip_by_global_norm,最后,多次梳理代码以查找错误也有帮助,例如在一个conv层之后缺少batch norm层。 :)
检查 NAN 值它解决了我的问题... :)

1
1''

神经网络的回归很难发挥作用,因为输出是无界的,所以你特别容易出现 exploding gradients problem(可能是 nans 的原因)。

从历史上看,梯度爆炸的一个关键解决方案是降低学习率,但随着像 Adam 这样的每参数自适应学习率算法的出现,您不再需要设置学习率来获得良好的性能。除非您是神经网络爱好者并且知道如何调整学习计划,否则几乎没有理由再使用 SGD 和动量。

以下是您可以尝试的一些事情:

通过分位数归一化或 z 评分来归一化您的输出。严格地说,在训练数据上计算这种转换,而不是在整个数据集上。例如,对于分位数归一化,如果一个示例位于训练集的第 60 个百分位,则它的值为 0.6。 (您也可以将分位数归一化值向下移动 0.5,使第 0 个百分位数为 -0.5,第 100 个百分位数为 +0.5)。添加正则化,可以通过增加 dropout 率或向权重添加 L1 和 L2 惩罚。 L1 正则化类似于特征选择,既然你说将特征数量减少到 5 个可以获得良好的性能,L1 也可以。如果这些仍然没有帮助,请减小您的网络规模。这并不总是最好的主意,因为它会损害性能,但在您的情况下,相对于输入特征 (35),您有大量的第一层神经元 (1024),因此它可能会有所帮助。将批量大小从 32 增加到 128。128 是相当标准的,可能会增加优化的稳定性。


关于 1. 为什么不对整个输出集进行归一化?另外,我可以改用缩放吗?
@Eran如果您在决定如何规范化时使用整个数据集(训练+测试),那么您会间接地将有关测试集的信息合并到训练集中,这是训练测试污染的一种形式。但是,只要您在决定如何进行归一化时仅使用训练集,您就可以使用缩放或任何其他类型的归一化来提供良好的性能。
检查batch size,发现太小了(16),将batch size增加到128就可以了!
关于批量大小,我的经验法则是它应该与内存允许的一样大,但最多为观察次数的 1%。 1% 会给你 100 个随机批次,这意味着你仍然有随机梯度下降的随机部分。
据我所知,使用“adam”优化器不需要手动将 lr 作为参数
p
pir

1" 的答案非常好。但是,所有修复似乎都是间接而不是直接解决问题。我建议使用渐变剪裁,它将剪裁任何高于某个值的渐变。

在 Keras 中,您可以使用 clipnorm=1(参见 https://keras.io/optimizers/)简单地裁剪范数高于 1 的所有渐变。


有道理!这是一个完全合法的策略,例如,经常与循环神经网络一起使用。但是,在诉诸于此之前,最好检查一下简单的优化是否没有出错。
这应被标记为正确的解决方案,因为它实际上解决了特定问题,而不是就更广泛的主题提供建议。
相同的 keras 链接表明不再支持渐变裁剪。有类似的解决方案吗?
这适用于所有优化器吗?设置为 1.0 总是一个好主意吗?
是的,它应该跨优化器工作。如果您的优化问题足够简单/稳定,那么这不是必需的,并且可能会减慢训练速度而不会产生任何好处。
n
nbro

我以前也遇到过同样的问题。我搜索并找到这个问题和答案。上面提到的所有这些技巧对于训练深度神经网络都很重要。我都试过了,但还是得到了 NAN。

我也在这里找到了这个问题。 https://github.com/fchollet/keras/issues/2134。我引用了作者的总结如下:

我想指出这一点,以便将其存档以供将来可能遇到此问题的其他人使用。在我的损失函数进入训练过程之后,我突然返回了一个 nan。我检查了 relus、优化器、损失函数、根据 relus 的 dropout、我的网络大小和网络的形状。我仍然感到损失,最终变成了一个 nan,我感到非常沮丧。然后我恍然大悟。我可能有一些不好的输入。事实证明,我交给 CNN 的其中一张图像(并进行平均归一化)只不过是 0。当我减去平均值并通过标准偏差进行归一化时,我没有检查这种情况,因此我最终得到了一个示例矩阵,它只不过是 nan 的。一旦我修复了我的标准化函数,我的网络现在就可以完美地训练了。

我同意上述观点:输入对您的网络很敏感。在我的例子中,我使用密度估计的对数值作为输入。绝对值可能非常大,经过几步梯度后可能会导致 NaN。我认为输入检查是必要的。首先,您应该确保输入不包含 -inf 或 inf,或绝对值中的一些非常大的数字。


我和你有同样的问题。在检查我的数据时,我发现多个地方有 inf 数据点。把那些拿出来解决了这个问题。
这解决了我的问题,我的嵌入矩阵中有多个 NaN :) 谢谢。
我将输入图像(png)从 0-255(uint8)缩放到 0.-1.(float32),我从来没有想过输入是罪魁祸首....在将输入传递给之前添加一个 tf.clip_by_value net for training 似乎解决了我长达 9 个月的调试之旅......
另外,请注意 np.isnan(np.inf) == False。为确保您的示例不包含 NaN 或 Inf,您可以执行 assert np.all(np.isfinite(X)) 之类的操作。 (这让我多次感到困惑:我认为我的数据很好,因为我正在检查 NaN。但我忘记了 np.isnan 没有注意到 Infs!)
@pangyuteng 您能否详细说明导致您的错误的原因?如果输入总是按 /255 缩放到 0-1,我看不出这将如何导致 NaN...
j
javac

我在使用 LSTM 时遇到了同样的问题,问题是我的数据在标准化后有一些 nan 值,因此,如果你看到你会有 nan 值,我们应该检查标准化后的输入模型数据:

print(np.any(np.isnan(X_test)))
print(np.any(np.isnan(y_test)))

你可以通过像这样向 Std 添加一个小值(0.000001)来解决这个问题,

def standardize(train, test):


    mean = np.mean(train, axis=0)
    std = np.std(train, axis=0)+0.000001

    X_train = (train - mean) / std
    X_test = (test - mean) /std
    return X_train, X_test

A
Arnav

我遇到了一个非常相似的问题,这就是我让它运行的方式。

您可以尝试的第一件事是将激活更改为 LeakyReLU,而不是使用 Relu 或 Tanh。原因是层中的许多节点的激活值通常为零,并且反向传播不会更新这些节点的权重,因为它们的梯度也为零。这也称为“垂死的 ReLU”问题(您可以在此处了解更多信息:https://datascience.stackexchange.com/questions/5706/what-is-the-dying-relu-problem-in-neural-networks)。

为此,您可以使用以下方法导入 LeakyReLU 激活:

from keras.layers.advanced_activations import LeakyReLU

并将其合并到您的图层中,如下所示:

model.add(Dense(800,input_shape=(num_inputs,)))
model.add(LeakyReLU(alpha=0.1))

此外,输出特征(您试图预测的连续变量)可能是一个不平衡的数据集并且有太多的 0。解决此问题的一种方法是使用平滑。您可以通过将此列中所有值的分子加 1 并将此列中的每个值除以 1/(此列中所有值的平均值)来执行此操作

这实际上将所有值从 0 转换为大于 0 的值(可能仍然非常小)。这可以防止曲线预测 0 并最小化损失(最终使其变为 NaN)。较小的值比较大的值受到的影响更大,但总的来说,数据集的平均值保持不变。


O
Othmane

总结此处和此 github 讨论中提到的不同解决方案,这当然取决于您的具体情况:

添加正则化以向权重添加 l1 或 l2 惩罚。否则,请尝试使用较小的 l2 reg。即 l2(0.001),或者如果已经存在则删除它。

尝试较小的辍学率。

剪裁渐变以防止它们爆炸。例如,在 Keras 中,您可以使用 clipnorm=1。或剪辑值 = 1。作为优化器的参数。

检查输入的有效性(无 NaN 或有时为 0)。即 df.isnull().any()

用更易于处理的 Adam 替换优化器。有时也用 rmsprop 替换 sgd 会有所帮助。

使用带有大量正则化的 RMSProp 来防止梯度爆炸。

尝试规范化您的数据,或检查规范化过程中是否引入了任何错误值。

验证您是否使用了正确的激活函数(例如,使用 softmax 而不是 sigmoid 进行多类分类)。

尝试增加批量大小(例如,从 32 增加到 64 或 128)以增加优化的稳定性。

尝试降低你的学习率。

检查最后一批的大小,这可能与批次大小不同。


注意:如果 batch_size 太大,您可以stuck in local minimum
K
Kushagra Bhatia

我有同样的问题,我使用 Keras 来解决多元回归问题。后来我意识到我的数据集中的一些值是 nan,这导致了 nan 损失。我使用了命令:

df=df.dropna()

它解决了我的问题。


诚然,我们提供给 NeuralNet 的数据中不应该有任何 NaN 值。
D
Dmitry Senkovich

就我而言,问题是我复制粘贴了我之前的二进制分类工作,并在输出层使用了 sigmoid 激活而不是 softmax(新网络是关于多类分类的)。


w
wutzebaer

当我的一个训练数据条目包含一个 nan 时,我遇到了这个问题


K
Krithi07

训练开始后,我在第一个 epoch 就以 nan 的身份遭受损失。像从输入数据中删除 nas 一样简单的解决方案对我有用 (df.dropna())

我希望这可以帮助遇到类似问题的人


你是如何从第一个 epoch 中删除 nans 的?在我开始训练之前我有 nans
R
RobC

我在使用 keras 时遇到了类似的问题。第二批输入后loss变成了NAN。

我尝试过了:

使用 softmax 作为输出密集层的激活 Drop nan in the input 归一化输入

然而,这并没有奏效。所以,然后我尝试:

降低学习率

问题解决了。


j
joran

我的 RNN 与 keras LSTM 层有同样的问题,所以我尝试了上面的每个解决方案。我已经缩放了我的数据(使用 sklearn.preprocessing.MinMaxScaler),缩放后我的数据中没有 NaN 值。使用 LeakyRelU 或更改学习率等解决方案没有帮助。

所以我决定将缩放器从 MinMaxScaler 更改为 StandardScaler,即使我没有 NaN 值并且我发现它很奇怪,但它确实有效!


K
Keng Chan

如果有 NAN 值,请尝试检查您的数据。删除 NAN 值为我解决了这个问题。


C
Clay Coleman

我尝试了此页面上的所有建议以及许多其他建议,但均无济于事。我们使用 pandas 导入 csv 文件,然后使用带有文本输入的 keras Tokenizer 创建词汇表和词向量矩阵。在注意到一些 CSV 文件导致 nan 而其他文件工作后,突然我们查看了文件的编码并意识到 ascii 文件不适用于 keras,导致 nan 丢失和 {3 };但是,utf-8 和 utf-16 文件工作!突破。

如果您在尝试这些建议后执行文本分析并丢失 nan,请使用 file -i {input} (linux) 或 file -I {input} (osx) 来发现您的文件类型。如果您有 ISO-8859-1us-ascii,请尝试转换为 utf-8utf-16le。没有尝试过后者,但我想它也会起作用。希望这可以帮助非常非常沮丧的人!


N
Not_Dave

我的 logloss、MAE 和其他都是 NA 时遇到了类似的问题。我查看了数据并发现,我几乎没有包含 NA 的功能。我用近似值估算了 NA,并能够解决这个问题。


f
from_mars

我的 keras CNN 遇到了同样的问题,就像其他人一样,我尝试了上述所有解决方案:降低学习率,从训练数据中删除空值,规范化数据,添加 dropout 层......但是无法解决 nan 问题,我尝试改变分类器(最后)层中的激活函数,从 sigmoid 到 softmax。有效!尝试将最后一层的激活函数更改为 softmax!


T
Talha Chafekar

当我尝试创建边界框回归器时,我得到了同样的结果。我的神经网络层比你的大。我增加了 dropout 值并得到了合适的结果。


F
Fateh Singh

正在为我的分类网络获取 NaN。在这里回答,因为它可能对某人有所帮助。

犯了一个错误——

训练标签中的类数为 5。即从 0 到 4。

在最后一个密集的分类层中有 4 个节点,这意味着 4 个类,这是问题所在。

将网络最后一层中的节点数更改为 5 为我解决了这个问题。


M
Max

我遇到了类似的问题,我尝试将激活从 Sigmoid 更改为 Softmax,从 RelU 更改为 LeakyRelU,问题得到了解决。所以我想只要输入中没有 NaN,并且您尝试降低学习率,可行的解决方案就是使用您的激活!


S
Super Eiskalt

我的情况:

Train Loss: nan, Train Accuracy: 0.0, Validation Loss: nan, Validation Accuracy: 0.0

后来我发现这是因为我的标签是 1, 2, 3, 4 不是以 0 开头的。所以我重新标记它们,使用 0, 1, 2, 3 而不是 1, 2, 3, 4 作为标签。问题解决了!

希望我的回答有帮助!


A
Abdellatif

在 keras 中,类标签从 0 开始。例如,如果您有 7 个类,则要么从 0 到 6 开始标记它们,并以单位 = 7 提供最后一个密集层(使用 softmax 激活函数)。或者,如果您应该从 1 到 7 标记数据,在这种情况下,您必须设置 units=8(在最后一个密集层中)。


正如目前所写的那样,您的答案尚不清楚。请edit添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。您可以找到有关如何写出好答案的更多信息in the help center
S
S.B

我得到了二进制分类的 nan 值,然后我将损失函数从分类交叉熵更改为“二进制交叉熵”,并且效果很好。


J
JeeyCi

顺便说一句,它似乎是一个垂死的梯度而不是爆炸。

当所有训练实例的输入为负时,神经元就会死亡。

here 'adam' 优化器有助于对抗 NaN。但就您的情况而言 - 请确保您拥有规模化数据集 & loss='mean_squared_error' (与您的相反)

model.compile(optimizer = 'adam', loss = keras.losses.mean_squared_error, metrics=keras.metrics.mean_absolute_error)

R
Rinaldo Nikilson

我遇到了同样的问题。成功地您可以使用 keras 进行回归。将您的所有数据转换为解决我的问题的四舍五入数。例如。 23.43 至 23


a
abbas abaei

我有同样的问题。检查数据,我意识到在数据采集过程中发生了错误。


更多评论

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅