На самом деле я работаю над проектом сегментации изображений с Keras.
Я использую реализацию Unet. У меня есть 2 класса, идентифицируемых по значению пикселя, 0 = фон 1 = объект, который я ищу.
У меня есть один выход с функцией активации сигмоида. Я использую двоичную кросс-энтропию с функцией потерь.
Вот проблема: у меня очень несбалансированный набор данных. У меня есть приблизительно 1 белый пиксель на 100 черных пикселей. И из того, что я понял, двоичная кросс-энтропия не очень совместима с несбалансированным набором данных.
Поэтому я пытаюсь реализовать взвешенную кросс-энтропию по следующей формуле:
![enter image description here](https://i.stack.imgur.com/m8CeG.png)
Это мой код:
def weighted_cross_entropy(y_true, y_pred):
w = [0.99, 0.01]
y_true_f = K.flatten(y_true)
y_pred_f = K.flatten(y_pred)
val = - (w[0] * y_true_f * K.log(y_pred_f) + w[1] * (1-y_true_f) * K.log(1-y_predf))
return K.mean(val, axis=-1)
Я использую F1-Score / Dice для измерения результата в конце каждой эпохи.
Но если пройти 5 эпох, потери равны NaN, а показатель F1 остается очень низким (0,02). Кажется, моя сеть не учится, но я не понимаю, почему. Может быть, моя формула неверна? Я также пытался инвертировать значение весов, но результат тот же.
После некоторых исследований я заметил, что можно задавать определенные веса непосредственно в функции подгонки.
Вот так:
from sklearn.utils import class_weight
w = class_weight.compute_class_weight('balanced', np.unique(y.train.ravel()) , y_train.ravel())
model.fit(epochs = 1000, ..., class_weight = w)
Делая это с помощью функции двоичного кросс-энтропийного базиса c, сеть учится правильно и дает лучшие результаты по сравнению без использования предопределенных весов.
Так что я не понимаю Разница между двумя методами. Действительно ли необходимо реализовать функцию взвешенной кросс-энтропии?