Создайте сбалансированную партию с помощью ImageDataGenerator() и flow_from_directory().

Вопрос или проблема

Привет, я новичок в Python и глубоком обучении. Я занимаюсь многоклассовой классификацией. Мой датасет с тремя классами несбалансирован: классы занимают примерно 50%, 40% и 20%. Я пытаюсь создать мини-пакеты с балансированными классами. Я использую class_weight для генерации сбалансированного пакета в fit_generator(), но сомневаюсь, действительно ли это работает, потому что пакеты, сгенерированные train_datagen.flow_from_directory(), не сбалансированы. Сгенерированные пакеты имеют веса около [0.43, 0.38, 0.19]. Мой код выглядит следующим образом:

train_datagen = ImageDataGenerator(rescale=1./255,
                                    featurewise_center=True,
                                    rotation_range=30,
                                    width_shift_range=0.3,
                                    height_shift_range=0.3,
                                    shear_range=0.2,
                                    zoom_range=0.2,
                                    horizontal_flip=True,
                                    fill_mode="constant")

# Training Set
train_set = train_datagen.flow_from_directory(
                                             directory=train_folder,
                                             target_size=input_shape[:2],
                                             batch_size=32,
                                             shuffle=True,
                                             class_mode="categorical")
# Validation Set
val_set = test_datagen.flow_from_directory(
                                            directory=val_folder,
                                            target_size=input_shape[:2],
                                            batch_size=32,
                                            class_mode="categorical",
                                            shuffle=True)

call_backs = [EarlyStopping(monitor="val_loss", patience=train_patience),
             ModelCheckpoint(filepath=output_model, monitor="val_loss", save_best_only=True)]

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

history = model.fit_generator(
          train_set,
          steps_per_epoch=2000 // batch_size,
          epochs=300,
          validation_data=val_set,
           validation_steps=800 // batch_size,
           class_weight=class_weights,
           verbose=1,
           callbacks=call_backs)

Достаточно ли этого кода для генерации сбалансированных пакетов для обучения? Я проверил пакеты, сгенерированные из train_set, они составляют около [0.43, 0.38, 0.19]. Буду признателен за любой совет. Спасибо.

class_weight не влияет на состав пакетов. Вместо этого он применяет вес к функции потерь, который зависит от веса класса.

Ответ или решение

Введение в глубокое обучение и работу с изображениями предполагает сложные настройки и понимание того, как работает модель с неравномерными классами. Ваша задача создания сбалансированной выборки с помощником ImageDataGenerator и методом flow_from_directory в контексте многоклассовой классификации требует детального подхода.

Теоретическая база (Theory)

Основной проблемой, с которой вы столкнулись, является дисбаланс классов в ваших данных. Когда один класс составляет, например, 50% всех данных, а другой 20%, модель может дать предпочтение более частым классам, что приведет к снижению эффективности на реже представленных классах. Это особенно актуально для задач классификации, где чувствительность к каждому классу имеет критическое значение.

Метод class_weight предназначен для компенсации этой проблемы во время обучения, но он накладывает веса на функцию потерь, а не на сами данные. Это значит, что распределение классов в созданных партиях данных не изменится, даже если метрики останутся корректными благодаря весам потерь.

Пример (Example)

Предположим, у вас есть классы "A", "B" и "C" с распределением 50%, 30% и 20% соответственно. Желаемый результат будет выглядеть как набор батчей, в каждом из которых классы представлены в более равномерном количестве. Однако, используя только class_weight, вы увидите, что ваши батчи по-прежнему содержат обилие класса "A". Это потому что веса классов влияют лишь на то, как модель "оценивает" ошибки, но не на то, как эти данные попадают в каждый батч.

Для обеспечения сбалансированных батчей важно учитывать создание выборки, уже сбалансированной на уровне извлечения данных. Обычно это достигается с помощью таких методов, как:

  1. Рандомизированное дублирование данных менее представленных классов для их искусственного увеличения.

  2. Удаление части данных из более частых классов для достижения приблизительного баланса.

  3. Использование специфических методов генерации батчей, таких как BalancedBatchGenerator, или использование библиотеки imbalanced-learn.

Рассмотрим на практике, как это может быть реализовано.

Приложение (Application)

Чтобы сбалансировать сами батчи, а не только учитывать веса на уровне функции потерь, вы можете применить следующие шаги к вашему процессу:

  1. Используйте настраиваемый генератор: Создайте свой собственный генератор батчей, который будет поочередно добавлять изображения из разных классов, пока не достигнет необходимого размера батча. Это можно сделать, создав объект Python-генератора, который важно правильно интегрировать в ваш цикл обучения.

  2. Сравните с доступными средствами: Попробуйте воспользоваться продвинутыми утилитами, которые позволяют более гибко формировать батчи. Например, расширение функциональности ImageDataGenerator, чтобы контролировать распределение классов в батче.

  3. Альтернативные технологии и библиотеки: Такие библиотеки, как imbalanced-learn, предлагают инструменты для балансировки выборок, которые интегрируются с устоявшимися методами машинного обучения из scikit-learn.

Пример настраиваемого генератора батчей:

def balanced_batch_generator(generator, subset_size, batch_size):
    while True:
        x, y = generator.next()
        # Здесь необходима ваша логика для балансировки выборки 
        index_balanced = balance_indices(y, subset_size)  # функция балансировки индексов
        yield x[index_balanced], y[index_balanced]
  1. Используйте стратифицированную выборку: При инициировании выборки в flow_from_directory, можно заранее выделить равные доли классов.

Применив эти методы, вы сможете создать более сбалансированные батчи, что приведет к улучшению точности и устойчивости модели.

Заключение

Сбалансированные батчи — это важный шаг к обеспечению хорошего обобщения вашей модели на различных данных. Понимание механизма весов классов и влияние распределения данных на обучение играет ключевую роль в машинном обучении. Зная и применяя на практике вышеупомянутые методы, вы сможете корректировать неравномерное представление классов и добиться более качественных результатов в ваших экспериментах.

Оцените материал
Добавить комментарий

Капча загружается...