Вопрос или проблема
Я новичок в tensorflow, и сейчас я пытаюсь найти лучший способ сбалансировать классы в наборе данных, который я загружаю с помощью image_dataset_from_directory. Но я не нашёл способ это сделать. Я видел из разных источников, что SMOTE может помочь, но я не смог найти способ заставить его работать с image_dataset_from_directory.
Набор данных содержит 4 разных класса, один из которых сильно несбалансирован. Ниже показан способ, которым я извлекаю набор данных. Набор данных, который я использую, находится на Kaggle (https://www.kaggle.com/datasets/tourist55/alzheimers-dataset-4-class-of-images/data).
from keras.utils import image_dataset_from_directory as IDFD
IMAGE_SIZE = (176, 208)
BATCH_SIZE = 32
BASE_DIR = '/content/drive/' #это путь к папке на диске, где сохранены изображения
train_ds = IDFD(DATASET_DIR+"/train",
seed=7891,
validation_split=0.13,
subset="training",
labels="inferred",
label_mode="categorical",
interpolation="bilinear",
image_size=IMAGE_SIZE,
batch_size=BATCH_SIZE,
color_mode="rgb")
Я читал документацию по image_dataset_from_directory и искал примеры, но пока не нашёл ничего, что бы работало. Даже Gemini и ChatGPT не приближают меня к ответу.
Очень надеюсь, что кто-то сможет мне помочь с этим. Я был бы очень благодарен за вашу помощь.
Вы не можете сделать это напрямую с image_dataset_from_directory
, так как эта функция предназначена только для создания набора данных из ваших файлов. Тем не менее, вы можете преобразовать свой набор данных train_ds
, чтобы получить другой набор данных с некоторым балансом, если захотите. Посмотрите на tf.data.Dataset, в частности, метод rejection_resample
может быть тем, что вам нужно. Он позволяет вам проводить выборку из данного набора данных таким образом, чтобы достичь определенного целевого распределения классов, например $[0.25, 0.25, 0.25, 0.25]$ в случае четырех классов.
.
Ответ или решение
Для балансировки набора данных, извлеченного с помощью функции image_dataset_from_directory
в TensorFlow, вам потребуется использовать различные методы, поскольку сама функция не предоставляет встроенные механизмы для балансировки классов. Ваша ситуация, при которой в наборе данных несколько классов, причем один из них имеет значительно меньшее количество изображений, требует особого подхода. Рассмотрим несколько способов решения этой проблемы.
Шаг 1: Создание набора данных
Ваш код для извлечения данных выглядит корректно. Вы загружаете изображения, которое автоматически разбивается на наборы для обучения и проверки. Таким образом, мы начнем с загрузки данных:
from keras.utils import image_dataset_from_directory as IDFD
IMAGE_SIZE = (176, 208)
BATCH_SIZE = 32
DATASET_DIR = '/content/drive/' # Путь к папке с изображениями
train_ds = IDFD(DATASET_DIR+"/train",
seed=7891,
validation_split=0.13,
subset="training",
labels="inferred",
label_mode="categorical",
interpolation="bilinear",
image_size=IMAGE_SIZE,
batch_size=BATCH_SIZE,
color_mode="rgb")
Шаг 2: Балансировка классов после извлечения данных
После того как вы извлекли данные, мы можем использовать несколько стратегий для балансировки классов:
-
Повторяющаяся выборка классов: Вы можете создавать примеры для классов с минимальным количеством данных, продублировав их в вашем наборе, чтобы достичь желаемого баланса. Например, вы можете использовать метод
tf.data.Dataset
иflat_map
для увеличения представительства классов с меньшей выборкой. -
rejection_resample: Этот метод позволяет реформировать набор данных так, чтобы достичь желаемой пропорции классов. Однако, он может оказаться не самым простым в реализации.
Реализация повтора выборки классов
Вот пример, как можно реализовать повтора выборки:
import tensorflow as tf
# Подсчет количества экземпляров каждого класса
class_counts = tf.constant([count_class_0, count_class_1, count_class_2, count_class_3]) # замените на свои значения
target_count = tf.reduce_max(class_counts)
# Функция для увеличения экземпляров классов
def oversample(dataset):
sampled_ds = dataset.flat_map(lambda x, y: tf.data.Dataset.from_tensor_slices((x, y)).repeat(target_count // tf.reduce_max(class_counts)))
return sampled_ds
balanced_train_ds = oversample(train_ds)
Шаг 3: Создание и обучение модели
После создания сбалансированного набора данных вы можете приступить к обучению модели как обычно:
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(balanced_train_ds, epochs=epochs)
Заключение
Балансировка классов в наборе данных, созданном с помощью image_dataset_from_directory
, может потребовать дополнительных усилий, но с помощью методов повторной выборки вы сможете достичь желаемых результатов. Используйте приведенные шаги и адаптируйте их к вашим данным. Это обеспечит более качественное обучение вашей модели и улучшит её производительность на различных классах.