clase:iabd:pia:2eval:tema08.intervalo_confianza
Diferencias
Muestra las diferencias entre dos versiones de la página.
| — | clase:iabd:pia:2eval:tema08.intervalo_confianza [2025/11/03 11:37] (actual) – creado - editor externo 127.0.0.1 | ||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| + | ====== 8.e Intervalos de confianza ====== | ||
| + | Cuando calculamos una métrica realmente no tenemos el valor real de la métrica sino un valor (llamado estimador) que nos ayuda para saber el verdadero valor de la métrica. | ||
| + | |||
| + | |||
| + | El valor real de la métrica no lo podemos obtener pero si al menos in intervalo en el que es probable que esté ese valor real. A ese intervalo se le llama el intervalo de confianza. | ||
| + | |||
| + | En este prospecto médico para un test de COVID se muestran los intervalos de confianza la para la sensibilidad y la especificidad: | ||
| + | |||
| + | Los datos que se muestran son los siguientes: | ||
| + | |||
| + | $$ | ||
| + | \begin{array} | ||
| + | \\ | ||
| + | E& | ||
| + | \\ | ||
| + | S& | ||
| + | \\ | ||
| + | TP& | ||
| + | \\ | ||
| + | TN& | ||
| + | \end{array} | ||
| + | $$ | ||
| + | |||
| + | $$ | ||
| + | \begin{array} | ||
| + | \\ | ||
| + | Sensibilidad& | ||
| + | \\ | ||
| + | Especificidad& | ||
| + | \end{array} | ||
| + | $$ | ||
| + | |||
| + | La sensibilidad real y la especificidad real no la conocemos ya que con otros paciente habría dado unos resultados distintos, por ello se calcula el intervalo de confianza que nos dice que ese intervalo con un 95% de probabilidad tendrá dentro el valor buscado. | ||
| + | |||
| + | Siguiendo con el test de covid los intervalos de confianza mostrados son: | ||
| + | |||
| + | $$ | ||
| + | \begin{array} | ||
| + | \\ | ||
| + | Sensibilidad& | ||
| + | \\ | ||
| + | Especificidad& | ||
| + | \end{array} | ||
| + | $$ | ||
| + | |||
| + | Es decir que: | ||
| + | * El intervalo de confianza de $[91,33\% \; ‑ \; 99,04\%]$ tiene una probabilidad del 95% de contener al valor real de la **Sensibilidad** | ||
| + | * El intervalo de confianza de $[98,22\% \; ‑ \; 99,99\%]$ tiene una probabilidad del 95% de contener al valor real de la **Especificidad** | ||
| + | |||
| + | |||
| + | ===== Cálculo del intervalo de confianza ===== | ||
| + | Hay varias formas de calcular el intervalo de confianza, en el ejemplo de COVID se usa '' | ||
| + | |||
| + | Para calcular esos intervalos se necesitan los siguientes datos: | ||
| + | * Tamaño de la muestra o número de intentos: Realmente es el denominador de nuestra métrica | ||
| + | * Número de éxitos o de positivos: Realmente es el numerador de nuestra métrica | ||
| + | * Nivel de confianza: Suele ser el 95% pero podría ser cualquier valor , aunque si se cambia debería ser un valor mayor aun para estar más seguro. | ||
| + | |||
| + | La forma de calcular los intervalos de confianza es: | ||
| + | * Mediante la siguiente página web: [[https:// | ||
| + | * Mediante la función '' | ||
| + | |||
| + | |||
| + | Desgraciadamente hay varios formas de calcular el intervalo de confianza, los vamos a nombrar ahora y tambien como se //llaman// en la función de '' | ||
| + | |||
| + | ^ Nombre ^ Nombre en '' | ||
| + | | Aproximación normal (Wald) | '' | ||
| + | | Clopper-Pearson exacto basado en la distribución Beta | '' | ||
| + | | Wilson | '' | ||
| + | | Jeffreys con pior Beta(0.5, 0.5) | '' | ||
| + | | Agresti-Coull | '' | ||
| + | |||
| + | Veamos un ejemplo en Python que calcula todos los intervalos de confianza para todos los tipos: | ||
| + | |||
| + | <sxh python> | ||
| + | from statsmodels.stats.proportion import proportion_confint | ||
| + | |||
| + | # Número de éxitos | ||
| + | success = 111 | ||
| + | # Número total de ensayos | ||
| + | total = 115 | ||
| + | # Nivel de confianza deseado | ||
| + | confianza=95 | ||
| + | |||
| + | methods=[' | ||
| + | for method in methods: | ||
| + | lower, upper = proportion_confint(success, | ||
| + | |||
| + | print(f" | ||
| + | </ | ||
| + | |||
| + | Y el resultado es: | ||
| + | <sxh base> | ||
| + | Intervalo de confianza al 95% con el método " | ||
| + | Intervalo de confianza al 95% con el método " | ||
| + | Intervalo de confianza al 95% con el método " | ||
| + | Intervalo de confianza al 95% con el método " | ||
| + | Intervalo de confianza al 95% con el método " | ||
| + | </ | ||
| + | |||
| + | Y podemos observar que el cálculo del intervalo del test de COVID se hizo con '' | ||
| + | |||
| + | ===== Elección del método ===== | ||
| + | De forma general y sin querer entrar en detalles el método que deberemos usar en las métricas será el Jeffreys ('' | ||
| + | |||
| + | ¿Porque Jeffreys? Porque es el que usa estadística bayesiana para calcular el intervalo de confianza. Así que realmente no es un intervalo de confianza sino un intervalo de credibilidad. ¿cual es la diferencia? Vamos a explicarlo con el ejemplo que estamos usando: | ||
| + | * **Intervalo de confianza** | ||
| + | * **Intervalo de credibilidad** | ||
| + | |||
| + | En el siguiente código se puede ver como da el mismo resultado usando '' | ||
| + | |||
| + | **NOTA:La explicación del cálculo bayesiano va más allá del ámbito de este curso de especialización.** | ||
| + | |||
| + | <sxh python> | ||
| + | from scipy.stats import beta | ||
| + | from statsmodels.stats.proportion import proportion_confint | ||
| + | |||
| + | success=111 | ||
| + | total=115 | ||
| + | confidence=0.95 | ||
| + | |||
| + | lower, | ||
| + | print(f" | ||
| + | beta_a=0.5+success | ||
| + | beta_b=0.5+total-success | ||
| + | lower, | ||
| + | print(f" | ||
| + | |||
| + | </ | ||
| + | |||
| + | <sxh base> | ||
| + | Intervalo de confianza usando " | ||
| + | Intervalo de confianza usando Bayes con prior Beta(0.5, | ||
| + | </ | ||
| + | |||
| + | ¿Y cuando se podrían usar otros? El resto no son bayesianos así que dan " | ||
| + | * Clopper-Pearson o Jeffreys: Tamaño de muestra pequeño | ||
| + | * Wilson o Agresti-Coull: | ||
| + | * Normal (Wald): No es recomendable | ||
| + | |||
| + | |||
| + | |||
| + | ===== Comparación de métricas ===== | ||
| + | |||
| + | La mayor utilidad del cálculo del intervalo de confianza es la comparación de las métricas entre distintos modelos y así saber si los modelos realmente tienen las mismas métricas. | ||
| + | |||
| + | Para ello seguiremos la siguiente regla: | ||
| + | * Dos modelos tienen la **misma** métrica si sus intervalos **se solapan** en algún punto | ||
| + | * Dos modelos tienen **distinta** métrica si sus intervalos **no se solapan** en ningún punto | ||
| + | * En caso de **" | ||
| + | |||
| + | Veamos un ejemplo. | ||
| + | |||
| + | Supongamos que tenemos la sensibilidad de 5 modelos y queremos saber si realmente son iguales o no. Los intervalos de confianza de la sensibilidad de los 4 modelos son: | ||
| + | |||
| + | $$ | ||
| + | \begin{array} | ||
| + | \\ | ||
| + | Modelo \; 1& | ||
| + | \\ | ||
| + | Modelo \; 2& | ||
| + | \\ | ||
| + | Modelo \; 3& | ||
| + | \\ | ||
| + | Modelo \; 4& | ||
| + | \\ | ||
| + | Modelo \; 5& | ||
| + | \\ | ||
| + | \end{array} | ||
| + | $$ | ||
| + | |||
| + | Podemos comparar los valores pero es mejor mostrarlos en una gráfica para ayudarnos en el trabajo. | ||
| + | |||
| + | {{: | ||
| + | |||
| + | Se puede apreciar que: | ||
| + | * Los modelos 1 y 2 son iguales aunque es mejor el 1 ya que tiene menor variabilidad. | ||
| + | * Los modelos 3 y 4 son iguales aunque es mejor el 3 ya que tiene menor variabilidad. | ||
| + | |||
| + | Por lo que el orden de los modelos de mejor a peor es: **1, 2, 5, 3 y 4** | ||
| + | |||
| + | |||
| + | La siguiente función en Python crea un gráfico para poder comparar intervalos de confianza: | ||
| + | <sxh python> | ||
| + | def plot_intervals(axes, | ||
| + | for index, (inferior, superior) in enumerate(intervalos): | ||
| + | position=len(intervalos)-index-1 | ||
| + | media=((superior-inferior)/ | ||
| + | axes.plot([inferior, | ||
| + | axes.scatter(media, | ||
| + | |||
| + | axes.set_yticks(np.arange(len(ylabels))) | ||
| + | axes.set_yticklabels(ylabels[:: | ||
| + | axes.set_xlabel(xlabel) | ||
| + | axes.set_title(title) | ||
| + | |||
| + | axes.set_facecolor("# | ||
| + | axes.grid(visible=True, | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | Y para crear la gráfica de nuestro ejemplo se llamaría así | ||
| + | <sxh python> | ||
| + | figure=plt.figure() | ||
| + | axes = figure.add_subplot() | ||
| + | |||
| + | intervalos=[ | ||
| + | [0.9678, | ||
| + | [0.9464, | ||
| + | [0.8567, | ||
| + | [0.7986, | ||
| + | [0.9245, | ||
| + | ] | ||
| + | ylabels=[' | ||
| + | |||
| + | plot_intervals(axes, | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | Otra forma de hacer el gráfico es poner lineas en los extremos de los intervalos, que aunque se ve mejor, queda un gráfico muy recargado. | ||
| + | |||
| + | <sxh python> | ||
| + | def plot_intervals_with_guides(axes, | ||
| + | for index, (inferior, superior) in enumerate(intervalos): | ||
| + | position=len(intervalos)-index-1 | ||
| + | media=((superior-inferior)/ | ||
| + | color=next(axes._get_lines.prop_cycler)[' | ||
| + | axes.plot([inferior, | ||
| + | axes.scatter(media, | ||
| + | axes.plot([inferior, | ||
| + | axes.plot([superior, | ||
| + | | ||
| + | axes.set_yticks(np.arange(len(ylabels))) | ||
| + | axes.set_yticklabels(ylabels[:: | ||
| + | axes.set_xlabel(xlabel) | ||
| + | axes.set_title(title) | ||
| + | |||
| + | axes.set_facecolor("# | ||
| + | axes.grid(visible=True, | ||
| + | |||
| + | |||
| + | </ | ||
| + | |||
| + | {{: | ||
| + | |||
| + | ===== Comparación avanzada de métricas ===== | ||
| + | En caso de que los intervalos se solapen, no significa exactamente que tengan la misma métrica. Para saber si realmente la tienen es necesario restar las distribuciones y ver si el cero (o algo cercano al cero) está en dicha resta. | ||
| + | |||
| + | Para hacer los cálculos vamos a crear una serie de funciones en python. | ||
| + | |||
| + | <sxh python> | ||
| + | def get_hdi(sample, | ||
| + | """ | ||
| + | Calculation of 100(1-a)% HDI for sample | ||
| + | Chen-Shao HPD Estimation algorithm | ||
| + | http:// | ||
| + | """ | ||
| + | smpl = np.sort(sample) | ||
| + | n = len(smpl) | ||
| + | ckW = max(smpl) - min(smpl) | ||
| + | cki = 0 | ||
| + | RB = int(n * (hdi_prob)) | ||
| + | L0 = 0 | ||
| + | U0 = n-1 | ||
| + | while (RB + cki < n): | ||
| + | if smpl[RB + cki] - smpl[cki] < ckW: | ||
| + | ckW = smpl[RB + cki] - smpl[cki] | ||
| + | L0 = cki | ||
| + | U0 = RB + cki | ||
| + | cki += 1 | ||
| + | ckW = max(smpl) - min(smpl) | ||
| + | cki = 1 | ||
| + | LB = n - int(n * (hdi_prob)) | ||
| + | L1 = 0 | ||
| + | U1 = n-1 | ||
| + | while (LB - cki >= 0): | ||
| + | if smpl[n - cki] - smpl[LB - cki] < ckW: | ||
| + | ckW = smpl[n - cki] - smpl[LB - cki] | ||
| + | U1 = n - cki | ||
| + | L1 = LB - cki | ||
| + | cki += 1 | ||
| + | return [smpl[int((L1+L0)/ | ||
| + | |||
| + | |||
| + | |||
| + | def get_interval(success, | ||
| + | beta_a=0.5+success | ||
| + | beta_b=0.5+total-success | ||
| + | actual_beta=beta(beta_a, | ||
| + | hdi=get_hdi(actual_beta.rvs(100000), | ||
| + | return hdi | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | def get_hdi_compare(success1, | ||
| + | beta_a1=0.5+success1 | ||
| + | beta_b1=0.5+total1-success1 | ||
| + | beta1=beta(beta_a1, | ||
| + | beta_a2=0.5+success2 | ||
| + | beta_b2=0.5+total1-success2 | ||
| + | beta2=beta(beta_a2, | ||
| + | |||
| + | n_samples = 100000 | ||
| + | datos1=beta1.rvs(n_samples) | ||
| + | datos2=beta2.rvs(n_samples) | ||
| + | |||
| + | resultado=datos1-datos2 | ||
| + | | ||
| + | lower, | ||
| + | |||
| + | return [lower, | ||
| + | </ | ||
| + | |||
| + | Lo primero es que hemos creado la función '' | ||
| + | |||
| + | <sxh python> | ||
| + | TP1=131 | ||
| + | FN1=16 | ||
| + | |||
| + | TP2=124 | ||
| + | FN2=23 | ||
| + | |||
| + | |||
| + | interval1=get_interval(TP1, | ||
| + | interval2=get_interval(TP2, | ||
| + | |||
| + | |||
| + | figure=plt.figure(figsize=(5.5, | ||
| + | axes = figure.add_subplot() | ||
| + | |||
| + | intervalos=[ | ||
| + | interval1, | ||
| + | interval2 | ||
| + | ] | ||
| + | ylabels=[' | ||
| + | |||
| + | plot_intervals(axes, | ||
| + | </ | ||
| + | |||
| + | La gráfica resultante es: | ||
| + | {{: | ||
| + | |||
| + | |||
| + | Y para saber si realmente tienen la misma métrica simplemente ejecutamos el siguiente código: | ||
| + | <sxh python> | ||
| + | print(get_hdi_compare(TP1, | ||
| + | </ | ||
| + | Y el resultado es: | ||
| + | <sxh base> | ||
| + | [-0.029769860656823077, | ||
| + | </ | ||
| + | |||
| + | **Si el intervalo incluye al cero es que tienen la misma métrica.** Y en el ejemplo como el intervalo contiene el cero es que tienen la misma métrica. | ||
| + | |||
| + | Veamos ahora otro ejemplo: | ||
| + | <sxh python> | ||
| + | TP1=131 | ||
| + | FN1=16 | ||
| + | |||
| + | TP2=116 | ||
| + | FN2=31 | ||
| + | |||
| + | |||
| + | interval1=get_interval(TP1, | ||
| + | interval2=get_interval(TP2, | ||
| + | |||
| + | |||
| + | figure=plt.figure(figsize=(5.5, | ||
| + | axes = figure.add_subplot() | ||
| + | |||
| + | intervalos=[ | ||
| + | interval1, | ||
| + | interval2 | ||
| + | ] | ||
| + | ylabels=[' | ||
| + | |||
| + | plot_intervals_with_guides(axes, | ||
| + | </ | ||
| + | {{: | ||
| + | |||
| + | <sxh python> | ||
| + | print(get_hdi_compare(TP1, | ||
| + | </ | ||
| + | |||
| + | <sxh base> | ||
| + | [0.018992455698845223, | ||
| + | </ | ||
| + | |||
| + | Por lo que en este caso se solapan pero no tiene la misma métrica. | ||
| + | |||
| + | De todas en este caso, el intervalo está rozando el cero, hay un concepto llamado [[https:// | ||
| + | |||
| + | Mas información: | ||
| + | * {{ : | ||
| + | * {{ : | ||
| + | * {{ : | ||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | |||
| + | ===== Ejercicios ===== | ||
| + | |||
| + | ==== Ejercicio 1 ==== | ||
| + | Mirando el test de COVID de {{ : | ||
| + | |||
| + | ==== Ejercicio 2 ==== | ||
| + | Mirando el test de COVID de {{ : | ||
| + | |||
| + | ==== Ejercicio 3 ==== | ||
| + | Crear 5 modelos distintos para el problema del cancer y para cada uno de ellos: | ||
| + | * Calcula las métricas de sensibilidad y especificidad. | ||
| + | * Calcula el intervalo de confianza de las métricas de sensibilidad y especificidad. ¿Que método se va a usar? | ||
| + | |||
| + | Tambien: | ||
| + | * Muestra en una gráfica el intervalo de confianza de la métrica de sensibilidad de todos los modelos | ||
| + | * Muestra en una gráfica el intervalo de confianza de la métrica de especificidad de todos los modelos | ||
| + | |||
| + | Ahora: | ||
| + | * Indica según la sensibilidad el orden de los bueno que es cada modelo (de mejor a peor). | ||
| + | * Indica según la especificidad el orden de los bueno que es cada modelo (de mejor a peor) | ||
| + | * ¿Que modelo elegirías? | ||
| + | |||
| + | {{: | ||
| + | |||
| + | |||
| + | ==== Ejercicio 4 ==== | ||
| + | Elige el mejor de los 5 modelos anteriores y muestra ahora una gráfica, en la que se mostrará: | ||
| + | |||
| + | * El valor de la sensibilidad y la especificidad según el valor del umbral. La gráfica tendrá un aspecto simular a la siguiente: | ||
| + | |||
| + | {{: | ||
| + | ¿Que umbral elegirías? | ||
| + | |||
| + | |||
| + | |||
| + | * Repite ahora la gráfica, pero incluyendo los intervalos de credibilidad de cada métrica. La gráfica tendrá un aspecto simular a la siguiente: | ||
| + | |||
| + | {{: | ||
| + | ¿Que umbral elegirías? | ||
| + | |||
| + | <note tip>Para hacer este típo de gráficas usa el método: | ||
| + | |||
| + | '' | ||
