Tavolo:
Introduzione
Naive Bayes è un algoritmo di machine learning di classificazione basato sul teorema di Bayes. È molto efficiente soprattutto quando si tratta di dati testuali come: analisi del sentiment, rilevamento dello spam e classificazione del testo.
Questo algoritmo è chiamato “Naive” perché presuppone che tutte le variabili del set di dati siano indipendenti, il che non è sempre vero.
Prima di approfondire ulteriormente la spiegazione di come funziona Naive Bayes, assicuriamoci di comprendere quanto segue:
Probabilità condizionale
L’algoritmo Naive Bayes si basa sul teorema di Bayes che si fonda sulla probabilità condizionata: è la probabilità che si verifichi un evento A dato che un evento B si è già verificato.
Esempio:
Prendiamo due barattoli che contengono palline colorate:
-
Il barattolo 1 ha 3 palline blu, 2 palline rosse e 4 palline verdi.
-
Il barattolo 2 ha 1 pallina blu, 4 palline rosse e 3 palline verdi.
Vogliamo calcolare la probabilità di estrarre casualmente una pallina blu da uno dei barattoli
Non è altro che la somma delle probabilità di selezionare una pallina blu da Jar1 o Jar2.
Ora vogliamo calcolare la probabilità di selezionare una pallina blu dato che abbiamo selezionato Jar1:
Infine, vogliamo calcolare la probabilità di selezionare Jar1 dato che abbiamo estratto una pallina blu. Qui usiamo il teorema di Bayes che è espresso come segue:
Classificazione ingenua di Bayes
Nel classificatore Naive Bayes, vogliamo trovare la classe che massimizza la probabilità condizionata dato il vettore di input X; quindi, Naive Bayes può essere formulato come segue:
Utilizzando il Teorema di Bayes la funzione diventa:
In questa formulazione è facile calcolare P(Ci) che non è altro che la probabilità della classe Ci, ed è facile calcolare P(x) che è la probabilità che si verifichi l’evento x.
Ciò che è difficile da calcolare è P(x|Ci); la probabilità dell'evento x data la classe Ci. Per semplificare ulteriormente questo concetto, dobbiamo assumere che tutte le variabili di input siano indipendenti; quindi, possiamo scrivere:
Ed è proprio a causa di questo presupposto che chiamiamo questo classificatore “Naive”, perché non sempre possiamo garantire l’indipendenza delle variabili di input. Il classificatore Naive Bayes diventa:
Possiamo infatti semplificare ulteriormente questa formulazione eliminando P(x), perché è uguale per tutte le classi:
Ora, diamo un’occhiata a un esempio:
| Meteo | Tempo | Giorno della settimana | Cena |
| ------- | -------- | --------------- | ------ |
| Cancella | Sera | Fine settimana | Cuochi |
| Nuvoloso | Notte | Giorno feriale | Ordini |
| Piovoso | Notte | Giorno feriale | Ordini |
| Piovoso | Mezzogiorno | Giorno feriale | Ordini |
| Nuvoloso | Mezzogiorno | Fine settimana | Cuochi |
| Cancella | Notte | Fine settimana | Cuochi |
| Nevoso | Sera | Fine settimana | Ordini |
| Cancella | Notte | Giorno feriale | Cuochi |
| Cancella | Mezzanotte | Fine settimana | Ordini |
Qui abbiamo un piccolo set di dati che contiene 3 variabili di input: Meteo, Ora e Giorno della settimana e una variabile Obiettivo: "Cena" che indica se una persona cucina o ordina la cena. Vorremmo trovare la classe dell'input x={Clear, Evening, Weekend}:
Dobbiamo calcolare la probabilità condizionale per la classe “Cuochi” e la classe “Ordini” dato l'input x={Sereno, Serata, Fine settimana}. La classe prevista è quella con la probabilità condizionata più alta.
Iniziamo calcolando la probabilità condizionata della classe “Cuochi”:
Ora calcoliamo ciascuna probabilità condizionata separatamente:
La probabilità che meteo="Clear" dato che la classe sia "Cooks" è il numero di righe con meteo "Clear" e classe "Cooks" sul numero totale di righe con classe "Cooks"
Lo stesso vale per le altre probabilità condizionali:
Ora per la probabilità P(Cooks) è il numero di righe con classe "Cooks" sul numero totale di righe:
Ora calcoliamo il prodotto di queste probabilità:
Questo è stato per la classe “Cuochi”, ora dobbiamo fare lo stesso per la classe “Ordini”:
Calcoliamo le probabilità individuali:
E infine calcoliamo il prodotto delle probabilità:
Infine, prendiamo la classe con la probabilità più alta che è la classe “Cuochi”:
Vantaggi e limiti di questo algoritmo
Vantaggi:
-
È un classificatore molto veloce.
-
È facile da implementare.
-
Non esiste una fase di formazione, ma è solo inferenza.
-
Non richiede molti dati per fare inferenze.
Limitazioni:
- Naive Bayes presuppone che le variabili di input siano indipendenti, il che non è sempre vero.
- Naive Bayes soffre del problema della frequenza zero: è quando assegna probabilità zero a una variabile di input. Ciò azzererà tutta la probabilità condizionata P(C|x). Un trucco per evitare ciò è utilizzare una frequenza minima pari a 1 (invece di 0) per tutte le variabili.
Esercizio
Ecco il dataframe dello stesso set di dati che abbiamo visto nell'esempio.
Il tuo compito è implementare tu stesso Naive Bayes usando Python:
import pandas as pd
dataset = pd.DataFrame()
dataset['Weather'] = ['Clear', 'Cloudy', 'Rainy', 'Rainy', 'Cloudy', 'Clear', 'Snowy', 'Clear', 'Clear']
dataset['Time'] = ['Evening', 'Night', 'Night', 'Midday', 'Midday', 'Night', 'Evening', 'Night', 'Midnight']
dataset['Day'] = ['Weekend', 'Weekday', 'Weekday', 'Weekday', 'Weekend', 'Weekend', 'Weekend', 'Weekday', 'Weekend']
dataset['Class'] = ['Cooks', 'Orders', 'Orders', 'Orders', 'Cooks', 'Cooks', 'Orders', 'Cooks', 'Orders']
def naive_bayes(weather, time, day):
# res_dict = {class1: probability of class 1, class1: probability of class 1
return res_dict
Soluzione
def naive_bayes(x_weather, x_time, x_day):
TARGET = 'Dinner' # The name of the target variable
CLASSES = list(dataset['Dinner'].unique()) # The classes of the target variable
len_dataset = len(dataset) # The length of the dataset
res_dict = {} # res_dict = {class1:probability1, ..., class_n:probability_n}
# for each class of the target classes, we calculate the it's conditional probability
for class_name in CLASSES:
# the number of lines that belong to the class "class_name"
len_c = len(dataset[ (dataset[TARGET] == class_name) ])
# the number of lines that belong to the class "class_name" and have weather="x_weather"
n_weather = len(dataset[ (dataset[TARGET] == class_name) & (dataset['Weather'] == x_weather) ])
# the number of lines that belong to the class "class_name" and have time="x_time"
n_time = len(dataset[ (dataset[TARGET] == class_name) & (dataset['Time'] == x_time) ])
# the number of lines that belong to the class "class_name" and have day="x_day"
n_day = len(dataset[ (dataset[TARGET] == class_name) & (dataset['Day'] == x_day) ])
# We calculate the conditional probability:
# P(class|x) = P(weather|class) x P(time|class) x P(day|class) x P(class)
p = (n_weather / len_c) * (n_time / len_c) * (n_day / len_c) * (len_c / len_dataset) res_dict[class_name] = p
return res_dict