Código Python: pronóstico de demanda con una red simple (comparado con el promedio móvil)

Código Python: pronóstico de demanda con una red simple (comparado con el promedio móvil)
Quien maneja un almacén vive con la misma pregunta al cerrar cada mes: ¿cuánto voy a vender el mes entrante? Si compra de más, el capital se queda quieto en el estante y la bodega se llena de mercancía que nadie pide; si compra de menos, se queda sin producto justo el día en que el cliente lo necesita. El programa que acompaña a este artículo responde esa pregunta con números y no con corazonadas: lee veinticuatro meses de ventas desde un archivo de texto, calcula dos pronósticos —el promedio móvil de tres meses, que es el método clásico de toda la vida, y una red neuronal diminuta— y compara los dos para decirle, con datos, cuál se equivocó menos. Está escrito para dueños de negocio, contadores y almacenistas que quieren entender qué hay detrás de una cifra de pronóstico sin convertirse en programadores.
⬇ Descargar el código (ZIP)| Archivo del ZIP | Para qué sirve |
|---|---|
| pronostico_demanda.py | El programa completo, comentado en español línea por línea. Es el único archivo que se ejecuta. |
| datos/ventas_mensuales.csv | Veinticuatro meses de ventas de ejemplo, con el mes y las unidades vendidas. Se abre con Excel y puede reemplazarlo por sus propios datos. |
| salida_ejemplo.txt | La salida real del programa, tal como aparece en la pantalla, para compararla con la que le dé a usted. |
| LEEME.md | Las instrucciones del paquete: cómo ejecutarlo, qué significa cada columna y las preguntas frecuentes. |
Qué hace el programa
El programa no adivina ni tiene ideas propias sobre su negocio: aprende del pasado de la propia serie y después se mide contra un método sencillo, para que usted juzgue si el esfuerzo vale la pena. Paso a paso, esto es lo que hace:
- Lee el archivo
datos/ventas_mensuales.csvy se queda con la lista de meses y la cantidad de unidades vendidas en cada uno: veinticuatro renglones en total. - Lleva toda la serie a una escala entre cero y uno. Suena técnico, pero es puro sentido común: la red trabaja cómoda con números pequeños y, si se le entregan las unidades en bruto, los cálculos se disparan.
- Arma las muestras de entrenamiento: cada mes se vuelve un ejemplo donde las entradas son los tres meses anteriores y la respuesta correcta es el mes actual. Así el programa no aprende de memoria: aprende la relación entre lo que pasó y lo que vino después.
- Crea una red de tres entradas, cuatro neuronas en la capa oculta y una salida. Los pesos iniciales son números al azar, pero con una semilla fija: eso garantiza que el programa dé siempre el mismo resultado, hoy y dentro de un año.
- La entrena dos mil veces sobre las mismas muestras, corrigiendo los pesos un poquito en cada pasada, siempre en la dirección que reduce el error.
- Calcula en paralelo el pronóstico del promedio móvil de tres meses: el promedio simple de los tres meses anteriores. Es el método que todo el mundo arma en Excel, y sirve de vara para medir.
- Compara los dos métodos sobre exactamente los mismos meses: veintiún meses tienen historia suficiente para ser evaluados; los tres primeros no, porque les faltan meses anteriores.
- Imprime cuánto se equivocó cada uno, dice cuál gana y deja la tabla completa en un archivo que se abre con Excel.
Cómo ejecutarlo
Solo necesita una cosa instalada: Python 3.11 o superior, que se descarga gratis desde la página oficial de Python y se instala con siguiente, siguiente, siguiente. Después, los pasos son estos:
- Descomprima el ZIP en una carpeta cualquiera; puede ser el escritorio, no importa dónde quede.
- Abra la terminal: en Windows, menú Inicio, escriba
cmdy entre; en Mac, la aplicación Terminal. - Escriba
cdseguido de la ruta de la carpeta donde descomprimió el paquete y presione Enter. - Escriba
python pronostico_demanda.pyy presione Enter.
No hay que instalar nada más: el programa usa solo lo que viene con Python de fábrica, así que no hay librerías por descargar ni dependencias que se rompan. Si el sistema le dice que python no existe, pruebe con py en Windows o con python3 en Mac y Linux. Cuando termine, además del resumen en pantalla, encontrará un archivo nuevo dentro de la carpeta salida.
El código, explicado
El programa cabe en una pantalla y está comentado de la primera a la última línea. Estas son las partes que vale la pena entender, sin meterse en honduras matemáticas.
# ==========================================================================
# PRONÓSTICO DE DEMANDA CON UNA RED SIMPLE
# Código Python didáctico para inventarios · Kardex Tauro · kardex-tauro.muisca.co
# Qué hace: lee 24 meses de ventas de datos/ventas_mensuales.csv, entrena a mano
# una red de 3 entradas, 4 neuronas ocultas y 1 salida, y la compara con el promedio
# móvil de 3 meses; deja la tabla y el pronóstico en salida/pronostico.csv
# ==========================================================================
import csv # csv: leer y escribir archivos separados por comas (Excel los abre directo)
import math # math: la función exponencial que necesita la curva sigmoide
import random # random: azar con semilla fija, para que el resultado se repita siempre
Esa cabecera dice en palabras para qué sirve el archivo y de dónde saca los datos, y trae las librerías: todo lo que se importa viene con Python, así que no hay nada exótico que instalar. Esa costumbre de explicar el archivo en su primera línea es la que le va a agradecer usted mismo dentro de un año.
Luego vienen juntos los números que gobiernan el experimento, cada uno con su explicación al lado. Están arriba, y no escondidos en medio del código, porque son los que usted va a querer tocar: cambie la semilla y verá otro resultado; baje las épocas y verá cómo el pronóstico pierde fineza.
# Los números que gobiernan la red: semilla, tasa, épocas, informe y forma
SEMILLA = 7 # Semilla fija: con el mismo dato el resultado es siempre el mismo
TASA = 0.1 # Tasa de aprendizaje: cuánto se corrige cada peso en cada muestra
EPOCAS = 2000 # Épocas: cuántas vueltas completas se le dan a las 21 muestras
INFORME = 250 # Cada cuántas épocas se imprime el error medio de la red
REZAGO = 3 # Entradas de la red: los 3 meses anteriores
OCULTAS = 4 # Neuronas de la capa oculta: ni tan pocas que no aprenda ni tantas que se memorice
VENTANA = 3 # Meses que promedia el promedio móvil para comparar método contra método
Después vienen dos funciones de tres líneas que sostienen todo lo demás. La primera lleva la serie a una escala cómoda —el rango de cero a uno— y la segunda es la curva de la neurona, esa que aplasta cualquier número a ese mismo rango. Sin esas dos funciones, los cálculos se van a infinito y el programa no aprende nada.
def escalar(valores: list[float]) -> tuple:
"""Lleva la serie al rango 0..1 (min-max): así la red trabaja con números pequeños."""
minimo, maximo = min(valores), max(valores)
rango = maximo - minimo
# Si toda la serie valiera lo mismo, el rango sería cero: el 0 evita dividir por cero
return [(valor - minimo) / rango for valor in valores], minimo, maximo
def sigmoide(suma: float) -> float:
"""Sigmoide: aplasta cualquier número al rango 0..1 (la curva de la neurona)."""
return 1.0 / (1.0 + math.exp(-suma))
Ahí está el corazón del asunto: cada vez que la red ve un mes de ejemplo, compara su respuesta con el dato real, mide la diferencia y mueve cada peso un poquito en contra del error. Eso es todo. Repetido dos mil veces, ese movimiento es lo que llamamos aprender.
# Descenso del gradiente: cada peso se mueve un poquito en contra del error
for j in range(OCULTAS):
red["w_salida"][j] += TASA * delta_salida * ocultas[j]
red["b_salida"] += TASA * delta_salida
Y por último, la vara con la que se mide todo: el promedio móvil de tres meses, que es la cuenta que cualquiera haría a mano, y el cálculo del error absoluto medio de cada método sobre exactamente los mismos meses. Ese detalle es la clave de una comparación honesta: si cada método se midiera en meses distintos, la comparación no valdría nada.
def promedio_movil(unidades: list[float], indice: int) -> float:
"""Pronóstico del promedio móvil: el promedio de los últimos meses antes de ese mes."""
return sum(unidades[indice - VENTANA:indice]) / VENTANA
evaluados = [fila for fila in filas if fila["promedio"] is not None]
error_pm = sum(abs(fila["unidades"] - fila["promedio"]) for fila in evaluados) / len(evaluados)
error_rd = sum(abs(fila["unidades"] - fila["red"]) for fila in evaluados) / len(evaluados)
Qué vas a ver en pantalla
Lo primero que imprime el programa es lo que leyó y con qué forma va a trabajar la red:
Meses leídos: 24 Red neuronal: 3 -> 4 -> 1 (sigmoide) Ventana del promedio móvil: 3 meses Rango de la serie: 150,00 a 310,00 unidades
Después muestra el avance del entrenamiento cada doscientas cincuenta vueltas. Ese detalle es más útil de lo que parece: el error baja rápido al principio y luego se estanca, y verlo con sus propios ojos explica por qué se eligen dos mil épocas y no veinte mil.
ENTRENAMIENTO: 2000 épocas, tasa 0,10, semilla 7 Época 500/2000 · error medio (escala 0-1) 0,093869 Época 1000/2000 · error medio (escala 0-1) 0,086684 Época 2000/2000 · error medio (escala 0-1) 0,078619
Y cierra con el veredicto, que es lo que usted venía a buscar:
RESUMEN: QUIÉN SE EQUIVOCA MENOS Meses evaluados (los que tienen 3 meses de historia): 21 Error absoluto medio del promedio móvil de 3 meses: 17,32 unidades Error absoluto medio de la red neuronal 3-4-1: 12,58 unidades Pronóstico de 2028-01 - promedio móvil de 3 meses: 300,33 unidades Pronóstico de 2028-01 - red neuronal 3-4-1: 289,71 unidades
El programa también guarda la tabla completa en salida/pronostico.csv, con una fila por mes y cuatro columnas: el mes, las unidades reales, el pronóstico del promedio móvil y el de la red. Ese archivo se abre con Excel y sirve para dibujar un gráfico y ver con sus propios ojos dónde se separan las dos líneas.
El resultado, contado sin exagerar
Con los datos de ejemplo, el veredicto es claro pero modesto: sobre los veintiún meses evaluados, el promedio móvil se equivocó en promedio 17,32 unidades por mes y la red en 12,58. La red ganó, sí, pero por poco: menos de cinco unidades por mes sobre una serie que se mueve entre 150 y 310 unidades. Para el mes siguiente los dos métodos también quedan cerca: el promedio móvil apunta a 300,33 unidades y la red a 289,71. Eso es lo que hay, ni más ni menos: con veinticuatro meses de historia, la red le ganó al promedio por poco, y ese resultado alcanza para seguir probándola con sus propios datos, no para creer que adivina el futuro.
Conviene tener claro qué es esa red antes de confiarle una decisión de compra. No es un programa que sepa de ventas ni un oráculo: es una regla que se ajusta sola. Imagine una regla escrita con una veintena de números; cada vez que la regla se equivoca, esos números se mueven un poquito hacia donde el error baja, y así hasta que quedan en la posición en que se equivocan lo menos posible. Nada más que eso. Por eso el programa se compara contra el promedio móvil: porque una regla que se ajusta sola solo vale la pena si le gana a la regla fija que usted ya venía usando.
Errores comunes y consejos
- Cambiar los datos y no volver a mirar el error. El programa imprime siempre el error de los dos métodos. Si al cargar sus ventas la red queda peor que el promedio, no hay nada roto: sus datos simplemente no se dejan capturar por una red tan pequeña. Quédese con el promedio y siga trabajando.
- Creer que el pronóstico es una promesa. Un pronóstico es una estimación con su error, y el programa se lo dice con nombre propio. Use la cifra para planear compras y para negociar con proveedores, no para firmar un compromiso de entrega.
- Pocos meses de historia. Con doce meses la red apenas tiene con qué aprender y el promedio móvil tampoco se puede medir bien. Este programa está pensado para dos años o más.
- Tapar la estacionalidad. Si su negocio vende el triple en diciembre, tres meses de historia no alcanzan para que la red vea venir el pico. Cargue dos o tres años completos y repita la comparación.
- Cambiar la semilla para mejorar el resultado. Si mueve la semilla hasta que la red gane, ya no está midiendo: está haciendo trampa. Deje la semilla fija y acepte el veredicto, gane quien gane.
- No revisar el archivo de datos antes de correrlo. Los encabezados del CSV y el separador decimal tienen que ser consistentes; si Excel guardó los meses en otro orden o con otro formato, el programa leerá otra cosa.
Cuándo esto no alcanza
Este programa es un buen punto de partida y una excelente manera de entender un pronóstico sin depender de nadie, pero se queda corto cuando el negocio crece. Aquí hay una sola serie, un producto y una carpeta de archivos: no hay usuarios, ni bodegas, ni historial de quién movió qué.
Cuando el inventario ya no cabe en una hoja de cálculo —cientos de referencias, varias bodegas y movimientos todos los días— y cuando usted quiere el pronóstico, el punto de reorden y el movimiento del día en el mismo lugar, ahí es donde Kardex Tauro hace lo que un script no hace. La idea de fondo no cambia: la red sigue siendo la misma regla que se ajusta sola, solo que ahora corre sobre datos ordenados y con respaldo. Empiece por el programa gratuito para entender el método y ordenar el inventario; el software completo es para cuando Excel y los scripts ya no alcanzan.
⬇ Descargar el código (ZIP)Descargue el ZIP, cámbiele el archivo de datos por sus propias ventas de los últimos dos años y mire el resumen. Si la red le gana al promedio por poco, felicitaciones: ya tiene un método de pronóstico medido con sus propios números, y sabe cuánto se equivoca.