Een Multinomial Naive Bayes-classifier trainen
U fit MultinomialNB op een spam/ham-dataset, stemt de alpha-smoothingparameter af en evalueert het model met classification_report.
Een Multinomial Naive Bayes-classifier trainen is een gratis Machine Learning Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Machine Learning Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Machine Learning Academy bevat in totaal 4 lessen.
Waarom Multinomial Naive Bayes voor tekst?
Scikit-learn biedt drie varianten van Naive Bayes. MultinomialNB is ontworpen voor discrete telgegevens, precies wat CountVectorizer produceert. Het modelleert de kans op elke woordfrequentie gegeven de klasse. BernoulliNB werkt met binaire kenmerken voor aanwezigheid of afwezigheid en is geschikt voor zeer korte documenten. GaussianNB gaat uit van continue kenmerken met Gauss-verdelingen, wat geschikt is voor numerieke gegevens maar niet voor woordfrequenties. Voor tekstclassificatie is MultinomialNB bijna altijd de juiste keuze, omdat woordfrequenties niet-negatieve gehele getallen zijn die perfect passen bij de aanname van een multinomiale verdeling.
from sklearn.naive_bayes import MultinomialNB, BernoulliNB, GaussianNB
from sklearn.feature_extraction.text import CountVectorizer
corpus = ['buy cheap meds now', 'hello friend meeting tomorrow',
'click here for discount', 'project update next week']
labels = [1, 0, 1, 0] # 1=spam, 0=ham
vec = CountVectorizer()
X = vec.fit_transform(corpus)
nb = MultinomialNB()
nb.fit(X, labels)
print('Classes:', nb.classes_)
print('Feature log probs shape:', nb.feature_log_prob_.shape)
# feature_log_prob_[class][feature] = log P(feature | class)De gegevensverzameling 20 Newsgroups laden en splitsen
De gegevensverzameling 20 Newsgroups is de standaardbenchmark voor tekstclassificatie. Deze bevat ongeveer 18.000 berichten uit nieuwsgroepen over 20 onderwerpen, van 'sci.space' tot 'talk.politics.guns'. Scikit-learn biedt deze gegevensverzameling aan via fetch_20newsgroups(), met de handige optie om kopteksten, voetteksten en citaten vooraf te verwijderen die de taak kunstmatig eenvoudig zouden maken. We selecteren een binaire deelverzameling (spam versus geen spam is in deze gegevensverzameling het moeilijkst; daarom vergelijken we twee nieuwsgroepen) en splitsen deze in train- en testgegevens.
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
# Load two categories for binary classification
cats = ['sci.space', 'rec.sport.hockey']
train = fetch_20newsgroups(subset='train', categories=cats,
remove=('headers', 'footers', 'quotes'))
test = fetch_20newsgroups(subset='test', categories=cats,
remove=('headers', 'footers', 'quotes'))
print('Train samples:', len(train.data))
print('Test samples:', len(test.data))
print('Categories:', train.target_names)
print('Sample (first 200 chars):', train.data[0][:200])Een volledige pijplijn voor tekstclassificatie opbouwen
Het standaardpatroon voor tekstclassificatie is: CountVectorizer → MultinomialNB → Pipeline. Door ze in een Pipeline te verpakken, zorgt u ervoor dat de vectoriseerder alleen op de trainingsgegevens wordt aangepast, ook tijdens kruisvalidatie. De Pipeline accepteert onbewerkte tekst als invoer en produceert rechtstreeks voorspellingen, waarbij alle tussentijdse transformatiestappen verborgen blijven. Dit is de netste structuur die het meest geschikt is voor implementatie voor NLP-pijplijnen in scikit-learn.
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score, classification_report
pipe = Pipeline([
('vec', CountVectorizer(stop_words='english')),
('clf', MultinomialNB())
])
pipe.fit(train.data, train.target)
preds = pipe.predict(test.data)
print('Accuracy:', accuracy_score(test.target, preds).round(3))
print(classification_report(test.target, preds,
target_names=train.target_names))De parameter voor alphavereffening
De belangrijkste hyperparameter in MultinomialNB is alpha: de Laplace/Lidstone-parameter voor vereffening. Zonder vereffening krijgt elk woord dat in de testgegevens voorkomt maar tijdens het trainen voor een bepaalde klasse nooit is gezien, de waarde P(word|class)=0, waardoor de volledige logwaarschijnlijkheid -infinity wordt. Door alpha toe te voegen, voorkomt u kansen van nul: P(word|class) = (count + alpha) / (total_counts + alpha * vocab_size). De standaardwaarde alpha=1.0 (Laplace-vereffening) is meestal een goed uitgangspunt; kleinere waarden (0.01-0.1) kunnen de prestaties verbeteren wanneer er veel gegevens beschikbaar zijn.
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import cross_val_score
alpha_values = [0.001, 0.01, 0.1, 0.5, 1.0, 2.0, 5.0]
best_alpha, best_score = 1.0, 0
for alpha in alpha_values:
pipe = Pipeline([
('vec', CountVectorizer(stop_words='english')),
('nb', MultinomialNB(alpha=alpha))
])
score = cross_val_score(pipe, train.data, train.target, cv=5).mean()
print(f'alpha={alpha:.3f}: CV accuracy = {score:.4f}')
if score > best_score:
best_score, best_alpha = score, alpha
print('Best alpha:', best_alpha)Geleerde kansen bekijken
Na het trainen slaat MultinomialNB feature_log_prob_ op: de logkans van elk woord gegeven elke klasse. Door de woorden met de hoogste logkans per klasse te bekijken, ziet u wat het model heeft geleerd. Voor een classificeerder voor sci.space versus rec.sport.hockey verwacht u 'nasa', 'orbit' en 'launch' als belangrijkste kenmerken voor ruimtevaart, en 'hockey', 'team' en 'goal' voor hockey. Als er onverwachte woorden verschijnen (zoals 'the'), moeten uw instellingen voor voorbewerking (stopwoorden, min_df) worden aangepast.
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
import numpy as np
pipe = Pipeline([
('vec', CountVectorizer(stop_words='english')),
('nb', MultinomialNB(alpha=0.1))
])
pipe.fit(train.data, train.target)
vec = pipe.named_steps['vec']
nb = pipe.named_steps['nb']
feature_names = vec.get_feature_names_out()
for class_idx, class_name in enumerate(train.target_names):
top_idx = np.argsort(nb.feature_log_prob_[class_idx])[-10:]
top_words = [feature_names[i] for i in top_idx]
print(f'Top words for {class_name}:', top_words)Classificatierapport: precisie, terugvindpercentage en F1
classification_report geeft per klasse de precision (van alle voorspelde positieve gevallen, hoeveel zijn correct), de recall (van alle werkelijke positieve gevallen, hoeveel hebben we gevonden) en de F1-score (het harmonische gemiddelde van precision en recall). Bij tekstclassificatie kan alleen nauwkeurigheid misleidend zijn als de ene klasse vaker voorkomt dan de andere. F1-score is de standaardmaatstaf voor benchmarks voor tekstclassificatie, omdat deze precision en recall in balans brengt. 'macro avg' berekent het gemiddelde van de maatstaven waarbij elke klasse even zwaar meetelt; 'weighted avg' weegt op basis van de omvang van elke klasse.
from sklearn.metrics import classification_report, confusion_matrix
import numpy as np
preds = pipe.predict(test.data)
print('=== Classification Report ===')
print(classification_report(test.target, preds,
target_names=train.target_names))
print('=== Confusion Matrix ===')
cm = confusion_matrix(test.target, preds)
print(cm)
print('Rows = actual class, Columns = predicted class')
print('Diagonal = correct predictions')Voorspellen met nieuwe tekstvoorbeelden
Na het trainen accepteert de pijplijn onbewerkte tekstreeksen voor voorspellingen — handmatige vectorisatie is niet nodig. predict() geeft klasselabels terug; predict_proba() geeft de kansen van de klassen terug (waarbij intern softmax wordt toegepast op de logaritmische a-posteriorikansen). De kansen geven aan hoe zeker het model is. Voor spamfiltering kun je een strengere drempel instellen (0,9 voor spam) om fout-positieven te beperken — je laat dan liever wat spam door dan dat je per ongeluk legitieme e-mail blokkeert.
new_emails = [
'NASA launches new Mars mission with rocket booster',
'The team scored three goals in the hockey championship',
'Buy cheap meds online click here for discount offer'
]
predictions = pipe.predict(new_emails)
probabilities = pipe.predict_proba(new_emails)
for text, pred, prob in zip(new_emails, predictions, probabilities):
class_name = train.target_names[pred]
confidence = max(prob)
print(f'Pred: {class_name} ({confidence:.2%})')
print(f'Text: {text[:60]}...')
print()Vergelijking van TF-IDF en Count Vectoriser
Bij het vergelijken van CountVectorizer en TfidfVectorizer met MultinomialNB is extra zorgvuldigheid nodig: MultinomialNB verwacht niet-negatieve, telachtige invoer en TF-IDF-waarden zijn fractioneel — technisch geldig, maar het model kan ze anders interpreteren. TfidfVectorizer met sublinear_tf=True en use_idf=True levert vaak betere resultaten met Naive Bayes. Voor logistische regressie en SVM is TF-IDF vrijwel altijd beter. Voor Naive Bayes zijn onbewerkte tellingen met Laplace-smoothing theoretisch gezien de juiste aanpak.
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score
for VecClass, name in [
(CountVectorizer, 'CountVec'),
(TfidfVectorizer, 'TfidfVec')
]:
pipe = Pipeline([
('vec', VecClass(stop_words='english')),
('nb', MultinomialNB(alpha=0.1))
])
score = cross_val_score(pipe, train.data, train.target, cv=5).mean()
print(f'{name} + MultinomialNB: {score:.4f}')Tekstclassificatie met meerdere klassen en 20 categorieën
Naive Bayes verwerkt classificatie met meerdere klassen van nature zonder aanpassingen. Met alle 20 categorieën van de nieuwsgroepen traint de pijplijn één verzameling woordkansen per klasse en voorspelt deze de klasse met de hoogste a-posteriorikans. F1-macro-scores voor meerdere klassen van ongeveer 0,75–0,85 zijn gebruikelijk voor Naive Bayes op 20 Newsgroups — opmerkelijk concurrerend voor zo'n eenvoudig model. Verwarring tussen vergelijkbare categorieën (bijvoorbeeld 'sci.space' en 'sci.astronomy') is te verwachten en kan worden vastgesteld door de elementen buiten de diagonaal van de verwarringsmatrix te bekijken.
from sklearn.datasets import fetch_20newsgroups
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import f1_score
# All 20 categories
train_all = fetch_20newsgroups(subset='train', remove=('headers','footers','quotes'))
test_all = fetch_20newsgroups(subset='test', remove=('headers','footers','quotes'))
pipe = Pipeline([
('vec', TfidfVectorizer(stop_words='english', max_features=50000)),
('nb', MultinomialNB(alpha=0.05))
])
pipe.fit(train_all.data, train_all.target)
preds = pipe.predict(test_all.data)
f1 = f1_score(test_all.target, preds, average='macro')
print(f'20-class Macro F1: {f1:.3f}')ComplementNB: beter voor tekstklassen met ongelijke omvang
ComplementNB is een variant van MultinomialNB die corrigeert voor de aanname dat klassen gelijkmatig verdeeld zijn. In plaats van P(word|class) te schatten, schat deze P(word|NOT class) — de kans op het woord in alle andere klassen samen — en gebruikt hij het complement. Deze aanpak is robuuster wanneer de klassen verschillende omvang hebben (wat vaak voorkomt in echte e-maildatasets, waar spam bijvoorbeeld 10% van het verkeer kan uitmaken). ComplementNB presteert op tekstbenchmarks consequent beter dan MultinomialNB en is de aanbevolen standaard voor tekstclassificatie in de eigen documentatie van scikit-learn.
from sklearn.naive_bayes import MultinomialNB, ComplementNB
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score
for NB_Class in [MultinomialNB, ComplementNB]:
pipe = Pipeline([
('vec', TfidfVectorizer(stop_words='english')),
('nb', NB_Class(alpha=0.1))
])
score = cross_val_score(
pipe, train_all.data, train_all.target, cv=5
).mean()
print(f'{NB_Class.__name__}: {score:.4f}')
# ComplementNB typically 1-3% betterGaussianNB voor continue kenmerken
Wanneer kenmerken continu zijn (geen woordtellingen), gebruik je GaussianNB. Deze gaat ervan uit dat elk kenmerk binnen elke klasse een Gaussische (normale) verdeling volgt en schat voor elke combinatie van kenmerk en klasse het gemiddelde en de variantie uit de trainingsgegevens. Bij het voorspellen wordt de log-waarschijnlijkheid onder het Gaussische model van elke klasse berekend en de log-prior opgeteld. GaussianNB werkt goed wanneer kenmerken per klasse daadwerkelijk Gaussisch verdeeld zijn, zoals sensormetingen of fysische metingen. Het is snel, vereist geen afstemming van hyperparameters (geen alpha) en vormt een redelijke eerste basis voor elk classificatieprobleem met continue kenmerken.
from sklearn.naive_bayes import GaussianNB
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
X, y = load_iris(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, random_state=42)
gnb = GaussianNB()
gnb.fit(X_tr, y_tr)
print('GaussianNB test accuracy:', gnb.score(X_te, y_te).round(3))
print('CV accuracy:', cross_val_score(gnb, X, y, cv=10).mean().round(3))
print()
print('Learned means per class and feature:')
print(gnb.theta_.round(2))Korte controle
Test je begrip van de concepten uit deze les over machine learning met Python.
Samenvatting van de les
In deze les heb je geleerd dat MultinomialNB woordtelkansen modelleert op basis van de uitvoer van CountVectorizer, dat de alpha-smoothingparameter kansen van nul voor niet-geziene woorden voorkomt en dat het onderbrengen van vectorisatie en classificatie in een pijplijn een helder, implementeerbaar tekstclassificatiesysteem oplevert. Hierna bekijken we Laplace-smoothing in detail en het probleem met kansen van nul dat hiermee wordt opgelost.
Leer Python met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 30
- Lessen
- 120
Veelgestelde vragen
Is de les “Een Multinomial Naive Bayes-classifier trainen” gratis?
Ja — de volledige tekst van “Een Multinomial Naive Bayes-classifier trainen” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Machine Learning Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Machine Learning Academy bevat in totaal 4 lessen.
Wat leer ik in “Een Multinomial Naive Bayes-classifier trainen”?
U fit MultinomialNB op een spam/ham-dataset, stemt de alpha-smoothingparameter af en evalueert het model met classification_report. Je oefent met Machine Learning Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Machine Learning Academy te beginnen?
Ervaring vooraf is niet nodig. Machine Learning Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.
Hoe lang duurt de les “Een Multinomial Naive Bayes-classifier trainen”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Machine Learning Academy?
Ja. Elke les over Machine Learning Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- De stelling van Bayes in begrijpelijke taal
- Bag of Words: CountVectorizer en TfidfVectorizer
- Een Multinomial Naive Bayes-classifier trainen
- Laplace-smoothing en het probleem van nulwaarschijnlijkheden