Кросс-энтропийная потеря для семантической сегментации 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 и вывод слоя. Я думаю, что вы заметите порядок, если не будете использовать тот же способ для изменения их формы и то и другое. Другими словами, операция изменения формы должна быть последовательной. Я надеюсь, что это не лишний совет. Хорошо, дай мне знать.