In molte applicazioni di data mining i dati vengono visti come sequenze di eventi, dove ogni evento ha associato un tipo e un tempo in cui accade.
Un problema fondamentale nell'analisi di sequenze di eventi è trovare episodi frequenti, cioè collezioni di eventi che accadono frequentemente insieme.
Gli episodi, in generale, sono insiemi parzialmente ordinati di eventi.
Dato un insieme E di tipi di evento, un evento è una coppia (A,t), dove A è un tipo di evento e t è un intero che rappresenta il tempo in cui un evento occorre.
Una sequenza di eventi s su E è una tripla (s, TS, Te) dove s = {(A1, t1),(A2, t2), ...,(An, tn)} è una sequenza ordinata di eventi tali che Ai sta in E per i = 1,...,n, ti<=ti+1 per i = 1, ..., n-1. TS e Te sono rispettivamente il tempo di inizio e il tempo di fine e TS <=ti<=Te per i = 1, ..., n.
Una finestra su una sequenza di eventi s = (s, TS, Te) è una sequenza di eventi w = (w, tS, te) dove tS
Un episodio a è una tripla (V, <=, g) dove V è un insieme di nodi, <= è un ordinamento parziale su V, g:V --> E è una funzione che associa ogni nodo con un tipo di evento.
Un episodio quindi si può interpretare come un insieme di eventi g(V) che devono accadere nell'ordine descritto da <=.
Un episodio a è parallelo se non vale x <=y per ogni x,y in V tali che x diverso da y. Un episodio a è seriale se l'ordinamento è totale, cioè si può sempre dire se x<=y o se y<=x per ogni x,y in V.
Sapendo che la frequenza di un episodio è la frazione di finestre dove esso accade, sia data una certa lunghezza di finestra e sia s una frequenza di soglia, allora un episodio è frequente se accade in almeno s finestre.
Gli episodi frequenti sono monotoni, cioè se a è un episodio frequente allora lo è anche ogni suo sottoepisodio ottenuto cancellando alcuni eventi. Allora procederemo con una tecnica Apriori:
Vediamo, ora, come costruire Li da una sola scansione di Ci, cioè ol metodo MTV. Per episodi paralleli consideriamo la struttura dati seguente:
Il cuore dell'algoritmo riguarda cosa succede quando un evento A viene inserito o cancellato da una finestra:
Per episodi seriali si usa un automa finito non deterministico che riconosce la sequenza di eventi. La struttura dati utilizzata è simile al caso parallelo.
A.count --;
if (A.count == 0) // abbiamo perso A
for (all E in A.contains) {
E.missing++;
if(E.missing == 1) // abbiamo perso E
E.support + = (currentTime-E.startingTIme);
}
B.count++;
if(B.count==1) //abbiamo guadagnato B
for(all E in B.contains) {
E.missing--;
if(E.missing==0) //abbiamo guadagnato E
E.startingTime = currentTime;
}
Mentre simuliamo l'automa, manteniamo per ogni stato in cui si viene a trovare l'automa, traccia del più recente istante da cui si può iniziare per arrivare in quello stato. Questo è:
Se l'automa per l'episodio E entra in uno stato accettante, allora poniamo E.startingTime = all'istante associato con quello stato.
Se l'istante associato ad uno stato è <= dell'istante corrente meno w allora cancella lo stato da quelli in cui si trova l'automa. Se lo stato accettante viene così cancellato aggiungi a E.support la quantità currentTime-E.startingTime.