Я работаю над тестовым заданием по обнаружению вулканов по изображениям с радара. Изображения имеют размер 100x100 пикселей и одноканальные. Набор обучающих данных был сильно несбалансированным (количество изображений без вулканов в 5 раз больше, чем с вулканами).
Существует множество способов решить эту проблему, например веса классов, передискретизацию обучающего набора данных, потерю фокуса и т. Д.
В этой статье я представлю ручную передискретизацию обучающего набора данных, чтобы решить проблему дисбаланса классов.
Давайте сначала рассмотрим распределение классов в данных. Здесь мы видим количество выборок на класс до передискретизации:
Мы можем увидеть 1K образцов с вулканами и около 6K образцов без вулканов.
Передискретизация означает, что мы увеличиваем количество выборок в второстепенных классах, так что количество выборок в разных классах становится равным или близким к нему, таким образом, становится более сбалансированным.
Давайте применим ручную передискретизацию при подготовке обучающих выборок.
Я применил передискретизацию в методе prepareImages:
def prepareImages(train, shape, data_path, mode): for index, row in train.iterrows(): has_volcano = row['Volcano?'] ... if has_volcano and mode == 'train': x_train[count] = img_to_array( cv2.flip( img, 1 ) ) y_train[count] = int(has_volcano) count += 1 // repeat the same step three more times applying different transformation and incrementing count
Здесь читаем атрибут образца «Вулкан?». Если изображение содержит вулкан, мы применяем некоторые преобразования к исходному изображению и добавляем измененное изображение в набор данных вместе с соответствующей меткой. В моем случае я применил 3 переворота (со значениями 0, 1 и -1) и повернул (cv2.ROTATE_90_CLOCKWISE).
Давайте отобразим распределение классов после передискретизации
Экспериментальная оценка передискретизации
Результаты с передискретизацией
Когда не применяется передискретизация
loss: 0.2359 — acc: 0.9202 — val_loss: 0.4253 — val_acc: 0.8626 AUC = 0.500
и график потерь / точности
При выполнении прогноза на тестовом наборе данных мы получаем следующие результаты:
number of images with volcanoes: 0 number of images without volcanoes: 2734
Мы видим, что все тестовые образцы были классифицированы как не имеющие вулканов.
Результаты с передискретизацией
Когда мы применяем передискретизацию
loss: 0.6885 — acc: 0.5264 — val_loss: 0.6856 — val_acc: 0.5718 AUC = 0.504
и наши кривые обучения
При выполнении прогноза на тестовом наборе данных мы получаем следующие результаты:
number of images with volcanoes: 27 number of images without volcanoes: 2707
Вот и все.