Proyecto 01 | Estadística para Machine Learning

Estadística Descriptiva: El Preprocesamiento Invisible

Antes de entrenar cualquier modelo de IA, los datos deben ser "entendidos" estadísticamente. Media, mediana, desviación estándar y coeficiente de variación no son ejercicios académicos — son el primer paso del pipeline de ML que determina si tu modelo aprenderá o fallará.

🐍 Nota educativa:
Esta página simula en JavaScript el comportamiento de librerías Python como NumPy para que puedas interactuar sin necesidad de un entorno Python local. El código que ves abajo es Python auténtico — el mismo que usamos en este proyecto.

🐍 Laboratorio Estadístico (Simulación de NumPy)

Ingresa cualquier conjunto de números (separados por comas) para ver métricas esenciales de preprocesamiento. Los cálculos replican el comportamiento de np.mean(), np.std(ddof=1) y scipy.stats.variation:

Media (x̄) -
Mediana (M) -
Moda -
Desviación Estándar (σ) -
Varianza (σ²) -
Coef. de Variación -
Rango -
Tamaño de Muestra (n) - n ≥ 30 → Distribución aproximadamente normal (Teorema del Límite Central)
⚡ Regla de oro para ML:

Si el Coeficiente de Variación > 30%, tus datos tienen alta dispersión. ¡Normaliza con (x - μ) / σ antes de entrenar tu modelo!

01. ¿Por Qué la Desviación Estándar es Crítica en Machine Learning?

En redes neuronales, los pesos iniciales se escalan según la varianza de las entradas. Si tus datos tienen σ = 100 pero los pesos inician con σ = 0.01, el gradiente desaparecerá (vanishing gradient). La desviación estándar es tu diagnóstico preventivo antes de tocar el código de entrenamiento.

02. Métricas Esenciales para Preprocesamiento

Media (x̄)

Fórmula: $$\bar{x} = \frac{1}{n}\sum_{i=1}^{n} x_i$$
Python: np.mean(datos)
Uso: Centro de gravedad del dataset (sensible a outliers)

Mediana (M)

Fórmula: $$M = \begin{cases} x_{\frac{n+1}{2}} & \text{si $n$ impar} \\ \frac{x_{\frac{n}{2}} + x_{\frac{n}{2}+1}}{2} & \text{si $n$ par} \end{cases}$$
Python: np.median(datos)
Uso: Resistente a outliers (ideal para datos asimétricos)

Desviación Estándar (σ)

Fórmula (muestra): $$\sigma = \sqrt{\frac{1}{n-1}\sum_{i=1}^{n} (x_i - \bar{x})^2}$$
Python: np.std(datos, ddof=1)
⚠️ ddof=1: Corrección de Bessel para muestras pequeñas

Coeficiente de Variación (CV)

Fórmula: $$CV = \frac{\sigma}{|\bar{x}|} \times 100\%$$
Python: from scipy.stats import variation; variation(datos, ddof=1) * 100
Interpretación:
• CV < 15% → Baja dispersión
• CV 15-30% → Dispersión moderada
• CV > 30% → Alta dispersión (¡normalizar!)

Rango

Fórmula: $$R = x_{\text{max}} - x_{\text{min}}$$
Python: np.ptp(datos) o datos.max() - datos.min()
Uso: Detección rápida de outliers extremos

03. Código Python Auténtico del Proyecto

Este es el código real que usamos para análisis estadístico de preprocesamiento en Python:

statistics_analyzer.py

# ========================================
# ANÁLISIS ESTADÍSTICO PARA PREPROCESAMIENTO DE ML
# Autor: Gabriel - The Nexo Brief
# Dependencias: numpy, scipy
# ========================================

import numpy as np
from scipy import stats
from collections import Counter

def analizar_distribucion(datos):
    """
    Analiza distribución completa: media, mediana, moda, σ, σ², CV%
    Replica el comportamiento de scikit-learn para diagnóstico previo a model.fit()
    
    Args:
        datos (list|np.ndarray): Valores numéricos (ej: [35000, 42000, 38000, 120000])
    
    Returns:
        dict: Métricas esenciales para preprocesamiento
    """
    if len(datos) == 0:
        raise ValueError("Dataset vacío")
    
    # Convertir a array NumPy para operaciones vectorizadas
    datos = np.array(datos, dtype=float)
    n = len(datos)
    
    # Media (x̄) - centro de gravedad
    media = np.mean(datos)
    
    # Mediana (M) - resistente a outliers
    mediana = np.median(datos)
    
    # Moda - valor más frecuente (maneja multimodalidad)
    frecuencia = Counter(datos)
    max_freq = max(frecuencia.values())
    modas = [valor for valor, freq in frecuencia.items() if freq == max_freq]
    moda = modas[0] if len(modas) == 1 else f"{len(modas)} modas"
    
    # Desviación estándar (σ) con corrección Bessel (ddof=1)
    # Equivalente a np.std(datos, ddof=1) - estándar para muestras
    desviacion = np.std(datos, ddof=1)
    
    # Varianza (σ²)
    varianza = np.var(datos, ddof=1)
    
    # Coeficiente de Variación (CV%) - dispersión RELATIVA
    cv = (desviacion / abs(media)) * 100 if media != 0 else float('inf')
    
    # Rango
    rango = np.ptp(datos)  # peak-to-peak (máximo - mínimo)
    
    return {
        'media': round(media, 2),
        'mediana': round(mediana, 2),
        'moda': moda,
        'desviacion': round(desviacion, 2),  # σ
        'varianza': round(varianza, 2),      # σ²
        'cv': f"{cv:.1f}%",                  # CV%
        'rango': round(rango, 2),
        'n': n
    }

# === EJEMPLO DE USO ===
if __name__ == "__main__":
    # Dataset de salarios con outlier (CEO)
    salarios = [35000, 42000, 38000, 45000, 120000]
    
    resultados = analizar_distribucion(salarios)
    
    print("📊 Análisis Estadístico para Preprocesamiento ML")
    print(f"   Media (x̄):        {resultados['media']:>10}")
    print(f"   Mediana (M):      {resultados['mediana']:>10}")
    print(f"   Moda:             {resultados['moda']:>10}")
    print(f"   Desv. Estándar (σ): {resultados['desviacion']:>8}")
    print(f"   Varianza (σ²):    {resultados['varianza']:>10}")
    print(f"   Coef. Variación:  {resultados['cv']:>10}")
    print(f"   Rango:            {resultados['rango']:>10}")
    print(f"   Tamaño (n):       {resultados['n']:>10}")
    
    # Regla de decisión automática
    cv_valor = float(resultados['cv'].rstrip('%'))
    if cv_valor > 30:
        print("\n🚨 ALERTA: CV > 30% → ¡Normalizar datos antes de model.fit()!")
    elif cv_valor > 15:
        print("\n⚠️  AVISO: CV 15-30% → Normalización recomendada")
    else:
        print("\n✅ DATOS HOMOGÉNEOS: CV < 15% → Listo para entrenamiento")
                

🔍 ¿Por qué ddof=1 en np.std()?
La corrección de Bessel (ddof=1) compensa el sesgo en muestras pequeñas. Con n=5 (como el ejemplo de salarios), usar ddof=0 subestimaría σ en ~22%. scikit-learn y pandas usan ddof=1 por defecto para muestras — este código lo replica fielmente.

04. Caso Real: Salarios con Outlier (CEO)

Análisis de un dataset realista de salarios en una startup:

Dataset Original
5 valores
[35k, 42k, 38k, 45k, 120k]
Análisis Estadístico
x̄ = 56k, M = 42k
σ = 34.2k | CV = 61.1%
Decisión de Ingeniería
🚨 CV = 61.1%
¡Normalizar datos antes de entrenar!

💡 Lección clave:
La media (56k) está inflada por el outlier (120k CEO), mientras la mediana (42k) representa al empleado típico. El CV de 61.1% indica alta dispersión — sin normalización, tu modelo de predicción salarial aprendería patrones distorsionados.

05. Reglas de Oro para Preprocesamiento en Python

Regla 1: Compara Media vs Mediana

if abs(media - mediana) / mediana > 0.2:
→ Tus datos tienen outliers o sesgo
→ Usa np.median() para imputación, no np.mean()

Regla 2: Coeficiente de Variación

cv = variation(datos, ddof=1) * 100
• CV < 15% → Datos homogéneos (entrenar sin normalizar)
• CV 15-30% → Normalización recomendada
• CV > 30% → ¡Normalización obligatoria con StandardScaler!

Regla 3: Normalización Z-Score

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
datos_normalizados = scaler.fit_transform(datos.reshape(-1, 1))
→ Transforma datos a μ = 0, σ = 1 (estándar para redes neuronales)

🐍 Descarga el Analizador Estadístico en Python

Script completo con análisis de distribución, detección de outliers y reglas automáticas de preprocesamiento. Listo para usar en tu entorno Python 3.x con NumPy y SciPy.

⬇️ statistics_analyzer.py (v1.0)

Requisitos: pip install numpy scipy
Uso: from statistics_analyzer import analizar_distribucion

← Explorar otros proyectos del Laboratorio