Implementazione grafica dell’algoritmo KNN
Wednesday, January 30th, 2008Stamattina mi sono divertito a realizzare in Java una semplice implementazione grafica dell’algoritmo KNN (K-Nearest Neighbor). Nonostante si tratti del più banale metodo di classificazione di oggetti, viene utilizzato moltissimo proprio per la sua semplicità e tutto sommato discreta efficienza, e quindi vale la pena tenerlo presente perché in ambito di programmazione può spesso tornare utile. La classificazione si basa sul numero di oggetti che circondano l’oggetto da classificare all’interno di un raggio stabilito di valore k. Per una definizione puntuale vi rimando a Wikipedia. Supponendo il caso più semplice di scelta tra due sole possibilità, rappresentate da punti rossi e punti blu, si tratta quindi di effettuare due conteggi da confrontare alla fine per stabilire se il nuovo punto sarà rosso, blu oppure indeterminato (rappresentato in verde) nel caso in cui i conteggi risultino uguali.
Qui sotto il programmino inserito all’interno di un’applet (richiede il runtime di Java 6 o versioni successive), in cui è sufficiente inserire i valori di k e dei punti random iniziali rossi e blu. K è un intero positivo, tipicamente piccolo. Se non si seleziona l’opzione riempimento si ha una visualizzazione dinamica del colore determinato dall’algoritmo direttamente spostando il cursore del mouse all’interno del pannello.
Molto più interessante è però avere una vista d’insieme sulle aree di medesima catalogazione, spuntando l’opzione riempimento di cui sopra. Variando i valori numerici si osserva molto bene come si originano le aree dall’intersezione di più cerchi di raggio k e come prevale il colore rosso o blu a seconda se i punti di partenza sono in numero maggiore per il rosso o per il blu rispettivamente.
Partendo da un solo punto rosso ed uno blu con k=3:

Poi, sempre con k=3, dando la prevalenza al rosso (5 rossi e 3 blu):

Ancora con k=3, ma stavolta aumentando i valori di partenza e dando la prevalenza al blu (20 rossi e 25 blu):

Diminuendo k al valore minimo ed aumentando ulteriormente i valori di partenza con prevalenza di nuovo del rosso (50 rossi e 40 blu):

Con i valori predefiniti k=4, 80 punti rossi e 80 blu si ottengono risultati molto più uniformi:

Con il massimo di punti rossi e blu, 99 ciascuno, si ottiene un risultato che si discosta poco a valori di k limitrofi, ad esempio con k=3 e k=5 si ottengono:


Tutt’altro discorso invece per valori estremi di k, ad esempio per k=1, sempre con il massimo di punti rossi e blu:

Si nota una diminuzione dell’uniformità, ancora più evidente nel caso di k=9, sempre con il massimo di punti rossi e blu:

L’implementazione in Java richiede veramente pochissimo tempo senza nemmeno l’utilizzo di un IDE. Se siete interessati al codice sorgente potete scaricarlo da qui
e modificarlo liberamente. La classe GenPoints per la generazione dei punti random implementa anche la creazione dei punti all’interno di un cerchio tramite coordinate polari (non utilizzata nell’esempio). Buon divertimento!

Ormai ho installato Debian dappertutto… desktop, laptop e minipc (di cui racconterò prossimamente in un post dedicato!). Ad Ubuntu va comunque il merito di avermi instradato verso Debian! Windows continuo ad usarlo in taluni casi e anche per mantenermi aggiornato sulla sua evoluzione (o involuzione?).