La région de décision d'un classificateur Bayes naïf gaussien. Image de l'auteur.
Je pense que c'est un classique au début de chaque carrière en science des données : le Classificateur Naive Bayes. Ou devrais-je plutôt dire le famille de classificateurs naïfs de Bayes, car ils se déclinent en plusieurs saveurs. Par exemple, il existe un Bayes naïf multinomial, un Bayes naïf de Bernoulli, et aussi un classificateur Bayes naïf gaussien, chacun différent dans un seul petit détail, comme nous allons le découvrir. Les algorithmes naïfs de Bayes sont assez simples dans leur conception mais se sont avérés utiles dans de nombreuses situations complexes du monde réel.
Dans cet article, vous pouvez apprendre
- comment fonctionnent les classificateurs naïfs de Bayes,
- pourquoi il est logique de les définir comme ils sont et
- comment les implémenter en Python en utilisant NumPy.
Vous pouvez trouver le code sur mon Github.
Cela pourrait aider un peu à consulter mon introduction aux statistiques bayésiennes Une douce introduction à l'inférence bayésienne s'habituer à la formule de Bayes. Comme nous allons implémenter le classificateur d'une manière conforme à scikit learn, il vaut également la peine de consulter mon article Créez votre propre régression scikit-learn personnalisée. Cependant, la surcharge de scikit-learn est assez faible et vous devriez pouvoir suivre de toute façon.
Nous commencerons par explorer la théorie étonnamment simple de la classification naïve de Bayes, puis nous nous tournerons vers la mise en œuvre.
Qu'est-ce qui nous intéresse vraiment lors de la classification ? Que faisons-nous réellement, quelles sont les entrées et les sorties ? La réponse est simple :
Étant donné un point de données x, quelle est la probabilité que x appartienne à une certaine classe c ?
C'est tout ce que nous voulons répondre tous classification. Vous pouvez modéliser directement cet énoncé sous la forme d'une probabilité conditionnelle : p(c|x).
Par exemple, s'il y a
- les classes 3 c₁, c₂, c₃et une
- x se compose de 2 fonctions x₁, x₂,
le résultat d'un classificateur pourrait être quelque chose comme p(c₁|x₁, x₂) = 0.3, p(c₂|x₁, x₂)=0.5 et p(c₃|x₁, x₂)=0.2. Si nous nous soucions d'une seule étiquette comme sortie, nous choisirons celle avec la probabilité la plus élevée, c'est-à-dire c₂ avec une probabilité de 50% ici.
Le classificateur naïf de Bayes essaie de calculer directement ces probabilités.
Naïf Bayes
Ok, donc étant donné un point de données x, on veut calculer p(c|x) pour toutes les catégories c puis sortir le c avec la probabilité la plus élevée. Dans les formules, vous voyez souvent cela comme
Image de l'auteur.
Remarque: max p(c|x) renvoie la probabilité maximale tandis que argmax p(c|x) renvoie le c avec cette probabilité la plus élevée.
Mais avant de pouvoir optimiser p(c|x), nous devons pouvoir le calculer. Pour cela, nous utilisons théorème de Bayes:
Théorème de Bayes. Image de l'auteur.
C'est la partie Bayes du Bayes naïf. Mais maintenant, nous avons le problème suivant : Quels sont p(x|c) et p(c)?
C'est à cela que sert l'entraînement d'un classificateur bayésien naïf.
La formation
Pour illustrer le tout, utilisons un ensemble de données de jouets avec deux vraies caractéristiques x₁, x₂et une trois classes c₁, c₂, c₃ dans ce qui suit.
Les données, visualisées. Image de l'auteur.
Vous pouvez créer cet ensemble de données exact via
from sklearn.datasets import make_blobs X, y = make_blobs(n_samples=20, centers=[(0,0), (5,5), (-5, 5)], random_state=0)
Commençons par le probabilité de classe p(c), la probabilité qu'une classe c est observé dans le jeu de données étiqueté. Le moyen le plus simple d'estimer cela consiste simplement à calculer les fréquences relatives des classes et à les utiliser comme probabilités. Nous pouvons utiliser notre ensemble de données pour voir ce que cela signifie exactement.
Il y a 7 points sur 20 étiquetés classe c₁ (bleu) dans le jeu de données, donc on dit p(c₁)=7/20. Nous avons 7 points pour la classe c₂ (rouge) également, donc nous fixons p(c₂)=7/20. La dernière classe c₃ (jaune) n'a que 6 points, donc p(c₃)=6/20.
Ce calcul simple des probabilités de classe ressemble à une approche du maximum de vraisemblance. Cependant, vous pouvez également utiliser un autre avant distribution, si vous le souhaitez. Par exemple, si vous savez que cet ensemble de données n'est pas représentatif de la vraie population parce que la classe c₃ doit apparaître dans 50 % des cas, alors vous définissez p(c₁) = 0.25, p(c₂)=0.25 et p(c₃)=0.5. Tout ce qui vous aide à améliorer les performances sur l'ensemble de test.
Nous passons maintenant à la probabilité p(x|c)=p(x₁, x₂|c). Une approche pour calculer cette probabilité consiste à filtrer l'ensemble de données pour les échantillons avec étiquette c puis essayez de trouver une distribution (par exemple une gaussienne bidimensionnelle) qui capture les caractéristiques x₁, x₂.
Malheureusement, généralement, nous n'avons pas assez d'échantillons par classe pour faire une estimation correcte de la vraisemblance.
Pour pouvoir construire un modèle plus robuste, nous faisons le hypothèse naïve que les fonctionnalités x₁, x₂ stochastiquement indépendant, donné c. C'est juste une façon élégante de faciliter les calculs via
Image de l'auteur
pour chaque classe c. C'est là que le naïf une partie de Bayes naïf vient du fait que cette équation ne tient pas en général. Pourtant, même dans ce cas, le Bayes naïf donne de bons résultats, parfois exceptionnels, dans la pratique. Surtout pour les problèmes de PNL avec des caractéristiques de sac de mots, le Bayes naïf multinomial brille.
Les arguments donnés ci-dessus sont les mêmes pour tout classificateur Bayes naïf que vous pouvez trouver. Maintenant, cela dépend de la façon dont vous modélisez p(x₁|c₁), p(x₂|c₁), p(x₁|c₂), p(x₂|c₂), p(x₁|c₃) ainsi que le p(x₂|c₃).
Si vos caractéristiques sont 0 et 1 uniquement, vous pouvez utiliser un Distribution de Bernoulli. S'il s'agit d'entiers, un Distribution multinomiale. Cependant, nous avons de vraies valeurs de caractéristiques et décidons pour un Gaussienne distribution, d'où le nom de Bayes naïf gaussien. On suppose la forme suivante
Image de l'auteur.
De μᵢ, ⱼ est la moyenne et σᵢ,ⱼ est l'écart type que nous devons estimer à partir des données. Cela signifie que nous obtenons une moyenne pour chaque caractéristique i couplé à une classe cⱼ, dans notre cas 2*3=6 signifie. Il en va de même pour les écarts-types. Cela appelle un exemple.
Essayons d'estimer µ₂,₁ ainsi que le σ₂,₁. Car j=1, seule la classe nous intéresse c₁, ne gardons que les échantillons portant cette étiquette. Les échantillons suivants restent :
# samples with label = c_1 array([[ 0.14404357, 1.45427351], [ 0.97873798, 2.2408932 ], [ 1.86755799, -0.97727788], [ 1.76405235, 0.40015721], [ 0.76103773, 0.12167502], [-0.10321885, 0.4105985 ], [ 0.95008842, -0.15135721]])
Maintenant, à cause de i=2 nous n'avons qu'à considérer la deuxième colonne. µ₂,₁ est la moyenne et σ₂,₁ l'écart type pour cette colonne, c'est-à-dire µ₂,₁ = 0.49985176 et σ₂,₁ = 0.9789976.
Ces chiffres ont du sens si vous regardez à nouveau le nuage de points d'en haut. Les caractéristiques x₂ des échantillons de la classe c₁ sont autour de 0.5, comme vous pouvez le voir sur la photo.
Nous calculons cela maintenant pour les cinq autres combinaisons et nous avons terminé !
En Python, vous pouvez le faire comme ceci :
from sklearn.datasets import make_blobs
import numpy as np # Create the data. The classes are c_1=0, c_2=1 and c_3=2.
X, y = make_blobs( n_samples=20, centers=[(0, 0), (5, 5), (-5, 5)], random_state=0
) # The class probabilities.
# np.bincounts counts the occurence of each label.
prior = np.bincount(y) / len(y) # np.where(y==i) returns all indices where the y==i.
# This is the filtering step.
means = np.array([X[np.where(y == i)].mean(axis=0) for i in range(3)])
stds = np.array([X[np.where(y == i)].std(axis=0) for i in range(3)])
Nous recevons
# priors
array([0.35, 0.35, 0.3 ])
# means array([[ 0.90889988, 0.49985176], [ 5.4111385 , 4.6491892 ], [-4.7841679 , 5.15385848]])
# stds
array([[0.6853714 , 0.9789976 ], [1.40218915, 0.67078568], [0.88192625, 1.12879666]])
Ceci est le résultat de l'apprentissage d'un classificateur Bayes naïf gaussien.
Faire des prédictions
La formule de prédiction complète est
Image de l'auteur.
Supposons un nouveau point de données x*=(-2, 5) entre.
Image de l'auteur.
Pour voir à quelle classe il appartient, calculons p(c|x*) pour toutes les catégories. D'après la photo, il devrait appartenir à la classe c₃ = 2, mais voyons. Ignorons le dénominateur p(x) pour une seconde. À l'aide de la boucle suivante, calculez les nominateurs pour j = 1, 2, 3.
x_new = np.array([-2, 5]) for j in range(3): print( f"Probability for class {j}: {(1/np.sqrt(2*np.pi*stds[j]**2)*np.exp(-0.5*((x_new-means[j])/stds[j])**2)).prod()*p[j]:.12f}" )
Nous recevons
Probability for class 0: 0.000000000263
Probability for class 1: 0.000000044359
Probability for class 2: 0.000325643718
Bien sûr, ces probabilités (nous ne devrions pas les appeler ainsi) ne totalisez pas un puisque nous avons ignoré le dénominateur. Cependant, ce n'est pas un problème puisque nous pouvons simplement prendre ces probabilités non normalisées et les diviser par leur somme, puis elles totaliseront un. Ainsi, en divisant ces trois valeurs par leur somme d'environ 0.00032569, nous obtenons
Image de l'auteur.
Un gagnant clair, comme nous l'attendions. Maintenant, mettons-le en œuvre !
Cette implémentation n'est de loin pas efficace, pas stable numériquement, elle n'a qu'un but pédagogique. Nous avons discuté de la plupart des choses, il devrait donc être facile de suivre maintenant. Vous pouvez ignorer tous les check
fonctions, ou lisez mon article Construisez votre propre scikit-learn personnalisé si vous êtes intéressé par ce qu'ils font exactement.
Notez juste que j'ai implémenté un predict_proba
première méthode pour calculer les probabilités. La méthode predict
appelle simplement cette méthode et renvoie l'indice (= classe) avec la probabilité la plus élevée à l'aide d'une fonction argmax (le revoilà !). La classe attend les classes de 0 à k-1, où k est le nombre de classes.
import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.utils.validation import check_X_y, check_array, check_is_fitted class GaussianNaiveBayesClassifier(BaseEstimator, ClassifierMixin): def fit(self, X, y): X, y = check_X_y(X, y) self.priors_ = np.bincount(y) / len(y) self.n_classes_ = np.max(y) + 1 self.means_ = np.array( [X[np.where(y == i)].mean(axis=0) for i in range(self.n_classes_)] ) self.stds_ = np.array( [X[np.where(y == i)].std(axis=0) for i in range(self.n_classes_)] ) return self def predict_proba(self, X): check_is_fitted(self) X = check_array(X) res = [] for i in range(len(X)): probas = [] for j in range(self.n_classes_): probas.append( ( 1 / np.sqrt(2 * np.pi * self.stds_[j] ** 2) * np.exp(-0.5 * ((X[i] - self.means_[j]) / self.stds_[j]) ** 2) ).prod() * self.priors_[j] ) probas = np.array(probas) res.append(probas / probas.sum()) return np.array(res) def predict(self, X): check_is_fitted(self) X = check_array(X) res = self.predict_proba(X) return res.argmax(axis=1)
Tester la mise en œuvre
Bien que le code soit assez court, il est encore trop long pour être complètement sûr que nous n'avons pas fait d'erreurs. Alors, vérifions comment il se comporte par rapport au classificateur GaussianNB scikit-learn.
my_gauss = GaussianNaiveBayesClassifier()
my_gauss.fit(X, y)
my_gauss.predict_proba([[-2, 5], [0,0], [6, -0.3]])
sorties
array([[8.06313823e-07, 1.36201957e-04, 9.99862992e-01], [1.00000000e+00, 4.23258691e-14, 1.92051255e-11], [4.30879705e-01, 5.69120295e-01, 9.66618838e-27]])
Les prédictions utilisant le predict
méthode sont
# my_gauss.predict([[-2, 5], [0,0], [6, -0.3]])
array([2, 0, 1])
Maintenant, utilisons scikit-learn. Lancer du code
from sklearn.naive_bayes import GaussianNB gnb = GaussianNB()
gnb.fit(X, y)
gnb.predict_proba([[-2, 5], [0,0], [6, -0.3]])
rendements
array([[8.06314158e-07, 1.36201959e-04, 9.99862992e-01], [1.00000000e+00, 4.23259111e-14, 1.92051343e-11], [4.30879698e-01, 5.69120302e-01, 9.66619630e-27]])
Les chiffres ressemblent un peu à ceux de notre classificateur, mais ils sont un peu décalés dans les derniers chiffres affichés. Avons-nous fait quelque chose de mal ? No. La version scikit-learn utilise simplement un autre hyperparamètre var_smoothing=1e-09
. Si nous réglons celui-ci sur zéro, nous obtenons exactement nos chiffres. Parfait!
Jetez un œil aux régions de décision de notre classifieur. J'ai également marqué les trois points que nous avons utilisés pour les tests. Ce point proche de la frontière n'a que 56.9 % de chances d'appartenir à la classe rouge, comme vous pouvez le voir sur le predict_proba
les sorties. Les deux autres points sont classés avec une confiance beaucoup plus élevée.
Les régions de décision avec les 3 nouveaux points. Image de l'auteur.
Dans cet article, nous avons appris comment fonctionne le classificateur Bayes naïf gaussien et donné une intuition sur la raison pour laquelle il a été conçu de cette façon - c'est une approche directe pour modéliser la probabilité d'intérêt. Comparez cela avec la régression logistique : là, la probabilité est modélisée à l'aide d'une fonction linéaire avec une fonction sigmoïde appliquée au-dessus. C'est toujours un modèle facile, mais il ne semble pas aussi naturel qu'un classificateur Bayes naïf.
Nous avons continué en calculant quelques exemples et en collectant quelques morceaux de code utiles en cours de route. Enfin, nous avons implémenté un classificateur Bayes naïf gaussien complet d'une manière qui fonctionne bien avec scikit-learn. Cela signifie que vous pouvez l'utiliser dans les pipelines ou la recherche de grille, par exemple.
En fin de compte, nous avons effectué une petite vérification de cohérence en important scikit-learns propre classificateur Bayes naïf gaussien et en testant si les deux, notre classificateur et celui de scikit-learn donnent le même résultat. Ce test a réussi.
Dr Robert Kübler est Data Scientist chez Publicis Media et Auteur chez Towards Data Science.
ORIGINALE. Republié avec permission.
- Contenu propulsé par le référencement et distribution de relations publiques. Soyez amplifié aujourd'hui.
- Platoblockchain. Intelligence métaverse Web3. Connaissance Amplifiée. Accéder ici.
- La source: https://www.kdnuggets.com/2023/03/gaussian-naive-bayes-explained.html?utm_source=rss&utm_medium=rss&utm_campaign=gaussian-naive-bayes-explained
- :est
- $UP
- 1
- 7
- 8
- 9
- a
- Capable
- A Propos
- au dessus de
- actually
- à opposer à
- algorithmes
- Tous
- ainsi que le
- Une autre
- répondre
- apparaître
- appliqué
- une approche
- SONT
- arguments
- autour
- article
- AS
- At
- auteur
- base
- Bayésien
- BE
- car
- before
- Début
- Bit
- Bleu
- frontière
- construire
- by
- calculer
- le calcul
- Appelez-nous
- Appels
- CAN
- captures
- les soins
- Carrière
- maisons
- cas
- Chance
- vérifier
- Selectionnez
- classe
- les classes
- classiques
- classification
- classifié
- clair
- Fermer
- code
- Collecte
- Colonne
- комбинации
- comment
- comparer
- complet
- complètement
- complexe
- calcul
- confiance
- Considérer
- a continué
- pourriez
- accouplé
- cours
- engendrent
- Customiser
- données
- science des données
- Data Scientist
- ensembles de données
- décider
- décision
- dépend
- Conception
- un
- détail
- déviation
- DID
- différent
- chiffres
- directement
- discuté
- distribution
- faire
- Ne pas
- e
- chacun
- plus facilement
- pédagogique
- efficace
- assez
- notamment
- estimation
- Pourtant, la
- Chaque
- peut
- exactement
- exemple
- exemples
- attendu
- expliqué
- Explorer
- Fonctionnalité
- Fonctionnalités:
- few
- une fonction filtre
- filtration
- finalement
- Trouvez
- Prénom
- suivre
- Abonnement
- Pour
- formule
- De
- fonction
- fonctions
- Général
- doux
- obtenez
- donné
- Goes
- Bien
- Grille
- Vous avez
- vous aider
- aide
- ici
- augmentation
- le plus élevé
- appuyez en continu
- Comment
- Cependant
- HTML
- HTTPS
- i
- image
- Mettre en oeuvre
- la mise en oeuvre
- mis en œuvre
- importer
- l'importation
- l'amélioration de
- in
- indice
- Indices
- contribution
- intérêt
- intéressé
- Introduction
- intuition
- IT
- KDnuggetsGenericName
- XNUMX éléments à
- Genre
- Savoir
- Libellé
- Nom de famille
- savant
- comme
- peu
- Location
- Style
- a prendre une
- FAIT DU
- Fabrication
- de nombreuses
- marqué
- math
- maximales
- veux dire
- Médias
- seulement
- méthode
- pourrait
- erreurs
- modèle
- PLUS
- (en fait, presque toutes)
- prénom
- Nature
- Nouveauté
- nlp
- nombre
- numéros
- numpy
- of
- on
- ONE
- Autre
- sortie
- exceptionnel
- propre
- partie
- performant
- autorisation
- image
- pièces
- Platon
- Intelligence des données Platon
- PlatonDonnées
- Point
- des notes bonus
- population
- pratique
- prédiction
- Prédictions
- apprêt
- Avant
- probabilité
- Problème
- d'ouvrabilité
- correct
- prouvé
- but
- Python
- plutôt
- Lire
- réal
- monde réel
- Rouge
- région
- régions
- régression
- rester
- représentant
- Ressemble
- résultat
- Résultats
- retourner
- Retours
- ROBERT
- robuste
- même
- Sciences
- Scientifique
- scikit-apprendre
- Rechercher
- Deuxièmement
- AUTO
- sens
- sert
- set
- Shorts
- devrait
- similaires
- étapes
- depuis
- unique
- situations
- petit
- So
- quelques
- quelque chose
- stable
- Standard
- Commencer
- Déclaration
- étapes
- Encore
- réussi
- Prenez
- tester
- Essais
- qui
- La
- leur
- Les
- donc
- Ces
- des choses
- trois
- Lancement
- à
- trop
- top
- vers
- jouet
- Formation
- oui
- TOUR
- us
- utilisé
- d'habitude
- validation
- Valeurs
- version
- Façon..
- WELL
- Quoi
- Qu’est ce qu'
- qui
- tout en
- Wikipédia
- sera
- comprenant
- activités principales
- vos contrats
- digne d'intérêt
- pourra
- faux
- X
- Rendement
- rendements
- Votre
- zéphyrnet