Подтвердить что ты не робот

Дискуссия классового дисбаланса: масштабирование вклада в потери и sgd

(добавлено обновление к этому вопросу.)

Я аспирант в университете Гента, Бельгия; мои исследования касаются распознавания эмоций глубокими сверточными нейронными сетями. Я использую Caffe для реализации CNN.

Недавно я столкнулся с проблемой дисбаланса классов. Я использую 9216 учебных образцов, прибл. 5% помечены положительно (1), остальные образцы обозначены отрицательно (0).

Я использую слой SigmoidCrossEntropyLoss для вычисления потерь. Во время обучения потери уменьшаются, и точность достигается даже после нескольких эпох. Это связано с дисбалансом: сеть просто всегда предсказывает отрицательный (0). (Точность и отзыв ноль, поддерживая это требование)

Чтобы решить эту проблему, я хотел бы масштабировать вклад в потерю в зависимости от комбинации предсказания-истины (строго наказать ложные негативы). Мой наставник также посоветовал мне использовать масштабный коэффициент, когда backpropagating через стохастический градиентный спуск (sgd): фактор будет коррелирован с дисбалансом в партии. Партия, содержащая только отрицательные образцы, вообще не обновляет веса.

Я добавил только один пользовательский слой в Caffe: чтобы сообщить другие показатели, такие как точность и отзыв. Мой опыт с кодом Caffe ограничен, но у меня много опыта написания кода на С++.


Может ли кто-нибудь помочь мне или указать мне в правильном направлении, как настроить SigmoidCrossEntropyLoss и Sigmoid для размещения следующих изменений:

  • отрегулировать вклад образца в общую потерю в зависимости от комбинации предсказания-истины (истинный положительный, ложноположительный, истинный отрицательный, ложноотрицательный).
  • масштабировать обновление веса, выполняемое стохастическим градиентным спуском, в зависимости от дисбаланса в партии (отрицательные и положительные).

Спасибо заранее!


Update

Я включил InfogainLossLayer, как было предложено Shai. Я также добавил еще один настраиваемый уровень, который создает infogain-матрицу H на основе дисбаланса в текущей партии.

В настоящее время матрица конфигурируется следующим образом:

H(i, j) = 0          if i != j
H(i, j) = 1 - f(i)   if i == j (with f(i) = the frequency of class i in the batch)

Я планирую экспериментировать с различными конфигурациями для матрицы в будущем.

Я тестировал это на дисбалансе 10: 1. Результаты показали, что сеть сейчас изучает полезные вещи: (результаты после 30 эпох)

  • Точность ок. ~ 70% (от ~ 97%);
  • Точность ок. ~ 20% (от 0%);
  • Напомним, ок. ~ 60% (от 0%).

Эти числа были достигнуты примерно в 20 эпох и после этого существенно не изменились.

!! Результаты, изложенные выше, являются просто доказательством концепции, они были получены путем обучения простой сети с несбалансированным набором данных 10: 1.!!

4b9b3361

Ответ 1

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

Потери Infogain определяются с использованием весовой матрицы H (в вашем случае 2 на 2). Значение его записей

[cost of predicting 1 when gt is 0,    cost of predicting 0 when gt is 0
 cost of predicting 1 when gt is 1,    cost of predicting 0 when gt is 1]

Итак, вы можете установить записи H, чтобы отразить разницу между ошибками в прогнозировании 0 или 1.

Вы можете найти, как определить матрицу H для caffe в этой теме.

Что касается весов образцов, вы можете найти этот пост интересный: он показывает, как изменить слой SoftmaxWithLoss, чтобы учитывайте весы образцов.


Недавно модификация потери кросс-энтропии была предложена Цун-Йи Линь, Прия Гойял, Росс Гиршик, Каимлинг Он, Петр Доллар Фокусное потеря для обнаружения плотных объектов, (ICCV 2017).
Идея фокальной потери - назначить разный вес для каждого примера, основываясь на относительной сложности предсказания этого примера (скорее, на основе размера класса и т.д.). С короткого времени, которое я получил, чтобы поэкспериментировать с этой потерей, он чувствует себя выше "InfogainLoss" с весами класса.

Ответ 2

Я также столкнулся с проблемой дисбаланса класса в моей задаче классификации. Прямо сейчас я использую CrossEntropyLoss с весом (документация здесь), и он отлично работает. Идея состоит в том, чтобы дать больше потерь образцам в классах с меньшим количеством изображений.

Вычисление веса

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

cls_num = []
# train_labels is a list of class labels for all training samples
# the labels are in range [0, n-1] (n classes in total)
train_labels = np.asarray(train_labels)
num_cls = np.unique(train_labels).size

for i in range(num_cls):
    cls_num.append(len(np.where(train_labels==i)[0]))

cls_num = np.array(cls_num)

cls_num = cls_num.max()/cls_num
x = 1.0/np.sum(cls_num)

# the weight is an array which contains weight to use in CrossEntropyLoss
# for each class.
weight = x*cls_num