разница в расчете точности между keras и scikit-learn - PullRequest
1 голос
/ 09 июля 2020

В настоящее время я работаю над классификацией изображений с несколькими метками, используя CNN в keras. В дополнение к точности keras, мы также подтвердили точность scikit-learn с использованием различных методов оценки (отзыв, точность, оценка F1 и точность).

Мы обнаружили, что точность, рассчитанная keras, показывает около 90 %, в то время как scikit-learn показывает только около 60%.

Я не знаю, почему это происходит, поэтому дайте мне знать.

Что-то не так с расчетом keras?

Мы используем сигмоид для функции активации, binary_crossentropy для функции потерь и adam для оптимизатора.

Тренировка Кераса

input_tensor = Input(shape=(img_width, img_height, 3))

base_model = MobileNetV2(include_top=False, weights='imagenet')

#model.summary()

x = base_model.output
x = GlobalAveragePooling2D()(x)
#x = Dense(2048, activation='relu')(x)
#x = Dropout(0.5)(x)
x = Dense(1024, activation = 'relu')(x)

x = Dropout(0.5)(x)
predictions = Dense(6, activation = 'sigmoid')(x)

for layer in base_model.layers:
    layer.trainable = False


model = Model(inputs = base_model.input, outputs = predictions)
print("{}層".format(len(model.layers)))


model.compile(optimizer=sgd, loss="binary_crossentropy", metrics=["acc"])

history = model.fit(X_train, y_train, epochs=50, validation_data=(X_val, y_val), batch_size=64, verbose=2)

model_evaluate()

Керас показал 90% (Точность).

проверка scikit-learn

 from sklearn.metrics import precision_score, recall_score, f1_score, accuracy_score
thresholds=[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]

y_pred = model.predict(X_test)

for val in thresholds:
    print("For threshold: ", val)
    pred=y_pred.copy()
  
    pred[pred>=val]=1
    pred[pred<val]=0
    
    accuracy = accuracy_score(y_test, pred)
    precision = precision_score(y_test, pred, average='micro')
    recall = recall_score(y_test, pred, average='micro')
    f1 = f1_score(y_test, pred, average='micro')
   
    print("Micro-average quality numbers")
    print("Acc: {:.4f}, Precision: {:.4f}, Recall: {:.4f}, F1-measure: {:.4f}".format(accuracy, precision, recall, f1))

Вывод (scikit-learn)

  For threshold:  0.1
Micro-average quality numbers
Acc: 0.0727, Precision: 0.3776, Recall: 0.8727, F1-measure: 0.5271
For threshold:  0.2
Micro-average quality numbers
Acc: 0.1931, Precision: 0.4550, Recall: 0.8033, F1-measure: 0.5810
For threshold:  0.3
Micro-average quality numbers
Acc: 0.3323, Precision: 0.5227, Recall: 0.7403, F1-measure: 0.6128
For threshold:  0.4
Micro-average quality numbers
Acc: 0.4574, Precision: 0.5842, Recall: 0.6702, F1-measure: 0.6243
For threshold:  0.5
Micro-average quality numbers
Acc: 0.5059, Precision: 0.6359, Recall: 0.5858, F1-measure: 0.6098
For threshold:  0.6
Micro-average quality numbers
Acc: 0.4597, Precision: 0.6993, Recall: 0.4707, F1-measure: 0.5626
For threshold:  0.7
Micro-average quality numbers
Acc: 0.3417, Precision: 0.7520, Recall: 0.3383, F1-measure: 0.4667
For threshold:  0.8
Micro-average quality numbers
Acc: 0.2205, Precision: 0.7863, Recall: 0.2132, F1-measure: 0.3354
For threshold:  0.9
Micro-average quality numbers
Acc: 0.1063, Precision: 0.8987, Recall: 0.1016, F1-measure: 0.1825

1 Ответ

2 голосов
/ 09 июля 2020

В случае классификации с несколькими метками могут быть два типа правильных ответов.

  1. Если все вложенные метки верны для прогноза. Пример: в демонстрационном наборе данных y_true есть 5 выходов. В y_pred 3 из них полностью правильные. В этом случае точность должна быть 60%.

  2. Если мы также рассмотрим под-метки многометровой классификации, то точность изменится. Пример: демонстрационный набор данных y_true содержит всего 15 прогнозов. y_pred правильно предсказывает 10 из них. В этом случае точность должна быть 66.7%.

SkLearn обрабатывает классификацию по нескольким меткам, как указано в пункте 1. В то время как метрика точности Keras c соответствует методу, указанному в пункт 2. Пример кода приведен ниже.

Код:

import tensorflow as tf
from sklearn.metrics import accuracy_score
import numpy as np

# A demo dataset 
y_true = np.array([[0, 1, 0], [1, 0, 0], [1, 1, 1], [0, 0, 0], [1, 0, 1]])
y_pred = np.array([[1, 0, 0], [1, 0, 0], [0, 0, 0], [0, 0, 0], [1, 0, 1]])

kacc = tf.keras.metrics.Accuracy()
_ = kacc.update_state(y_true, y_pred)
print(f'Keras Accuracy acc: {kacc.result().numpy()*100:.3}')

kbacc = tf.keras.metrics.BinaryAccuracy()
_ = kbacc.update_state(y_true, y_pred)
print(f'Keras BinaryAccuracy acc: {kbacc.result().numpy()*100:.3}')

print(f'SkLearn acc: {accuracy_score(y_true, y_pred)*100:.3}')

Вывод:

Keras Accuracy acc: 66.7
Keras BinaryAccuracy acc: 66.7
SkLearn acc: 60.0

Следовательно, вы должны выбрать любой из вариантов. Если вы выберете go с помощью метода 1, то вам придется ввести метрику точности c вручную. Однако обучение с несколькими метками обычно выполняется с использованием sigmoid с потерями binary_crossentropy. binary_crossentropy минимизирует потери на основе метода 2. Поэтому вам также следует следовать ему.

...