„Машинно обучение“

Метрики за оценка на класификационни модели

От точност до f-резултати, ето 8 показателя за изследване на силните и слабите страни на вашия класификатор, заедно с това как да ги внедрите в Python

Въведение

След много дълги дни и безсънни нощи, вие най-накрая изградихте това, което смятате, че е най-добрият класификационен модел досега и сте готови да го представите на вашия клиент. Докато създавате презентацията, вие се опитвате да измислите най-добрия начин да представите, че вашият модел се е представил наистина добре спрямо тестовите данни.

Опитвате се да кажете, че е имал „висок резултат“, когато сте извикали неговия .score() метод, но това просто го кара да звучи като видео игра. Взирате се в екрана си и осъзнавате, че дори не разбирате напълно как този метод оценява модел.

Класификационните модели понякога са по-трудни за оценка и представяне, отколкото за изграждане, но не се страхувайте, тук съм, за да помогна. В тази статия ще направя следното:

  • Представя ви 8 различни показателя за оценка на вашите класификационни модели по ясен и стегнат начин
  • Преведете ви как да ги импортирате или изградите в python с демо модел
  • Предоставя ви случаи на използване за всеки показател, за да можете да решите кой най-добре отговаря на вашите нужди

Среща с нашия демонстрационен модел и данни

За по-голяма простота в тази статия ще използваме данните за оцелелите от „Titanic Competition“ на Kaggle. Тази статия по никакъв начин не е за това как да се изгради най-добрият модел за класификация за това състезание. Моят съвет е да разгледате „видеото“ на Ken Jee, където той разглежда изграждането на данни и модел, ако не сте запознати с този набор от данни.

По-долу ще импортираме данните и ще ги подготвим за обработка:

Днес ще преценим само един модел: класическата логистична регресия. Ако не сте запознати с този модел, моят съвет е да проверите как Джош Стармър третира темата в това „видео“ на StatQuest и не забравяйте, че ако можете да поставите линия, можете да поставите и завивка!

from sklearn.linear_model import LogisticRegression
# Build a logistic regression object
log_reg = LogisticRegression()
# Fit the training data to the model
log_reg.fit(X_train, y_train)
# Make predictions for our test data
y_pred = log_reg.predict(X_test)

Има модели, за които е доказано, че са по-добри при решаването на този конкретен проблем с класификацията, но оценката на резултатите е една и съща, независимо дали е прогноза от логистичния регресионен модел, който сте импортирали от Scikit-learn, или от невронната мрежа, която сте изградили сами.

Матрица на объркването

Най-визуалният начин да разберете производителността на вашия модел е с матрица на объркване. Импортирана от Scikit-learn, матрицата на объркването е проста матрица, която ви казва къде прогнозите на вашия модел попадат в 4 различни категории:

  • Предсказаните от вашия модел записи са в целевия клас и са правилни, те са известни като Истински положителни резултати
  • Предсказаните от вашия модел записи не в целевия клас и бяха правилни, там са известни като Истински отрицателни
  • Предсказаните от вашия модел записи са в целевия клас и са неправилни, те са известни като Грешни положителни резултати
  • Записите, предвидени от вашия модел, не са в целевия клас и са неправилни, те са известни като Грешни отрицания

За данните от Титаник тези четири термина ще означават следното:

  • Истински положителни резултатище бъдат, когато моделът ни правилно прогнозира, че човек ще оцелее
  • Истински негативи ще бъдат, когато моделът ни правилно прогнозира, че човек ще умре
  • Грешни положителни резултати ще бъдат, когато моделът ни неправилно прогнозира, че човек ще оцелее
  • Грешни отрицанияще бъдат, когато моделът ни неправилно прогнозира, че човек ще умре
from sklearn.metrics import confusion_matrix
# This creates our matrix for plotting
con_mat = confusion_matrix(y_test, y_pred)

Двоични проблеми като този винаги ще доведат до масив 2x2. Scikit-Learn всъщност има свой собствен вътрешен начин за начертаване на матрици на объркване, но ние ще го направим отначало със следното предупреждение: Матрицата на объркване на Scikit-Learn винаги ще има прогнозите на вашия модел за x -ос и истинските стойности на оста y, това не е универсално и други програми/ръководства може да ги поставят по различен начин.

Когато разглеждаме нашата матрица, нашата цел е колкото се може повече прогнози да попаднат или в горния ляв (Истински отрицателен), или в долния десен (Истински положителен) квадрат. Колкото по-високи са тези две в сравнение с фалшивите прогнози на нашия модел, толкова по-добре. Нека да разгледаме как изграждаме този сюжет по-долу:

import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
# Changing our dpi enables us to easily resize our image
plt.figure(dpi=100)
# Build a heatmap using the con_mat array
sns.heatmap(con_mat, cmap="YlGnBu", annot=True,
       xticklabels=['Lost at Sea', 'Survived'],
       yticklabels=['Lost at Sea', 'Survived'])
# Remember that our x-axis is always predictions in Scikit-Learn
plt.xlabel('Predicted')
# Our y-axis is always the actual results
plt.ylabel('Actual')
plt.title('Logistic Regression Confusion Matrix');

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

Сега можем лесно да видим, че по-голямата част от прогнозите на нашия модел са правилни и че той е малко по-склонен към фалшиви положителни резултати спрямо фалшиви отрицания, когато е неправилен.

Seaborn също поддържа множество „различни цветови палитри“, от които да избирате в зависимост от вкуса, четливостта или цветовата схема на вашия клиент.

Случаи на употреба:

  • Искате лесно и детайлно да видите къде вашият модел успява и къде се проваля
  • Изграждате презентация и искате визуално да предадете резултатите от вашия модел по ясен и персонализиран начин

Точност, прецизност, припомняне и специфичност

Колкото и добре да изглежда нашата матрица за объркване, може да е трудно да се сравняват модели с нея. Ако се опитвахме да разберем дали логистична регресия, KNN, дърво на решенията или произволна гора са най-добри за нашия проблем, необходимостта да сортираме и сравняваме 4 различни графики, всеки с 4 различни категории, би отнело много време.

За щастие има четири резултата, които можем да изчислим въз основа на връзката между нашите истински прогнози и фалшиви прогнози. Всеки от тях подчертава различен аспект от нашите резултати и кой от тях ще изберем може да се основава на няколко различни фактора, включително нуждите на клиента, това, което предвиждаме, и всички дисбаланси в нашите данни.

Точност:(Истински положителни + Истински отрицателни) / Всички прогнози

Балансиран показател, който възнаграждава модела за правилно прогнозиране както на положителни, така и на отрицателни резултати. Това е по подразбиране за много модели, когато извиквате неговия .score() метод.

Това може да бъде подвеждащо, ако има дисбаланс в нашите данни между целевия клас и нецелевия, т.е. ако имаше 5 от нашия целеви клас в набор от данни от 100 записа и моделът ни прогнозира, че всичко е отрицателно, той все още ще получи точност резултат от 95%.

Показателят за оценка на точността е вграден в Scikit-Learn и просто трябва да бъде импортиран и предвижданията на нашия модел да бъдат вмъкнати заедно с истинските резултати.

from sklearn.metrics import accuracy_score
# Remember to place the true results first 
accuracy = accuracy_score(y_test, y_pred)

Прецизност: Истински положителни резултати / (Истински положителни + фалшиви положителни резултати)

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

Основното притеснение на този показател е, че вашият модел е правилен, когато прогнозира, че точка от данни е положителна, като същевременно прощава всички положителни резултати, които може да е пропуснал. Добър начин да помислите за това е с цитата: „По-добре е десет виновни да избягат, отколкото един невинен да страда.“

Това се използва най-добре, когато последствията от положителната прогноза далеч надхвърлят последствията от отрицателната. Подобно на точността, прецизността може да бъде импортирана от Scikit-Learn.

from sklearn.metrics import precision_score
precision = precision_score(y_test, y_pred)

Припомняне: Истински положителни резултати / (Истински положителни + фалшиви отрицателни)

Мислете за припомнянето като за огледалото на прецизността. Вместо да се приоритизират положителните прогнози, приоритетът на припомнянето е да се гарантира, че всички от целевия клас са правилно идентифицирани, независимо колко други точки от данни са били неправилно обединени с тях.

Акцентът на Recall върху идентифицирането на целия целеви клас е най-добре уловен с хипотетичната ситуация на модел, който трябва да класифицира дали дадено лице има силно инфекциозно заболяване. Фалшиво положителен резултат води до известна уплаха и човекът остава под карантина за няколко седмици. Фалшиво отрицателен резултат означава, че лицето ще бъде свободно да разпространява болестта надлъж и нашир.

Подобно на точността и прецизността, припомнянето може да бъде импортирано от Scikit-Learn.

from sklearn.metrics import recall_score
recall = recall_score(y_test, y_pred)

Специфичност: Истински отрицателни резултати / (Истински отрицателни + фалшиви положителни резултати)

Конкретността не се харесва много и е лесно да се разбере защо. Когато повечето хора изграждат модели, те имат предвид как най-добре ще идентифицират нещо, независимо дали е рядко заболяване, неизпълнение на кредити или „хот-дог/не хот-дог“. Специфичността възнаграждава вашия модел за правилно прогнозиране, че дадена точка от данни не е в целевия клас, наказва го за фалшиви положителни резултати и игнорира всички негови правилни прогнози!

Специфичността все още има своето място като показател, който си струва да се спомене. Ако считаме резултата за специфичност на модела като комплимент към неговия резултат за прецизност, можем, като вземем предвид всички дисбаланси на данните, да използваме двете заедно, за да видим дали моделът е по-добър при връщането на истински отрицателни или истински положителни резултати.

За разлика от другите показатели, спецификата не е включена в Scikit-Learn. Можем да преодолеем това, като създадем универсална функция, тъй като всички матрици на объркване, генерирани от confusion_matrix(), имат идентично индексиране.

def specificty_score(confusion_matrix):
    true_negatives = confusion_matrix[0][0]
    false_positives = confusion_matrix[0][1]
    
    return true_negatives / (true_negatives + false_positives)
specificty = specificty_score(con_mat)

Случаи на употреба:

  • Имате нужда от начин бързо и лесно да сравнявате различни модели
  • Вашият клиент има ясно предпочитание за това как иска моделът да се представя, което може да се изрази в приоритизиране на един от тези 4 резултата

F-резултати

Когато изведем резултати като прецизност и припомняне на клиент, техният отговор може логично да бъде „и двете звучат добре, можем ли да се уверим, че моделът е добър и в двете?“ Макар че да имаме нашата торта и да я изядем също може да бъде трудна задача при класификацията, има поне начин да оцените модел въз основа на връзката между неговата прецизност и запомняне: F-резултати.

F1 резултат: 2 * (прецизност * припомняне) / (прецизност + припомняне)

Резултатът F1 на даден модел е неговата хармонична средна стойност между прецизност и запомняне. Ако искате вашият модел да бъде еднакво добър и в двете, без да предпочитате единия пред другия, това е вашият показател.

F1 може да се импортира директно от Scikit-Learn.

from sklearn.metrics import f1_score
f1 = f1_score(y_test, y_pred)

FβРезултат: (1 +β² ) * (Прецизност * припомняне) / (β² * прецизност + припомняне)

Използването на резултат F1 предполага, че грешните класификации на фалшиво отрицателни или фалшиво положителни резултати водят до равни разходи, нещо, което почти никога не е вярно в реалния живот. За ситуации, в които предпочитаме прецизността или припомнянето, но все пак искаме приноса на другия, можем да използваме резултата Fβ.

За разлика от другите резултати, които сме виждали досега, изчисляването на нашия Fβ резултат изисква допълнителен параметър освен прогнозите на нашия модел и правилните целеви стойности: параметърът β. Един лесен начин да мислите за параметъра β е колко пъти повече предпочитаме припомнянето пред прецизността, т.е. β от .5 означава, че предпочитаме припомнянето наполовина по-малко от прецизността, β от 1 означава, че предпочитаме всеки еднакво, а β от 2 означава, че предпочитаме припомнянето два пъти повече от прецизността.

За щастие, Sciki-Learn има вградена функция за оценка на Fβ, която можем да импортираме.

from sklearn.metrics import fbeta_score
# Our score where we favor recall
fbeta_2 = fbeta_score(y_test, y_pred, 2)
# Our score where we favor precision
fbeta_half = fbeta_score(y_test, y_pred, .5)

Случаи на употреба:

  • Говорили сте с клиента си за различни резултати и те искат баланс между припомняне и прецизност
  • Имате ясно съотношение доколко искате да предпочитате едното пред другото

Модел „манекен“.

Последният показател, който ще разгледам, е измамно прост: колко добре се представя нашият модел в сравнение с прости правила? При сегашното ни състояние можем уверено да кажем, че нашият модел е по-добър от хвърлянето на монета, но какво ще стане, ако просто предвидим всичко като отрицателно или предвидим, че всички жени ще оцелеят и всички мъже ще умрат? Те са известни като „манекени“ модели и могат да бъдат изключително полезни при измерването на това колко успешен е всъщност нашият модел.

Scikit-Learn всъщност има свой собствен „фиктивен класификатор“, който можем да импортираме, но в този случай ще създадем наш собствен масив от прогнози въз основа на правилото за пола, споменато по-горе. Нашата цел е да победим прогнозите, направени с помощта на това просто правило. Ако това не е възможно, трябва да се върнем и да направим следното:

  • Съберете по-добри данни (ако е възможно)
  • Проектирайте нашите функции по-добре
  • Опитайте различни модели и/или различни параметри на модела
# A simple trick since Sex_female is already a binary array
dummy_y = X_test["Sex_female"]
# Generate a dummy confustion matrix
dummy_con_mat = confusion_matrix(y_test, dummy_y)
# Generate the dummy variant of each score
dummy_acc = accuracy_score(y_test, dummy_y)
dummy_prec = precision_score(y_test, dummy_y)
dummy_recall = recall_score(y_test, dummy_y)
dummy_spec = = specificty_score(dummy_con_mat)
dummy_f1 = f1_score(y_test, dummy_y)
dummy_fbeta_2 = fbeta_score(y_test, dummy_y, 2)
dummy_fbeta_half = fbeta_score(y_test, dummy_y, .5)

О, о... изглежда, че трябва да се върнем към чертожната дъска по този въпрос!

Случаи на употреба:

  • Искате да проверите здравината на вашия модел, за да се уверите, че наистина си струва да го използвате в сравнение с прости правила
  • Искате първоначален бенчмарк, който вашите модели да победят

Заключение

Надявам се, че тази статия ще ви даде повече познания за това как да преценявате класификационните модели извън просто използването на вътрешния метод на оценка на модела. При прегледа научихме следното:

  • 8 показателя за оценка на вашите класификационни модели, включително теорията зад тях
  • Как да ги импортирате или изградите в python
  • Използвайте случаи за всеки показател, за да ви помогне да решите кой най-добре отговаря на вашите нужди

Тази статия не е изчерпателна за класификационните показатели и ако никой от тях не се стори подходящ за вашата ситуация, моето предложение е първо да прочетете документацията за „метрики и точкуване“ на Scikit-Learn и да експериментирате оттам. Приятно ловуване!