Tensorflow взвешенный по сравнению с сигмоидальной кросс-энтропийной потерей

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

Лучший способ решить проблему должен состоять в том, чтобы использовать tf.nn.weighted_cross_entropy_with_logits функция. Тем не менее, я получаю эту ошибку во время выполнения:

ValueError: Tensor conversion requested dtype uint8 for Tensor with dtype float32

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

positive_class_weight = 10
loss = tf.nn.weighted_cross_entropy_with_logits(targets=labels, logits=logits, pos_weight=positive_class_weight)

Любые советы о том, как решить эту проблему? Если я просто передам те же самые метки и тензоры логитов tf.losses.sigmoid_cross_entropy Функция потерь, все работает хорошо (в том смысле, что Tensorflow работает правильно, но, конечно, следующие прогнозы обучения всегда равны нулю).

Смотрите связанную проблему здесь.

1 ответ

Решение

Ошибка, скорее всего, будет выброшена после потери функции, потому что единственное существенное различие между tf.losses.sigmoid_cross_entropy а также tf.nn.weighted_cross_entropy_with_logits является формой возвращенного тензора.

Взгляните на этот пример:

logits = tf.linspace(-3., 5., 10)
labels = tf.fill([10,], 1.)

positive_class_weight = 10
weighted_loss = tf.nn.weighted_cross_entropy_with_logits(targets=labels, logits=logits, pos_weight=positive_class_weight)
print(weighted_loss.shape)

sigmoid_loss = tf.losses.sigmoid_cross_entropy(multi_class_labels=labels, logits=logits)
print(sigmoid_loss.shape)

Тензор logits а также labels вид искусственный, и оба имеют форму (10,), Но важно что weighted_loss а также sigmoid_loss разные. Вот вывод:

(10,)
()

Это потому что tf.losses.sigmoid_cross_entropy выполняет уменьшение (сумма по умолчанию). Таким образом, чтобы воспроизвести это, вы должны обернуть взвешенную потерю tf.reduce_sum(...),

Если это не поможет, убедитесь, что labels тензор имеет тип float32, Эту ошибку очень легко сделать, например, следующее объявление не будет работать:

labels = tf.fill([10,], 1)  # the type is not float!

Вам также может быть интересно прочитать этот вопрос.

Другие вопросы по тегам