Tensorflow / Keras: функция стоимости, которая штрафует определенные ошибки / путаницы - PullRequest
1 голос
/ 27 июня 2019

У меня есть сценарий классификации с более чем 10 классами, где один класс является выделенным «мусорным» классом. С CNN я в настоящее время достигаю точности около 96%, что для меня достаточно.

В этом конкретном приложении ложные срабатывания (распознающие «мусор» как любой не-мусорный класс) намного хуже, чем путаница между не-мусорными классами или ложными отрицаниями (распознавание любого не-мусорного класса вместо «мусора»). Чтобы уменьшить эти ложные срабатывания, я ищу подходящую функцию потерь.

Моей первой идеей было использование категорической кроссентропии и добавление значения штрафа при обнаружении ложного срабатывания: (псевдокод)

loss = categorical_crossentropy(y_true, y_pred) + weight * penalty
penalty = 1 if (y_true == "garbage" and y_pred != "garbage") else 0

Моя реализация Keras:

def penalized_cross_entropy(y_true, y_pred, garbage_id=0, weight=1.0):
    ref_is_garbage = K.equal(K.argmax(y_true), garbage_id)
    hyp_not_garbage = K.not_equal(K.argmax(y_pred), garbage_id)
    penalty_ind = K.all(K.stack([ref_is_garbage, hyp_not_garbage], axis=0), axis=0) # logical and
    penalty = K.cast(penalty_ind, dtype='float32')
    return K.categorical_crossentropy(y_true, y_pred) + weight * penalty

Я пробовал разные значения для weight, но мне не удалось уменьшить количество ложных срабатываний. Для малых значений штраф не имеет никакого эффекта (как и ожидалось), а для очень больших значений (например, weight = 50) сеть распознает только один класс.

  • Является ли мой подход полной чепухой или это теоретически сработает? (Я впервые работаю с нестандартной функцией потерь).

  • Существуют ли другие / лучшие способы наказания за такие ложноположительные ошибки? К сожалению, большинство статей посвящено бинарной классификации, и я не смог найти много для случая мультикласса.

Edit:

Как указано в комментариях, вышеуказанное наказание не дифференцируемо и, следовательно, не влияет на повышение квалификации. Это была моя следующая попытка:

penalized_cross_entropy(y_true, y_pred, garbage_id=0, weight=1.0):
    ngs = (1 - y_pred[:, garbage_id]) # non garbage score (sum of scores of all non-garbage classes)
    penalty = y_true[:, garbage_id] * ngs / (1.-ngs)
    return K.categorical_crossentropy(y_true, y_pred) + weight * penalty

Здесь комбинированные оценки всех классов без мусора добавляются для всех выборок мини-пакета, которые являются ложноположительными. Для образцов, которые не являются ложными срабатываниями, штраф составляет 0.

Я протестировал реализацию на mnist с небольшой сетью с прямой связью и оптимизатором sgd, используя класс "5" в качестве "мусора":

  • Только с кроссцентропией точность составляет около 0,9343 и «ложноположительный показатель» (изображения класса «5» распознаются как нечто иное) 0,0093.

  • При штрафной перекрестной энтропии (вес 3,0) точность равна 0,9378. и ложноположительный показатель составляет 0,0016

Так что, очевидно, это работает, однако я не уверен, что это лучший подход. Также оптимизатор adam не работает с этой функцией потерь, поэтому мне пришлось использовать sgd.

...