cesparzaf commited on
Commit
cad4df5
·
1 Parent(s): bd5f55e

Compat: Chronos-T5 + chronos-forecasting==1.5.3

Browse files
Files changed (2) hide show
  1. app.py +8 -26
  2. requirements.txt +4 -1
app.py CHANGED
@@ -1,35 +1,23 @@
 
1
  import gradio as gr
2
  import pandas as pd
3
  import numpy as np
4
  import torch
5
  import matplotlib.pyplot as plt
6
-
7
- # 🔽 Import del pipeline de Chronos (lib 'chronos-forecasting')
8
  from chronos import ChronosPipeline
9
 
10
- # ANTES:
11
- # MODEL_ID = "amazon/chronos-bolt-base"
12
-
13
- # AHORA:
14
  MODEL_ID = "amazon/chronos-t5-base"
15
 
16
- # Cargar el modelo UNA sola vez
17
  PIPELINE = ChronosPipeline.from_pretrained(
18
  MODEL_ID,
19
  device_map="auto",
20
- dtype=torch.float32, # antes usábamos torch_dtype (deprecado)
21
  )
22
 
23
  def _prepare_series(df: pd.DataFrame, freq: str | None):
24
- """
25
- Espera columnas: date,value
26
- - Ordena por fecha
27
- - Infere o aplica frecuencia
28
- - Interpola huecos
29
- """
30
  if "date" not in df.columns or "value" not in df.columns:
31
  raise gr.Error("El CSV debe tener columnas: date,value")
32
-
33
  df = df.copy()
34
  df["date"] = pd.to_datetime(df["date"])
35
  df = df.sort_values("date")
@@ -39,13 +27,11 @@ def _prepare_series(df: pd.DataFrame, freq: str | None):
39
  else:
40
  inferred = pd.infer_freq(df["date"])
41
  if inferred is None:
42
- # fallback: tamaño de paso por mediana en días
43
  step = max(int((df["date"].diff().median() / pd.Timedelta(days=1)) or 1), 1)
44
  df = df.set_index("date").asfreq(f"{step}D").reset_index()
45
  else:
46
  df = df.set_index("date").asfreq(inferred).reset_index()
47
 
48
- # Rellenar faltantes
49
  df["value"] = pd.to_numeric(df["value"], errors="coerce")
50
  df["value"] = df["value"].interpolate("linear").bfill().ffill()
51
  return df
@@ -56,15 +42,12 @@ def forecast_fn(file, horizon: int = 12, freq: str = "MS"):
56
  df = pd.read_csv(file.name)
57
  df = _prepare_series(df, freq.strip() or None)
58
 
59
- # Serie a tensor
60
  y = torch.tensor(df["value"].values, dtype=torch.float32)
61
 
62
- # Predicción probabilística (múltiples trayectorias -> cuantiles)
63
  samples = PIPELINE.predict(y, prediction_length=horizon, num_samples=200) # [1, N, H]
64
- samples = samples[0].numpy() # [N, H]
65
  p10, p50, p90 = np.quantile(samples, [0.10, 0.50, 0.90], axis=0)
66
 
67
- # Fechas futuras
68
  inferred = pd.infer_freq(df["date"])
69
  if inferred is None:
70
  step = max(int((df["date"].diff().median() / pd.Timedelta(days=1)) or 1), 1)
@@ -79,19 +62,18 @@ def forecast_fn(file, horizon: int = 12, freq: str = "MS"):
79
  "p90": np.round(p90, 4),
80
  })
81
 
82
- # Gráfica
83
  fig = plt.figure(figsize=(8, 4))
84
  plt.plot(df["date"], df["value"], label="Histórico")
85
  plt.plot(out["date"], out["p50"], label="Pronóstico (P50)")
86
  plt.fill_between(out["date"], out["p10"], out["p90"], alpha=0.3, label="Banda P10–P90")
87
- plt.title("Pronóstico con Chronos-Bolt (P10 / P50 / P90)")
88
  plt.xlabel("Fecha"); plt.ylabel("Valor")
89
  plt.legend()
90
 
91
  return out, fig
92
 
93
- with gr.Blocks(title="Pronóstico de Demanda (Chronos-Bolt)") as demo:
94
- gr.Markdown("## Análisis predictivo de mercado (Hugging Face + Chronos-Bolt)\nSube un CSV con columnas **date,value**. Elige horizonte y frecuencia.")
95
  with gr.Row():
96
  file = gr.File(label="CSV: date,value", file_types=[".csv"])
97
  horizon = gr.Slider(1, 36, value=12, step=1, label="Horizonte (pasos)")
@@ -100,8 +82,8 @@ with gr.Blocks(title="Pronóstico de Demanda (Chronos-Bolt)") as demo:
100
  btn = gr.Button("Generar pronóstico")
101
  out_table = gr.Dataframe(label="Tabla de pronóstico")
102
  out_plot = gr.Plot(label="Gráfica")
103
- # api_name → te da un endpoint gratis para consumir como API
104
  btn.click(forecast_fn, inputs=[file, horizon, freq], outputs=[out_table, out_plot], api_name="/forecast")
105
 
106
  if __name__ == "__main__":
107
  demo.queue().launch()
 
 
1
+ @'
2
  import gradio as gr
3
  import pandas as pd
4
  import numpy as np
5
  import torch
6
  import matplotlib.pyplot as plt
 
 
7
  from chronos import ChronosPipeline
8
 
9
+ # Modelo compatible con chronos-forecasting==1.5.3
 
 
 
10
  MODEL_ID = "amazon/chronos-t5-base"
11
 
 
12
  PIPELINE = ChronosPipeline.from_pretrained(
13
  MODEL_ID,
14
  device_map="auto",
15
+ dtype=torch.float32, # usar "dtype" (no "torch_dtype")
16
  )
17
 
18
  def _prepare_series(df: pd.DataFrame, freq: str | None):
 
 
 
 
 
 
19
  if "date" not in df.columns or "value" not in df.columns:
20
  raise gr.Error("El CSV debe tener columnas: date,value")
 
21
  df = df.copy()
22
  df["date"] = pd.to_datetime(df["date"])
23
  df = df.sort_values("date")
 
27
  else:
28
  inferred = pd.infer_freq(df["date"])
29
  if inferred is None:
 
30
  step = max(int((df["date"].diff().median() / pd.Timedelta(days=1)) or 1), 1)
31
  df = df.set_index("date").asfreq(f"{step}D").reset_index()
32
  else:
33
  df = df.set_index("date").asfreq(inferred).reset_index()
34
 
 
35
  df["value"] = pd.to_numeric(df["value"], errors="coerce")
36
  df["value"] = df["value"].interpolate("linear").bfill().ffill()
37
  return df
 
42
  df = pd.read_csv(file.name)
43
  df = _prepare_series(df, freq.strip() or None)
44
 
 
45
  y = torch.tensor(df["value"].values, dtype=torch.float32)
46
 
 
47
  samples = PIPELINE.predict(y, prediction_length=horizon, num_samples=200) # [1, N, H]
48
+ samples = samples[0].numpy()
49
  p10, p50, p90 = np.quantile(samples, [0.10, 0.50, 0.90], axis=0)
50
 
 
51
  inferred = pd.infer_freq(df["date"])
52
  if inferred is None:
53
  step = max(int((df["date"].diff().median() / pd.Timedelta(days=1)) or 1), 1)
 
62
  "p90": np.round(p90, 4),
63
  })
64
 
 
65
  fig = plt.figure(figsize=(8, 4))
66
  plt.plot(df["date"], df["value"], label="Histórico")
67
  plt.plot(out["date"], out["p50"], label="Pronóstico (P50)")
68
  plt.fill_between(out["date"], out["p10"], out["p90"], alpha=0.3, label="Banda P10–P90")
69
+ plt.title("Pronóstico con Chronos-T5 (P10 / P50 / P90)")
70
  plt.xlabel("Fecha"); plt.ylabel("Valor")
71
  plt.legend()
72
 
73
  return out, fig
74
 
75
+ with gr.Blocks(title="Pronóstico de Demanda (Chronos-T5)") as demo:
76
+ gr.Markdown("## Análisis predictivo de mercado (Hugging Face + Chronos-T5)\nSube un CSV con **date,value**. Elige horizonte y frecuencia.")
77
  with gr.Row():
78
  file = gr.File(label="CSV: date,value", file_types=[".csv"])
79
  horizon = gr.Slider(1, 36, value=12, step=1, label="Horizonte (pasos)")
 
82
  btn = gr.Button("Generar pronóstico")
83
  out_table = gr.Dataframe(label="Tabla de pronóstico")
84
  out_plot = gr.Plot(label="Gráfica")
 
85
  btn.click(forecast_fn, inputs=[file, horizon, freq], outputs=[out_table, out_plot], api_name="/forecast")
86
 
87
  if __name__ == "__main__":
88
  demo.queue().launch()
89
+ '@ | Set-Content app.py -Encoding UTF8
requirements.txt CHANGED
@@ -1,6 +1,9 @@
 
1
  gradio>=4.44.0
2
  pandas>=2.0.0
3
  numpy>=1.24.0
4
  matplotlib>=3.7.0
5
  torch>=2.2.0
6
- chronos-forecasting>=1.7.0
 
 
 
1
+ @'
2
  gradio>=4.44.0
3
  pandas>=2.0.0
4
  numpy>=1.24.0
5
  matplotlib>=3.7.0
6
  torch>=2.2.0
7
+ chronos-forecasting==1.5.3
8
+ '@ | Set-Content requirements.txt -Encoding UTF8
9
+