Вы, скорее всего, используете параметр average='micro'
для расчета F1-балла. Согласно docs , указание 'micro'
в качестве стратегии усреднения будет:
Глобальное вычисление показателей путем подсчета общего количества истинных положительных, ложных отрицательных и ложных срабатываний.
В задачах классификации, где каждый тестовый пример гарантированно относится к одному классу, вычисление микро F1-оценки эквивалентно вычислению оценки точности. Просто проверьте:
from sklearn.metrics import accuracy_score, f1_score
y_true = [[1, 0, 0]]*950 + [[0, 1, 0]]*30 + [[0, 0, 1]]*20
y_pred = [[1, 0, 0]]*1000
print(accuracy_score(y_true, y_pred)) # 0.95
print(f1_score(y_true, y_pred, average='micro')) # 0.9500000000000001
Вы в основном вычисляли одни и те же метри c дважды. Если вместо этого указать average='macro'
, оценка F1 будет сначала вычисляться для каждой метки независимо, а затем усредняться:
print(f1_score(y_true, y_pred, average='macro')) # 0.3247863247863248
Как видите, общая оценка F1 зависит от стратегии усреднения и Макро F1-оценка менее 0,33 является четким индикатором недостатка модели в задаче прогнозирования.
РЕДАКТИРОВАТЬ:
Поскольку OP спрашивал, когда выбрать, какую стратегию, и я думаю, что это может быть полезно и для других, я постараюсь немного подробнее остановиться на этом вопросе.
scikit-learn
фактически реализует четыре разные стратегии для показателей, которые поддерживают средние значения для задач классификации с несколькими классами и метками. Удобно, что classification_report
вернет все те, которые применяются для данной задачи классификации для Precision , Recall и F1-score :
from sklearn.metrics import classification_report
# The same example but without nested lists. This avoids sklearn to interpret this as a multilabel problem.
y_true = [0 for i in range(950)] + [1 for i in range(30)] + [2 for i in range(20)]
y_pred = [0 for i in range(1000)]
print(classification_report(y_true, y_pred, zero_division=0))
######################### output ####################
precision recall f1-score support
0 0.95 1.00 0.97 950
1 0.00 0.00 0.00 30
2 0.00 0.00 0.00 20
accuracy 0.95 1000
macro avg 0.32 0.33 0.32 1000
weighted avg 0.90 0.95 0.93 1000
Все они дают разную перспективу в зависимости от того, сколько внимания уделяется распределению классов.
micro
среднее - это глобальная стратегия, которая в основном игнорирует наличие различие между классами. Это может быть полезно или оправдано, если кого-то действительно интересуют общие разногласия с точки зрения истинных положительных, ложноотрицательных и ложноположительных результатов, и его не беспокоят различия внутри классов. Как указывалось ранее, если основная проблема не заключается в задаче классификации с несколькими метками, это фактически соответствует оценке точности. (Вот почему функция classification_report
вернула accuracy
вместо micro avg
).
macro
среднее значение в качестве стратегии будет вычислять каждый метри c для каждой метки отдельно и вернуть их невзвешенное среднее значение. Это подходит, если каждый класс имеет одинаковую важность и результат не должен искажаться в пользу какого-либо из классов в наборе данных.
weighted
среднее значение также сначала вычислит каждый метрич. c для каждой этикетки отдельно. Но среднее значение взвешивается в соответствии с поддержкой классов. Это желательно, если важность классов пропорциональна их важности, т. Е. Недопредставленный класс считается менее важным.
samples
среднее значение имеет значение только для классификации с несколькими ярлыками и, следовательно, не возвращается classification_report
в этом примере и также здесь не обсуждается;)
Таким образом, выбор стратегии усреднения и полученного числа, которому можно доверять, действительно зависит от важности классов. Я вообще забочусь о различиях классов (если нет -> микро-среднее), и если да, то все ли классы одинаково важны (если да -> среднее макро) или более важен класс с более высокой поддержкой (-> средневзвешенное значение) .