MACHINE LEARNING - COSTRUIAMO UN CLASSIFICATORE PER LA RACCOMANDAZIONE
di Nanni Bassetti - https://nannibassetti.com/
Tutti quelli che hanno letto
il titolo e si sono fiondati a leggere l’articolo pensando di aver trovato il
modo di svoltare la loro vita grazie ad un sistema automatico per esser
raccomandati, rimarranno delusi.
Infatti, in questo articolo
andremo a vedere come costruire, in modo semplice e didattico un piccolo
programma di machine learning, che serve a prevedere e raccomandare degli
articoli da acquistare, esattamente come vediamo che funzionano i grandi
servizi online di musica, e-commerce, film, ecc..
Tutti sappiamo che servizi
come Netflix, Spotify, Amazon, Facebook e tanti altri
spesso ci suggeriscono qualcosa da vedere, ascoltare o comprare, basandosi
sulle nostre scelte fatte nel passato, ma anche sulle scelte di altri utenti
che hanno avuto gusti simili ai nostri.
Quindi se ad esempio ho
scelto di guardare un film di fantascienza, il servizio di streaming, mi
proporrà altri film di fantascienza, ma anche film di altri generi, che magari
sono stati scelti da altri utenti che avevano visionato lo stesso mio film.
Questo meccanismo si chiama
“filter bubbles”, ossia delle bolle di filtraggio, poiché si rimane dentro un
sistema di raccomandazione filtrato attraverso delle scelte più o meno
omogenee.
Ci sono tanti vantaggi in questo
sistema, come la velocità, il servizio di avere qualcuno che “ti conosce” o
presume di conoscerti e quindi ti serve bene, ma ci sono anche gli svantaggi
dati dal “confinamento” dell’informazione, quindi si riceve sempre una stessa
linea di pensiero, cosa meno grave per i film o la musica, ma potrebbe esser
più grave per l’informazione politica o generale.
Fatte queste considerazioni,
possiamo dare un’occhiata a come funziona un sistema di raccomandazione
(recommendation), nel machine learning, che ricordiamo essere un metodo
dell’Intelligenza Artificiale (IA), che utilizza modelli matematici per poter
classificare o prevedere alcuni risultati, partendo da dei dati inseriti
dall’uomo.
Ma andiamo subito sul
pratico, quindi iniziamo parlando di un classificatore semplice ma efficace, il
Nearest Neighbor, un algoritmo che classifica gli oggetti in base alla
“vicinanza” ad altri oggetti, creando così la previsione per similitudine.
La vicinanza è un concetto
che può essere geometrico o numerico, nel
k-Nearest Neighbors (k-NN), l’input è dato dal dataset, ossia gli oggetti
inseriti sui quali il programma di machine learning dovrà addestrarsi per
imparare e l’output è dato dal numero di oggetti più vicini definito dal
parametro k.
Quindi, come in Figura 1, se
k=3 allora il pallino verde (oggetto incognito) sarà classificato come simile
ai triangoli rossi, perché i primi tre oggetti più vicini a lui sono due
triangoli ed un quadrato, quindi è classificabile più come appartenente alla
famiglia dei triangoli, se k=5 invece sarà classificato come più vicino ai
quadrati blu, perché ci sono più quadrati, che triangoli, nelle sue vicinanze.
Figura 1- https://commons.wikimedia.org/wiki/File:KnnClassification.svg
La distanza che potremmo
usare è quella Euclidea, ossia dati i punti [1,2,3,4] e [5,6,7,8]
La distanza è:
Se applichiamo le distanze di [5,6,7,8]
anche da altri punti avremo una serie di numeri e potremmo identificare quali
sono quelli “meno distanti” dal nostro input per poterlo classificare.
Ma nell’esempio qui riportato useremo la
distanza di Hamming, ossia
sum(abs(X1 - X2))/ len(X1)
che si calcola tenendo conto
le componenti diverse di due vettori, per semplicità, se si considerano le due
stringhe: ABCD e AECL, la distanza di hamming è pari a 2, cioè sono solo due le
lettere diverse nelle corrispondenti posizioni.
Quindi se abbiamo [1,5,3,6]
e [2,5,1,6] la distanza di hamming sarà così calcolata:
(|2-1|+|5-5|+|1-3|+|6-6|) /
4 = 0,75
Adesso abbiamo contezza del
classificatore, quindi cosa ci rimane?
Dobbiamo creare il dataset
iniziale, chiaramente per comodità personale, sarà tutto numerico, ricordiamoci
che i computer lavorano sempre meglio con i numeri!
Dopo la creazione del
dataset, scriveremo il programmino in Python, che sfrutterà l’algoritmo di k-NN
e vedremo i risultati.
Il tipo d’apprendimento del
machine learning utilizzato sarà “supervisionato” (Figura 2)
Figura 2
- definizioni del tipo d'apprendimento nel machine learning
Iniziamo col dataset,
acquisti.csv:
Figura 3- dataset dei clienti C1-C21 e dei
loro acquisti
Dove i codici numerici
corrispondono ad i seguenti articoli:
# 1 shoes
# 2 gloves
# 3 coffee
# 4 computer
# 5 book
# 6 newspaper
# 7 T-shirt
# 8 sunglasses
I clienti sono identificati
con i codici da C1 a C21, i loro acquisti passati sono nelle sei colonne
successive, codificati numericamente come dalla legenda precedente, nell’ultima
colonna c’è l’articolo suggerito dal sistema.
Adesso ipotizziamo un
cliente C22, che acquista questi oggetti:
[6,5,0,8,1,7] ossia giornale,
libro, nulla, occhiali da sole, scarpe ed una t-shirt.
Cosa consiglierà il sistema?
Ecco il risultato:
Accuracy
Train: 78.57 % Accuracy Test: 14.29 % Predicted
target name: ['shoes'] [6, 5, 0, 8, 1, 7] ['shoes'] |
In questo piccolo esempio si
ha un’accuratezza dell’addestramento pari al 78,57% e del testing al 14,29%
quindi non si hanno fenomeni di overfitting o underfitting, ma è anche vero che
stiamo parlando di un dataset veramente misero, di soli 21 elementi, non fa
testo!
Se l’accuratezza fosse stata
del 100% avremmo avuto un modello che si adatta male sugli input nuovi, ossia
non è in grado di generalizzare bene e la forza del machine learning è saper generalizzare
in modo da risolvere un problema che non si è mai palesato in precedenza,
quindi trovare una soluzione nuova, se generalizza poco significa che sulle
cose note va benissimo, ma di fronte a qualcosa di diverso lavorerà male.
Figura 4
- tipologie di modello
Guardiamo il codice sorgente
dello script in Python:
Importiamo
le librerie che ci servono:
from
sklearn.model_selection import train_test_split from
sklearn.metrics import accuracy_score import
pandas as pd from
sklearn.neighbors import KNeighborsClassifier import matplotlib.pyplot as plt |
Carichiamo
il dataset acquisti.csv
#
Load dataset url
= "acquisti.csv" dataset
= pd.read_csv(url) names
= ["1 - shoes","2 - gloves","3 - coffee","4
- computer","5 - book","6 - newspaper","7 -
T-shirt","8 - sunglasses"] |
Carichiamo
nella variabile X le colonne da 1 a 6 che contengono gli acquisti passati dei
vari utenti e nella variabile y la settima colonna che contiene la “label”,
ossia l’acquisto consigliato o l’ultimo acquisto fatto.
#
calculate the Hamming distance between two vectors def
hamming_distance(a, b): return sum(abs(e1 - e2) for e1, e2
in zip(a, b)) / len(a) #
Split-out validation dataset dataset
= pd.read_csv(url, header=0) array
= dataset.values print(dataset,"\n\n",names,"\n") X
= array[:,1:7] y
= array[:,7] |
Addestriamo la macchina, considerando che il dataset
è piccolo, abbiamo visto che il miglior setting per è fatto prendendo il gruppo
di test pari al 30% del gruppo totale e il parametro “k” ossia n_neighbors pari
a 3 punti, la distanza “hamming”.
X_train,
X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,
random_state=0) model
= KNeighborsClassifier(n_neighbors = 3, metric='hamming') model.fit(X_train,
y_train) pred_train
= model.predict(X_train) pred_test
= model.predict(X_test) acctest=accuracy_score(y_test,pred_test) acctrain=accuracy_score(y_train,pred_train) |
Inseriamo nella variabile “valori” gli
acquisti del nuovo cliente, non presente nel dataset
valori=[6,5,0,8,1,7]
i=0
ds
= [] for
row in X: i=i+1 distance = hamming_distance(valori, row) print(row,"
",round(distance,2)," ",y[i-1]) ds.append(distance) #print(ds) plt.plot(ds,
y,'ro') plt.show() prediction
= model.predict([valori]) print("Accuracy
Train:",round(acctrain*100,2),"% Accuracy Test: ",round(acctest*100,2),"%") print("Predicted
target name: {}".format(prediction)," \n\n",valori," ",prediction) |
ed
ecco il nostro output
Accuracy
Train: 78.57 % Accuracy Test: 14.29 % Predicted
target name: ['shoes'] [6, 5, 0, 8, 1, 7] ['shoes'] |
[6, 5, 0, 8, 1, 7] ['shoes']
Dalla lettura del grafico, vediamo
che le due distanze minori ricadono nella label “shoes”, quindi siccome due
punti sono maggiori di uno e noi abbiamo impostato il k=3 ossia tre punti,
l’algoritmo sceglie “shoes”.
Con questo piccolo e
probabilmente bruttino programma in Python, speriamo di aver reso più chiari i
meccanismi che ci sono dietro il sistema “intelligente” di raccomandazione, che
ha reputato gli acquisti del nuovo cliente più vicini a tre punti del dataset ed
in questi tre punti la maggioranza è formata da quelli che hanno acquistato o
ricevuto come consiglio d’acquisto delle scarpe e quindi gli ha proposto la
stessa cosa.
Lo stesso algoritmo e modo
di ragionare sarebbe servito anche solo per classificare un input sconosciuto.
That’s all folks!
Qui il link per il programma in Python
Commenti