不均匀的数据集,如果我不能一次加载所有图片,我应该如何训练模型

数据挖掘 机器学习 Python 喀拉斯 张量流
2022-02-21 03:22:19

我有多个类的数据集(大约 50 个)。数据集每个类的图片数量不同,有些有 300 个,有些有 1000 个,还有一些更多,我发现这破坏了我的模型的准确性

首先,数据太大,我无法存储在 RAM 中,所以我必须将其分成几部分(我一次为每个班级拍摄 300 张照片),根据该数据训练网络,然后重复该过程,直到我有没有更多的照片了。

我的问题是,如果我这样做会不会有问题(我想这是来自我的结果)?例如,我有 100 个类别的图片,只剩下 10 个,我只在这 10 个上训练模型,然后只在 5 个上,然后在 3 个上等等?因为我这样做了,在我检查了最小的类之后,整体准确率上升了,但那些较小的类准确率下降了,最后从每个类的 80% 开始,我在 48 个类中得到了 0-2%,和 99% 的 2 节课。

我怎样才能解决这个“不均匀”(我不知道这个词)然后我就不会再有这个问题了?

2个回答

从您的标签中,我看到您使用的是 keras。Keras 为您提供了ImageDataGenerator具有该方法的类flow_from_directory()(请参见此处)。此方法从硬盘驱动器批量加载训练目录中的图像,并仅将当前批次存储在 RAM 中。这消除了您当前在加载图像时面临的瓶颈。

为了解决类不平衡,推荐的方法是使用class_weightkeras 分类器的参数。此参数为数据中的每个类别分配一个权重,允许您对少数类别的图像赋予更高的重要性。这个答案显示了如何计算班级权重。

在下面的代码中,我将所有内容放在一起:

# Define constants - change them according to your requirements
BATCH_SIZE = 128
EPOCHS = 50
IMAGE_SIZE = 224

# Set up Image Data Generator
train_datagen = ImageDataGenerator(dtype=np.float16) # here you can also do some data augmentation

# Set up flow from directory
train_generator = train_datagen.flow_from_directory(directory="path/to/your/directory",
                                                    class_mode="categorical",
                                                    target_size=(IMAGE_SIZE, IMAGE_SIZE),  # resize the images if required
                                                    batch_size=BATCH_SIZE)

# Calculate class weights
counter = Counter(train_generator.classes)
max_val = float(max(counter.values()))
class_weights = {class_id: max_val/num_images for class_id, num_images in counter.items()}

# 
# Here you set up your model ...
# 

# After compiling the model, you fit it to your data using fit_generator
model.fit_generator(train_generator,
                    steps_per_epoch=train_generator.n // BATCH_SIZE,
                    epochs=EPOCHS,
                    class_weight=class_weights,  # use the class_weights as method parameter
                    verbose=1)

您的方法的问题在于,在某些时候,您的网络永远不会获得稀有类的示例。因此,如果他进行更新以降低小规模类的准确性(因为没有剩下的例子),它不会受到惩罚。

您可以考虑以下几种方法来规避此问题:

  1. 您可以重新采样(替换)较小的类,以便在每个类中拥有相同数量的示例。然后,您可以打乱重新采样的数据集并将其用作训练。

  2. 您可以在稀有类上具有更高权重的加权损失(网络在稀有类上出错时会受到更多惩罚)。然而,这可能更难训练,因为它会产生更大的梯度。

但总的来说,我认为你应该只是打乱你的整个数据集,而不是(如果我理解正确的话)取相同数量的每个数据集并最终检查剩余的类。它肯定会增加对最后这些课程的偏见。