Причина этого очевидного несоответствие производительности между категоричны & двоичным кросс-энтропия - это то, что @ xtof54 уже сообщал в его ответе, то есть:
Точность, вычисленная с помощью th е Keras метод «оценка» это просто неправильно при использовании binary_crossentropy с более чем 2 этикеткой
Я хотел бы подробнее рассказать об этом, показывает фактическую основную проблему, объяснить, и предлагает средство.
Такое поведение не является ошибкой; основная причина - довольно тонкая & недокументированная проблема о том, как Keras фактически догадывается, какую точность использовать, в зависимости от выбранной вами функции потерь, когда вы включаете просто metrics=['accuracy']
в свою компиляцию модели. Другими словами, в то время как ваш первый вариант компиляции
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
действительно, ваш второй один:
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
не будет производить то, что вы ожидаете, но причина не использование бинарной перекрестной энтропии (что, по крайней мере, в принципе, является абсолютно допустимой функцией потерь).
Почему? Если вы проверите metrics source code, Keras не определит одну метрику точности, а несколько разных, среди которых binary_accuracy
и categorical_accuracy
. Что происходит under the hood, так это то, что вы выбрали бинарную кросс-энтропию как функцию потерь и не указали определенную метрику точности, Keras (ошибочно ...) сообщает, что вас интересует binary_accuracy
, и это то, что он возвращает - в то время как на самом деле вас интересует categorical_accuracy
.
Давайте проверим, что это так, используя MNIST CNN example в 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
UPDATE: После моего сообщения я обнаружил, что этот вопрос уже был идентифицирован в this answer.
Если это мультиклассируют проблема, вы должны использовать 'categorical_crossentropy'. Также метки необходимо преобразовать в категориальный формат. См. ['To_categorical'] (https://keras.io/utils/np_utils/) для этого. Также см. Определения категориальных и бинарных кроссентропий [здесь] (http://deeplearning.net/software/theano/library/tensor/nnet/nnet.html#theano.tensor.nnet.nnet.binary_crossentropy). –
Мои ярлыки категоричны, создаются с использованием to_categorical (один горячий вектор для каждого класса). Означает ли это, что точность 80% от бинарной кроссентропии - это просто фиктивная цифра? –
думаю. Если вы используете категориальные ярлыки, то есть один горячий вектор, то вы хотите 'категориальный_crossentropy'. Если у вас есть два класса, они будут представлены как «0, 1» в бинарных меток и «10, 01» в формате категориальной метки. –