【问题标题】:tf.keras loss becomes NaNtf.keras 损失变为 NaN
【发布时间】:2019-03-24 21:58:17
【问题描述】:

我正在 tf.keras 中编写一个有 3 层的神经网络。我的数据集是 MNIST 数据集。我减少了数据集中的示例数量,因此运行时间更低。这是我的代码:

import tensorflow as tf
from tensorflow.keras import layers
import numpy as np
import pandas as pd

!git clone https://github.com/DanorRon/data
%cd data
!ls

batch_size = 32
epochs = 10
alpha = 0.0001
lambda_ = 0
h1 = 50

train = pd.read_csv('/content/first-repository/mnist_train.csv.zip')
test = pd.read_csv('/content/first-repository/mnist_test.csv.zip')

train = train.loc['1':'5000', :]
test = test.loc['1':'2000', :]

train = train.sample(frac=1).reset_index(drop=True)
test = test.sample(frac=1).reset_index(drop=True)

x_train = train.loc[:, '1x1':'28x28']
y_train = train.loc[:, 'label']

x_test = test.loc[:, '1x1':'28x28']
y_test = test.loc[:, 'label']

x_train = x_train.values
y_train = y_train.values

x_test = x_test.values
y_test = y_test.values

nb_classes = 10
targets = y_train.reshape(-1)
y_train_onehot = np.eye(nb_classes)[targets]

nb_classes = 10
targets = y_test.reshape(-1)
y_test_onehot = np.eye(nb_classes)[targets]

model = tf.keras.Sequential()
model.add(layers.Dense(784, input_shape=(784,)))
model.add(layers.Dense(h1, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(lambda_)))
model.add(layers.Dense(10, activation='sigmoid', kernel_regularizer=tf.keras.regularizers.l2(lambda_)))

model.compile(optimizer=tf.train.GradientDescentOptimizer(alpha), 
             loss = 'categorical_crossentropy',
             metrics = ['accuracy'])

model.fit(x_train, y_train_onehot, epochs=epochs, batch_size=batch_size)

每当我运行它时,都会发生以下三种情况之一:

  1. 在几个 epoch 内损失减少,准确度增加,直到损失无明显原因变为 NaN,准确度直线下降。

  2. 每个 epoch 的损失和准确率保持不变。通常loss是2.3025,准确率是0.0986。

  3. 损失从 NaN 开始(并一直保持这种状态),而准确度仍然很低。

大多数时候,模型会做这些事情之一,但有时它会做一些随机的事情。似乎发生的不稳定行为类型是完全随机的。我不知道问题是什么。我该如何解决这个问题?

编辑:有时,损失会减少,但准确性保持不变。此外,有时损失减少而准确度增加,然后过一段时间准确度降低而损失仍然减少。或者,loss减少,准确率增加,然后切换,loss上升很快,而准确率下降,最终以loss: 2.3025 acc: 0.0986结束。

编辑 2:这是有时会发生的事情的一个例子:

Epoch 1/100
49999/49999 [==============================] - 5s 92us/sample - loss: 1.8548 - acc: 0.2390

Epoch 2/100
49999/49999 [==============================] - 5s 104us/sample - loss: 0.6894 - acc: 0.8050

Epoch 3/100
49999/49999 [==============================] - 4s 90us/sample - loss: 0.4317 - acc: 0.8821

Epoch 4/100
49999/49999 [==============================] - 5s 104us/sample - loss: 2.2178 - acc: 0.1345

Epoch 5/100
49999/49999 [==============================] - 5s 90us/sample - loss: 2.3025 - acc: 0.0986

Epoch 6/100
49999/49999 [==============================] - 4s 90us/sample - loss: 2.3025 - acc: 0.0986

Epoch 7/100
49999/49999 [==============================] - 4s 89us/sample - loss: 2.3025 - acc: 0.0986

编辑 3:我将损失更改为均方误差,现在网络运行良好。有没有办法让它保持交叉熵而不收敛到局部最小值?

【问题讨论】:

    标签: python machine-learning neural-network mnist tf.keras


    【解决方案1】:

    我将损失更改为均方误差,现在网络运行良好

    MSE 不是适合此类分类问题的损失函数;你当然应该坚持loss = 'categorical_crossentropy'

    问题很可能是由于您的 MNIST 数据未标准化;您应该将最终变量标准化为

    x_train = x_train.values/255
    x_test = x_test.values/255
    

    不规范化输入数据是梯度爆炸问题的一个已知原因,这可能就是这里发生的情况。

    其他建议:为你的第一个密集层设置activation='relu',并去掉所有层的正则化器和初始化器参数(默认的glorot_uniform实际上是一个更好的初始化器,而这里的正则化实际上可能对性能)。

    作为一般建议,请尝试不要重新发明轮子 - 从使用内置 MNIST 数据的Keras example 开始...

    【讨论】:

      【解决方案2】:

      您对看似随机的代码输出感到沮丧是可以理解和正确识别的。每次模型开始训练时,它都会随机初始化权重。根据此初始化,您会看到三个输出场景之一。

      这个问题很可能是由于梯度消失造成的。当反向传播导致非常小的权重乘以一个小数以创建一个几乎无限小的值时,就会发生这种现象。解决方案是向每个梯度(从成本函数内)添加小抖动(1e-10),使它们永远不会达到零。

      网上有大量关于消失梯度的更详细的博客,有关实现示例,请查看TensorFlow Network 的第 217 行

      【讨论】:

      • 这似乎可行,但如何在 tf.keras 中实现呢?无法访问实际的成本函数。
      • 在深入 那个 之前,特别是对于像 MNIST 这样的数据集,我们事先知道它应该适用于这样的模型,尝试更简单的补救措施(见上面自己的答案).. .
      猜你喜欢
      • 2017-10-12
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 2022-06-14
      • 2019-03-23
      • 2020-09-27
      • 2021-03-26
      • 1970-01-01
      相关资源
      最近更新 更多