Muestra las diferencias entre dos versiones de la página.
Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
clase:iabd:pia:2eval:tema08.metricas_clasificacion [2025/01/09 11:21] admin [Mejores valores de las métricas] |
clase:iabd:pia:2eval:tema08.metricas_clasificacion [2025/02/26 20:11] (actual) admin [Ejercicios] |
||
---|---|---|---|
Línea 4: | Línea 4: | ||
* [[tema08.seleccion-metricas]] | * [[tema08.seleccion-metricas]] | ||
* [[tema08.intervalo_confianza]] | * [[tema08.intervalo_confianza]] | ||
+ | * [[tema08.otras-metricas]] | ||
Línea 242: | Línea 243: | ||
En la siguiente imagen vamos a obtener las métricas y vamos a ver como varían las métricas si aumenta o disminuye el número de positivos. Es decir vamos a ver como dependen la precisión y el VPN según la prevalencia. | En la siguiente imagen vamos a obtener las métricas y vamos a ver como varían las métricas si aumenta o disminuye el número de positivos. Es decir vamos a ver como dependen la precisión y el VPN según la prevalencia. | ||
- | {{ :temp: | + | {{ :clase: |
Vemos que si aumentamos el número de positivos (por lo tanto aumentando la prevalencia), | Vemos que si aumentamos el número de positivos (por lo tanto aumentando la prevalencia), | ||
Línea 358: | Línea 359: | ||
<sxh python> | <sxh python> | ||
metrics=[tf.keras.metrics.Recall()] | metrics=[tf.keras.metrics.Recall()] | ||
- | metrics=[" | + | metrics=[" |
</ | </ | ||
Línea 366: | Línea 367: | ||
history.history[' | history.history[' | ||
</ | </ | ||
+ | |||
+ | <note important> | ||
+ | En versiones antiguas de Tensorflow, se llamaba '' | ||
+ | </ | ||
Ejemplo: | Ejemplo: | ||
Línea 386: | Línea 391: | ||
<sxh python> | <sxh python> | ||
- | def specificity(y_true, | ||
- | threshold=0.5 | ||
- | y_pred = tf.cast(tf.greater(y_score, | ||
+ | from tensorflow.keras import backend as K | ||
- | true_negatives = tf.logical_and(tf.equal(y_true, 0), tf.equal(y_pred, 0)) | + | def specificity(y_true, |
- | | + | |
+ | y_true = K.cast(y_true, dtype=' | ||
+ | | ||
- | negatives =tf.equal(y_true, | ||
- | num_negatives= tf.reduce_sum(tf.cast(negatives, | ||
+ | y_true = tf.reshape(y_true, | ||
+ | y_pred = tf.reshape(y_pred, | ||
+ | |||
+ | |||
+ | TN = K.sum((1 - y_true) * (1 - y_pred)) | ||
+ | FP = K.sum((1 - y_true) * y_pred) | ||
+ | |||
+ | specificity = TN / (TN + FP + K.epsilon()) | ||
- | specificity = num_true_negatives / (num_negatives + tf.keras.backend.epsilon()) | ||
- | | ||
return specificity | return specificity | ||
</ | </ | ||
Línea 426: | Línea 435: | ||
</ | </ | ||
+ | El motivo de éstas 2 líneas de código | ||
+ | <sxh python> | ||
+ | TN = K.sum((1 - y_true) * (1 - y_pred)) | ||
+ | FP = K.sum((1 - y_true) * y_pred) | ||
+ | </ | ||
+ | se puede ver en la siguiente tabla de verdad: | ||
+ | |||
+ | ^ Entradas | ||
+ | ^ '' | ||
+ | | 1 | ||
+ | | 0 | ||
+ | | 0 | ||
+ | | 1 | ||
+ | |||
+ | |||
+ | Y se puede calcular de 2 maneras distintas: | ||
+ | |||
+ | * Aritméticamente | ||
+ | |||
+ | <sxh python> | ||
+ | TP = sum(y_true * y_pred) | ||
+ | TN = sum((1 - y_true) * (1 - y_pred)) | ||
+ | FP = sum((1 - y_true) * y_pred) | ||
+ | FN = sum(y_true * (1 - y_pred)) | ||
+ | </ | ||
+ | |||
+ | |||
+ | * Lógicamente | ||
+ | <sxh python> | ||
+ | TP = sum((y_true==1) & (y_pred==1)) | ||
+ | TN = sum((y_true==0) & (y_pred==0)) | ||
+ | FN = sum((y_true==1) & (y_pred==0)) | ||
+ | FP = sum((y_true==0) & (y_pred==1)) | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
Línea 455: | Línea 501: | ||
Para mostrar la matriz de confusión se usará la siguiente función que usa de '' | Para mostrar la matriz de confusión se usará la siguiente función que usa de '' | ||
<sxh python> | <sxh python> | ||
- | def plot_matriz_confusion(axes, | + | def plot_matriz_confusion(axes, |
success_color=matplotlib.colors.to_rgb('# | success_color=matplotlib.colors.to_rgb('# | ||
failure_color=matplotlib.colors.to_rgb("# | failure_color=matplotlib.colors.to_rgb("# | ||
Línea 461: | Línea 507: | ||
- | if ((vpp is not None) | | + | if ((vpp is not None) | |
- | (vpn is not None) | | + | (vpn is not None) | |
(sensibilidad is not None) | | (sensibilidad is not None) | | ||
- | (especificidad is not None) | | + | (especificidad is not None) | |
(prevalencia is not None) | | (prevalencia is not None) | | ||
- | (f1_score is not None) | | + | (f1_score is not None) | |
(mcc is not None) | | (mcc is not None) | | ||
(auc is not None) ): | (auc is not None) ): | ||
Línea 480: | Línea 526: | ||
+ | if titulo==None: | ||
+ | titulo=" | ||
+ | else: | ||
+ | titulo=titulo+" | ||
labels = [' | labels = [' | ||
Línea 488: | Línea 538: | ||
axes.set_yticklabels(labels, | axes.set_yticklabels(labels, | ||
axes.text(0, | axes.text(0, | ||
- | axes.text(0, | + | axes.text(0, |
axes.text(1, | axes.text(1, | ||
- | axes.text(1, | + | axes.text(1, |
axes.xaxis.tick_top() | axes.xaxis.tick_top() | ||
- | axes.set_xlabel(' | + | axes.set_xlabel(titulo, fontsize=fontsize, |
- | axes.xaxis.set_label_position(' | + | axes.xaxis.set_label_position(' |
- | axes.set_ylabel(' | + | axes.set_ylabel(' |
Línea 505: | Línea 555: | ||
axes.text(1, | axes.text(1, | ||
if (sensibilidad is not None): | if (sensibilidad is not None): | ||
- | axes.text(2, | + | axes.text(2, |
if (especificidad is not None): | if (especificidad is not None): | ||
- | axes.text(2, | + | axes.text(2, |
metricas_generales="" | metricas_generales="" | ||
Línea 513: | Línea 563: | ||
metricas_generales=metricas_generales+f" | metricas_generales=metricas_generales+f" | ||
if (f1_score is not None): | if (f1_score is not None): | ||
- | metricas_generales=metricas_generales+f" | + | metricas_generales=metricas_generales+f" |
if (mcc is not None): | if (mcc is not None): | ||
metricas_generales=metricas_generales+f" | metricas_generales=metricas_generales+f" | ||
if (auc is not None): | if (auc is not None): | ||
- | metricas_generales=metricas_generales+f" | + | metricas_generales=metricas_generales+f" |
- | axes.text(2, | + | axes.text(2, |
</ | </ | ||
Línea 610: | Línea 660: | ||
Crea una red neuronal con los datos de //bread cancer// con las siguientes características: | Crea una red neuronal con los datos de //bread cancer// con las siguientes características: | ||
- | * neuronas por capa:'' | + | * neuronas por capa:'' |
- | * Función de activation: '' | + | * Función de activation: '' |
- | * Nº de epocas: '' | + | * Nº de epocas: '' |
- | * Optimizador: | + | * Optimizador: |
- | Muestra las siguientes métricas durante el entrenamiento (para cada una de las épocas): | + | Muestra las siguientes métricas durante el entrenamiento |
* Loss | * Loss | ||
* Sensibilidad | * Sensibilidad | ||
Línea 621: | Línea 671: | ||
{{: | {{: | ||
+ | |||
+ | <note important> | ||
+ | Separa los datos en 3 conjuntos: | ||
+ | * Entrenamiento (60%) | ||
+ | * Validación (20%) | ||
+ | * Test (20%) | ||
+ | </ | ||
+ | |||
==== Ejercicio 3.B ==== | ==== Ejercicio 3.B ==== | ||
En este ejercicio vamos a mostrar la matriz de confusión de la red que acabamos de crear. | En este ejercicio vamos a mostrar la matriz de confusión de la red que acabamos de crear. | ||
- | Para ello vamos a usar los valores de test que los tenemos en las siguientes variables del ejercicio anterior: | + | Para ello vamos a usar los valores de validación |
- | * '' | + | * '' |
- | * '' | + | * '' |
- | La variable '' | + | La variable '' |
Para ello sigue los siguientes pasos: | Para ello sigue los siguientes pasos: | ||
+ | * Crea una función llamada '' | ||
* Crea una función llamada '' | * Crea una función llamada '' | ||
- | * Calcula '' | + | * Calcula '' |
- | * Haz que '' | + | * Haz que '' |
* Llama a la función '' | * Llama a la función '' | ||
* Muestra la matriz de confusión | * Muestra la matriz de confusión | ||
Línea 658: | Línea 717: | ||
- | ==== Ejercicio | + | ==== Ejercicio |
- | En un nuevo jupyter notebook, carga el modelo y con los datos de test , vuelve | + | Ahora , vamos a calcular |
+ | Para ello en un nuevo jupyter notebook, carga el modelo que guardaste en el ejercicio anterior y vuelve a mostrar la matriz de confusión con todas las métricas. | ||
+ | <note important> | ||
+ | Usa los datos de **test** para obtener las métricas. | ||
+ | </ | ||
- | ==== Ejercicio | + | ==== Ejercicio |
- | Muestra ahora 1 gráfica, en la que se mostrará: | + | Muestra ahora una gráfica, en la que se mostrará: |
* El valor de la sensibilidad y la especificidad según el valor del umbral | * El valor de la sensibilidad y la especificidad según el valor del umbral | ||
Línea 670: | Línea 733: | ||
{{: | {{: | ||
- | ¿Que valor de umbral dejarías? | ||
- | ==== Ejercicio 3.G ==== | + | <note important> |
- | Muestra una gráfica similar a las anteriores pero ahora sea la suma los valores | + | Usa los datos de **test** para obtener las métricas. |
+ | </ | ||
- | A la suma de los 2 valores para obtener el máximo pero restando 1 se le llama $Informedness$ | ||
- | $$ | + | ==== Ejercicio 5.B ==== |
- | Informedness=Sensibilidad+Especificidad-1 | + | Muestra varias matrices de confusión, una para cada uno de estos umbrales: '' |
- | $$ | + | {{: |
- | Muestra un punto con el máximo de la gráfica y el threshold correspondiente al máximo.Además para ese nivel de threshold, **imprime la sensibilidad y la especificidad** | ||
- | {{: | + | ¿Que es mejor una alta precisión alta (VPP) o un alto VPN? Elije el umbral adecuado. |
+ | <note important> | ||
+ | Usa los datos de **test** para obtener las métricas. | ||
+ | </ | ||
+ | ==== Ejercicio 5.C ==== | ||
+ | Ahora calcula una tabla similar a esta para ver resultado de 8 pacientes. | ||
- | ==== Ejercicio 4 ==== | + | <sxh python> |
- | Indica en los siguientes problemas si subirías o bajarías el umbral | + | Paciente |
+ | | ||
+ | ---------- | ||
+ | Nº 347 0.32628 | ||
+ | Nº 270 0.95804 | ||
+ | Nº 213 0.958995 | ||
+ | Nº 3 0.31489 | ||
+ | Nº 214 0.286227 | ||
+ | Nº 265 0 | ||
+ | Nº 92 | ||
+ | Nº 476 0.275804 | ||
+ | </ | ||
- | * Una IA que detecta si hay petroleo en el subsuelo | + | Responde ahora a estas preguntas: |
- | * Una IA que predice si un usuario en Amazon está cometiendo fraude | + | * ¿Que tiene de extraño el valor de algunos resultados? |
- | * Una IA que decide si te concede un préstamo | + | * ¿Es útil el '' |
- | * Una IA que decide una persona en un juicio | + | * Porque $P(Enfermo|Positivo)=VPP=Precisión$ |
- | * Una IA que corrige automáticamente un examen y te dice si has aprobado | + | * Porque $P(Sano|Negativo)=VPN$ es siempre la misma? |
+ | Para saber con que pacientes debe probar concretamente en tu modelo, usa la función '' | ||
+ | <sxh python> | ||
+ | def get_paciente_a_probar(indices, | ||
+ | y_pred_values = y_pred[indices] | ||
+ | sorted_indices = indices[0][np.argsort(order*y_pred_values)] | ||
- | ==== Ejercicio 5.A ==== | + | return sorted_indices[0] |
- | Crea una nueva red neuronal para el problema del //bread cancer// | + | |
- | Ahora razona con cual de las 2 redes te quedarías y que threshold elegirías para cada uno de ellos. | + | def get_pacientes_a_probar(model): |
+ | breast_cancer=load_breast_cancer() | ||
+ | tolerancia=0.07 | ||
+ | desc=-1 | ||
+ | asc=1 | ||
+ | numeros_pacientes=[] | ||
- | Para elegir debes mostrar gráficas | + | y_pred=model.predict(breast_cancer.data,verbose=False).reshape(-1) |
- | * Gráficos de perdida, sensibilida y especificidad durante el entrenamiento | + | |
- | * Matriz de confusión con las métricas: Sensibilidad, | + | |
- | * Threshold vs (Sensibilidad y Especificidad) | + | |
- | * Threshold vs Informedness | + | |
+ | #TP Malo: | ||
+ | numeros_pacientes.append(get_paciente_a_probar(np.where((breast_cancer.target==1) & (y_pred> | ||
+ | #TP Bueno | ||
+ | numeros_pacientes.append(get_paciente_a_probar(np.where((breast_cancer.target==1) & (y_pred> | ||
- | ¿Con que red te quedarías? | + | #FP Malo |
+ | numeros_pacientes.append(get_paciente_a_probar(np.where((breast_cancer.target==0) & (y_pred> | ||
+ | #FP Casi bueno | ||
+ | numeros_pacientes.append(get_paciente_a_probar(np.where((breast_cancer.target==0) & (y_pred> | ||
- | {{: | + | #TN Malo |
+ | numeros_pacientes.append(get_paciente_a_probar(np.where((breast_cancer.target==0) & (y_pred> | ||
+ | #TN Bueno | ||
+ | numeros_pacientes.append(get_paciente_a_probar(np.where((breast_cancer.target==0) & (y_pred> | ||
+ | |||
+ | #FN Malo | ||
+ | numeros_pacientes.append(get_paciente_a_probar(np.where((breast_cancer.target==1) & (y_pred> | ||
+ | #FN Casi bueno | ||
+ | numeros_pacientes.append(get_paciente_a_probar(np.where((breast_cancer.target==1) & (y_pred> | ||
+ | |||
+ | return numeros_pacientes | ||
+ | </ | ||
+ | |||
+ | ==== Ejercicio 6 ==== | ||
+ | Indica en los siguientes problemas si es mejor una precisión alta (VPP) o un alto VPN | ||
+ | |||
+ | * Una IA que detecta si hay petroleo en el subsuelo | ||
+ | * Una IA que predice si un usuario en Amazon está cometiendo fraude | ||
+ | * Una IA que decide si te concede un préstamo | ||
+ | * Una IA que decide una persona en un juicio es inocente | ||
+ | * Una IA que corrige automáticamente un examen y dice si se ha aprobado | ||
- | Además para el nivel de threshold de la red que ha " | ||
- | ==== Ejercicio 5.B ==== | ||
- | Con el modelo elegido, guarda el modelo a disco | ||
- | ==== Ejercicio 5.C ==== | ||
- | Con modelo que has elegido, cárgalo desde disco en otro Jupyter notebook y realiza inferencia de 10 pacientes. | ||
- | Para cada paciente: | ||
- | * Indica su prevalencia (te la tienes que inventar de forma aleatoria) | ||
- | * Indica la probabilidad de que la red haya acertado. | ||