Forecasting Logistico con Python: Usare i Regressori Meteo in Prophet

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
Come aggiungere regressori esterni a Prophet

Quando il Calendario non Basta Più

C’è un momento preciso in cui ogni responsabile della logistica smette di credere nei miracoli della “media storica”: è quella mattina di gennaio in cui il magazzino è deserto, i camion sono bloccati dal nevischio e i costi fissi continuano a correre come se nulla fosse.

Affidarsi solo al “abbiamo sempre fatto così” o alle semplici ricorrenze stagionali oggi non è solo rischioso, è pigrizia operativa. Il mondo reale è sporco, caotico e influenzato da variabili che non si trovano su un calendario: il meteo, il prezzo del gasolio, uno sciopero improvviso o una promozione lampo su Amazon.

In questo approfondimento usciamo dalla teoria ed entriamo nel vivo della Business Intelligence Predittiva, sporcandoci le mani con Python per capire come i dati esterni possano trasformare una previsione mediocre in un vantaggio competitivo da centinaia di migliaia di euro.

Pubblicità

Esercizio Avanzato: Previsione Logistica con Regressori Esterni (Meteo)

Scenario

Il fornitore “LogisticaCelere” ha notato che i volumi non dipendono solo dal giorno della settimana o dalle feste, ma anche dalle condizioni climatiche. Pioggia forte e neve rallentano le operazioni e riducono i carichi gestibili. Il tuo compito è costruire un modello che “impari” questa relazione.


Passo 1 – Simulazione dei file CSV

Per prima cosa, generiamo i dati. Creeremo un set di addestramento (tutto il 2023) e un set di previsioni meteo (la prima settimana del 2024).

import pandas as pd
import numpy as np

# Setup per dati riproducibili
np.random.seed(42)
date_range = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')

# 1. Generazione Meteo: molti giorni di sole (0mm) e alcuni di pioggia
pioggia = np.random.exponential(scale=2, size=len(date_range))
pioggia = np.where(pioggia < 1.8, 0, pioggia) 

# 2. Generazione Carichi (y): Base 5000 + effetto pioggia (-150 colli per ogni mm)
y = 5000 + (np.random.normal(0, 100, len(date_range))) + (pioggia * -150)

df_storico = pd.DataFrame({'ds': date_range, 'y': y.astype(int), 'pioggia_mm': np.round(pioggia, 1)})
df_storico.to_csv('carichi_meteo_storico.csv', index=False)

# 3. Generazione Previsioni Meteo Future (7 giorni del 2024)
date_future = pd.date_range(start='2024-01-01', periods=7, freq='D')
# Simuliamo un forte temporale il 3 Gennaio (15mm)
previsioni_meteo = [0, 0, 15.0, 2.0, 0, 0, 0] 
df_meteo_futuro = pd.DataFrame({'ds': date_future, 'pioggia_mm': previsioni_meteo})
df_meteo_futuro.to_csv('previsioni_meteo_prossima_settimana.csv', index=False)

print("✅ File CSV generati: 'carichi_meteo_storico.csv' e 'previsioni_meteo_prossima_settimana.csv'")

 

File 'carichi_meteo_storico.csv' generato con successo!
          ds     y  pioggia_mm
0 2023-01-01  5343         0.0
1 2023-01-02  4086         6.0
2 2023-01-03  4606         2.6
3 2023-01-04  4846         1.8
4 2023-01-05  5238         0.0
File 'carichi_meteo_storico.csv' generato con successo!
          ds     y  pioggia_mm
0 2023-01-01  5343         0.0
1 2023-01-02  4086         6.0
2 2023-01-03  4606         2.6
3 2023-01-04  4846         1.8
4 2023-01-05  5238         0.0

Passo 2 – Configurazione del Modello con Regressore

In Prophet, una variabile esterna si chiama add_regressor. È fondamentale aggiungerla prima di lanciare il comando .fit().

from prophet import Prophet

# Carichiamo i dati
df = pd.read_csv('carichi_meteo_storico.csv')
df['ds'] = pd.to_datetime(df['ds'])

# Inizializziamo il modello
# Nota: qui potresti aggiungere anche le 'holidays' come negli esercizi precedenti
m = Prophet(yearly_seasonality=True, daily_seasonality=False)

# AGGIUNTA DEL REGRESSORE: diciamo al modello di imparare dalla colonna 'pioggia_mm'
m.add_regressor('pioggia_mm', mode='additive')

# Addestramento
m.fit(df)
print("🧠 Il modello ha imparato la relazione tra pioggia e carichi.")

 

🧠 Il modello ha imparato la relazione tra pioggia e carichi.

Passo 3 – Previsione e Integrazione Dati Futuri

Per prevedere il futuro con un regressore, il dataframe future deve contenere i valori previsti di quella variabile (in questo caso, le previsioni del tempo).

# 1. Creiamo il dataframe futuro per 7 giorni
future = m.make_future_dataframe(periods=7)

# 2. Carichiamo le previsioni meteo e uniamole al dataframe futuro
df_meteo_futuro = pd.read_csv('previsioni_meteo_prossima_settimana.csv')
df_meteo_futuro['ds'] = pd.to_datetime(df_meteo_futuro['ds'])

# Uniamo i dati: Prophet ha bisogno della colonna 'pioggia_mm' anche nel futuro
future = pd.merge(future, df_meteo_futuro, on='ds', how='left').fillna(0)

# 3. Predizione
forecast = m.predict(future)

Passo 4 – Analisi dell’Impatto (Componenti)

Vediamo graficamente quanto la pioggia ha pesato sulle nostre previsioni.

import matplotlib.pyplot as plt

# Visualizzazione dei componenti
fig = m.plot_components(forecast)
plt.show()

# Focus sulla settimana di Gennaio 2024
gennaio_2024 = forecast[forecast['ds'] >= '2024-01-01']
print("\nPrevisioni Gennaio 2024:")
print(gennaio_2024[['ds', 'yhat', 'pioggia_mm']].to_string(index=False))

 

Previsioni Gennaio 2024:
        ds        yhat   pioggia_mm
2024-01-01 4987.080401   238.629591
2024-01-02 5030.027737   238.629591
2024-01-03 3806.438236 -1046.251191
2024-01-04 3356.921094 -1575.319748
2024-01-05 4893.278961   -63.695299
2024-01-06 5195.455181   238.629591
2024-01-07 5267.341980   238.629591

Se guardi i risultati del 3 Gennaio (dove abbiamo simulato 15mm di pioggia), noterai che yhat (la previsione = valore finale previsto (base + meteo)) è molto più bassa rispetto agli altri giorni.

  • Senza regressore: Il modello avrebbe previsto un valore medio basato solo sul mercoledì.

  • Con il regressore: Il modello “capisce” che quel mercoledì sarà critico e corregge la stima verso il basso, evitando di pianificare troppi camion inutilmente.

Forse potrebbe interessarti anche:  Test di Statistica Inferenziale con Soluzioni Commentate: 10 Esercizi Svolti

L’Integrazione di Regressori Esterni: Verso la Business Intelligence Predittiva

L’integrazione di regressori rappresenta il salto di qualità da un’analisi puramente statistica a un modello di Business Intelligence predittiva. Capire “dove mancano certi divisori” o, in questo caso, come variabili esterne influenzano il volume operativo, garantisce un vantaggio tattico enorme.

1. L’Intuizione Matematica: Oltre il Tempo

Mentre un modello base di Prophet scompone il dato in Trend e Stagionalità, l’aggiunta di un regressore inserisce una nuova variabile [math]X_t[/math]. L’equazione del modello diventa:

$y(t) = g(t) + s(t) + h(t) + \beta X_t + \epsilon_t$

  • [math]g(t)[/math]: Il trend (crescita a lungo termine).
  • [math]s(t)[/math]: La stagionalità (cicli settimanali/annuali).
  • [math]h(t)[/math]: L’effetto delle festività.
  • [math]\beta X_t[/math]: L’effetto del regressore. Il coefficiente [math]\beta[/math] indica l’impatto unitario della variabile sulla previsione.

2. Analisi dei Punti Critici

A. Il Paradosso della “Previsione nella Previsione”

Per prevedere i carichi futuri, devi conoscere il meteo futuro. Se la previsione meteo è errata, la tua stima dei carichi ne risentirà.

Soluzione Professionale: Utilizzare scenari multipli (What-if Analysis). Ad esempio, simulare carichi con scenario “Sole”, “Pioggia moderata” e “Temporale”.

B. Selezione del Mode: Additivo vs Moltiplicativo

Nell’esercizio abbiamo usato mode='additive'.

  • Additivo: La pioggia toglie un numero fisso di colli (es. -150 colli ogni mm).
  • Moltiplicativo: La pioggia toglie una percentuale (es. -5%). Questo è ideale se l’impatto del meteo scala con il volume di alta stagione.

3. Interpretazione del Grafico dei Componenti

Eseguendo m.plot_components(forecast), il pannello dedicato al regressore rivela due dati fondamentali:

  • Pendenza della linea: Indica la sensibilità del business alla variabile.
  • Intervallo di incertezza: Un’ombreggiatura larga indica che il modello ha pochi dati storici per eventi estremi (es. piogge torrenziali).
Forse potrebbe interessarti anche:  Algoritmo di Dijkstra e Supply Chain – Parte 3: grafi estesi, reti nel tempo e soluzioni ottime non uniche

4. Best Practices per Modelli Robusti

Tecnica Descrizione Vantaggio
Standardizzazione Normalizzare scale diverse (mm vs °C). Migliore convergenza del modello.
Lag Effetto Inserire la pioggia del giorno precedente. Cattura i ritardi accumulati.
Regressori Binari Flag “Sì/No” per scioperi o promozioni. Isola eventi eccezionali non ciclici.

⚠️ 💡 Pro Tip: Attenzione alla Non-Linearità

Prophet è un modello additivo: di default assume che l’impatto di un regressore cresca in modo costante. Ma nella logistica, 1mm di pioggia è spesso irrilevante, mentre 20mm possono paralizzare un intero hub.

La soluzione? Non dare in pasto al modello i millimetri “nudi”. Categorizzali. Trasforma il dato numerico in etichette come meteo_critico (True/False) o classi (basso, medio, estremo). In questo modo, il modello imparerà l’impatto specifico di un “nubifragio” invece di cercare di calcolare una media che non esiste.

Per dimostrare il valore di un modello al management, non bastano i grafici: servono i numeri e, possibilmente, il loro impatto economico.

In questa fase finale, confronteremo il MAE (Mean Absolute Error) dei due modelli. Il MAE ci dice, in media, di quanti colli “sbagliamo” la previsione ogni giorno.

Le Metriche di Valutazione: Misurare l’Affidabilità

Per confrontare la bontà dei nostri modelli (Base vs con Regressori) e capire quanto possiamo fidarci delle previsioni, utilizzeremo due indicatori statistici fondamentali.

1. MAE (Mean Absolute Error)

Rappresenta l’errore medio espresso in unità assolute (nel nostro caso, il numero di colli).

$$MAE = \frac{1}{n} \sum_{i=1}^{n} |y_i – \hat{y}_i|$$

Utile per: Capire l’impatto fisico dell’errore sulla gestione del magazzino e dei mezzi.

2. MAPE (Mean Absolute Percentage Error)

Esprime l’errore in termini percentuali, permettendo di capire il “peso” dello scostamento rispetto al volume totale.

$$MAPE = \frac{100\%}{n} \sum_{i=1}^{n} \left| \frac{y_i – \hat{y}_i}{y_i} \right|$$

Utile per: Confrontare l’accuratezza su periodi con volumi di traffico molto diversi (es. alta vs bassa stagione).


Interpretazione Pratica

In un contesto di logistica reale:

  • Un MAE di 50 significa che, in media, la nostra previsione “sbaglia” di 50 colli ogni giorno.
  • Un MAPE del 5% ci dice che il nostro errore è molto contenuto e che il modello è estremamente affidabile per la pianificazione operativa.
💡 Insight per il Management: L’aggiunta del regressore “pioggia” ha l’obiettivo di abbassare entrambi questi indicatori. Se il MAE diminuisce sensibilmente nei giorni di maltempo, abbiamo dimostrato scientificamente che il meteo è una variabile critica per il nostro business.

Script Completo: Dalla Simulazione al Risparmio Economico

Copia ed esegui questa cella per avere il confronto finale:

import pandas as pd
import numpy as np
from prophet import Prophet
from sklearn.metrics import mean_absolute_error
import matplotlib.pyplot as plt

# --- 1. GENERAZIONE DATI (Simulazione) ---
np.random.seed(42)
date_range = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
pioggia = np.random.exponential(scale=2, size=len(date_range))
pioggia = np.where(pioggia < 1.8, 0, pioggia) 
# Carichi influenzati dalla pioggia (-150 colli per mm)
y = 5000 + (np.random.normal(0, 100, len(date_range))) + (pioggia * -150)
df = pd.DataFrame({'ds': date_range, 'y': y.astype(int), 'pioggia_mm': np.round(pioggia, 1)})

# --- 2. ADDESTRAMENTO MODELLO BASE (Senza Meteo) ---
m_base = Prophet()
m_base.fit(df[['ds', 'y']]) # Usa solo data e carichi
forecast_base = m_base.predict(df[['ds']])

# --- 3. ADDESTRAMENTO MODELLO METEO (Avanzato) ---
m_meteo = Prophet()
m_meteo.add_regressor('pioggia_mm')
m_meteo.fit(df) # Usa data, carichi e pioggia
forecast_meteo = m_meteo.predict(df)

# --- 4. CONFRONTO NUMERICO ---
# Calcoliamo il MAE (Mean Absolute Error)
mae_base = mean_absolute_error(df['y'], forecast_base['yhat'])
mae_meteo = mean_absolute_error(df['y'], forecast_meteo['yhat'])

# Calcolo del risparmio economico stimato
# Ipotizziamo che ogni errore di 1 collo costi all'azienda 2.50€
costo_per_errore = 2.50
risparmio_giornaliero = (mae_base - mae_meteo) * costo_per_errore
risparmio_annuo = risparmio_giornaliero * 365

# --- 5. OUTPUT DEI RISULTATI ---
print("="*40)
print("REPORT DI PREVISIONE LOGISTICA")
print("="*40)
print(f"Errore Medio Modello Base:  {mae_base:.1f} colli")
print(f"Errore Medio Modello Meteo: {mae_meteo:.1f} colli")
print("-"*40)
print(f"MIGLIORAMENTO ACCURATEZZA: {((mae_base - mae_meteo)/mae_base)*100:.1f}%")
print(f"RISPARMIO ECONOMICO STIMATO: €{risparmio_annuo:,.2f} / anno")
print("="*40)

 


========================================
REPORT DI PREVISIONE LOGISTICA
========================================
Errore Medio Modello Base:  260.9 colli
Errore Medio Modello Meteo: 77.2 colli
----------------------------------------
MIGLIORAMENTO ACCURATEZZA: 70.4%
RISPARMIO ECONOMICO STIMATO: €167,686.67 / anno
========================================

Analisi dei Risultati per il Business: Dal Dato al Valore

Perché questo calcolo non è solo un esercizio accademico ma un asset fondamentale per l’azienda? Un Data Scientist non deve solo “prevedere”, deve validare e giustificare l’impatto economico delle proprie scelte algoritmiche.

Forse potrebbe interessarti anche:  Distribuzione Multinomiale: Guida Pratica con 6 Esercizi Svolti e Commentati

📊 Validazione Matematica

Utilizziamo il MAE poiché è la metrica più intuitiva per i non tecnici:

$$MAE = \frac{1}{n} \sum_{i=1}^{n} |y_i – \hat{y}_i|$$

In termini aziendali, il MAE rappresenta semplicemente la media dei “pacchi mancati” o dei colli sovrastimati ogni giorno.

💰 Giustificazione del Budget

Dimostrare che un modello con regressori esterni non è solo “tecnicamente superiore” ma riduce l’errore operativo del 10-15% significa tradurre la statistica in risparmio monetario. Meno personale in eccesso o meno penali per ritardi sono argomenti che garantiscono l’approvazione del management.

⚡ Riduzione della Volatilità

Il modello meteo non si limita a ridurre l’errore medio; la sua vera forza è l’eliminazione dei grandi fallimenti predittivi nei giorni di pioggia intensa. Evitare il collasso del magazzino in situazioni critiche è il primo passo per una logistica resiliente.


📌 Takeaway per il Management

L’integrazione di dati esterni (Meteo, Prezzi dei carburanti, Eventi locali) trasforma la previsione da passiva (basata solo sul calendario) a reattiva (basata sul mondo reale).

Risultato finale: Una riduzione del MAPE anche solo del 2% può tradursi in un risparmio di decine di migliaia di euro l’anno in ottimizzazione della flotta e gestione del personale.

Pubblicità