<jupyter_start><jupyter_text>Precisión (precision) vs cobertura/sensibilidad (recall/sensitivity) Definiciones:Precisión: Total de verdaderos positivos diagnosticados por el modelo de prueba (prueba rápida en el ejemplo del virus SARS-Cov2) dividido entre el total de observaciones (individuos) clasificadas (diagnosticados) como positivas por el modelo de prueba.Cobertura/Sensibilidad: Total de verdaderos positivos diagnosticados por el modelo de prueba respecto al total de observaciones clasificadas como positivas mediante el modelo de entrenamiento (técnica de PCR en el caso del ejemplo del virus SARS-Cov2 o Gold Standard). También se le conoce como sensibilidad.La siguiente imagen busca esquematizar ambos conceptos, ésta fue tomada de: https://commons.wikimedia.org/wiki/File:Precisionrecall.svg ![preciss_recall.png](https://upload.wikimedia.org/wikipedia/commons/2/26/Precisionrecall.svg) A continuación realizaremos un ejemplo para abordar ambos conceptos a partir de un conjunto de datos de pacientes que tienen una enfermedad cardiaca. La prueba diagnóstica o en otras palabras, el algoritmo clasificatorio que pondremos a prueba será K-Nearest-Neighbors (KNN), dicho algoritmo no será abordado en este momento pero nos servirá para contrastar estas dos métricas de evaluación (así como otras) y entender por qué son útiles para evaluar la calidad de un modelo clasificatorio.<jupyter_code># Loading modules
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
from sklearn.metrics import roc_curve
from sklearn.metrics import roc_auc_score
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import auc
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
# Loading dataset
datos = pd.read_csv("heart.csv")# Download your dataset from here https://www.kaggle.com/ronitf/heart-disease-uci
datos.isnull().sum()# Checking for null elements in observations
len(datos)# Verifying the total "N" of the dataset
# Checking how many patients have the condition and how many not
sns.countplot(datos['target'])
# Add labels
plt.title('Countplot of Target')
plt.xlabel('target')
plt.ylabel('Patients')
plt.show()
# Separating dataset into Target and Input variables
y = datos["target"].values # Target variable, dependent variable.
x = datos.drop(["target"], axis = 1) # Input variables, independent variables.

#Scaling - mandatory for knn
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
x = ss.fit_transform(x)

#SPlitting into train and test
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size = 0.3) # 70% training and 30%<jupyter_output><empty_output><jupyter_text>Un aspecto que aún no heos tratado es ¿cómo determinar la K óptima para un algoritmo clasificatorio?, existen varios criterios, sin embargo, los abordaremos en clases posteriores. De momento sepamos que dicho valor puede ser determinado a partir de un "test score" o puntaje de prueba calculado para varios valores de K, y en consecuencia el valor más alto nos indicará que número de grupos o "clusters" (K) es el adecuado.Para este ejemplo usaremos el valor de K = 3 para construir nuestro clasificador.<jupyter_code>#Setup a knn classifier with k=3 neighbors
knn = KNeighborsClassifier(3)
knn.fit(X_train, y_train)
knn.score(X_test, y_test)
knn.fit(X_train, y_train)<jupyter_output><empty_output><jupyter_text>Ahora bien, ¿cómo evaluamos si el desempeño del clasificador es bueno o malo?Pues utilizando nuestras métricas de evaluación y para obtenerlas tenemos que construir nuestra matriz de confusión:<jupyter_code># Building confussion matrix
y_pred = knn.predict(X_test)
confusion_matrix(y_pred,y_test)
pd.crosstab(y_pred, y_test, rownames = ['Predicted'], colnames = ['Actual'], margins = True)<jupyter_output><empty_output><jupyter_text>Ejercicio y definición de Exactitud (Accuracy) : Calcula a partir de la matriz anterior los valores de Precisión (Precision), Sensibilidad o Cobertura (Recall) y el valor de Exactitud (Accuracy). Para esto puedes consultar el material que previamente se te compartió en donde viene la definición de Exactitud (o si no consulta wikipedia). Una vez calculados estos valores, ponte en la posición de un médico que debe de tomar una decisión en función de estas medidas y discute brevemente qué sería mejor en el caso que estamos abordando: 1. ¿Que la prueba detecte más a los verdaderos positivos (alta Sensibilidad)? y/o ¿que de los positivos que detecte la prueba se tengan pocos falsos positivos (alta Precisión)? 2. ¿Con base en el ejemplo anterior, podría ocurrir un caso hipotético en el que tuvieras un alto valor de Exactitud y un bajo valor de Precisión y/o un bajo valor de Sensibilidad? En función de tu respuesta da un ejemplo de matriz de confusión que la soporte o argumenta por qué no puede darse un ejemplo así.<jupyter_code># print(classification_report(y_test, y_pred)) Exercice correct calculations.<jupyter_output><empty_output><jupyter_text>Definición de valor de F1 (F1-score) : A partir de la pregunta 2 te darás cuenta de que se pueden tener varios casos en cuanto a las métricas de evaluación para una prueba clasificatoria o clasificador. Hablaremos también de una métrica de evaluación que busca ponderar la calidad de la Precisión y la de la Sensibilidad, ya que existen ocasiones en que nos gustaría que ambas métricas fueran lo más altas posibles. Esto se logra a partir de la optimización del llamado valor de F1 (F1-score) el cual se define como la media armónica entre la Precisión y la Sensibilidad.$F1-score=$ ${Precisión~*~Sensibilidad} \over {Precisión~+~Sensibilidad}$  Curva ROC (Receiver Operating Characteristic):  Se trata de un gráfico bidimensional que en el caso de un clasificador binario (clasificador de dos categoría) muestra en el Eje-Y la Tasa de Verdaderos Positivos (True Positive Rate o TPR) contra la la Tasa de Falsos Positivos (False Positive Rate o FPR) en el Eje-X. Es importante mencionar que la Tasa de Verdaderos Positivos es otra manera de llamar a la Sensibilidad, también conocida como Cobertura o como Recall, mientras que la Tasa de Falsos Positivos recordemos que también es conocida como Valor-P en estadística y son todos aquellos individuos u observaciones en donde se cometió un error de Tipo 1, esta segunda tasa puede calcularse como 1-Especificidad, la cual es conocida como Tasa de Verdaderos Negativos o True Negative Rate).Sin embargo, dado el ejemplo anterior sólo tenemos un valor de TPR y uno de FPR, ¿cómo podemos entonces generar una curva o en otras palabras, más parejas de estos valores para graficarlos en dos dimensiones?Para responder lo anterior debemos notar algo, nosotros ya generamos un modelo clasificatorio con KNN para el dataset de enfermedades cardiácas. Dicho modelo "decide" si una observación del conjunto de prueba pertenece o no a una categoría a partir de una cierta probabilidad, éste valor se fija por convención en 0.5, por lo tanto si la probabilidad de que la observación pertenezca a una categoría supera dicho valor dicha observación será clasificada dentro de la categoría y viceversa. Esto no impide que modifiquemos el valor de dicho umbral y por lo tanto que seamos capaces de generar distintos valores de TPR y FPR para distintos valores del umbral de clasificación, que en consecuencia ahora sí podremos graficar como una curva y analizarla.Considerando esto generemos una curva ROC para nuestro clasificador con k=3:<jupyter_code>y_pred_proba = knn.predict_proba(X_test)[:,1]
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)# Generating
print(thresholds)
roc_auc = roc_auc_score(y_test, y_pred_proba)# Calculating Area Under the Curve
plt.title('Receiver Operating Characteristic')
plt.plot(fpr, tpr, 'b', label = 'AUC = %0.2f' % roc_auc)
plt.legend(loc = 'lower right')
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()<jupyter_output>[2.         1.         0.66666667 0.33333333 0.        ]
{'fraction_non_alphanumeric': 0.058124014075961655, 'fraction_numerical': 0.0072806698216235895, 'mean_word_length': 5.583067092651757, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 20, 'https://': 3, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '257139', 'license': 'MIT', 'n_tokens_mistral': 2685, 'n_tokens_neox': 2578, 'n_words': 1077, 'path': 'estadistica/Cobertura, Sensibilidad, F1-Score y Curva Roc.ipynb', 'repo_name': 'mentesniker/Notebooks-Ciencia-de-Datos', 'size': '8241'}