Як обчислити точність, відкликання, точність та f1-бал для багатокласового випадку за допомогою scikit?


109

Я працюю над проблемою аналізу настроїв, дані виглядають так:

label instances
    5    1190
    4     838
    3     239
    1     204
    2     127

Таким чином, мої дані незбалансовані, оскільки 1190 instancesпозначено міткою 5. Для класифікації Im використовують SVC scikit . Проблема полягає в тому, що я не знаю, як правильно врівноважувати свої дані, щоб точно обчислити точність, відкликання, точність та f1-бал для випадку багатокласового. Тому я спробував такі підходи:

Перший:

    wclf = SVC(kernel='linear', C= 1, class_weight={1: 10})
    wclf.fit(X, y)
    weighted_prediction = wclf.predict(X_test)

print 'Accuracy:', accuracy_score(y_test, weighted_prediction)
print 'F1 score:', f1_score(y_test, weighted_prediction,average='weighted')
print 'Recall:', recall_score(y_test, weighted_prediction,
                              average='weighted')
print 'Precision:', precision_score(y_test, weighted_prediction,
                                    average='weighted')
print '\n clasification report:\n', classification_report(y_test, weighted_prediction)
print '\n confussion matrix:\n',confusion_matrix(y_test, weighted_prediction)

Друге:

auto_wclf = SVC(kernel='linear', C= 1, class_weight='auto')
auto_wclf.fit(X, y)
auto_weighted_prediction = auto_wclf.predict(X_test)

print 'Accuracy:', accuracy_score(y_test, auto_weighted_prediction)

print 'F1 score:', f1_score(y_test, auto_weighted_prediction,
                            average='weighted')

print 'Recall:', recall_score(y_test, auto_weighted_prediction,
                              average='weighted')

print 'Precision:', precision_score(y_test, auto_weighted_prediction,
                                    average='weighted')

print '\n clasification report:\n', classification_report(y_test,auto_weighted_prediction)

print '\n confussion matrix:\n',confusion_matrix(y_test, auto_weighted_prediction)

Третє:

clf = SVC(kernel='linear', C= 1)
clf.fit(X, y)
prediction = clf.predict(X_test)


from sklearn.metrics import precision_score, \
    recall_score, confusion_matrix, classification_report, \
    accuracy_score, f1_score

print 'Accuracy:', accuracy_score(y_test, prediction)
print 'F1 score:', f1_score(y_test, prediction)
print 'Recall:', recall_score(y_test, prediction)
print 'Precision:', precision_score(y_test, prediction)
print '\n clasification report:\n', classification_report(y_test,prediction)
print '\n confussion matrix:\n',confusion_matrix(y_test, prediction)


F1 score:/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:676: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
  sample_weight=sample_weight)
/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1172: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
  sample_weight=sample_weight)
/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1082: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
  sample_weight=sample_weight)
 0.930416613529

Однак я отримую такі попередження:

/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1172:
DeprecationWarning: The default `weighted` averaging is deprecated,
and from version 0.18, use of precision, recall or F-score with 
multiclass or multilabel data or pos_label=None will result in an 
exception. Please set an explicit value for `average`, one of (None, 
'micro', 'macro', 'weighted', 'samples'). In cross validation use, for 
instance, scoring="f1_weighted" instead of scoring="f1"

Як я можу правильно поводитися зі своїми незбалансованими даними, щоб обчислити правильні показники класифікатора?


То чому б не додати averageпараметр у третьому випадку?
Янцзі

1
@yangjie я не знаю. Я просто перевіряю документацію, але я не розумію, як правильно використовувати показники для незбалансованих даних. Не могли б ви надати більш широке пояснення та приклад? Дякую!
new_with_python

Відповіді:


164

Думаю, існує велика плутанина щодо того, які ваги використовуються для чого. Я не впевнений, що точно знаю, що вас турбує, тому я збираюсь висвітлювати різні теми, нехай мати з собою;).

Вага класу

Ваги з class_weightпараметра використовуються для тренування класифікатора . Вони не використовуються для обчислення будь-якої з показників, які ви використовуєте : при різній вазі класів цифри будуть різними просто тому, що класифікатор різний.

Як правило, у кожному класифікаторі наукового навчання, ваги класів використовуються, щоб сказати вашій моделі, наскільки важливий клас. Це означає, що під час тренінгу класифікатор докладе додаткових зусиль, щоб правильно класифікувати класи з великою вагою.
Як це зробити, залежить від алгоритму. Якщо ви хочете отримати детальну інформацію про те, як він працює для SVC, і документ не має для вас сенсу, сміливо зазначайте це.

Показники

Коли у вас є класифікатор, ви хочете дізнатися, наскільки добре він працює. Тут ви можете використовувати метрики ви згадали: accuracy, recall_score, f1_score...

Зазвичай, коли розподіл класів є незбалансованим, точність вважається поганим вибором, оскільки дає високі бали моделям, які просто прогнозують найчастіший клас.

Я не буду деталізувати всі ці показники, але зауважу, що, за винятком accuracy, вони, природно, застосовуються на рівні класу: як ви бачите в цьому printзвіті про класифікацію, вони визначаються для кожного класу. Вони покладаються на такі поняття, як true positivesабо false negativeякі вимагають визначити, який клас є позитивним .

             precision    recall  f1-score   support

          0       0.65      1.00      0.79        17
          1       0.57      0.75      0.65        16
          2       0.33      0.06      0.10        17
avg / total       0.52      0.60      0.51        50

Попередження

F1 score:/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:676: DeprecationWarning: The 
default `weighted` averaging is deprecated, and from version 0.18, 
use of precision, recall or F-score with multiclass or multilabel data  
or pos_label=None will result in an exception. Please set an explicit 
value for `average`, one of (None, 'micro', 'macro', 'weighted', 
'samples'). In cross validation use, for instance, 
scoring="f1_weighted" instead of scoring="f1".

Ви отримуєте це попередження, оскільки використовуєте f1-бал, відкликання та точність, не визначаючи, як вони повинні бути обчислені! Питання може бути перефразоване: з наведеного вище звіту про класифікацію, як вивести одне глобальне число для оцінки f1? Ти міг:

  1. Візьміть середню оцінку f1 для кожного класу: ось avg / totalрезультат вище. Це також називається макро усередненням.
  2. Обчисліть f1-бал за допомогою загального підрахунку істинних позитивних / помилкових негативів тощо (ви підсумовуєте кількість справжніх позитивних / хибних негативів для кожного класу). Aka мікро усереднення.
  3. Обчисліть середньозважене середнє значення f1-балу. Використання 'weighted'в scikit-learn буде зважувати f1-бал на підтримку класу: чим більше елементів має клас, тим важливіше f1-оцінка для цього класу в обчисленні.

Це 3 варіанти у scikit-learn, попередження є, щоб сказати, що потрібно вибрати один . Отже, вам потрібно вказати averageаргумент для методу оцінки.

Який ви обираєте, залежить від того, як ви хочете виміряти ефективність класифікатора: наприклад, макро-усереднення не враховує дисбаланс класу, а оцінка f1 класу 1 буде такою ж важливою, як і оцінка f1 класу 5. Якщо ви використовуєте усереднене зважене значення, ви отримаєте більше значення для 5 класу.

Вся специфікація аргументів у цих показниках зараз не надто чітка в scikit-learn, вона стане кращою у версії 0.18 згідно з документами. Вони видаляють деяку неочевидну стандартну поведінку, і вони видають попередження, щоб розробники помітили це.

Обчислення балів

Останнє, що я хочу зазначити (не соромтеся пропустити його, якщо ви це знаєте) - це те, що бали мають значення лише тоді, коли вони обчислюються за даними, які класифікатор ніколи не бачив . Це надзвичайно важливо, оскільки будь-який бал, який ви отримуєте за даними, які використовувались у підгонці класифікатора, абсолютно не має значення.

Ось спосіб зробити це за допомогою StratifiedShuffleSplit, який дає вам випадкові розбиття ваших даних (після перетасування), які зберігають розподіл міток.

from sklearn.datasets import make_classification
from sklearn.cross_validation import StratifiedShuffleSplit
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, classification_report, confusion_matrix

# We use a utility to generate artificial classification data.
X, y = make_classification(n_samples=100, n_informative=10, n_classes=3)
sss = StratifiedShuffleSplit(y, n_iter=1, test_size=0.5, random_state=0)
for train_idx, test_idx in sss:
    X_train, X_test, y_train, y_test = X[train_idx], X[test_idx], y[train_idx], y[test_idx]
    svc.fit(X_train, y_train)
    y_pred = svc.predict(X_test)
    print(f1_score(y_test, y_pred, average="macro"))
    print(precision_score(y_test, y_pred, average="macro"))
    print(recall_score(y_test, y_pred, average="macro"))    

Сподіваюся, це допомагає.


Як для багатокласового класу визначити вагу класу? Наприклад, що class_weight={1:10}означає дані, які мають 3 класи?
Азіз Джавед

Чи є в будь-якому випадку отримати оцінки мудрої оцінки точності?
Анкур Сінья

Чи можете ви пояснити, як мікро чіткіше працює. Також ви нічого не згадуєте про бінарне
покірне

Для мене стратифікований перемикання створював проблеми, тому я перейшов на тренувальний тест розбиття, як це було показано ValueError: The least populated class in y has only 1 member, which is too few. The minimum number of labels for any class cannot be less than 2.. Він добре працює з розбиткою на тест поїзда, але хтось може мені допомогти, чому я отримую цю помилку з SSS? Дякую.
Акаш Кандпал

Я перевірив ваш код, але у мене є повідомлення про помилки C: \ Users \\ Anaconda3 \ lib \ site-пакети \ sklearn \ metrics \ Class.py: 976: DeprecationWarning: З версії 0.18, бінарний ввід не буде оброблятися спеціально при використанні усереднена точність / відкликання / F-оцінка. Будь ласка, використовуйте prosjeний = 'двійковий', щоб повідомити лише про позитивні показники класу. 'Позитивний виступ у класі.', DeprecationWarning)
Чеді Бечіх

73

Тут дуже багато детальних відповідей, але я не думаю, що ти відповідаєш на правильні запитання. Як я розумію питання, є два питання:

  1. Як оцінити багатокласну проблему?
  2. Як мені поводитися з незбалансованими даними?

1.

Ви можете використовувати більшість функцій оцінювання в scikit-learn як із задачею багаторівневого класу, так і з проблемами одного класу. Наприклад:

from sklearn.metrics import precision_recall_fscore_support as score

predicted = [1,2,3,4,5,1,2,1,1,4,5] 
y_test = [1,2,3,4,5,1,2,1,1,4,1]

precision, recall, fscore, support = score(y_test, predicted)

print('precision: {}'.format(precision))
print('recall: {}'.format(recall))
print('fscore: {}'.format(fscore))
print('support: {}'.format(support))

Таким чином ви отримуєте відчутні та інтерпретаційні номери для кожного з класів.

| Label | Precision | Recall | FScore | Support |
|-------|-----------|--------|--------|---------|
| 1     | 94%       | 83%    | 0.88   | 204     |
| 2     | 71%       | 50%    | 0.54   | 127     |
| ...   | ...       | ...    | ...    | ...     |
| 4     | 80%       | 98%    | 0.89   | 838     |
| 5     | 93%       | 81%    | 0.91   | 1190    |

Тоді...

2.

... Ви можете сказати, чи неврівноважені дані навіть є проблемою. Якщо оцінка балів для менш представлених класів (1 та 2 класу) є нижчою, ніж для класів з більшою кількістю навчальних зразків (4 та 5 класів), то ви знаєте, що незбалансовані дані насправді є проблемою, і ви можете діяти відповідно, як описано в деяких інших відповідях у цій темі. Однак якщо в даних, які ви хочете передбачити, присутній той самий розподіл класів, ваші незбалансовані дані навчання є хорошим представником даних, а значить, незбалансованість - це хороша річ.


1
Чудовий пост і добре сказано. Дякую
Алвіс,

1
Гей, лише наступне запитання: як ви надрукували етикетки за допомогою precision_recall_fscore_support? Чи надруковані етикетки на замовлення?
BigD

@BigD Так, див. Scikit-learn.org/stable/modules/generated/… в самому дні. Встановіть average=Noneі визначте мітки, після чого ви отримаєте метрику, яку шукаєте, для кожної вказаної мітки.
wonderkid2

Чи є в будь-якому випадку отримати оцінки мудрої оцінки точності?
Анкур Сінья

@trollster Я не впевнений, що ти маєш на увазі? Чи не те, що я показую у відповідях оцінок точності?
wonderkid2

16

Поставлене питання

Відповідаючи на запитання "яку метрику слід використовувати для класової класифікації з незбалансованими даними": Macro-F1-мера. Macro Precision і Macro Recall також можуть бути використані, але вони не так легко інтерпретуються, як для двійкової класифікації, вони вже включені у F-міру, а надлишкові метрики ускладнюють порівняння методів, налаштування параметрів тощо.

Мікро усереднення чутливе до дисбалансу класів: якщо ваш метод, наприклад, працює добре для найпоширеніших міток і повністю змішує інші, мікро-усереднені показники показують хороші результати.

Усереднення зважування не дуже підходить для незбалансованих даних, оскільки воно важить за кількістю міток. Більше того, це занадто важко для інтерпретації та непопулярності: наприклад, про таке усереднення не згадується в наступному дуже детальному опитуванні, яке я настійно рекомендую переглянути:

Соколова, Марина та Гай Лапальме. "Систематичний аналіз ефективності заходів для класифікаційних завдань". Обробка та управління інформацією 45.4 (2009): 427-437.

Питання щодо програми

Однак, повертаючись до свого завдання, я б дослідив 2 теми:

  1. метрики, які зазвичай використовуються для вашої конкретної задачі - це дозволяє (a) порівнювати ваш метод з іншими і розуміти, чи ви робите щось не так, і (b) не досліджувати це самостійно і використовувати повторно чужі висновки;
  2. вартість різних помилок ваших методів - наприклад, використання вашої програми може покладатися лише на огляди 4- і 5-зіркових - у цьому випадку для хорошої метрики слід нараховувати лише ці 2 мітки.

Поширені показники. Як я можу зробити висновок про перегляд літератури, є 2 основні показники оцінки:

  1. Точність , яка використовується, наприклад, в

Ю, Квітень та Даріл Чанг. "Багатокласове передбачення настрій за допомогою Yelp Business."

( посилання ) - зауважте, що автори працюють з майже однаковим розподілом оцінок, див. малюнок 5.

Панг, Бо та Лілліан Лі. "Бачення зірок: Використання класових відносин для категоризації настроїв відносно рейтингової шкали." Матеріали 43-ї щорічної зустрічі Асоціації обчислювальної лінгвістики. Асоціація обчислювальної лінгвістики, 2005.

( посилання )

  1. MSE (або, рідше, середня абсолютна помилка - MAE ) - див., Наприклад,

Лі, Мунтаї та Р. Графе. "Аналіз настроїв у багатокласовій формі із відгуками ресторанів". Фінальні проекти від CS N 224 (2010).

( посилання ) - вони досліджують і точність, і MSE, вважаючи останнє кращим

Паппас, Ніколаос, Руе Марконі та Андрій Попеску-Беліс. "Пояснення зірок: зважене багатозначне навчання для аналізу почуттів на основі аспекту". Матеріали конференції 2014 року про емпіричні методи обробки природних мов. № EPFL-CONF-200899. 2014 рік.

( посилання ) - вони використовують scikit-learn для оцінювання та базових підходів та заявляють, що їх код доступний; однак я не можу його знайти, тому, якщо вам це потрібно, напишіть листа авторам, робота є досить новою і, здається, написана на Python.

Вартість різних помилок . Якщо ви більше піклуєтесь про те, щоб уникнути грубих помилок, наприклад, призначаючи 1-зірковий огляд на 5 зірок чи щось подібне, подивіться на MSE; якщо різниця має значення, але не так вже й багато, спробуйте MAE, оскільки вона не має різного рівня; інакше залишайтеся з точністю.

Про підходи, а не про метрики

Спробуйте підходи до регресії, наприклад, SVR , оскільки вони, як правило, перевершують класичні класи класифікаторів, такі як SVC або OVA SVM.


13

Перш за все, трохи складніше, використовуючи лише підрахунок аналізу, щоб дізнатись, чи ваші дані незбалансовані чи ні. Наприклад: 1 на 1000 позитивних спостережень - це лише шум, помилка чи прорив у науці? Ти ніколи не дізнаєшся.
Тому завжди краще використовувати всі наявні у вас знання та обрати його статус усіма розумними.

Гаразд, що робити, якщо це дійсно незбалансовано?
Ще раз - зверніться до своїх даних. Іноді можна знайти одне-два спостереження, помножене на сто разів. Іноді корисно створити ці підроблені однокласні спостереження.
Якщо всі дані чисті, наступним кроком є ​​використання вагових класів у моделі прогнозування.

То як щодо багатокласних показників?
На мій досвід, жодна з ваших показників зазвичай не використовується. Є дві основні причини.
По-перше: завжди краще працювати з ймовірностями, ніж із твердим прогнозом (адже як інакше можна розділити моделі з прогнозуванням 0,9 і 0,6, якщо вони обидва дають вам один клас?)
І по-друге: набагато простіше порівняти свої моделі прогнозування та створити нові ті, що залежать від лише однієї хорошої метрики.
Зі свого досвіду я можу порекомендувати logloss або MSE (або просто середню помилку у квадраті).

Як виправити застереження про склеарн?
Просто (як зауважив Янцзі) перезаписати averageпараметр одним із цих значень: 'micro'(обчислювати показники в усьому світі), 'macro'(обчислювати показники для кожної мітки) або 'weighted'(те саме, що макрос, але з автоматичними вагами).

f1_score(y_test, prediction, average='weighted')

Усі Ваші попередження з'явилися після виклику функцій метрики зі averageзначенням за замовчуванням, 'binary'що не підходить для багатокласового прогнозування.
Удачі та веселощів із машинним навчанням!

Редагувати:
Я знайшов ще одну рекомендацію для відповіді щодо переходу на регресійні підходи (наприклад, SVR), з якими я не можу погодитися. Наскільки я пам’ятаю, немає навіть такого поняття, як багатокласова регресія. Так, є багатозначна регресія, яка набагато відрізняється, і так, можливо, в деяких випадках перемикатися між регресією та класифікацією (якщо класи якимось чином відсортовано), але це досить рідко.

Що я б рекомендував (в рамках scikit-learn) - спробувати ще один дуже потужний інструмент класифікації: збільшення градієнта , випадковий ліс (мій улюблений), KNeighbors та багато іншого.

Після цього ви можете обчислити середнє арифметичне або геометричне між прогнозами та більшу частину часу, ви отримаєте ще кращий результат.

final_prediction = (KNNprediction * RFprediction) ** 0.5

1
> "перемикатися між регресією та класифікацією (якщо класи якимось чином відсортовано), але це досить рідко" Так буває: 5> 4> 3> 2> 1. Я б запропонував вам поглянути на документи для цього завдання - є багато регресійних та класифікаційних підходів до завдання (іноді в одній роботі).
Микита Астраханцев

Тоді це навіть не багатокласова класифікація, а проста регресія.
Влад Миронов

Так, внутрішньо або з точки зору ML це регресія, але на завершальному етапі ми перетворюємо результати регресії в мітки, тому це багатокласова класифікація - з точки зору користувача, або програми.
Микита Астраханцев
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.