Previsione della domanda

Previsione probabilistica della domanda












Home » Risorse » Qui

Le previsioni probabilistiche della domanda sono essenziali nell'ottimizzazione delle scorte. Le previsioni della domanda si definiscono integrate nel lead time quando i valori delle previsioni corrispondono alla domanda totale nel lead time; differiscono quindi dalle previsioni tradizionali, che considerano un arco temporale preciso (di solito giorni, settimane o mesi) e ignorano i lead time. Il motore di previsione di Lokad genera previsioni probabilistiche ed integrate della domanda, che partono da lead time probabilistici, sfruttando nativamente i pattern di comportamento statistico più comuni per i dati commerciali, dalla stagionalità al trend fino al ciclo di vita del prodotto. Il nostro motore è inoltre in grado di gestire le distorsioni della domanda, come le rotture di stock e le promozioni. Le previsioni Lokad rappresentano le probabilità attese per ogni singola unità di domanda futura: in questa pagina, vedremo in dettaglio la sintassi usata per generare previsioni integrate della domanda con Lokad.

Sintassi generale

Il nostro motore di previsione è dotato di una funzione specifica per le previsioni probabilistiche. Questa è la sintassi:

Demand = forecast.demand(
  category: C1, C2, C3, C4
  hierarchy: H1, H2, H3, H4
  label: PlainText
  demandStartDate: LaunchDate
  demandEndDate: EndDate
  horizon: Leadtime
  offset: 0
  present: (max(Orders.Date) by 1) + 1
  demandDate: Orders.Date
  demandValue: Orders.Quantity
  // "SO" sta per rotture di stock
  censoredDemandDate: (SO.StartDate, SO.EndDate)
  inflatedDemandDate: (TVAds.StartDate, TVAds.EndDate)
  // "Promos" sta per promozioni
  promotionDate: (Promos.StartDate, Promos.EndDate)
  promotionDiscount: Promos.Discount
  promotionCategory: Promos.Type)

A differenza delle funzioni canoniche, le funzioni di chiamata hanno argomenti per nome invece che per posizione. Gli argomenti per nome sono più adatti alla funzioni più complesse, perché rendono il codice sorgente molto più leggibile (anche se leggermente più lungo), ma, per il resto, si comportano come gli argomenti delle altre funzioni e sono quindi supportati da Envision.

La funzione restituisce un vettore Demand (domanda) di tipo distribuzione (vedi anche Algebra delle distribuzioni). Le distribuzioni costituiscono un tipo di dati avanzati, che rappresentano le funzioni $p: \mathbb{Z} \to \mathbb{R}$. Più specificatamente, il nostro motore di previsione restituisce variabili casuali, ossia distribuzioni che sono positive e hanno una massa pari a 1. Nel nostro caso, $p(k)$ rappresenta la probabilità di una domanda associata a $k$ unità. Ogni articolo (nel senso del termine usato in Envision) viene associato alla propria distribuzione.

La sintassi forecast.demand (previsione, domanda) comprende molti argomenti, ma solo quattro sono obbligatori:

  • present (presente): valore scalare di una data;
  • demandDate (domanda, data): vettore data associato a un articolo;
  • demandValue (domanda, valore): vettore numerico associato a un articolo;
  • horizon (orizzonte): vettore distribuzione.

Il valore present è la data del primo giorno da prevedere, partendo dal presupposto che i dati siano completi fino al giorno precedente. In realtà, alcune aziende sono chiuse un giorno a settimana, ad esempio la domenica: in questo caso, se la data più recente trovata nel set di dati è un sabato, potremmo chiederci se iniziare le previsioni dalla domenica o dal lunedì successivo. Nella sintassi di esempio mostrata sopra, usiamo max(Orders.Date) + 1, ipotizzando che gli ordini vengano effettuati ogni giorno e che i dati di input risalgano al giorno precedente.

I valori demandDate e demandValue dovrebbero appartenere alla stessa tabella che mostra affinità con un articolo, ossia con [Id, *], nella terminologia di Envision. Le date indicano quando la domanda è stata osservata in passato. I valori rappresentano le dimensioni della domanda, di solito calcolata in unità o ognuno. Non sono supportati valori frazionari della domanda. La tabella contiene lo storico della domanda prevista con il motore di previsione. Lo storico della domanda dovrebbe essere il più lungo possibile, anche se, in realtà, superare i 5 anni di dati sulla domanda non porta benefici visibili. Il motore di previsione è in grado di lavorare sia con uno storico breve, sia con uno più lungo: in quest'ultimo caso, i dati meno recenti diventano semplicemente irrilevanti dal punto di vista statistico.

Il valore horizon rappresenta il lead time probabilistico da utilizzare nella previsione della domanda. Il lead time è usato come dato di input nel calcolo della previsione integrata della domanda: in realtà, il lead time è già di per sé una previsione, che il nostro motore di previsione consente di calcolare. Abbiamo, però, deciso di scorporare le previsioni del lead time da quelle della domanda, in modo da rendere possibili eventuali aggiustamenti alle distribuzioni del lead time prima di passare alle previsioni della domanda.

Al di là di questi argomenti obbligatori, l'accuratezza delle previsioni può essere migliorata sensibilmente fornendo dati ulteriori al motore di previsione. Nelle prossime sezioni vedremo come.

Definizione formale

In questa sezione, passeremo in rassegna la definizione formale dell'operazione statistica eseguita dal motore di previsione durante il calcolo di una previsione integrata della domanda.

Sia $y(t)$ la funzione della domanda e $t$ il tempo. Sia la domanda integrata $D$ associata alla variabile casuale $\Lambda$, che rappresenta i lead time, definita come segue:

$$\text{D} : (y,\Lambda,t_0) \to \int_0^{\infty} \mathbf{P}[\Lambda=\lambda] \left( \int_{t_0}^{t_0+\lambda} y(t) dt \right) d\lambda$$ dove $\mathbf{P}[\Lambda=\lambda]$ rappresenta la probabilità della variabile casuale di lead time $\Lambda$ pari a $\lambda$. La domanda è definita integrata, poiché, effettivamente, si tratta di una integrazione su un lead time probabilistico.

Se $t_0$ rappresenta il giorno presente, allora la domanda sarà nota (perché osservata) fino al tempo $t_0$, ma ignota per il periodo successivo. Scopo del motore di previsione è calcolare $\hat{D}(y, \Lambda)$, ossia una stima probabilistica della domanda futura espressa come variabile casuale.

Categorie, gerarchia, etichette

Dal punto di vista del motore di previsione, le categorie, la gerarchia e le etichette in plain text ricoprono un ruolo piuttosto simile: aiutano, cioè, il motore di previsione a gestire dati storici scarsi.

Vedi Previsioni con categorie e gerarchia.

Previsioni per nuovi prodotti

In un'ottica di previsione, un nuovo prodotto altro non è se non un prodotto mai venduto prima, il che rappresenta senz'altro una sfida, dato che, per definizione, non esistono dati storici associati al prodotto. Il motore di previsione consente di prevedere la domanda per nuovi prodotti grazie all'argomento demandStartDate (domanda, data di inizio). Per inciso, quando le date di inizio dei dati storici sono note, è consigliabile inserirle comunque nel motore di previsione, al fine di rendere più accurate le previsioni, sia dei prodotti nuovi che di quelli meno recenti.

L'argomento demandStartDate si aspetta che sia specificata una data per ogni articolo. Questa data dovrà indicare il giorno in cui la domanda per quel prodotto diventa effettiva. La data sarà quindi passata se riferita a prodotti già venduti, o futura se riferita a prodotti ancora da lanciare.

Fornire l'argomento demandStartDate porta due benefici. Il primo è, ovviamente, quello di prevedere nuovi articoli: in questo caso, è importante specificare anche l'argomento offset, perché, se questo viene mantenuto al valore predefinito (pari a zero), il periodo coperto dalla previsione potrebbe non sovrapporsi al periodo attivo per l'articolo in questione.

Esempio: oggi è il 1° luglio. L'orizzonte di previsione è una distribuzione di Dirac a 7 giorni; abbiamo quindi un lead time costante di 7 giorni. Il prodotto A viene lanciato il 15 luglio (data di inizio). Se la previsione viene eseguita oggi, allora la distribuzione prevista per il prodotto A è una distribuzione Dirac a zero, perché l'orizzonte termina prima della data di inizio del prodotto A. Per prevedere la prima settimana di domanda del prodotto A, il valore offset del prodotto A dovrà essere impostato su 14 giorni.

Il secondo beneficio dell'argomento demandStartDate è quello di rendere più accurate le previsioni di tutti gli articoli, non solo di quelli non ancora lanciati. Osservare la prima unità venduta nella data di inizio del prodotto, infatti, non è la stessa cosa che osservare la prima unità venduta a sei mesi dal lancio: se nel primo caso possiamo ipotizzare vendite future costanti, nel secondo vediamo spesso una domanda limitata a pochissime unità l'anno. Il nostro motore di previsione sfrutta quindi demandStartDate per affinare le previsioni della domanda per tutti gli articoli.

Distorsioni della domanda

Il nostro intento è quello di prevedere la domanda. Tuttavia, capita spesso che i dati storici non facciano altro che approssimare la domanda, creando così, più o meno coscientemente, una distorsione. Un esempio di dati storici sono quelli che compongono lo storico delle vendite: in caso di rotture di stock, i volumi di vendita crollano, mentre la domanda rimane stabile. Ebbene, il motore di previsione di Lokad è progettato per gestire nativamente queste distorsioni, grazie agli argomenti censoredDemandDate e inflatedDemandDate. Entrambi questi argomenti necessitano di un'affinità tra un vettore data e un articolo, o (Id, Date) nella terminologia di Envision.

Se usiamo l'argomento censoredDemandDate (data domanda censurata), segnaliamo al motore di previsione che la data di un particolare prodotto è censurata, ossia maggiore o uguale al valore osservato. Il motore di previsione non cercherà di calcolare quanto sarebbe stata elevata la domanda in quel giorno, poiché questo è un valore che rimarrà ignoto, ma, evidenziando l'errore sistematico, potrà dispiegare diversi strumenti di ottimizzazione adatti a quel caso particolare. Nella pratica, la domanda censurata si verifica soprattutto in corrispondenza delle rotture di stock, perché, in questi casi, i dati storici non registrano quanti clienti vanno via senza aver trovato quello che cercavano.

La domanda può risultare anche gonfiata. L'argomento inflatedDemandDate (data domanda gonfiata) offre la possibilità di segnalare le date e gli articoli per cui la domanda deve essere considerata inferiore o uguale al valore osservato. Anche in questo caso, la domanda reale rimane ignota, ma segnalare l'errore sistematico è già abbastanza per agevolare il compito del motore di previsione. Nella pratica, la domanda risulta gonfiata quando si verificano picchi di domanda temporanei e non ricorrenti: ad esempio, la vittoria eccezionale di una squadra sportiva locale in un campionato nazionale può dare nuovo slancio alle vendite dei supermercati locali per qualche giorno.

I due argomenti inflatedDemandDate e censoredDemandDate possono sfruttare due o più vettori come input. Se sono indicati due vettori data, allora le coppie (start, end), ossia (inizio, fine), sono trattate come segmenti inclusivi, con la prima data che funge da inizio del segmento e la seconda da fine del segmento. Se viene indicato un solo vettore data, invece, i segmenti sono considerati della durata di un solo giorno; le date segnalano quali sono esattamente i giorni da considerare come date censurate o gonfiate dal punto di vista della domanda.

Se le distorsioni della domanda si verificano periodicamente (ogni anno, ogni settimana, ecc.), non c'è bisogno di segnalare la domanda come censurata o gonfiata, perché il motore di previsione è in grado, in questi casi, di gestire automaticamente questi schemi.

Previsione delle promozioni

Il motore di previsione supporta nativamente le promozioni. Fornire dati sulle promozioni non è obbligatorio, ma, se questi vengono specificati, va precisato quando la promozione inizia e quando finisce. Al limite, può essere fornito solo l'argomento promotionDate (data promozione), che segue lo stesso schema dell'argomento censoredDemandDate: quando è fornito un singolo vettore data, la promozione è considerata della durata di 1 giorno; se sono fornite due date, il primo vettore rappresenterà la data di inizio (inclusa), mentre il secondo vettore rappresenterà la data di fine (inclusa).

L'argomento promotionDiscount (sconto promozione) è opzionale, ma può essere fornito per dare ulteriori indicazioni al motore di previsione sull'estensione della promozione. Questo argomento prevede un vettore numero, che il motore di previsione tratta come una serie di valori ordinali: maggiore è lo sconto, maggiore è l'impatto atteso della promozione. In pratica, è il motore di previsione che calcola l'aumento stimato della domanda, sulla base degli aumenti osservati durante le promozioni passate.

Anche l'argomento promotionCategory (categoria promozione) è opzionale, ma può essere fornito per classificare gli eventi promozionali. Se viene specificato, il motore di previsione lo sfrutta per testare le affinità tra i vari eventi promozionali osservati e individuare quali eventi, tra quelli classificati all'interno della stessa categoria, ottengono aumenti simili nella domanda. Il principio è molto simile a quello dell'argomento category (categoria): l'unica differenza è che in questo caso viene applicato alle promozioni e non agli articoli.

Attenzione! Le promozioni sono notoriamente difficili da prevedere, anche se lo storico dei dati è di qualità eccellente. La nostra esperienza con Lokad ci ha insegnato che la maggioranza delle aziende non ha a disposizione dati sulle promozioni altamente accurati già pronti. Questi dati possono però essere ottenuti in un secondo momento attraverso un'adeguata preparazione: in linea di massima, per raccogliere dati sulle promozioni sufficientemente validi da rendere le previsioni più accurate è necessario un certo sforzo; "dare in pasto" al motore di previsione dati approssimativi può solo intaccare l'accuratezza delle previsioni.

Quando sono forniti dati sulle promozioni, i periodi delle promozioni non vanno indicati con l'argomento inflatedDemandDate: indicare un periodo con entrambi gli argomenti promotionDate e inflatedDemandDate segnala infatti che l'aumento promozionale è stato gonfiato oltre il limite che ci si poteva ragionevolmente aspettare da una promozione e che la promozione stessa va considerata come distorta.