【问题标题】:Loss is NaN on image classification task图像分类任务的损失为 NaN
【发布时间】:2019-12-02 13:54:58
【问题描述】:

我正在尝试在图像数据集上训练一个基本的 CNN,该数据集包含名人的面孔,其类别对应于每个人。鉴于大约有 10,000 个类,我使用了 sparse_categorical_crossentropy 而不是 one-hot 对类进行编码,但是一旦网络开始训练,损失就会停留在一个数字上,并且在几个批次后变为 NaN 我尝试了不同的图像缩放比例和一个较小的网络,但没有运气。关于可能导致 NaN 的任何线索?

生成批次的函数:

def Generator(data, label, batch_size):
    url = "../input/celeba-dataset/img_align_celeba/img_align_celeba/"
    INPUT_SHAPE = (109, 109)
    i = 0
    while True:
        image_batch = [ ]
        label_batch = [ ]
        for b in range(batch_size):
            if i == len(data):
                i = 0
                data, label = shuffle(data, label)
            sample = data[i]
            label_batch.append(label[i])
            i += 1
            image = cv2.resize(cv2.imread(url + sample), INPUT_SHAPE)
            image_batch.append((image.astype(float)) / 255)

        yield (np.array(image_batch), np.array(label_batch))

型号:

class CNN():

def __init__(self, train, val, y_train, y_val, batch_size):
    ## Load the batch generator
    self.train_batch_gen = Generator(train, y_train, batch_size)
    self.val_batch_gen = Generator(val, y_val, batch_size)

    self.input_shape = (109, 109, 3)
    self.num_classes = len(np.unique(y_train))
    self.len_train = len(train)
    self.len_val = len(val)

    self.batch_size = batch_size
    self.model = self.buildModel()

def buildModel(self):

    model = models.Sequential()
    model.add(layers.Conv2D(32, (3, 3), activation='relu', padding="same", input_shape=self.input_shape))
    model.add(layers.Conv2D(64, (3, 3), activation='relu', padding="same", input_shape=self.input_shape))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(64, (3, 3), activation='relu', padding="same"))
    model.add(layers.Conv2D(128, (3, 3), activation='relu', padding="same"))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(96, (3, 3), activation='relu', padding="same"))
    model.add(layers.Conv2D(192, (3, 3), activation='relu', padding="same"))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(128, (3, 3), activation='relu', padding="same"))
    model.add(layers.Conv2D(256, (3, 3), activation='relu', padding="same"))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(160, (3, 3), activation='relu', padding="same"))
    model.add(layers.Conv2D(320, (3, 3), activation='relu', padding="same"))
    model.add(layers.AveragePooling2D(pool_size=(4, 4)))
    model.add(layers.Flatten())
    model.add(layers.Dense(128, activation='tanh'))
    model.add(layers.Dropout(rate=0.1))
    model.add(layers.Dense(self.num_classes, activation = "softmax")) #Classification layer or output layer
    opt = tf.keras.optimizers.Adam(learning_rate=0.00001)
    model.compile(optimizer=opt, loss='sparse_categorical_crossentropy', metrics=['accuracy'])

    return model

def trainModel(self, epochs):

    self.model.fit_generator(generator=self.train_batch_gen,
                            steps_per_epoch = int(self.len_train // self.batch_size),
                            epochs=epochs,
                            validation_data = self.val_batch_gen,
                            validation_steps = int(self.len_val // self.batch_size))

【问题讨论】:

  • 您是否尝试过改变 Adam 优化器的学习率?它可能太小了,您应该更喜欢默认值。

标签: python tensorflow keras deep-learning conv-neural-network


【解决方案1】:

就我而言,我使用了sparse_categorical_crossentropy 和编号为[1,2,3] 的标签(3 个类别)。在这种情况下,它从一开始就产生了 NaN。

当我将标签从 [1,2,3] 更改为 [0,1,2] 时,问题就消失了。

【讨论】:

  • 这是正确的,尤其是在多分类问题中将最后一层设置为'softmax'时
【解决方案2】:

不知道你为什么会看到那些 nans。我怀疑这与您在dense layer 上的tanh 激活有关。我会用relu 替换它。我还建议在这个密集层上使用更多的神经元,因为对于 10000 的输出来说,128 可能很小。

如果我是你,我也会尝试预训练模型和/或连体网络。

【讨论】:

  • 谢谢,是的,我已经尝试过 relu 和更大的密集层,但没有帮助,大量的类和每个类的少量图像可能会导致这个问题吗?
【解决方案3】:

这看起来像爆炸梯度问题。我建议您检查权重和梯度如何变化。看到这个:https://github.com/keras-team/keras/issues/2226

查看https://www.dlology.com/blog/how-to-deal-with-vanishingexploding-gradients-in-keras/,了解如何发现梯度爆炸问题及其解决方案。还可以在密集层中尝试 Xavier 初始化,以防止梯度爆炸。

【讨论】:

    猜你喜欢
    • 2020-09-30
    • 2018-08-03
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多