Elaborazione accurata di date, giorni della settimana e orari del giorno per il deep learning e altri modelli di previsione.
Molte attività di previsione richiedono informazioni temporali come input del modello. Pensa a un modello di regressione per prevedere le vendite di limonata di un’azienda di vendita al dettaglio (potresti ricordare l’esempio del mio articolo sulle funzionalità arricchite di contesto). La richiesta di bevande rinfrescanti è ovviamente più elevata in estate determinando una curva di vendita periodica con picchi a luglio/agosto (pensando ad una località in Europa qui).
In questo caso, il periodo dell’anno è ovviamente una preziosa informazione stagionale che dovremmo inserire nel modello. Ma come dovremmo farlo? Le date sono difficili, il numero dei giorni cambia a seconda del mese (e per febbraio anche a seconda dell’anno) ed esistono in vari formati:
13 gennaio 2023
13.01.2023
2023/03/13
Innanzitutto possiamo omettere l’anno. Per tenere conto dell’effetto stagionale, abbiamo solo bisogno del giorno e del mese. Con un approccio molto semplice (e poco ponderato), potremmo semplicemente inserire il mese come un numero e il giorno come un altro numero.
Perché è una cattiva idea? Il modello dovrebbe imparare come funziona il calendario gregoriano cristiano (circa 30 giorni al mese, 12 mesi all’anno, anni bisestili ecc.). Con dati di addestramento sufficienti, un modello di deep learning sarà sicuramente in grado di “comprendere” il nostro calendario. “Comprensione” significa in questo caso: il modello può dedurre la posizione temporale relativa all’interno dell’anno dagli input di mese e data. Ma dovremmo rendere l’apprendimento il più semplice possibile per il nostro modello e assumerci questo lavoro sulle spalle (almeno sappiamo già come funziona il calendario). Usiamo Python appuntamento libreria e calcola il tempo relativo all’interno dell’anno con una logica abbastanza semplice: importa datetime come
from datetime import datetime
import calendaryear = 2023
month = 12
day = 30
passed_days = (datetime(year, month, day) - datetime(year, 1, 1)).days + 1
nr_of_days_per_year= 366 if calendar.isleap(year) else 365
position_within_year = passed_days / nr_of_days_per_year
Il risultato posizione_entro_anno caratteristica con un intervallo di valori da vicino a 0,0 (1 Gennaio) A 1.0 (31 dicembre) è molto più facile da interpretare tramite il modello rispetto al (dannatamente complicato) calendario gregoriano.
Ma non è ancora l’ideale. IL posizione_entro_anno la caratteristica descrive uno schema “a dente di sega” con un forte salto da 1.0 A 0,0 ad ogni fine dell’anno. Questa forte discontinuità può rappresentare un problema per un apprendimento efficace. 31 dicembre E 1 Gennaio sono date molto simili: sono vicine dirette e hanno molto in comune (ad esempio condizioni meteorologiche simili) e probabilmente hanno un potenziale simile per le vendite di limonata. Tuttavia, la funzionalità posizione_entro_anno non riflette questa somiglianza per 31 dicembre E 1 Gennaio; in effetti, è quanto di più diverso possa essere.
Idealmente, i punti temporali molto vicini tra loro dovrebbero avere valori temporali simili. Dobbiamo in qualche modo progettare una caratteristica che rappresenti la natura ciclica dell’anno. In altre parole, da 31 dicembre dovremmo arrivare alla posizione da cui siamo partiti 1 Gennaio. Quindi, ovviamente, ha senso modellare la posizione entro l’anno come posizione su un cerchio. Possiamo farlo trasformandoci posizione_entro_anno dentro X E sì coordinata di una circonferenza unitaria.
Per questo usiamo il seno E coseno funzioni:
peccato(a) = x
cos(α) = y
Dove UN è l’angolo applicato al cerchio. Se il cerchio unitario rappresenta l’anno, UN rappresenta il tempo all’interno dell’anno che è già trascorso.
UN è quindi equivalente a posizione_entro_anno caratteristica, l’unica differenza è quella UN ha una scala diversa (UN: 0,0–2 pag¹, posizione_entro_anno: 0,0–1.0).
Semplicemente ridimensionando posizione_entro_anno A UN e calcolo seno E coseno, trasformiamo il motivo “a dente di sega” in una rappresentazione circolare con transizioni morbide.
import math# scale to 2pi (360 degrees)
alpha = position_within_year * math.pi * 2
year_circle_x = math.sin(alpha)
year_circle_y = math.cos(alpha)
# scale between 0 and 1 (original unit circle positions are between -1 and 1)
year_circle_x = (year_circle_x + 1) / 2
year_circle_y = (year_circle_y + 1) / 2
time_feature = (year_circle_x, year_circle_y) # so beautiful ;)
Il risultato time_feature è un vettore a due elementi scalato tra 0 E 1 questo è facile da digerire dal tuo modello di previsione. Con poche righe di codice, abbiamo eliminato molti sforzi di apprendimento inutili dalle spalle del nostro modello.
Il modello del cerchio unitario può essere applicato a qualsiasi informazione temporale periodica come giorno del mese, giorno della settimana, ora del giornominuto dell’ora ecc. Il concetto può essere esteso anche a caratteristiche cicliche al di fuori del dominio del tempo:
- Logistica/Trasporti pubblici: Posizione relativa di un autobus nel suo viaggio di andata e ritorno attraverso la città
- Biologia: Stato di una cella all’interno del ciclo cellulare.
- Hai in mente altri casi d’uso? Puoi scrivere un commento!