scipy.stats y PhitterAsignatura: Estadística Aplicada con Python y R
Programa: Ingeniería Agrícola — Universidad de Sucre
Semana de referencia: Semana 7 — Ajuste de Distribuciones, Bondad de Ajuste y Modelos Empíricos/Semiempíricos de Secado
Modalidad: Individual, trabajo autónomo en Google Colab
Entregable: Notebook .ipynb alojado en
un repositorio de GitHub (se entrega la
URL del notebook en GitHub, no un enlace de Colab)
En la Semana 7 aprendimos que ajustar un modelo a datos —ya sea una distribución de probabilidad o una curva de secado— sigue el mismo método: proponer candidatas con sentido físico, estimar parámetros, diagnosticar visualmente, contrastar con pruebas formales y criterios de información, y usar el resultado para decidir. También vimos un puente que conecta ambos mundos: la ecuación de Page, \(MR(t) = e^{-k\,t^{n}}\), es exactamente la función de supervivencia de una distribución Weibull con forma \(n\) y escala \(k^{-1/n}\). Esta actividad pone a prueba ese puente con datos que cada estudiante simula para su propio caso.
Cada estudiante recibirá, a partir de su código estudiantil, un producto agrícola, una temperatura de secado y unos parámetros de proceso ocultos (no se revelan como fórmula: se generan con una semilla aleatoria y no se consultan directamente). Con esos datos personalizados, el estudiante trabaja dos escalas del mismo fenómeno:
scipy.stats y,
principalmente, con un barrido automático en
Phitter.scipy.optimize.curve_fit.El cierre de la actividad es verificar el puente entre las dos partes: la forma \(n\) y la escala del modelo de Page (Parte B) deben ser coherentes con la forma y la escala de la distribución Weibull que mejor ajustó los tiempos de secado (Parte A). Si no coinciden, el estudiante debe investigar por qué.
Esta actividad extiende —no reemplaza— el notebook de clase de la Semana 7, y se enmarca en la pedagogía del “Lápiz y el Algoritmo”: antes de aceptar cualquier código generado por IA, el estudiante debe predecir el resultado esperado (¿el tiempo de diseño debería ser mayor o menor que el tiempo promedio?) y verificarlo.
Objetivo general
Aplicar el ajuste de distribuciones de probabilidad
(scipy.stats y Phitter) y de modelos
empíricos/semiempíricos de secado
(scipy.optimize.curve_fit) sobre datos simulados y
personalizados, para estimar un tiempo de diseño de secado con criterio
ingenieril, mediante un notebook desarrollado con apoyo crítico de un
agente de IA.
Objetivos específicos
scipy.stats al menos dos distribuciones
candidatas (incluida la Weibull) a los tiempos de secado simulados, con
diagnóstico Q-Q y prueba de bondad de ajuste.scipy.stats e interpretar
el ranking con sentido crítico (no aceptarlo sin verificar).curve_fit)
al menos cuatro modelos de secado en capa delgada (Lewis,
Henderson-Pabis, Page y uno adicional) a la curva promedio de humedad,
comparando su desempeño con AICc.| Competencia | Resultado de aprendizaje | Estrategia pedagógica |
|---|---|---|
| Ajuste de distribuciones de probabilidad | Ajusta y compara distribuciones candidatas con
scipy.stats y Phitter, diagnosticando con Q-Q y pruebas de
bondad de ajuste |
Barrido guiado en Phitter, restringido por sentido físico,
contrastado con scipy.stats |
| Modelación empírica y semiempírica en ingeniería agrícola | Ajusta modelos de secado en capa delgada por mínimos cuadrados no lineales y los compara con criterios de información (AICc) | Réplica personalizada del flujo de trabajo de la Semana 7 sobre datos propios |
| Pensamiento computacional y programación asistida por IA | Traduce una especificación estadística en código Python correcto
(scipy.stats, Phitter, curve_fit),
verificándolo línea por línea |
Prompting guiado, verificación humana obligatoria, Bitácora de IA |
| Integración conceptual (puente Page–Weibull) | Verifica numéricamente que un modelo semiempírico de secado y una distribución de probabilidad describen el mismo fenómeno desde dos escalas distintas | Comparación explícita de parámetros entre la Parte A y la Parte B |
| Juicio técnico e ingenieril | Traduce el resultado del ajuste en un tiempo de diseño del secador que considera la variabilidad entre lotes, no solo el promedio | Cálculo de un cuantil de diseño (p. ej. 90 %) y justificación técnica |
| Reserva cognitiva y uso ético de la IA | Documenta el prompt usado, si el código funcionó al primer intento y qué ajustes humanos fueron necesarios | Bitácora de IA obligatoria (conforme a la Hoja de Ruta de IA ética 2024) |
| Reproducibilidad y buenas prácticas | Publica un notebook reproducible, versionado y accesible en un repositorio de GitHub propio | Alojamiento del entregable en GitHub en lugar de un enlace de Colab |
Para que cada notebook sea distinto —y verificable— no se usa un dataset compartido: cada estudiante genera el suyo a partir de su propio código estudiantil. Copia y ejecuta esta celda sin modificarla, salvo la línea del código estudiantil:
import numpy as np
import scipy.stats as stats
codigo = "XXXXXXXXX" # <-- REEMPLAZA por tu código estudiantil completo, como texto
semilla = int(codigo[-4:]) # los últimos 4 dígitos del código, como semilla reproducible
rng = np.random.default_rng(semilla)
# --- Escenario asignado (no lo cambies: identifica tu notebook) ---
productos = ["Ñame", "Yuca", "Plátano", "Mango", "Cacao", "Ajonjolí"]
producto = productos[semilla % len(productos)]
temperatura = [50, 60, 70, 80][semilla % 4]
humedad_objetivo = 15 + (semilla % 6) # % base húmeda (entre 15 y 20 %)
print(f"Código: {codigo} -> semilla = {semilla}")
print(f"Producto asignado: {producto} | Temperatura: {temperatura} °C | Humedad objetivo: {humedad_objetivo} % b.h.")
# --- Parámetros "verdaderos" OCULTOS del proceso (no los mires, no los copies en tus resultados) ---
n_verdadero = rng.uniform(0.65, 1.35)
k_verdadero = rng.uniform(0.15, 0.55) * (1 + 0.15 * (temperatura - 60) / 10)
# --- Parte A: tiempos de secado hasta la humedad objetivo, lote a lote (40 lotes) ---
# Bridge Page <-> Weibull: si MR(t) = exp(-k t^n), el tiempo hasta MR = objetivo
# se distribuye Weibull(forma = n, escala = k^(-1/n)).
n_lotes = 40
tiempos_lote = stats.weibull_min(c=n_verdadero, scale=k_verdadero ** (-1 / n_verdadero)) \
.rvs(size=n_lotes, random_state=rng)
# --- Parte B: curva promedio de secado, 2 repeticiones, cada hora durante 10 horas ---
t_h = np.tile(np.arange(0, 11), 2)
MR_teorico = np.exp(-k_verdadero * t_h ** n_verdadero) # ecuación de Page
MR_obs = np.clip(MR_teorico + rng.normal(0, 0.02, size=t_h.size), 0.002, 1.05)
No borres ni recalcules semilla,
producto, temperatura ni
humedad_objetivo: son la huella digital de tu
notebook y permiten verificar que los resultados corresponden a tu
código. tiempos_lote es el insumo de la Parte A;
t_h y MR_obs son el insumo de la Parte B.
tiempos_lote):
scipy.stats (obligatoria la Weibull; la segunda a tu
elección con sentido físico: Gamma, Lognormal o Exponencial), con
gráfico Q-Q y al menos una prueba de bondad de ajuste
(stats.kstest o stats.goodness_of_fit).distributions_to_fit a candidatas con sentido físico para
datos de tiempo (no dejes el barrido libre de 80+ distribuciones sin
filtrar). Reporta el ranking y la mejor distribución.scipy.stats y por Phitter.t_h,
MR_obs):
curve_fit al menos cuatro
modelos: Lewis, Henderson-Pabis, Page (obligatorios, por el puente con
la Parte A) y uno adicional a tu elección (Page
modificado, dos términos, Wang y Singh, Thompson o logarítmico).humedad_objetivo) con el mejor modelo.Entrega: subir el notebook a un repositorio de
GitHub (público, o con acceso de lectura habilitado) y compartir la
URL del archivo .ipynb en GitHub en el
grupo de la asignatura. Ver la sección 8 con instrucciones si es tu
primera vez usando GitHub.
Escala institucional 0.0 a 5.0. La nota de la actividad corresponde al promedio ponderado de los ocho criterios.
| # | Criterio | Peso | Excelente (4.6–5.0) | Bueno (3.6–4.5) | Aceptable (3.0–3.5) | Insuficiente (0.0–2.9) |
|---|---|---|---|---|---|---|
| 1 | Identificación y datos personalizados | 5% | Encabezado completo (nombres, código, asignatura, grupo) y celda de datos ejecutada sin modificar su lógica, con escenario impreso correctamente | Completo con algún detalle menor de formato | Falta un dato del encabezado o se alteró parcialmente la celda de datos | Falta el encabezado o la celda de datos fue modificada de forma que invalida la personalización |
| 2 | Parte A: ajuste con scipy.stats (Weibull + una
candidata más) |
15% | Ambas distribuciones ajustadas correctamente, Q-Q y prueba de bondad de ajuste bien ejecutados e interpretados | Ajuste correcto con interpretación parcial del Q-Q o de la prueba | Ajuste con error menor de parametrización o sin diagnóstico completo | Ajuste ausente o distribuciones mal parametrizadas |
| 3 | Parte A: barrido con Phitter y comparación con
scipy.stats |
20% | Barrido restringido con criterio físico, ranking interpretado con
sentido crítico, parámetros comparados correctamente entre Phitter y
scipy.stats |
Barrido correcto con comparación de parámetros incompleta o poco crítica | Barrido ejecutado pero sin restricción de candidatas o sin comparar
con scipy.stats |
Phitter ausente o mal utilizado (p. ej. barrido de 80+ sin ningún filtro ni análisis) |
| 4 | Parte B: ajuste de modelos de secado con curve_fit
(mínimo 4 modelos) |
20% | Los 4+ modelos correctamente definidos (ecuaciones exactas) y ajustados, con AICc, RMSE y residuos bien interpretados | Modelos ajustados correctamente con comparación (AICc/RMSE) incompleta | Menos de 4 modelos, o alguna ecuación mal escrita mecánicamente (p. ej. signo de Page modificado) | Ajuste ausente o modelos insuficientes/incorrectos |
| 5 | Verificación del puente Page–Weibull | 15% | Compara explícitamente forma y escala entre Parte A y Parte B, con conclusión razonada sobre la coherencia (o falta de ella) | Comparación presente con interpretación parcial | Comparación mencionada pero sin cálculo explícito o sin interpretación | Ausente: no se relacionan las dos partes |
| 6 | Tiempo de diseño del secador (cuantil 0.90 vs. modelo de curva) | 10% | Calcula y compara ambos tiempos, recomienda uno con justificación ingenieril clara | Calcula ambos tiempos con justificación general | Calcula solo uno de los dos tiempos, o sin comparación explícita | Ausente o sin sentido físico |
| 7 | Bitácora de IA | 10% | Prompt(s) exacto(s) documentado(s), honestidad sobre ajustes/errores, reflexión crítica genuina | Documentada pero con detalle limitado | Bitácora superficial o genérica | Ausente o copiada sin evidencia real de uso |
| 8 | Conclusión técnica, reproducibilidad y entrega en GitHub | 5% | Conclusión sólida con interpretación física de \(n\); notebook reproducible y correctamente alojado en GitHub con URL accesible | Conclusión adecuada; notebook en GitHub con algún detalle menor de acceso o de formato | Conclusión superficial, o el notebook está en GitHub pero incompleto/no reproducible | Conclusión ausente, o el entregable no es un enlace de GitHub válido |
Nota de la actividad = Σ (nota del criterio × peso del criterio), redondeada a un decimal según la escala institucional (0.0–5.0).
distributions_to_fit a
candidatas con sentido para un tiempo (siempre positivo): evita dejar el
barrido libre de 80+ distribuciones, tal como se discutió en el notebook
de clase sobre el riesgo de “pesca de resultados”.estadistica-secado-tuapellido..ipynb directamente.
.ipynb dentro de tu repositorio en
GitHub (se renderiza automáticamente con salidas y gráficos) y copia la
URL de esa página —no la URL del repositorio completo,
sino la del archivo— para entregarla.