keras flow_from_directory 过度或欠采样 class

keras flow_from_directory over or undersample a class

我正在尝试用 Keras 做一个二进制 classification 问题,使用 ImageDataGenerator.flow_from_directory 方法生成批次。然而,我的 classes 非常不平衡,比如一个 class 比另一个多 8 倍或 9 倍,导致模型在为每个示例预测相同输出 class 时卡住。有没有办法将 flow_from_directory 设置为在每个时期从我的小 class 过采样或从我的大 class 欠采样?目前,我刚刚在较小的 class 中创建了每个图像的多个副本,但我希望有更多的灵活性。

对于当前版本的 Keras - 仅使用 Keras built-in 方法无法平衡您的数据集。 flow_from_directory 只是构建所有文件及其 类 的列表,对其进行洗牌(如果需要),然后对其进行迭代。

但是你可以做一个不同的技巧 - 通过编写你自己的生成器来平衡 python:

def balanced_flow_from_directory(flow_from_directory, options):
    for x, y in flow_from_directory:
         yield custom_balance(x, y, options)

这里 custom_balance 应该是给定批处理 (x, y) 平衡它并返回平衡批处理 (x', y') 的函数。对于大多数应用程序,批处理的大小不需要相同 - 但有一些奇怪的用例(例如 stateful RNN) - 其中批处理大小应该具有固定大小)。

您还可以计算每个 class 中的文件数并归一化 class_weights

files_per_class = []
for folder in os.listdir(input_foldr):
    if not os.path.isfile(folder):
            files_per_class.append(len(os.listdir(input_foldr + '/' + folder)))
total_files = sum(files_per_class)
class_weights = {}
for i in xrange(len(files_per_class)):
    class_weights[i] = 1 - (float(files_per_class[i]) / total_files)
print (class_weights)
...
...
...
model.fit_generator(... ,class_weight=class_weights)

您可以做的一件事是在调用 model.fit()model.fit_generator() 时设置 class_weight 参数。

您还可以使用 sklearnnumpy 库轻松计算 class_weights,如下所示:

from sklearn.utils import class_weight
import numpy as np

class_weights = class_weight.compute_class_weight(
           'balanced',
            np.unique(train_generator.classes), 
            train_generator.classes)

之后,只需将 class_weights 设置为 class_weight 参数就变得简单了:

model.fit_generator(..., class_weight=class_weights)