# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Метрики классификации

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.read_csv('pokemon.csv')
print(df.shape)
df.head()

predictors = ['attack', 'defense', 'speed']
X = df[predictors].values
y = df['is_legendary'].values

X

y[:10]

y.mean()

# +
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X,y, stratify=y, test_size=0.2)
# -

y_train.mean(), y_test.mean()

# +
from sklearn.linear_model import LogisticRegression

model = LogisticRegression(C=10**6)
model.fit(X_train, y_train)
model.coef_
# -

p_hat = model.predict_proba(X_test)[:,-1]  
p_hat[:20] # P(y = 1)

y_hat = model.predict(X_test)
y_hat[:20]

# +
from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=10000)
rf.fit(X_train, y_train)

q_hat = rf.predict_proba(X_test)[:,-1]  
y_rf = rf.predict(X_test)
# -

# ## 1. Доля правильных ответов, accuracy

np.mean(y_hat == y_test)

from sklearn.metrics import accuracy_score
accuracy_score(y_test, y_hat)

y_zero_hat = np.zeros_like(y_test)
y_zero_hat

accuracy_score(y_test, y_zero_hat)

# ## 2. Матрица ошибок, полнота и точность

tr = 0.1
p_hat = model.predict_proba(X_test)[:,-1]  
y_hat = 1*(p_hat > tr)
y_hat

from sklearn.metrics import confusion_matrix
confusion_matrix(y_hat, y_test)

confusion_matrix(y_rf, y_test)

# + active=""
#              y = 0   y = 1
# y_hat = 0     TN      FN
# y_hat = 1     FP      TP
#
# Сколько в принципе единиц из существующих я нашёл? 
# Recall = TP/(TP + FN)
#
# Насколько точно я нахожу единички?
# Precision = TP/(TP + FP)
#
# -

from sklearn.metrics import recall_score, precision_score
print( recall_score(y_test, y_hat) )
print( precision_score(y_test, y_hat) )

print( recall_score(y_test, y_rf) )
print( precision_score(y_test, y_rf) )

# ## 3. Precision-Recall curve
#
# > ЛОЛ! А что если перебирать порог и смотреть какими получаются метрики и рисовать их

# +
from sklearn.metrics import precision_recall_curve

plt.figure(figsize=(6,5))

pr, rc, tres = precision_recall_curve(y_test, p_hat)
plt.plot(rc, pr, lw=2, label='logreg')

pr, rc, tres = precision_recall_curve(y_test, q_hat)
plt.plot(rc, pr, lw=2, label='rf')

plt.xlabel('Recall', fontsize=16)
plt.ylabel('Precision', fontsize=16)
plt.legend(fontsize=16);
# -

# Как принять решение? 
#
# - Можно сказать, что мы хотим максимальную точность при ограничениях на полноту
#
# $$
# \max_{tr} (precision \mid recall > 0.4)
# $$

ind = np.where(pr == pr[rc >= 0.4].max())
pr[ind][0], rc[ind][0], tres[ind][0]

# > ЛМАО! Эту стратегию можно расширить. Можно пытаться накладывать ограничения на precision лиюо другие бизнес-штуки

# - Либо мы можем задать свои предпочтения на множестве метрик => f-мера, если предпочтения выпуклые 

from sklearn.metrics import f1_score
f1_score(y_test, y_hat)

# > ОМГ, все метрики, которые мы посмотрели, зависят от значения порога, а хочется, чтобы не зависили и мы не зацикливались на выборе порога, ну то есть мы хотим сначала обучить модель и понять какая из них самая классная, а уже вторым шагом хотим выбирать порог для принятия решения.
#
# => pr-auc (площадь под pr-кривой)

from sklearn.metrics import average_precision_score
average_precision_score(y_test, y_hat)

average_precision_score(y_test, y_rf)

# ## 4. Roc-auc curve

# + active=""
# # Модель правильно отсортирорвала наблюдения
# y = 1    P(y = 1) = 0.8
# y = 0    P(y = 1) = 0.2 
#
# # Модель неверно отсортирорвала наблюдения
# y = 1    P(y = 1) = 0.3
# y = 0    P(y = 1) = 0.7 
#
# Могу взять все пары из нулей и единий и могу посмотреть насколько хорошо они отсортирорваны, а дальше я могу посчитать долю правильно расположенных пар => ROC-AUC
# -

from sklearn.metrics import roc_auc_score
roc_auc_score(y_test, p_hat)

# +
from sklearn.metrics import roc_curve

plt.figure(figsize=(6,5))

fpr, tpr, tres = roc_curve(y_test, p_hat)
plt.plot(fpr, tpr, lw=2, label='logreg')

fpr, tpr, tres = roc_curve(y_test, q_hat)
plt.plot(fpr, tpr, lw=2, label='rf')

plt.plot([[0,0], [1,1]], linestyle='dashed', color='grey')

plt.xlabel('Recall', fontsize=16)
plt.ylabel('Precision', fontsize=16)
plt.legend(fontsize=16);
# -

#  

StarcoderdataJupyterScriptsDedupFiltered