L' addestramento

L'addestramento è la fase più importante per un sistema di filtraggio statistico, perchè è in base alla storia precedente che l'applicazione impara a distinguere fra un messaggio ham e uno che invece è spam. Questa fase è assolutamente opzionale: se il sistema non venisse addestrato infatti si partirebbe con un filtro che ha conoscenza nulla riguardo i pattern utilizzati nelle email ricevute abitualmente, sia per ciò che riguarda la categoria di messaggi desiderati che di quelli non desiderati. Pertanto l'addestramento è altamente raccomandato prima di poter utilizzare l'applicazione per poter filtrare i messaggi.

Per addestrare il sistema occorrono, come già detto, due insiemi: uno di messaggi ham e uno di messaggi spam. E' importante che tali messaggi siano manualmente separati dall'utente secondo le proprio preferenze personali. L'applicazione, essendo stata sviluppata e testata su un sistema Unix (Linux) richiede come input per l'addestramento che i due insiemi di messaggi siano fisicamente salvati in formato mbox[35] (futuri sviluppi prevederebbero anche l'accettazione di input in formato maildir[36] o altri formati ``aperti'').

Prima di cominciare a entrare in maggior dettaglio è utile osservare il diagramma di Figura 3.6.

Figura 3.6: diagramma addestramento
\includegraphics[scale=0.45]{DiagramTraining.ps}

Come si vede dalla figura, la sequenza di passi da compiere è la stessa per ciascuna delle due categorie. Partendo dall'insieme di messaggi della categoria specifica (ham o spam), per ognuno di essi avviene la procedura di parsing e tokenizzazione. Questi token altro non sono che i termini distinti presenti nel messaggio e serviranno per la categorizzazione statistica.

La separazione di una stringa in token viene effettuata con la seguente espressione regolare:

	token_list = re.split("[!\"\#'*+<>()\^`|\s\n\r\t]", string)
che restituisce una lista di token generata dallo splittare la stringa (string) usando i caratteri fra parentesi quadre come separatori di token.

C' è da dire che la stringa (lo stream di testo che rappresenta il messaggio email nella sua interezza) viene, prima di essere tokenizzata, ridotta tutta a caratteri minuscoli perchè si è scelto che il case dei termini dovesse essere non rilevante. Tale scelta consente di ottenere delle buone prestazioni di classificazione anche quando la dimensione dei training set è esigua (circa 200 messaggi per ogni categoria), mentre il preservare il case avrebbe causato una dispersione enorme richiedendo un numero ben più grande di messaggi. Inoltre non viene effettuato nessuno stemming dei termini.

Una volta che si ha l'insieme dei token del messaggio, essi vanno a comporre un set (quindi termini presenti più di una volta non vengono ripresi) a patto che il token soddisfi una di queste proprietà:

In aggiunta, i token ottenuti dai principali header del body del messaggio (From, To, Subject) vengono inseriti in tale struttura dati con l'aggiunta di un prefisso indicante l' header in cui sono stati trovati. Se ad esempio un messaggio ha come valore dell'header Subject (il soggetto dell' email) la stringa ``Join for FREE!!'', essa verrà tokenizzata come subject*join, subject*for, subject*free. Si noti la conversione tutto a minuscolo e il prefisso subject* ad indicare la provenienza dei token. In questo modo se tale messaggio contenesse al suo interno di nuovo il termine free, esso verrebbe aggiunto (senza nessun prefisso speciale). Questo approccio, secondo risultati prettamente empirici e seguendo le indicazioni fornite da Paul Graham nel suo A Plan For Spam, conduce a risultati migliori perchè rende più discriminante il fatto di avere certe parole, esempio, nel subject o nel body.

Con questo approccio gli eventuali tag html vengono considerati token validi (a patto che la loro lunghezza rientri nei limiti stabiliti). In principio veniva effettuato un parsing del codice html e veniva pressochè convertito in plain text; successivamente la conversione è stata accantonata perchè si è visto che considerando anche i tag si ottengono risultati migliori di classificazione. Ciò è dovuto al fatto che la stragrande maggioranza di messaggi spam è in formato html, e il riconoscimento di tali pattern in un nuovo messaggio fa si che esso parta già con un certo peso nel computo del suo coefficiente di spammosità (cfr. paragrafo categorizzazione). Gli eventuali contenuti binari (gli attachment) non vengono consideratida SpamGAME, mentre molti altri filtri anti spam basati statici tentato di effettuare la decodifica di alcuni allegati per utilizzare il loro contenuto (quando esso è testo).

Una volta che per ogni messaggio è stato calcolato il set di termini rilevanti, viene calcolato per la categoria di messaggi un dizionario (viene usata una Hash Map) complessivo in cui viene associato ad ogni termine presente nella categoria un numero intero che indica in quanti documenti della categoria compare (almeno una volta) quella parola.

Successivamente a partire da tale dizionario per ogni categoria ne viene calcolato un altro, che sarebbe la Presenza: ad ogni termine presente nell'insieme di documenti dello stesso tipo viene associata una percentuale: quanti documenti sul totale contengono quella data parola (almeno una volta).

Al termine della fase di addestramento si ottengono quindi 2 Hash Map per ciascuna categoria: una che associa ad ogni termine il numero di documenti in cui compare, l'altro (la Presenza) indicante per ogni termine la percentuale di documenti in cui appare. Chiaramente la Presenza dipende ed è ricavata direttamente dal primo dizionario, basta sapere quanti sono in tutto i documenti con cui è stata addestrata la categoria.

Alessio Pace 2004-03-26