Aller au contenu principal

Classifieur Naïf Bayésien

Le classifieur Bayésien est une technique supervisée de classement dont la particularité est qu'il préfère disposer de prédicteurs de type qualitatifs. Cela ne signifie pas pour autant que les variables quantitatives doivent être écartées mais ces dernières devront être transformées via le principe de discrétisation des variables continues.

Cette technique prédit des probabilités de classes et part de l'hypothèse que les variables sont conditionnellement indépendantes les unes des autres pour pouvoir définir la classe. Cette technique se base sur la probabilité individuelle ( de charque variable ) d'appartenance à une classe et multiplie ces probabilités individuelles ainsi que la probabilité générale de la classe.

Principe de Bayes

Le principe de Bayes s'intéresse à la probabilité conditionnelle qui consiste à relier la probabilité de A étant donné B à la probabilité de B étant donné A :

P(AB)=P(BA)P(A)P(B)P(A|B) = \frac{P(B|A) P(A)}{P(B)}

La probabilité de A étant donné B est la probabilité de B étant donné A multiplié par le rapport des probabilités de A et B

Par exemple :

  • Quelle est la probabilité qu’un client qui utilise un iPhone ne renouvelle pas son abonnement ?
  • Quelle est la probabilité qu’un client qui ne renouvelle pas son abonnement utilise un iPhone ?

Si A = arrêter son abonnement et B = utiliser un iPhone alors la probabilité d’arrêter son abonnement étant donné l’utilisation d’un iPhone est la probabilité d’avoir un iPhone étant donné un arrêt d’abonnement multiplié par la probabilité totale d’arrêter son abonnement, divisé par la probabilité totale d’avoir un iPhone

Probabilité conditionnelle individuelle

Le classifieur Naïf Bayésien suppose que les variables sont indépendantes. Une voiture peut être considérée comme une Ferrari si elle est rouge, sportive et dont la puissance max est de 780 Cv. Même si ces caractéristiques sont liées dans la réalité, l’algorithme déterminera que la voiture est une Ferrari en considérant indépendamment ses caractéristiques de couleur, type et de puissance et procédera comme suit :

  • Quelle est la probabilité qu'une voiture rouge est une Ferrari ?
    ( probabilité conditionnelle individuelle )
  • Quelle est la probabilité qu'une voiture sportive est une Ferrari ?
    ( probabilité conditionnelle individuelle )
  • Quelle est la probabilité qu'un moteur de 780 cv est une Ferrari ?
    ( probabilité conditionnelle individuelle )
  • Quelle est la probabilité d'une Ferrari sur toutes les voitures ?
    ( probabilité de classe )

L'algorithme multipliera ensuite ces probabilités individuelles qui seront divisées au dénominateur par les probabilités de toutes les classes afin d'obtenir une probabilité finale.

Formule

La formule de Bayes tente de répondre à la question suivante :

« Quelle est la probabilité qu’un enregistrement contenant un ensemble de valeurs prédictives 𝒙𝟏𝒙_𝟏, 𝒙𝟐𝒙_𝟐, …., 𝒙n𝒙_n  appartienne une classe parmi l’ensemble des classes ? »

Pnb(C1x1,,xp)=P_{nb}(C_1 | x_1, \dots, x_p) =
P(C1)[P(x1C1)P(x2C1)P(x3C1)...P(xnC1)][P(C1)P(x1C1)P(x2C1)P(x3C1)]+...+[P(Cm)P(x1Cm)P(x2Cm)P(x3Cm)]\frac{P(C_1) [P(x_1 | C_1) P(x_2 | C_1) P(x_3 | C_1) ... P(x_n | C_1)]}{[P(C_1) P(x_1 | C_1) P(x_2 | C_1) P(x_3 | C_1)] + ... + [P(C_m) P(x_1 | C_m) P(x_2 | C_m) P(x_3 | C_m)]}

Cette formule peut être réécrite comme suit :

Pnb(C1x1,,xp)=P(C1)i=1pP(xiC1)j=1mP(Cj)i=1pP(xiCj)P_{nb}(C_1 | x_1, \dots, x_p) = \frac{P(C_1) \prod_{i=1}^{p} P(x_i | C_1)}{\sum_{j=1}^{m} P(C_j) \prod_{i=1}^{p} P(x_i | C_j)}

Le symbole i=1p\prod_{i=1}^{p} représente le produit de toutes les classes.

Si nous décomposons cette formule, nous retrouvons les étapes suivantes :

  1. Estimer la probabilité conditionnelle individuelle pour chaque prédicteur d’appartenance aux classes 𝐶1,...Cn𝐶_1,...C_n - soit la probabilité que la valeur de l’enregistrement qui doit être classé appartienne à la classe C1P(xjC1)C_1 \cdot P(x_j | C_1), pour la première classe, C2P(xjC2)C_2 \cdot P(x_j | C_2) pour la seconde classe, etc . Pour rappel, les caractéristiques sont évaluées de manière indépendantes

  2. Après évaluation indépendante, multiplier les probabilités conditionnelles individuelles d’appartenance à chacune des classes CiC_i de chaque prédicteur soit la probabilité conditionnelle de la classe C1[P(x1C1)P(x2C1)P(x3C1)P(xnC1)]C_1 \cdot [ P(x_1 | C_1) P(x_2 | C_1) P(x_3 | C_1) \dots P(x_n | C_1) ],..., la probabilité conditionnelle de la classe Ci[P(x1Ci)P(x2Ci)P(x3Ci)P(xnCi)]C_i \cdot [ P(x_1 | C_i) P(x_2 | C_i) P(x_3 | C_i) \dots P(x_n | C_i) ]

  3. Estimer la proportion d’enregistrements appartenant aux classes CiC_i soit le total des enregistrements 𝐶1𝐶_1 par rapport au total des enregistrements des autres classes. Le total des enregistrements 𝐶2𝐶_2,...,CnC_n rapport au total des enregistrements des autres classes ;

  4. Répéter les étapes 1,2 et 3 pour l’ensemble des classes (= probabilité conditionnelle de la classe 𝑪𝟐,...,Cn𝑪_𝟐,...,C_n… & proportion d’enregistrements appartenant à la classe 𝐶2,...,Cn𝐶_2,...,C_n)

  5. Appliquer la formule complète du classifieur naïf Bayésien pour l’ensemble des classes

  6. Assigner à l’enregistrement la classe correspondant à la probabilité la plus importante.

Décomposition des étapes

Prenons un exemple simplifié de l'utilisation du classifieur naïf Bayésien pour la détection de spam. Nous avons mis en place un modèle pour différencier les spams et emails. L’algorithme est entrainé ( il est capable de classer ) et reçoit l’email suivant :

« Cher John, serais-tu disponible pour un lunch entre amis demain ? Ne prends pas ton argent, c’est au tour de Lucas de régaler ».

Il identifie dans son set d’entrainement d’autres emails (25)( 25 ) pour lesquels on retrouve les mots « Cher, Lunch, Amis, Argent » et pour lesquels il dispose déjà d’une étiquette – soit un classement mail (17)( 17 ) ou spam (8)( 8 ).

Chaque mot est considéré comme une variable distincte et les enregistrements sont les emails :

x1x_1 = Cher (présence ou absence du mot "Cher")
x2x_2 = Amis (présence ou absence du mot "Amis")
x3x_3 = Lunch (présence ou absence du mot "Lunch")
x4x_4 = Argent (présence ou absence du mot "Argent")

Étape 1 : Estimer la probabilité conditionnelle individuelle pour chaque prédicteur d’appartenance aux classes 𝐶1,...Cn𝐶_1,...C_n.

Il s'agit de définir la probabilité d’appartenance individuelle à une classe sous-entend une probabilité conditionnelle individuelle c’est-à-dire la probabilité de l’évènement B étant donné que l’évènement A s’est produit. 𝑃 (𝐴│𝐵).

Dans notre cas, nous regarderons la probabilité d’appartenance à la classe 𝐶1𝐶_1 et C2C_2 étant donné chaque prédicteur 𝑥1,x2,x3,x4𝑥_1,x_2,x_3,x_4.

P(C1)[P(x1C1)P(x2C1)P(x3C1)P(x4C1)]P(C1)[P(x1C1)P(x2C1)P(x3C1)P(x4C1)]+P(C2)[P(x1C2)P(x2C2)P(x3C2)P(x4C2)]\frac{P(C_1) [\textcolor{blue}{P(x_1 | C_1)}\textcolor{green}{P( x_2 | C_1)} \textcolor{orange}{P(x_3 | C_1)} \textcolor{red}{P(x_4 | C_1)}]}{P(C_1)[P(x_1 | C_1)P( x_2 | C_1) P(x_3 | C_1) P(x_4 | C_1)] + P(C_2)[P(x_1 | C_2) P(x_2 | C_2) P(x_3 | C_2) P(x_4 | C_2)]}

Bayes Exemple 1 500

𝑃(𝑥𝑗𝐶1)𝑃 (𝑥_𝑗 │𝐶_1 ) Total 1717 emails

𝑃 (𝐶ℎ𝑒𝑟│𝐸𝑚𝑎𝑖𝑙) 𝑃(817)=0.47𝑃 (8│17) = 0.47
𝑃 (𝐴𝑚𝑖𝑠│𝐸𝑚𝑎𝑖𝑙) 𝑃(517)=0.29𝑃 (5│17) = 0.29
𝑃 (𝐿𝑢𝑛𝑐ℎ│𝐸𝑚𝑎𝑖𝑙) 𝑃(317)=0.18𝑃 (3│17) = 0.18
𝑃 (𝐴𝑟𝑔𝑒𝑛𝑡│𝐸𝑚𝑎𝑖𝑙) 𝑃(117)=0.06𝑃 (1│17) = 0.06

Regardons maintenant la probabilité d’appartenance à la classe 𝐶2𝐶_2 étant donné les valeurs du prédicteur 𝑥1𝑥_1 soit 𝑃(𝑥1𝐶2)𝑃(𝑥_1 │𝐶_2 ).

P(C1)[P(x1C1)P(x2C1)P(x3C1)P(x4C1)]P(C1)[P(x1C1)P(x2C1)P(x3C1)P(x4C1)]+P(C2)[P(x1C2)P(x2C2)P(x3C2)P(x4C2)]\frac{P(C_1) [P(x_1 | C_1)P( x_2 | C_1) P(x_3 | C_1) P(x_4 | C_1)]}{P(C_1)[P(x_1 | C_1)P( x_2 | C_1) P(x_3 | C_1) P(x_4 | C_1)] + P(C_2)[\textcolor{blue}{P(x_1 | C_2)}\textcolor{green}{P( x_2 | C_2)} \textcolor{orange}{P(x_3 | C_2)} \textcolor{red}{P(x_4 | C_2)}]}

Bayes Exemple 1 500

𝑃(𝑥𝑗𝐶2)𝑃 (𝑥_𝑗 │𝐶_2 ) Total 88 spams

𝑃 (𝐶ℎ𝑒𝑟│Spam) 𝑃(28)=0.25𝑃 (2│8) = 0.25
𝑃 (𝐴𝑚𝑖𝑠│Spam) 𝑃(18)=0.125𝑃 (1│8) = 0.125
𝑃 (𝐿𝑢𝑛𝑐ℎ│Spam) 𝑃(38)=0.125𝑃 (3│8) = 0.125
𝑃 (𝐴𝑟𝑔𝑒𝑛𝑡│Spam) 𝑃(38)=0.50𝑃 (3│8) = 0.50

Étape 2 : Estimation de la probabilité conditionnelle des classes.

Il s'agit de multiplier les probabilités conditionnelles individuelles d’appartenance des classes C_𝑖 de chaque prédicteur.

P(C1)[P(x1C1)P(x2C1)P(x3C1)P(x4C1)]P(C1)[P(x1C1)P(x2C1)P(x3C1)P(x4C1)]+P(C2)[P(x1C2)P(x2C2)P(x3C2)P(x4C2)]\frac{P(C_1) [\textcolor{orange}{P(x_1 | C_1)P( x_2 | C_1) P(x_3 | C_1) P(x_4 | C_1)}]}{P(C_1)[\textcolor{orange}{P(x_1 | C_1)P( x_2 | C_1) P(x_3 | C_1) P(x_4 | C_1)}] + P(C_2)[\textcolor{blue}{P(x_1 | C_2)P( x_2 | C_2) P(x_3 | C_2) P(x_4 | C_2)}]}

[ 𝑃 (𝐶ℎ𝑒𝑟 │𝐸𝑚𝑎𝑖𝑙) 𝑃 (𝐴𝑚𝑖𝑠 │𝐸𝑚𝑎𝑖𝑙) 𝑃 (𝐿𝑢𝑛𝑐ℎ │𝐸𝑚𝑎𝑖𝑙) 𝑃 (𝐴𝑟𝑔𝑒𝑛𝑡 │𝐸𝑚𝑎𝑖𝑙)]
[ 𝑃 (𝐶ℎ𝑒𝑟 │𝑆𝑝𝑎𝑚)𝑃 (𝐴𝑚𝑖𝑠 │𝑆𝑝𝑎𝑚)𝑃 (𝐿𝑢𝑛𝑐ℎ │𝑆𝑝𝑎𝑚) 𝑃 (𝐴𝑟𝑔𝑒𝑛𝑡 │𝑆𝑝𝑎𝑚)]

PrédicteurP(Prédicteur_Email)P(Prédicteur_Spam)
x1x_1 Cher0.470.25
x2x_2 Amis0.290.125
x3x_3 Lunch0.180.375
x4x_4 Argent0.060.50
Produit0.47 x 0.29 x 0.18 x 0.060.25 x 0.125 x 0.375 x 0.50

Étape 3 : Estimation des proportion d’enregistrements appartenant aux classes 𝐶1𝐶_1

Nous devons encore tenir compte d’un élément important pour estimer la probabilité : il s’agit de la proportion de la valeur de la classe par rapport à l’ensemble des valeurs des deux classes. Soit : quelle est la proportion de spams par rapport à tous les emails reçus (spams & email). C’est une manière de s’assurer que la proportion sera mesurée à même échelle.

P(C1)[P(x1C1)P(x2C1)P(x3C1)P(x4C1)]P(C1)[P(x1C1)P(x2C1)P(x3C1)P(x4C1)]+P(C2)[P(x1C2)P(x2C2)P(x3C2)P(x4C2)]\frac{\textcolor{red}{P(C_1)} [P(x_1 | C_1)P( x_2 | C_1) P(x_3 | C_1) P(x_4 | C_1)]}{\textcolor{red}{P(C_1)}[P(x_1 | C_1)P( x_2 | C_1) P(x_3 | C_1) P(x_4 | C_1)] + \textcolor{orange}{P(C_2)}[P(x_1 | C_2) P(x_2 | C_2) P(x_3 | C_2) P(x_4 | C_2)]}

Sur 2525 emails, 1717 étaient des emails normaux et 88 étaient des spams :

  • Proportion d’emails normaux 𝑃(𝐶1)=17/25=0.68𝑃(𝐶_1) = 17/25 = 0.68 soit 6868 %
  • Proportion de spams 𝑃(𝐶2)=8/25=0.32𝑃(𝐶_2) = 8/ 25 = 0.32 soit 3232 %

Étape 4 : répéter les étapes 1, 2 et 3 pour l’ensemble des classes. (Déjà réalisé dans notre exemple).

Étape 5 : appliquer la formule complète du classifieur naïf Bayésien pour l’ensemble des classes

P(C1)[P(x1C1)P(x2C1)P(x3C1)P(x4C1)]P(C1)[P(x1C1)P(x2C1)P(x3C1)P(x4C1)]+P(C2)[P(x1C2)P(x2C2)P(x3C2)P(x4C2)]\frac{P(C_1) [P(x_1 | C_1)P( x_2 | C_1) P(x_3 | C_1) P(x_4 | C_1)]}{P(C_1)[P(x_1 | C_1)P( x_2 | C_1) P(x_3 | C_1) P(x_4 | C_1)] + P(C_2)[P(x_1 | C_2) P(x_2 | C_2) P(x_3 | C_2) P(x_4 | C_2)]}
0.68[0.470.290.180.06]0.68[0.470.290.180.06]+0.32[0.250.1250.3750.50]\frac{\textcolor{green}{0.68 * [0.47 * 0.29 * 0.18 * 0.06]}}{\textcolor{green}{0.68 * [0.47 * 0.29 * 0.18 * 0.06]} + \textcolor{red}{0.32 [0.25 * 0.125 * 0.375 * 0.50]}}

Email:

0.0010009872(0.0010009872+0.000625)=0.00100098720.0016259872=61.44%\frac{0.0010009872}{(0.0010009872 + 0.000625)} = \frac{0.0010009872}{0.0016259872} = 61.44\%

Spams:

10.0010009872(0.0010009872+0.000625)=10.00100098720.0016259872=38.56%1 - \frac{0.0010009872}{(0.0010009872 + 0.000625)} = 1 - \frac{0.0010009872}{0.0016259872} = 38.56\%

Étape 6 : assigner à l’enregistrement la classe correspondant à la probabilité la plus importante

y^\hat{y} = Email

Particularités de la technique

Il est important de noter que cette technique démontrera ses qualités à la condition sine qua non que les variables sont toutes indépendantes entre elle. Or, cette hypothèse est peu souvent applicable.

Toutefois, son avantage est qu'elle nécessite peu de données et que son procédé de calcul est relativement simple. Le classifieur naïf Bayésien est régulièrement utilisé pour le traitement du language naturel ( classification de texte, l'analyse de sentiment, ...).

Code Python Bayesian Classifier

# Step 1: Import necessary libraries
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report, confusion_matrix

# Step 2: Load the dataset with a filter on two categories
# These categories represent texts about baseball and space
categories = ['rec.sport.baseball', 'sci.space']
data = fetch_20newsgroups(subset='all', categories=categories, remove=('headers', 'footers', 'quotes'))

# Step 3: Explore the dataset
# Print the total number of documents, available categories, and an example document
print(f"Total number of documents: {len(data.data)}")
print(f"Categories: {data.target_names}")
print(f"Example document: {data.data[0]}")

# Step 4: Split the dataset into training and testing sets
# 70% of the data will be used for training, and 30% for testing
X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.3, random_state=42)

# Step 5: Convert text data into a Bag of Words representation
# This creates a sparse matrix where each row corresponds to a document
# and each column corresponds to a word in the vocabulary
vectorizer = CountVectorizer()
X_train_counts = vectorizer.fit_transform(X_train)

# Step 6: Apply TF-IDF weighting to the Bag of Words matrix
"""
TF-IDF stands for Term Frequency-Inverse Document Frequency, a method used in Natural Language Processing (NLP)
to convert textual data into numerical vectors by assigning weights to words based on their importance.

1. Term Frequency (TF)
TF measures how frequently a word appears in a specific document. It is a local measure, specific to a single document.

TF (𝑡,𝑑) = (Number of occurrences of term 𝑡  in document 𝑑 ) / (Total number of terms in document 𝑑)
Words that appear more frequently in a document have a higher TF value.
Example: If the word "moon" appears 5 times in a document containing 100 words, then:
TF("moon")=5/100 =0.05


2. Inverse Document Frequency (IDF)
IDF measures the importance of a word across the entire corpus. It is a global measure, specific to all documents.

IDF(𝑡,𝐷) = log (N / (1+𝑛𝑡) )

N: Total number of documents in the corpus.
nt : Number of documents containing the term
Adding 1 in the denominator avoids division by zero if 𝑛𝑡 = 0

"""

# This adjusts the word frequencies based on their importance across all documents
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)

# Step 7: Train the Naive Bayes model
# Use the training data (TF-IDF matrix and corresponding labels)
model = MultinomialNB()
model.fit(X_train_tfidf, y_train)

# Step 8: Prepare the test data
# Transform the test set into the same format as the training set
X_test_counts = vectorizer.transform(X_test)
X_test_tfidf = tfidf_transformer.transform(X_test_counts)

# Step 9: Predict labels for the test data
y_pred = model.predict(X_test_tfidf)

# Step 10: Evaluate the model's performance
# Print the confusion matrix and classification report
cm_test = confusion_matrix(y_test, y_pred)
print(cm_test)

# Calculate overall accuracy
accuracy = cm_test.diagonal().sum() / cm_test.sum()
print(f"\nOverall Accuracy: {accuracy * 100:.2f}%")

# Step 11: Predict the class of a new message
# Example: A message that looks like spam
new_message = ["Bitcoin to the moons!!"]


# Transform the new message into a Bag of Words representation
new_message_counts = vectorizer.transform(new_message)

# Apply TF-IDF weighting to the new message
new_message_tfidf = tfidf_transformer.transform(new_message_counts)

# Step 12: Get the probabilities for each class
# This shows how likely the message is to belong to each category
proba = model.predict_proba(new_message_tfidf)

# Step 13: Predict the most likely class for the new message
prediction = model.predict(new_message_tfidf)


# Step 14: Display the results
print(f"\nMessage: {new_message[0]}")
print(f"Predicted Class: {data.target_names[prediction[0]]}")

# Display class probabilities in percentages
print("\nClass Probabilities:")
for i, category in enumerate(data.target_names):
print(f"Probability of '{category}': {proba[0][i] * 100:.2f}%")