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!
Вам также может быть интересно прочитать этот вопрос.