python - 过度拟合——训练和验证准确性之间的巨大差异

标签 python tensorflow keras conv-neural-network

我有一个包含 180k 图像的数据集,我尝试识别图像上的字符(车牌识别)。所有这些车牌都包含 7 个字符,可能有 35 个字符,因此输出向量 y 的形状为 (7, 35)。因此,我对每个车牌标签进行了 onehot 编码。

我应用了 EfficicentNet-B0 模型 ( https://keras.io/api/applications/efficientnet/#efficientnetb0-function ) 的底部和定制的顶部,它分为 7 个分支(因为每个车牌有七个字符)。我使用了 imagenet 的权重并卡住了 efnB0_model 的底层:

def create_model(input_shape = (224, 224, 3)):
    input_img = Input(shape=input_shape)
    model = efnB0_model (input_img)
    model = GlobalAveragePooling2D(name='avg_pool')(model)
    model = Dropout(0.2)(model)
    backbone = model

    branches = []
    for i in range(7):
        branches.append(backbone)
        branches[i] = Dense(360, name="branch_"+str(i)+"_Dense_16000")(branches[i])
        branches[i] = BatchNormalization()(branches[i])
        branches[i] = Activation("relu") (branches[i])
        branches[i] = Dropout(0.2)(branches[i])
              
        branches[i] = Dense(35, activation = "softmax", name="branch_"+str(i)+"_output")(branches[i])
    
    output = Concatenate(axis=1)(branches)
    output = Reshape((7, 35))(output)
    model = Model(input_img, output)

    return model

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

为了训练和验证模型,我只使用了 10,000 张训练图像和 3,000 张验证图像,因为我的模型很大,数据量很大,这会使我的训练非常非常慢。

我使用此 DataGenerator 将批处理提供给我的模型:

class DataGenerator(Sequence):

    def __init__(self, x_set, y_set, batch_size):
        self.x, self.y = x_set, y_set
        self.batch_size = batch_size

    def __len__(self):
        return math.ceil(len(self.x) / self.batch_size)

    def __getitem__(self, idx):
        batch_x = self.x[idx*self.batch_size : (idx + 1)*self.batch_size]
        batch_x = np.array([resize(imread(file_name), (224, 224)) for file_name in batch_x])
        batch_x = batch_x * 1./255
        batch_y = self.y[idx*self.batch_size : (idx + 1)*self.batch_size]
        batch_y = np.array(batch_y)

        return batch_x, batch_y

我使用这段代码拟合模型:

model.fit_generator(generator=training_generator,
                    validation_data=validation_generator,
                    steps_per_epoch = num_train_samples // 32,
                    validation_steps = num_val_samples // 32,
                    epochs = 10, workers=6, use_multiprocessing=True)

现在,经过几个 epoch 的训练,我发现训练准确率和验证准确率存在很大差异。我认为,原因之一是数据量小。在我的模型中还有哪些其他因素会影响这种过度拟合?你认为我的代码/模型有什么完全错误的地方吗?您是否认为该模型也过于庞大和复杂,或者可能是由于对数据进行了预处理?

注意:我已经尝试过数据增强并尝试了没有迁移学习的模型。这导致训练和验证数据的结果不佳。那么,还有什么我可以做的吗?

accuracy

最佳答案

首先是免责声明

您确定这是要遵循的正确方法吗? EfficientNet 是为图像识别而创建的模型,您的任务要求正确定位一张图像中的 7 个字符,识别每个字符,还要求保持字符的顺序。也许像 this medium post 中那样先检测 + 分割然后再识别的方法效率更高(双关语意)。尽管我认为这很可能是您真正的问题,但我会尽量回答您原来的问题。

关于过度拟合的一些一般技巧

有一个很好的指南here在关于如何使用 EfficientNet 进行迁移学习的 Keras 文档中。我将尝试在这里总结一些技巧。

从您的问题看来,您甚至没有进行网络更好地学习任务所必需的微调步骤。

Now, after several epochs of training, I observed big differences regarding training accuracy and validation accuracy.

几个,你的意思是多少个时代?因为从你提出问题的图像来看,我认为第二个完整的时代还为时过早,无法推断你的模型过度拟合。此外,根据代码(10 个时期)和您发布的图像(20 个时期),我会说要训练更多的时期,比如 40。

增加辍学率。尝试一些配置,例如 30%、40%、50%。

实践中的数据增强会增加您拥有的样本数量。然而,你有 180K 图像并且只使用 10K 图像,数据增强是好的,但是当你有更多可用图像时,请先尝试使用它们。从我提到的那个指南来看,似乎使用这个模型和 Google colab 可以使用更多图像进行训练。因此,请尝试增加火车的尺寸。仍然在 DA 主题中,一些转换可能对您的任务有害,例如在您尝试识别数字和字母时旋转或反射过多。

将批量大小减少到 16 可能会提供更多正则化,这有助于防止过度拟合。说正则化,试试申请regularization到您要添加的致密层。

编辑:

在快速阅读您链接的论文后,我重申了我关于纪元的观点,因为论文中显示了 100 个纪元的结果。同样从论文中的图表中,我们可以看出无法确认作者也没有过拟合。此外,Xception 网络的变化一点也不清楚。由于卷积运算的工作方式,更改输入层会对所有其他层的维度产生影响,本文未讨论这一点。为实现该输出维度而执行的操作也不清楚。除了你所做的,我还建议使用池化层来获得你想要的输出维度。最后,论文并没有说明板 block 的定位是如何保证的。我会尝试获取有关您尝试重现的这篇论文的更多详细信息,以确保您没有遗漏模型中的任何内容。

关于python - 过度拟合——训练和验证准确性之间的巨大差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62930951/

相关文章:

python - pandas txt 读取和绘图的问题

python - 单元测试 : How to assert multiple calls of same method?

python - 如何将 report_tensor_allocations_upon_oom 添加到 Keras 中的 RunOptions

python - Pandas - KeyError : '[] not in index' when training a Keras model

tensorflow - 如何提高卷积神经网络中GPU的使用率?

GPU 上的 Tensorflow 比 CPU 上的慢

python - sqlalchemy 一对多加入 Flask 应用程序以获得最大日期

python - choropleth Plotly map 中的自定义垃圾箱

python - 这个 'single' 值在梯度中代表什么?

python - 属性错误 : module 'tensorflow' has no attribute 'get_variable'