Tensorflow: Сигмоидальная кросс-энтропийная потеря не заставляет сетевые выходы быть равными 0 или 1 - PullRequest
1 голос
/ 09 апреля 2019

Я хотел бы изучить сегментацию изображения в TensorFlow со значениями в {0.0,1.0}. У меня есть два изображения ground_truth и prediction, каждое из которых имеет форму (120,160). Пиксели ground_truth содержат только значения, равные 0,0 или 1,0.

Прогнозное изображение - это выходной сигнал декодера, а последние два его слоя имеют вид tf.layers.conv2d_transpose и tf.layers.conv2d, например:

 transforms (?,120,160,30) -> (?,120,160,15)
outputs = tf.layers.conv2d_transpose(outputs, filters=15, kernel_size=1, strides=1, padding='same')
# ReLU
outputs = activation(outputs)

# transforms (?,120,160,15) -> (?,120,160,1)
outputs = tf.layers.conv2d(outputs, filters=1, kernel_size=1, strides=1, padding='same')

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

logits = tf.reshape(predicted, [-1, predicted.get_shape()[1] * predicted.get_shape()[2]])
labels = tf.reshape(ground_truth, [-1, ground_truth.get_shape()[1] * ground_truth.get_shape()[2]])

loss = 0.5 * tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=labels,logits=logits))

Эта установка хорошо сходится. Однако я понял, что выходные данные моего последнего NN-слоя во время проверки, похоже, находятся в [-inf, inf]. Если я визуализирую вывод, я вижу, что сегментированный объект не сегментирован, так как почти все пиксели «активированы». Распределение значений для одного выхода последнего слоя conv2d выглядит следующим образом:

imgur.com/a/kSPJneU

Вопрос:

Должен ли я постобработать выходные данные (обрезать отрицательные значения или запустить выход через сигмовидную активацию и т. Д.)? Что мне нужно сделать, чтобы мои выходные значения были равны {0,1}?

1 Ответ

3 голосов
/ 10 апреля 2019

Решил это.Проблема состояла в том, что tf.nn.sigmoid_cross_entropy_with_logits пропускает логиты через сигмовидную оболочку, которая, конечно, не используется во время проверки, так как операция потери вызывается только во время поезда.Поэтому решение:

убедитесь, что сетевые выходы проходят через tf.nn.sigmoid во время проверки / тестирования, например:

return output if is_training else tf.nn.sigmoid(output)
...