Gaussian Naive Bayes, Εξήγηση

Gaussian Naive Bayes, Εξήγηση

Κόμβος πηγής: 2021431

Gaussian Naive Bayes, Εξήγηση
Η περιοχή απόφασης ενός Gaussian naive ταξινομητή Bayes. Εικόνα από τον συγγραφέα.

 

Νομίζω ότι αυτό είναι ένα κλασικό στην αρχή κάθε καριέρας της επιστήμης δεδομένων: το Naive Bayes Classifier. Ή μάλλον θα έπρεπε να πω το οικογένεια των αφελών ταξινομητών Bayes, καθώς κυκλοφορούν σε πολλές γεύσεις. Για παράδειγμα, υπάρχει ένας πολυωνυμικός αφελής Bayes, ένας Bernoulli naive Bayes και επίσης ένας Gaussian naive Bayes ταξινομητής, ο καθένας διαφορετικός μόνο σε μια μικρή λεπτομέρεια, όπως θα μάθουμε. Οι αφελείς αλγόριθμοι Bayes είναι αρκετά απλοί στο σχεδιασμό, αλλά αποδείχθηκαν χρήσιμοι σε πολλές πολύπλοκες πραγματικές καταστάσεις.

Σε αυτό το άρθρο, μπορείτε να μάθετε

  • πώς λειτουργούν οι αφελείς ταξινομητές Bayes,
  • γιατί είναι λογικό να τα ορίζουμε όπως είναι και
  • πώς να τα εφαρμόσετε στην Python χρησιμοποιώντας το NumPy.

Μπορείτε να βρείτε τον κωδικό στο το Github μου.

Θα μπορούσε να βοηθήσει λίγο να ελέγξω το αστάρι μου για τις στατιστικές Bayes Μια ευγενική εισαγωγή στο συμπέρασμα Μπεϋζιάν για να συνηθίσετε τη φόρμουλα Bayes. Δεδομένου ότι θα εφαρμόσουμε τον ταξινομητή με τρόπο μαθηματικό σύμφωνα με το scikit, αξίζει επίσης να δείτε το άρθρο μου Δημιουργήστε τη δική σας προσαρμοσμένη παλινδρόμηση scikit-learn. Ωστόσο, το κόστος μάθησης scikit είναι αρκετά μικρό και θα πρέπει να μπορείτε να το ακολουθήσετε ούτως ή άλλως.

Θα αρχίσουμε να εξερευνούμε την εκπληκτικά απλή θεωρία της αφελούς ταξινόμησης Bayes και στη συνέχεια θα στραφούμε στην υλοποίηση.

Τι μας ενδιαφέρει πραγματικά κατά την ταξινόμηση; Τι κάνουμε στην πραγματικότητα, ποια είναι η είσοδος και η έξοδος; Η απάντηση είναι απλή:

Με δεδομένο ένα σημείο δεδομένων x, ποια είναι η πιθανότητα το x να ανήκει σε κάποια κατηγορία c;

Μόνο με αυτό θέλουμε να απαντήσουμε κάθε ταξινόμηση. Μπορείτε να μοντελοποιήσετε απευθείας αυτή τη δήλωση ως πιθανότητα υπό όρους: p(c|x).

Για παράδειγμα, αν υπάρχουν

  • τάξεις 3 cXNUMXcXNUMXc₃, να
  • αποτελείται από 2 χαρακτηριστικά x₁x₂,

το αποτέλεσμα ενός ταξινομητή θα μπορούσε να είναι κάτι σαν p(cXNUMX|x₁x₂) = 0.3, p(cXNUMX|x₁x₂)=0.5 και p(c₃|x₁x₂)=0.2. Εάν νοιαζόμαστε για μια μεμονωμένη ετικέτα ως έξοδο, θα επιλέγαμε αυτή με την υψηλότερη πιθανότητα, π.χ cXNUMX με πιθανότητα 50% εδώ.

Ο αφελής ταξινομητής Bayes προσπαθεί να υπολογίσει απευθείας αυτές τις πιθανότητες.

Ναϊβ Μπέις

Εντάξει, δίνεται λοιπόν ένα σημείο δεδομένων x, θέλουμε να υπολογίσουμε p(c|x) για όλες τις τάξεις και μετά βγάζουμε το c με τη μεγαλύτερη πιθανότητα. Στις φόρμουλες το βλέπετε συχνά ως

 

Gaussian Naive Bayes, Εξήγηση
Εικόνα από τον συγγραφέα.

 

Σημείωση: max p(c|x) επιστρέφει τη μέγιστη πιθανότητα ενώ το argmax p(c|x) επιστρέφει το c με αυτή την υψηλότερη πιθανότητα.

Αλλά πριν μπορέσουμε να βελτιστοποιήσουμε p(c|x), πρέπει να είμαστε σε θέση να το υπολογίσουμε. Για αυτό, χρησιμοποιούμε Το θεώρημα του Bayes:

 

Gaussian Naive Bayes, Εξήγηση
Θεώρημα Bayes. Εικόνα από τον συγγραφέα.

 

Αυτό είναι το μέρος Bayes του αφελούς Bayes. Αλλά τώρα, έχουμε το εξής πρόβλημα: Τι είναι p(x|c) Και p(c)?

Αυτό είναι το θέμα της εκπαίδευσης ενός αφελούς ταξινομητή Bayes.

Η προπόνηση

Για να τα επεξηγήσουμε όλα, ας χρησιμοποιήσουμε ένα σύνολο δεδομένων παιχνιδιών με δύο πραγματικά χαρακτηριστικά x₁x₂, να τρεις τάξεις cXNUMXcXNUMXc₃ στα ακόλουθα.

 

Gaussian Naive Bayes, Εξήγηση
Τα δεδομένα, οπτικοποιημένα. Εικόνα από τον συγγραφέα.

 

Μπορείτε να δημιουργήσετε αυτό το ακριβές σύνολο δεδομένων μέσω

from sklearn.datasets import make_blobs X, y = make_blobs(n_samples=20, centers=[(0,0), (5,5), (-5, 5)], random_state=0)

Ας ξεκινήσουμε με το πιθανότητα κατηγορίας p(c), η πιθανότητα κάποιας κατηγορίας c παρατηρείται στο επισημασμένο σύνολο δεδομένων. Ο απλούστερος τρόπος για να εκτιμηθεί αυτό είναι απλώς να υπολογίσουμε τις σχετικές συχνότητες των κλάσεων και να τις χρησιμοποιήσουμε ως πιθανότητες. Μπορούμε να χρησιμοποιήσουμε το σύνολο δεδομένων μας για να δούμε τι ακριβώς σημαίνει αυτό.

Υπάρχουν 7 στα 20 σημεία με την ένδειξη κατηγορία cXNUMX (μπλε) στο σύνολο δεδομένων, επομένως λέμε p(cXNUMX)=7/20. Έχουμε 7 βαθμούς για την κατηγορία cXNUMX (κόκκινο) επίσης, επομένως θέτουμε p(cXNUMX)=7/20. Η τελευταία τάξη c₃ (κίτρινο) έχει μόνο 6 βαθμούς, ως εκ τούτου p(c₃)=6/20.

Αυτός ο απλός υπολογισμός των πιθανοτήτων κατηγορίας μοιάζει με μια προσέγγιση μέγιστης πιθανότητας. Μπορείτε, ωστόσο, να χρησιμοποιήσετε και άλλο πριν διανομή, αν θέλετε. Για παράδειγμα, εάν γνωρίζετε ότι αυτό το σύνολο δεδομένων δεν είναι αντιπροσωπευτικό του πραγματικού πληθυσμού λόγω της κλάσης c₃ θα πρέπει να εμφανίζεται στο 50% των περιπτώσεων, τότε ορίζετε p(cXNUMX) = 0.25, p(cXNUMX)=0.25 και p(c₃)=0.5. Οτιδήποτε σας βοηθά να βελτιώσετε την απόδοση στο σετ δοκιμών.

Περνάμε τώρα στο πιθανότητα p(x|c)=p(x₁x₂|c). Μια προσέγγιση για τον υπολογισμό αυτής της πιθανότητας είναι να φιλτράρετε το σύνολο δεδομένων για δείγματα με ετικέτα και μετά προσπαθήστε να βρείτε μια κατανομή (π.χ. ένα δισδιάστατο Gaussian) που να καταγράφει τα χαρακτηριστικά x₁x₂.

Δυστυχώς, συνήθως, δεν έχουμε αρκετά δείγματα ανά τάξη για να κάνουμε μια σωστή εκτίμηση της πιθανότητας.

Για να μπορέσουμε να φτιάξουμε ένα πιο στιβαρό μοντέλο, φτιάχνουμε το αφελής υπόθεση ότι τα χαρακτηριστικά x₁x₂ are στοχαστικά ανεξάρτητη, δεδομένου c. Αυτός είναι απλώς ένας φανταχτερός τρόπος για να κάνετε τα μαθηματικά πιο εύκολα

 

Gaussian Naive Bayes, Εξήγηση
Εικόνα από τον συγγραφέα

 

για κάθε τάξη c. Αυτό είναι όπου το αφελής μέρος του αφελούς Bayes προέρχεται από επειδή αυτή η εξίσωση δεν ισχύει γενικά. Ωστόσο, ακόμη και τότε ο αφελής Bayes αποδίδει καλά, μερικές φορές εξαιρετικά αποτελέσματα στην πράξη. Ειδικά για προβλήματα NLP με χαρακτηριστικά bag-of-words, η πολυωνυμική αφελής Bayes λάμπει.

Τα επιχειρήματα που δίνονται παραπάνω είναι τα ίδια για οποιονδήποτε απλό ταξινομητή Bayes μπορείτε να βρείτε. Τώρα εξαρτάται μόνο από το πώς μοντελοποιείς p(xXNUMX|cXNUMX), p(xXNUMX|cXNUMX), p(xXNUMX|cXNUMX), p(xXNUMX|cXNUMX), p(xXNUMX|cXNUMX) και  p(xXNUMX|cXNUMX).

Εάν τα χαρακτηριστικά σας είναι μόνο 0 και 1, μπορείτε να χρησιμοποιήσετε το α Διανομή Bernoulli. Αν είναι ακέραιοι, α Πολυωνυμική κατανομή. Ωστόσο, έχουμε πραγματικές τιμές χαρακτηριστικών και αποφασίζουμε για α Gaussian διανομή, εξ ου και το όνομα Gaussian naive Bayes. Υποθέτουμε την παρακάτω μορφή

 

Gaussian Naive Bayes, Εξήγηση
Εικόνα από τον συγγραφέα.

 

όπου μᵢ,ⱼ είναι η μέση και σᵢ,ⱼ είναι η τυπική απόκλιση που πρέπει να υπολογίσουμε από τα δεδομένα. Αυτό σημαίνει ότι παίρνουμε έναν μέσο όρο για κάθε χαρακτηριστικό i σε συνδυασμό με μια τάξη γⱼ, στην περίπτωσή μας 2*3=6 σημαίνει. Το ίδιο ισχύει και για τις τυπικές αποκλίσεις. Αυτό απαιτεί ένα παράδειγμα.

Ας προσπαθήσουμε να εκτιμήσουμε μXNUMX και  σXNUMX. Επειδή j=1, μας ενδιαφέρει μόνο η τάξη cXNUMX, ας κρατάμε μόνο δείγματα με αυτήν την ετικέτα. Παραμένουν τα ακόλουθα δείγματα:

# 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]])

Τώρα, λόγω i=2 πρέπει να εξετάσουμε μόνο τη δεύτερη στήλη. μ₂,₁ είναι ο μέσος όρος και σ₂,XNUMX η τυπική απόκλιση για αυτήν τη στήλη, π.χ μ₂,0.49985176 = XNUMX και σ₂,0.9789976 = XNUMX.

Αυτοί οι αριθμοί έχουν νόημα αν ξανακοιτάξετε το διάγραμμα διασποράς από ψηλά. Τα γνωρίσματα x₂ των δειγμάτων από την τάξη cXNUMX είναι γύρω στο 0.5, όπως μπορείτε να δείτε από την εικόνα.

Το υπολογίζουμε τώρα για τους άλλους πέντε συνδυασμούς και τελειώσαμε!

Στην Python, μπορείτε να το κάνετε ως εξής:

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)])

Λαμβάνουμε

# 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]])

Αυτό είναι το αποτέλεσμα της εκπαίδευσης ενός Gaussian αφελούς ταξινομητή Bayes.

Κάνοντας προβλέψεις

Ο πλήρης τύπος πρόβλεψης είναι

 

Gaussian Naive Bayes, Εξήγηση
Εικόνα από τον συγγραφέα.

 

Ας υποθέσουμε ένα νέο σημείο δεδομένων x*=Το (-2, 5) μπαίνει.

 

Gaussian Naive Bayes, Εξήγηση
Εικόνα από τον συγγραφέα.

 

Για να δούμε σε ποια κατηγορία ανήκει, ας υπολογίσουμε p(c|x*) για όλες τις τάξεις. Από την εικόνα, πρέπει να ανήκει στην τάξη c₃ = 2, αλλά ας δούμε. Ας αγνοήσουμε τον παρονομαστή p(x) για ένα δευτερόλεπτο. Χρησιμοποιώντας τον ακόλουθο βρόχο υπολογίστηκαν οι υποψήφιοι για 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}" )

Λαμβάνουμε

Probability for class 0: 0.000000000263
Probability for class 1: 0.000000044359
Probability for class 2: 0.000325643718

Φυσικά, αυτά πιθανότητες (δεν θα έπρεπε να τους λέμε έτσι) μην αθροίζετε σε ένα αφού αγνοήσαμε τον παρονομαστή. Ωστόσο, αυτό δεν είναι πρόβλημα, καθώς μπορούμε απλώς να πάρουμε αυτές τις μη κανονικοποιημένες πιθανότητες και να τις διαιρέσουμε με το άθροισμά τους, τότε θα αθροιστούν σε ένα. Έτσι, διαιρώντας αυτές τις τρεις τιμές με το άθροισμά τους περίπου 0.00032569, παίρνουμε

 

Gaussian Naive Bayes, Εξήγηση
Εικόνα από τον συγγραφέα.

 

Ξεκάθαρος νικητής, όπως περιμέναμε. Τώρα, ας το εφαρμόσουμε!

Αυτή η υλοποίηση δεν είναι κατά πολύ αποτελεσματική, δεν είναι αριθμητικά σταθερή, εξυπηρετεί μόνο έναν εκπαιδευτικό σκοπό. Έχουμε συζητήσει τα περισσότερα από τα πράγματα, επομένως θα πρέπει να είναι εύκολο να το ακολουθήσουμε τώρα. Μπορείτε να τα αγνοήσετε όλα check λειτουργίες ή διαβάστε το άρθρο μου Δημιουργήστε το δικό σας προσαρμοσμένο scikit-learn αν σας ενδιαφέρει τι ακριβώς κάνουν.

Απλώς σημειώστε ότι εφάρμοσα α predict_proba μέθοδος πρώτα για τον υπολογισμό των πιθανοτήτων. Η μέθοδος predict απλώς καλεί αυτήν τη μέθοδο και επιστρέφει το ευρετήριο (=κλάση) με την υψηλότερη πιθανότητα χρησιμοποιώντας μια συνάρτηση argmax (εδώ είναι πάλι!). Η τάξη περιμένει μαθήματα από 0 έως k-1, όπου k είναι ο αριθμός των τάξεων.

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)

Δοκιμή της Υλοποίησης

Αν και ο κωδικός είναι αρκετά σύντομος, είναι ακόμα πολύς για να είμαστε απόλυτα σίγουροι ότι δεν κάναμε λάθη. Λοιπόν, ας ελέγξουμε πώς τα πάει σε σχέση με το scikit-learn ταξινομητής GaussianNB.

my_gauss = GaussianNaiveBayesClassifier()
my_gauss.fit(X, y)
my_gauss.predict_proba([[-2, 5], [0,0], [6, -0.3]])

εξόδους

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]])

Οι προβλέψεις χρησιμοποιώντας το predict μέθοδος είναι

# my_gauss.predict([[-2, 5], [0,0], [6, -0.3]])
array([2, 0, 1])

Τώρα, ας χρησιμοποιήσουμε το scikit-learn. Ρίχνοντας κάποιο κωδικό

from sklearn.naive_bayes import GaussianNB gnb = GaussianNB()
gnb.fit(X, y)
gnb.predict_proba([[-2, 5], [0,0], [6, -0.3]])

αποδόσεις

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]])

Οι αριθμοί φαίνονται κάπως παρόμοιοι με αυτούς του ταξινομητή μας, αλλά είναι λίγο μακριά στα τελευταία ψηφία που εμφανίζονται. Κάναμε κάτι λάθος; Όχι. Η έκδοση scikit-learn χρησιμοποιεί απλώς μια άλλη υπερπαράμετρο var_smoothing=1e-09 . Αν ρυθμίσουμε αυτό σε μηδέν, παίρνουμε ακριβώς τους αριθμούς μας. Τέλειος!

Ρίξτε μια ματιά στις περιοχές απόφασης του ταξινομητή μας. Σημείωσα επίσης τα τρία σημεία που χρησιμοποιήσαμε για τη δοκιμή. Αυτό το ένα σημείο κοντά στα σύνορα έχει μόνο 56.9% πιθανότητα να ανήκει στην κόκκινη τάξη, όπως μπορείτε να δείτε από το predict_proba εξόδους. Οι άλλοι δύο βαθμοί ταξινομούνται με πολύ μεγαλύτερη σιγουριά.

 

Gaussian Naive Bayes, Εξήγηση

Η απόφαση περιφέρειες με τα 3 νέα σημεία. Εικόνα από τον συγγραφέα.

 

Σε αυτό το άρθρο, μάθαμε πώς λειτουργεί ο Gaussian naive ταξινομητής Bayes και δώσαμε μια διαίσθηση για το γιατί σχεδιάστηκε με αυτόν τον τρόπο - είναι μια άμεση προσέγγιση για τη μοντελοποίηση της πιθανότητας ενδιαφέροντος. Συγκρίνετε αυτό με την λογιστική παλινδρόμηση: εκεί, η πιθανότητα μοντελοποιείται χρησιμοποιώντας μια γραμμική συνάρτηση με μια σιγμοειδή συνάρτηση που εφαρμόζεται πάνω της. Εξακολουθεί να είναι ένα εύκολο μοντέλο, αλλά δεν φαίνεται τόσο φυσικό όσο ένας αφελής ταξινομητής της Bayes.

Συνεχίσαμε υπολογίζοντας μερικά παραδείγματα και συλλέγοντας μερικά χρήσιμα κομμάτια κώδικα καθ' οδόν. Τέλος, έχουμε εφαρμόσει έναν πλήρη ταξινομητή Gaussian naive Bayes με τρόπο που λειτουργεί καλά με το scikit-learn. Αυτό σημαίνει ότι μπορείτε να το χρησιμοποιήσετε σε αγωγούς ή αναζήτηση πλέγματος, για παράδειγμα.

Στο τέλος, κάναμε έναν μικρό έλεγχο λογικότητας εισάγοντας τον δικό μας ταξινομητή Gaussian naive Bayes scikit-learns και δοκιμάζοντας εάν και ο δικός μας και ο ταξινομητής scikit-learn αποδίδουν το ίδιο αποτέλεσμα. Αυτή η δοκιμή ήταν επιτυχής.

 
 
Δρ Robert Kübler είναι Επιστήμονας Δεδομένων στο Publicis Media και συγγραφέας στο Towards Data Science.

 
Πρωτότυπο. Αναδημοσιεύτηκε με άδεια.
 

Σφραγίδα ώρας:

Περισσότερα από KDnuggets