Керрас бинарных crossentropy против категоричности crossentropy производительности?
Я пытаюсь обучить CNN классифицировать текст по темам. Когда я использую binary_crossentropy я получаю ~80% acc, с categorical_crossentrop я получаю ~50% acc.
Я не понимаю, почему это. Это многоклассовая проблема, означает ли это, что я должен использовать категориальные и двоичные результаты бессмысленны?
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'))
затем
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
или
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
7 ответов:
причиной этого очевидного несоответствия производительности между категориальной и двоичной перекрестной энтропией является то, что @xtof54 уже сообщил в своем ответе, т. е.:
точность, вычисленная с помощью метода Keras "evaluate", просто проста неправильно при использовании binary_crossentropy с более чем 2 метками
я хотел бы подробнее остановиться на этом, продемонстрировать фактическую основную проблему, объяснить ее и предложить средство правовой защиты.
этот поведение-это не ошибка; основная причина-довольно тонкая и недокументированная проблема в том, как Keras на самом деле предположения какую точность использовать, в зависимости от выбранной функции потерь, когда вы включаете просто
metrics=['accuracy']
в модели компиляции. Другими словами, пока ваш первый вариант компиляцииmodel.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
действительно, ваш второй:
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
не будет производить то, что вы ожидаете, но причина не в использовании двоичной перекрестной энтропии (что, по крайней мере в принципе, является абсолютно допустимой функцией потерь).
почему это? Если вы проверите исходный код метрики, Keras не определяет одну метрику точности, но несколько разных, среди них
binary_accuracy
иcategorical_accuracy
. Что происходит под капотом это так, поскольку вы выбрали двоичную перекрестную энтропию в качестве своей функции потерь и не указали конкретную метрику точности, Keras (ошибочно...) делает вывод, что вы заинтересованы в элементbinary_accuracy
, и это то, что он возвращает-в то время как на самом деле вы заинтересованы вcategorical_accuracy
.давайте проверим, что это так, с помощью MNIST CNN пример в Keras, со следующей модификацией:
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # WRONG way model.fit(x_train, y_train, batch_size=batch_size, epochs=2, # only 2 epochs, for demonstration purposes verbose=1, validation_data=(x_test, y_test)) # Keras reported accuracy: score = model.evaluate(x_test, y_test, verbose=0) score[1] # 0.9975801164627075 # Actual accuracy calculated manually: import numpy as np y_pred = model.predict(x_test) acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000 acc # 0.98780000000000001 score[1]==acc # False
чтобы исправить это, т. е. использовать действительно двоичную перекрестную энтропию в качестве функции потерь (как я уже сказал, ничего плохого в этом, по крайней мере в принципе), все еще получая категорический точность требуемая проблемой на рука, вы должны спросить явно для
categorical_accuracy
в модели компиляции следующим образом:from keras.metrics import categorical_accuracy model.compile(loss='binary_crossentropy', optimizer='adam', metrics=[categorical_accuracy])
в Примере MNIST, после обучения, подсчета очков и прогнозирования набора тестов, как я показываю выше, две метрики теперь одинаковы, как и должны быть:
# Keras reported accuracy: score = model.evaluate(x_test, y_test, verbose=0) score[1] # 0.98580000000000001 # Actual accuracy calculated manually: y_pred = model.predict(x_test) acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000 acc # 0.98580000000000001 score[1]==acc # True
настройка системы:
Python version 3.5.3 Tensorflow version 1.2.1 Keras version 2.0.4
обновление: после моего поста я обнаружил, что эта проблема уже была идентифицирована в ответ.
это действительно интересный случай. На самом деле в вашей настройке верно следующее утверждение:
binary_crossentropy = len(class_id_index) * categorical_crossentropy
это означает, что до постоянного коэффициента умножения ваши потери эквивалентны. Странное поведение, которое вы наблюдаете во время фазы обучения, может быть примером следующего явления:
- в начале самый частый класс доминирует над потерей - поэтому сеть учится предсказывать в основном этот класс для каждого образец.
- после того, как он узнал наиболее частый шаблон он начинает различать среди менее частых классов. Но когда вы используете
adam
- скорость обучения имеет гораздо меньшее значение, чем в начале обучения (это из-за природы этого оптимизатора). Это делает обучение медленнее и предотвращает вашу сеть, например, оставляя плохой локальный минимум менее возможным.вот почему этот постоянный фактор может помочь в случае
binary_crossentropy
. После многих эпохи - значение скорости обучения больше, чем вcategorical_crossentropy
случае. Я обычно перезапускаю обучение (и фазу обучения) несколько раз, когда замечаю такое поведение или/и корректирую вес класса, используя следующий шаблон:class_weight = 1 / class_frequency
это делает потери от менее частых занятий уравновешивающим влияние потери доминирующего класса в начале обучения и в дальнейшей части процесса оптимизации.
EDIT:
На Самом Деле - Я проверено, что даже если в случае математики:
binary_crossentropy = len(class_id_index) * categorical_crossentropy
должен держать-в случае
keras
это неправда, потому чтоkeras
автоматически нормализует все выходы, чтобы суммировать до1
. Это реальная причина такого странного поведения, так как в случае мультиклассификации такая нормализация вредит обучению.
я столкнулся с "перевернутой" проблемой-я получал хорошие результаты с categorical_crossentropy (с 2 классами) и плохой с binary_crossentropy. Похоже, что проблема была с неправильной функцией активации. Правильные настройки были:
- на
binary_crossentropy
: сигмовидная активация, скалярная цель- на
categorical_crossentropy
: активация softmax, одна горячая закодированная цель
после комментария @Marcin ответ, я более тщательно проверил один из моих студентов код, где я нашел такое же странное поведение, даже после всего лишь 2 эпох ! (Так что объяснение @Marcin было не очень вероятно в моем случае).
и я обнаружил, что ответ на самом деле очень прост: точность, вычисленная с помощью метода Keras "evaluate", просто ошибочна при использовании binary_crossentropy с более чем 2 метками. Вы можете проверить это, пересчитав точность самостоятельно (сначала вызовите Keras метод "предсказать", а затем вычислить количество правильных ответов, возвращенных предсказать): вы получаете истинную точность, которая намного ниже, чем Keras" оценить " один.
все зависит от типа проблемы классификации вы имеете дело. Есть три основные категории;
- binary классификация (два целевых класса)
- мульти-класс классификация (более двух эксклюзивные цели)
- мульти-метка классификация (более двух неисключительной цели), в которых несколько целевых классов могут быть включены одновременно время
в первом случае следует использовать двоичную перекрестную энтропию, а цели должны быть закодированы как однонаправленные векторы.
во втором случае следует использовать категориальную перекрестную энтропию, а цели должны быть закодированы как однонаправленные векторы.
в последнем случае следует использовать двоичную перекрестную энтропию, а цели должны быть закодированы как однонаправленные векторы. Каждый выходной нейрон (или блок) рассматривается как отдельная случайная двоичная переменная, а потери для всего вектор выходов-это произведение потерь одиночных двоичных переменных. Таким образом, это произведение двоичной перекрестной энтропии для каждого отдельного выходного блока.
двоичная перекрестная энтропия определяется как таковая: двоичная перекрестная энтропия и категориальная кросс-энтропия определяется как таковая: категориальных кросс-энтропии
поскольку это многоклассовая проблема, вы должны использовать categorical_crossentropy, двоичная перекрестная энтропия будет давать фиктивные результаты, скорее всего, будет оценивать только первые два класса.
50% для многоклассовой задачи может быть довольно хорошим, в зависимости от количества классов. Если у вас есть n классов, то 100/n-это минимальная производительность, которую вы можете получить, выведя случайный класс.