Кросс-энтропийная потеря для семантической сегментации Keras
Я почти уверен, что это глупый вопрос, но я не могу найти его нигде, поэтому я попрошу его здесь.
Я занимаюсь сегментацией семантического изображения, используя cnn (unet) в keras с 7 ярлыками. Поэтому мой ярлык для каждого изображения (7, n_rows, n_cols) используется с помощью theano. Таким образом, по 7 слоям для каждого пикселя он кодируется одним горячим. В этом случае правильная функция ошибки для использования категориальной кросс-энтропии? Кажется, что для меня, но для сети, кажется, лучше учиться с бинарной потерей кросс-энтропии. Может кто-то пролить свет на то, почему это было бы и какова принципиальная цель?
Ответы
Ответ 1
Двоичная потеря кросс-энтропии должна использоваться с активацией sigmod
в последнем слое, и это сильно наказывает противоположные предсказания. Он не учитывает, что выход является одним горячим кодом, а сумма предсказаний должна быть 1. Но поскольку ошибочные предсказания сильно наказывают, модель несколько учится правильно классифицировать.
Теперь для принудительного использования предыдущего горячего кода используется активация softmax
с категориальной кросс-энтропией. Это то, что вы должны использовать.
Теперь проблема заключается в использовании softmax
в вашем случае, поскольку Keras не поддерживает softmax на каждом пикселе.
Самый простой способ - перенести размеры (n_rows, n_cols, 7) с помощью слоя Permute
, а затем изменить его на (n_rows * n_cols, 7) с помощью слоя Reshape
. Затем вы можете добавить уровень активации softmax
и использовать кроссентопию. Данные также должны быть соответствующим образом изменены.
Другим способом сделать это будет реализация depth-softmax:
def depth_softmax(matrix):
sigmoid = lambda x: 1 / (1 + K.exp(-x))
sigmoided_matrix = sigmoid(matrix)
softmax_matrix = sigmoided_matrix / K.sum(sigmoided_matrix, axis=0)
return softmax_matrix
и использовать его как лямбда-слой:
model.add(Deconvolution2D(7, 1, 1, border_mode='same', output_shape=(7,n_rows,n_cols)))
model.add(Permute(2,3,1))
model.add(BatchNormalization())
model.add(Lambda(depth_softmax))
Если используется tf
image_dim_ordering
, вы можете сделать это с помощью слоев Permute
.
Подробнее см. здесь.
Ответ 2
Я проверил решение @indraforyou и думаю, что предложенный метод имеет некоторые ошибки. Поскольку секция комментариев не учитывает правильные сегменты кода, я думаю, что вот фиксированная версия:
def depth_softmax(matrix):
from keras import backend as K
exp_matrix = K.exp(matrix)
softmax_matrix = exp_matrix / K.expand_dims(K.sum(exp_matrix, axis=-1), axis=-1)
return softmax_matrix
Этот метод будет ожидать, что порядок матрицы будет (высота, ширина, каналы).
Ответ 3
Поскольку моя репутация ниже 50, я не могу добавить conmment на indraforyou ответ. Я думаю, что есть что-то важное, чтобы заметить. Функция reshape в numpy может указывать порядок изменения формы (т.е. сначала строку или сначала столбец), если вы используете изменение формы для метки groundtruth и вывод слоя. Я думаю, что вы заметите порядок, если не будете использовать тот же способ для изменения их формы и то и другое. Другими словами, операция изменения формы должна быть последовательной. Я надеюсь, что это не лишний совет. Хорошо, дай мне знать.