La inferencia estadística es el puente que nos permite pasar del mundo de lo observado (la muestra) al mundo de lo desconocido (la población). En el ecosistema del Machine Learning, este puente es vital para validar la estabilidad de nuestros modelos y asegurar que nuestros hallazgos no son meras coincidencias estocásticas.
Este proceso se ramifica en dos grandes vertientes:
Estimación por Intervalos: Definir un rango de confianza donde esperamos que resida el parámetro real.
Contraste de Hipótesis: Un marco de toma de decisiones para aceptar o rechazar afirmaciones basadas en la probabilidad.
La Anatomía de un Contraste de Hipótesis
Todo contraste de hipótesis es una partición del espacio de resultados. Basándonos en un estadístico de prueba (calculado a partir de la muestra), dividimos todos sus valores posibles en dos conjuntos disjuntos:
Región de Aceptación (): El conjunto de valores de para los cuales decidimos no rechazar .
Región Crítica o de Rechazo (): El conjunto de valores de que son tan improbables bajo que nos llevan a rechazarla.
Formalmente, nuestra regla de decisión se resume en:
La probabilidad de caer en la región crítica cuando es realmente cierta se define como el nivel de significancia ().
Flujo de un Contraste de Hipótesis
Tipos de Hipótesis: Simples y Compuestas
Hipótesis Simple: Aquella que especifica un único valor para el parámetro. Ejemplo: .
Hipótesis Compuesta: Aquella que abarca un rango de valores. Ejemplo: o .
El Vínculo entre Intervalos y Contrastes
Existe una relación profunda y elegante entre estas dos vertientes de la inferencia. Para un contraste bilateral del tipo frente a :
Aceptaremos con un nivel de significancia si, y solo si, el valor de la nula pertenece al intervalo de confianza de nivel calculado a partir de la muestra.
¿Cuándo usar cada Test?
Antes de sumergirnos en los detalles, esta tabla resume la elección del test según el escenario:
Situación
Parámetro
conocida
desconocida
Una media
Test Z (Normal)
Test t (Student)
Proporción
Test Z ( grande)
—
Varianza
—
Test (Ji-cuadrado)
Dos medias independientes
Test Z
Test t (Welch)
Inferencia sobre la Media (): Población Normal
Cuando trabajamos con una población que sigue una distribución , la estrategia depende de si conocemos la varianza poblacional ().
Caso 1: Varianza () Conocida
En este escenario usamos la Distribución Normal Estándar (). El intervalo de confianza se define como:
En Elixir, podemos implementar este contraste utilizando tensores de Nx para manejar los datos de entrada:
defmodule ElixirML.Inferencia.Media do
import Nx.Constants, only: [pi: 0]
@doc """
Realiza un test Z para la media.
Útil cuando la varianza poblacional es conocida.
"""
def z_test(tensor_muestra, mu0, sigma, alfa \\ 0.05) do
n = Nx.size(tensor_muestra)
media_muestral = Nx.mean(tensor_muestra) |> Nx.to_number()
# Estadístico Z observado (Normalizado)
z_obs = (media_muestral - mu0) / (sigma / :math.sqrt(n))
# En la práctica, usaríamos el Percent Point Function (PPF)
# de una librería como Scholar.
z_critico = 1.96 # Aproximación para alfa = 0.05 bilateral
if abs(z_obs) > z_critico, do: :rechazar_h0, else: :no_rechazar_h0
end
end
Caso 2: Varianza () Desconocida
Aquí debemos usar la cuasivarianza muestral () y la Distribución t de Student con grados de libertad. El intervalo de confianza se ensancha para compensar la incertidumbre:
defmodule ElixirML.Inferencia.MediaT do
@doc """
Test T de Student para una muestra.
Se utiliza cuando la varianza poblacional es desconocida.
Soporta tests bilaterales (:both) y unilaterales (:greater, :less).
"""
def t_test(tensor_muestra, mu0, opts \\ []) do
alfa = Keyword.get(opts, :alfa, 0.05)
tail = Keyword.get(opts, :tail, :both)
n = Nx.size(tensor_muestra)
media_m = Nx.mean(tensor_muestra) |> Nx.to_number()
varianza_m = Nx.subtract(tensor_muestra, media_m)
|> Nx.pow(2)
|> Nx.sum()
|> Nx.divide(n - 1)
|> Nx.to_number()
t_obs = (media_m - mu0) / (:math.sqrt(varianza_m / n))
# En un entorno real usaríamos: Scholar.Distributions.T.ppf(...)
# Para alfa=0.05 y n-1=9:
# Bilateral: t_critico = 2.262
# Unilateral: t_critico = 1.833
case tail do
:both -> if abs(t_obs) > 2.262, do: :rechazar_h0, else: :no_rechazar_h0
:greater -> if t_obs > 1.833, do: :rechazar_h0, else: :no_rechazar_h0
:less -> if t_obs < -1.833, do: :rechazar_h0, else: :no_rechazar_h0
end
end
end
Caso de Estudio: El Test del "Snack" (Bilateral)
Imagina que analizamos un nuevo producto alimenticio donde el nivel medio de azúcar esperado es . Tomamos una muestra aleatoria de productos y obtenemos:
Media muestral:
Cuasivarianza muestral: (Desviación )
¿Existe una diferencia significativa con un nivel ?
# Representación de nuestra muestra en Nx
muestra = Nx.tensor([185, 210, 205, 190, 220, 215, 195, 200, 202, 200], type: :f32)
# Ejecutamos el test T (Varianza desconocida)
resultado = ElixirML.Inferencia.MediaT.t_test(muestra, 200, tail: :both, alfa: 0.05)
# Cálculo manual para verificación:
# t_obs = (202 - 200) / sqrt(289/10) = 0.372
# Como 0.372 < 2.262, la conclusión es :no_rechazar_h0
Tests Unilaterales: Cuando la Dirección Importa
No siempre buscamos cualquier diferencia (bilateral). A veces nuestra sospecha tiene una dirección clara. Por ejemplo: "¿Ha aumentado el nivel de colesterol por este aceite?".
Bilateral (Dos colas):. La región crítica se reparte en los dos extremos ( en cada lado).
Unilateral (Una cola): o . Toda la masa de error se concentra en un solo extremo, haciendo el test más "sensible" en esa dirección.
Comparación de Dos Medias Independientes
Uno de los escenarios más frecuentes en ML es comparar el rendimiento de dos modelos o dos tratamientos. ¿El modelo A tiene mayor accuracy que el modelo B, o la diferencia se debe al azar?
El Problema
Tenemos dos muestras independientes de tamaños y , y queremos contrastar:
(No hay diferencia entre los modelos)
(Existe una diferencia significativa)
Test t de Welch
Cuando las varianzas de ambas poblaciones son desconocidas y potencialmente distintas, usamos el test t de Welch:
defmodule ElixirML.Inferencia.DosMedias do
@doc """
Test t de Welch para comparar dos medias independientes.
No asume varianzas iguales.
"""
def welch_test(muestra_1, muestra_2) do
n1 = Nx.size(muestra_1)
n2 = Nx.size(muestra_2)
media_1 = Nx.mean(muestra_1) |> Nx.to_number()
media_2 = Nx.mean(muestra_2) |> Nx.to_number()
var_1 = Nx.variance(muestra_1) |> Nx.to_number()
var_2 = Nx.variance(muestra_2) |> Nx.to_number()
# Estadístico t de Welch
t_obs = (media_1 - media_2) / :math.sqrt(var_1/n1 + var_2/n2)
# Grados de libertad de Welch-Satterthwaite
num = :math.pow(var_1/n1 + var_2/n2, 2)
den = :math.pow(var_1/n1, 2)/(n1-1) + :math.pow(var_2/n2, 2)/(n2-1)
df = num / den
%{t_observado: t_obs, grados_libertad: Float.round(df, 1)}
end
end
# Ejemplo: ¿El modelo A (accuracy) es significativamente mejor que el modelo B?
modelo_a = Nx.tensor([0.92, 0.89, 0.91, 0.93, 0.90, 0.88, 0.91], type: :f32)
modelo_b = Nx.tensor([0.85, 0.87, 0.84, 0.86, 0.83, 0.88, 0.85], type: :f32)
ElixirML.Inferencia.DosMedias.welch_test(modelo_a, modelo_b)
Muestras Grandes y el Teorema Central del Límite
Gracias al Teorema Central del Límite (TCL), si el tamaño de la muestra es suficientemente grande (habitualmente ), podemos aproximar la distribución de la media a una Normal, independientemente de la distribución original de la población.
Para inferir sobre la dispersión de una población normal, recurrimos a la distribución Ji-cuadrado ().
Varianza con desconocida:
I = \left[ \frac{(n-1)S^2}{\chi^2_{n-1:\alpha/2}} , \frac{(n-1)S^2}{\chi^2_{n-1:1-\alpha/2}} \right]
defmodule ElixirML.Inferencia.Varianza do
def intervalo_confianza(varianza_m, n, alfa \\ 0.05) do
# Los valores críticos dependen de los grados de libertad (n-1)
grados_libertad = n - 1
# Estos valores se obtendrían de tablas o Scholar.Distributions
chi_inf = 19.02 # Ilustrativo para alfa=0.05
chi_sup = 2.70
num = (n - 1) * varianza_m
{num / chi_inf, num / chi_sup}
end
end
El Cuadro de Decisiones: Errores en el Test
Al tomar una decisión basada en probabilidad, siempre existe un riesgo. En la ciencia de datos, debemos equilibrar estos dos tipos de fallos:
es Verdadera
es Falsa
Rechazar
❌ Error Tipo I ()
✅ Decisión Correcta (Potencia)
No rechazar
✅ Decisión Correcta
❌ Error Tipo II ()
Error Tipo I (): Rechazar la hipótesis nula cuando en realidad es cierta (un "falso positivo").
Error Tipo II (): No rechazar cuando la hipótesis alternativa es la verdadera (un "falso negativo").
En Machine Learning, el "poder" de un test es . Representa la capacidad del modelo para detectar una mejora real (un efecto) cuando este existe.
El p-valor: ¿Qué hubiera pasado si…?
Una de las críticas más comunes a los tests de hipótesis es su dependencia absoluta del nivel de significancia elegido antes de ver los datos. El p-valor surge como una respuesta natural a la pregunta:
¿Qué hubiera pasado si hubiéramos elegido un nivel mucho menor? ¿Seguiríamos aceptando ?
El p-valor es el nivel de significancia más pequeño para el cual la hipótesis nula sería rechazada.
Si el p-valor es muy pequeño: Nos dice que los datos observados son extremadamente raros bajo el supuesto de . La evidencia es abrumadora en su contra.
Si el p-valor es grande: Los datos son perfectamente compatibles con .
Cálculo del p-valor en Elixir
defmodule ElixirML.Inferencia.PValor do
@doc """
Calcula un p-valor aproximado para un test Z bilateral.
Usa la aproximación de la función error complementaria.
"""
def p_valor_z(z_obs) do
# Aproximación: P(Z > |z|) ≈ erfc(|z|/√2) / 2
# Para un test bilateral: p = 2 * P(Z > |z|)
z_abs = abs(z_obs)
# Aproximación usando la serie de Taylor de erfc
cola_derecha = 0.5 * :math.erfc(z_abs / :math.sqrt(2))
p = 2 * cola_derecha
%{
z_observado: z_obs,
p_valor: Float.round(p, 6),
significativo_005: p < 0.05,
significativo_001: p < 0.01
}
end
end
# Ejemplo: ¿Es significativo un z_obs = 2.5?
ElixirML.Inferencia.PValor.p_valor_z(2.5)
# => %{z_observado: 2.5, p_valor: 0.012419, significativo_005: true, significativo_001: false}
En la ciencia de datos moderna, no basta con decir "rechazamos" o "aceptamos". Reportar el p-valor permite que otros investigadores decidan si la evidencia es suficiente para sus propios estándares de rigor.
Conexión con Machine Learning
La inferencia estadística no es un ejercicio académico aislado; es una herramienta operativa en el ciclo de desarrollo de ML:
Validación de modelos: Un test t de dos muestras permite determinar si la diferencia en accuracy entre dos arquitecturas es estadísticamente significativa o solo ruido.
A/B Testing: El contraste de hipótesis es la columna vertebral de los experimentos en producción.
Feature selection: Los p-valores ayudan a distinguir qué variables tienen una relación real con la variable objetivo y cuáles son espurias.
Intervalos de predicción: No solo queremos una predicción puntual, sino un rango de confianza que cuantifique nuestra incertidumbre.