Я пытаюсь обучить Си-Эн-Эн классифицировать текст по темам. Когда я использую двоичную кросс-энтропию, я получаю точность ~ 80%, с категориальной кросс-энтропией я получаю точность ~ 50%.
Я не понимаю, почему это так. Это проблема мультикласса, не означает ли это, что я должен использовать категорическую перекрестную энтропию и что результаты с двоичной перекрестной энтропией бессмысленны?
model.add(embedding_layer)
model.add(Dropout(0.25))
# convolution layers
model.add(Conv1D(nb_filter=32,
filter_length=4,
border_mode='valid',
activation='relu'))
model.add(MaxPooling1D(pool_length=2))
# dense layers
model.add(Flatten())
model.add(Dense(256))
model.add(Dropout(0.25))
model.add(Activation('relu'))
# output layer
model.add(Dense(len(class_id_index)))
model.add(Activation('softmax'))
Затем я скомпилирую это либо так, используя categorical_crossentropy
в качестве функции потерь:
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
или
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
Интуитивно понятно, почему я хотел бы использовать категориальную кросс-энтропию, я не понимаю, почему я получаю хорошие результаты с двоичным кодом и плохие результаты с категориальным.
machine-learning
keras
neural-network
deep-learning
conv-neural-network
Даниэль Мессиас
источник
источник
categorical_crossentropy
. Также метки нужно конвертировать в категориальный формат. Смотрите,to_categorical
чтобы сделать это. Также см. Определения категориальных и бинарных кроссентропий здесь .categorical_crossentropy
. Если у вас есть два класса, они будут представлены0, 1
в виде двоичных меток и10, 01
в формате категориальных меток.Dense(1, activation='softmax')
для двоичной классификации это просто неправильно. Помните, что вывод softmax - это распределение вероятностей, равное единице. Если вы хотите иметь только один выходной нейрон с бинарной классификацией, используйте сигмоид с бинарной кросс-энтропией.Ответы:
Причина этого очевидного несоответствия между категориальной и двоичной кросс-энтропией заключается в том, что пользователь xtof54 уже сообщил в своем ответе ниже , а именно:
Я хотел бы подробнее остановиться на этом, продемонстрировать реальную проблему, объяснить ее и предложить решение проблемы.
Такое поведение не ошибка; основная причина является довольно тонким и недокументированным вопросом, как на самом деле Keras догадок , которые точность для использования, в зависимости от функции потерь вы выбрали, когда вы просто включить
metrics=['accuracy']
в вашей модели компиляции. Другими словами, пока ваш первый вариант компиляциидействительно, ваш второй:
не даст того, что вы ожидаете, но причина не в использовании двоичной кросс-энтропии (которая, по крайней мере в принципе, является абсолютно допустимой функцией потерь).
Это почему? Если вы проверите исходный код метрики , Keras определит не одну метрику точности, а несколько разных, среди них
binary_accuracy
иcategorical_accuracy
. Что происходит под капотом, так это то, что, поскольку вы выбрали двоичную перекрестную энтропию в качестве функции потерь и не указали конкретную метрику точности, Керас (ошибочно ...) делает вывод, что вы заинтересованы в этомbinary_accuracy
, и это то, что он возвращает - в то время как на самом деле вы заинтересованы вcategorical_accuracy
.Давайте проверим, что это так, используя пример MNIST CNN в Keras со следующей модификацией:
Чтобы исправить это, то есть использовать действительно бинарную кросс-энтропию в качестве функции потерь (как я уже сказал, в этом нет ничего плохого, по крайней мере, в принципе), в то же время получая категорическую точность, требуемую рассматриваемой проблемой, вы должны явно указать
categorical_accuracy
в Составление модели следующим образом:В примере MNIST после обучения, оценки и прогнозирования набора тестов, как я показываю выше, две метрики теперь совпадают, как и должно быть:
Настройка системы:
ОБНОВЛЕНИЕ : После моего сообщения я обнаружил, что эта проблема уже была определена в этом ответе .
источник
loss='categorical_crossentropy', metrics=['categorical_accuracy']
мультиклассовой классификации? Это была бы моя интуицияВсе зависит от типа проблемы классификации, с которой вы имеете дело. Есть три основных категории
В первом случае следует использовать двоичную кросс-энтропию и цели должны быть закодированы как векторы с одним горячим током.
Во втором случае следует использовать категорическую кросс-энтропию и цели должны быть закодированы как векторы с одним горячим током.
В последнем случае следует использовать двоичную кросс-энтропию и цели должны быть закодированы как векторы с одним горячим током. Каждый выходной нейрон (или единица) рассматривается как отдельная случайная двоичная переменная, и потеря для всего вектора выходных сигналов является продуктом потери одиночных двоичных переменных. Следовательно, это произведение двоичной кросс-энтропии для каждой единицы вывода.
Двоичная кросс-энтропия определяется как
и категориальная кросс-энтропия определяется как
где
c
индекс работает над количеством классовисточник
c
индекс является избыточным в двоичной формуле кросс-энтропии, он не должен быть там (так как есть только 2 класса, и вероятность каждого класса встроенаy(x)
. В противном случае эти формулы должны быть правильными, но замечать те не потери, те Вероятности Если вы хотите потери , вы должны принять.log
из них.Я столкнулся с «перевернутой» проблемой - я получал хорошие результаты с категориальной_кросентропией (с 2 классами) и плохой с двоичной_кросцентропией. Похоже, проблема была в неправильной активации. Правильные настройки были:
binary_crossentropy
: сигмовидная активация, скалярная цельcategorical_crossentropy
: softmax активация, горячая закодированная цельисточник
Это действительно интересный случай. На самом деле в вашей настройке верно следующее утверждение:
Это означает, что с постоянным коэффициентом умножения ваши потери эквивалентны. Странное поведение, которое вы наблюдаете на этапе обучения, может быть примером следующего явления:
adam
- скорость обучения имеет гораздо меньшее значение, чем в начале обучения (это связано с природой этого оптимизатора). Это замедляет обучение и препятствует тому, чтобы ваша сеть, например, оставляла плохой локальный минимум менее возможным.Вот почему этот постоянный фактор может помочь в случае
binary_crossentropy
. После многих эпох - скорость обучения выше, чем вcategorical_crossentropy
случае. Я обычно перезагружаю тренировку (и фазу обучения) несколько раз, когда замечаю такое поведение и / или корректирую вес класса, используя следующую схему:Это приводит к потере от менее частых занятий, уравновешивающих влияние доминирующей потери классов в начале обучения и в дальнейшей части процесса оптимизации.
РЕДАКТИРОВАТЬ:
На самом деле - я проверил это, хотя в случае математики:
должен держать - в случае, если
keras
это не так, потому чтоkeras
автоматически нормализует все выходы для суммирования до1
. Это реальная причина этого странного поведения, так как в случае мультиклассификации такая нормализация вредит обучению.источник
Прокомментировав ответ @Marcin, я более тщательно проверил код одного из моих учеников, где обнаружил такое же странное поведение, даже после всего 2 эпох! (Так что объяснение @ Marcin было не очень вероятно в моем случае).
И я обнаружил, что ответ на самом деле очень прост: точность, вычисленная с помощью метода
evaluate
Кераса, просто неверна при использовании двоичной_кросентропии с более чем 2 метками. Вы можете проверить это, пересчитав точность самостоятельно (сначала вызовите метод Keras «предсказать», а затем вычислите количество правильных ответов, возвращаемых предикатом): вы получите истинную точность, которая намного ниже, чем у Keras «оценивает» один.источник
простой пример под настройкой мультикласса, чтобы проиллюстрировать
Предположим, у вас есть 4 класса (закодированные одним выстрелом) и ниже только один прогноз
true_label = [0,1,0,0] Forecast_label = [0,0,1,0]
при использовании categoryorical_crossentropy точность равна 0, это важно только в том случае, если вы правильно поняли интересующий вас класс.
однако при использовании binary_crossentropy точность рассчитывается для всех классов, для этого прогноза она будет равна 50%. и окончательный результат будет означать индивидуальную точность для обоих случаев.
Рекомендуется использовать categoryorc_crossentropy для задачи с несколькими классами (классы являются взаимоисключающими), но binary_crossentropy для задачи с несколькими метками.
источник
Поскольку это проблема нескольких классов, вы должны использовать categoryorical_crossentropy, двоичная кросс-энтропия даст ложные результаты, скорее всего, будут оцениваться только первые два класса.
50% для многоклассовой задачи может быть достаточно хорошим, в зависимости от количества классов. Если у вас есть n классов, то 100 / n - это минимальная производительность, которую вы можете получить, выдав случайный класс.
источник
при использовании
categorical_crossentropy
потерь ваши цели должны быть в категориальном формате (например, если у вас есть 10 классов, целью для каждой выборки должен быть 10-мерный вектор со всеми нулями, кроме 1 в индексе, соответствующем классу образец).источник
Взгляните на уравнение, которое вы можете найти, что двоичная кросс-энтропия не только наказывает эти метки = 1, прогнозируемые = 0, но и метку = 0, прогнозируемые = 1.
Однако категорическая перекрестная энтропия только наказывает эти метки = 1, но предсказывает = 1. Поэтому мы предполагаем, что существует только ОДНА метка, положительная.
источник
Вы передаете целевой массив формы (x-dim, y-dim) при использовании в качестве потерь
categorical_crossentropy
.categorical_crossentropy
ожидает, что цели будут двоичными матрицами (1 и 0) формы (образцы, классы). Если ваши цели являются целочисленными классами, вы можете преобразовать их в ожидаемый формат с помощью:В качестве альтернативы вы можете использовать
sparse_categorical_crossentropy
вместо этого функцию потерь , которая ожидает целочисленные цели.источник
Двоичный_кроссцентроп (y_target, y_predict) не требуется применять в задаче двоичной классификации. ,
В исходном коде binary_crossentropy () , то на
nn.sigmoid_cross_entropy_with_logits(labels=target, logits=output)
самом деле была использована функция TensorFlow. И в документации сказано, что:источник