【问题标题】:Keras CNN overfitting for more than four classesKeras CNN 过拟合超过四个类别
【发布时间】:2019-09-29 20:59:24
【问题描述】:

我正在尝试使用KerasGoogle QuickDraw 绘图上训练分类器:

import numpy as np
from tensorflow.keras.layers import Conv2D, Dense, Flatten, MaxPooling2D
from tensorflow.keras.models import Sequential

model = Sequential()

model.add(Conv2D(filters=32, kernel_size=5, data_format="channels_last", activation="relu", input_shape=(28, 28, 1)))
model.add(MaxPooling2D(data_format="channels_last"))
model.add(Conv2D(filters=16, kernel_size=3, data_format="channels_last", activation="relu"))
model.add(MaxPooling2D(data_format="channels_last"))

model.add(Flatten(data_format="channels_last"))

model.add(Dense(units=128, activation="relu"))
model.add(Dense(units=64, activation="relu"))
model.add(Dense(units=4, activation="softmax"))

model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])

x = np.load("./x.npy")
y = np.load("./y.npy")

model.fit(x=x, y=y, batch_size=100, epochs=40, validation_split=0.2)

输入数据是一个 4d 数组,每类包含 12000 个标准化图像 (28 x 28 x 1)。输出数据是一个热编码向量的数组。

如果我在四个类上训练这个模型,它会产生令人信服的结果:

(红色为训练数据,蓝色为验​​证数据)

我知道该模型略微过度拟合。但是,我希望架构尽可能简单,所以我接受了。

我的问题是,只要我添加一个任意类,模型就会开始过度拟合:

我尝试了许多不同的方法来防止它过度拟合,例如 Batch Normalization、Dropout、Kernel Regularizers、更多的训练数据和不同的批量大小,但都没有带来任何显着的改进。

我的 CNN 过度拟合的原因可能是什么?


编辑:这是我用来创建x.npyy.npy的代码:

import numpy as np

from tensorflow.keras.utils import to_categorical

files = ['cat.npy', 'dog.npy', 'apple.npy', 'banana.npy', 'flower.npy']

SAMPLES = 12000

x = np.concatenate([np.load(f'./data/{f}')[:SAMPLES] for f in files]) / 255.0
y = np.concatenate([np.full(SAMPLES, i) for i in range(len(files))])

# (samples, rows, cols, channels)
x = x.reshape(x.shape[0], 28, 28, 1).astype('float32')
y = to_categorical(y)

np.save('./x.npy', x)
np.save('./y.npy', y)

.npy 文件来自here

【问题讨论】:

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


    【解决方案1】:

    问题在于如何完成数据拆分。请注意,有 5 个类,您执行 0.2 验证拆分。默认情况下没有改组,并且在您的代码中您按顺序提供数据。这意味着什么:

    • 训练数据完全由 4 个类组成:“cat.npy”、“dog.npy”、“apple.npy”、“banana.npy”。这就是0.8 训练分组。
    • 测试数据是“flower.npy”。这就是您的0.2 验证拆分。该模型从未对此进行过训练,因此其准确性非常差。

    只有validation_split=0.2 这样的结果才有可能实现,因此您可以接近完美的类分离。

    解决方案

    x = np.load("./x.npy")
    y = np.load("./y.npy")
    
    # Shuffle the data!
    p = np.random.permutation(len(x))
    x = x[p]
    y = y[p]
    
    model.fit(x=x, y=y, batch_size=100, epochs=40, validation_split=0.2)
    

    如果我的假设是正确的,请将 validation_split 设置为例如0.5 也应该会给你带来更好的结果(尽管它不是一个解决方案)。

    【讨论】:

    • “如果有四个类,你已经严重拟合了” - 如果你只看前几 (5) 个时期,你会看到相当不错的曲线。我多次运行训练过程,模型始终达到 >90% 的准确度。我得到的最好结果是 6 个 epoch 后达到 95%,这对于我的用例来说已经足够了,我对此很满意。
    • “删除dense_1;添加更多带有3x3内核的convnet;5x5内核相当大,考虑将其变小;考虑完全移除池化层。” - 我试过了所有这一切,都没有任何改进。
    • “考虑完全移除中间密集层。” - 你是什么意思中间密集层
    • “你能粘贴你的代码吗?” - 我使用了完全相同的模型(除了一个额外的输出神经元)。 - “这几乎是不可能的。” - 这也正是让我感到困惑的地方。这就是我在这里问的原因,希望有人知道问题可能是什么。
    • @Scriptim 这正是我要求粘贴确切代码的原因。然而,细微的差别似乎是它的主要嫌疑人。也许粘贴一个要点?
    猜你喜欢
    • 2019-02-10
    • 2021-12-31
    • 2020-10-05
    • 1970-01-01
    • 2020-01-06
    • 2021-03-17
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    相关资源
    最近更新 更多