Look for the interactive boxes: Bayes the Intern (Section 01), Bayes’ Theorem with 1000 Emails (02), Underflow (03), Hand Calculator (04), Spam Filter Playground (05), Gaussian NB Explorer (07) and Double Counting (12). Every number in them is computed live in your browser.
The Story That Explains Naïve Bayes
“The word FREE appears in 380 spam emails but only 12 ham emails.”
“The word meeting appears in 420 ham emails but only 3 spam emails.”
“The word winner appears in 350 spam emails but only 2 ham emails.”
A new email arrives: “You are a FREE WINNER — claim your prize now!”
Bayes does not read it like a human. He asks one cold question: “Given these words, how likely is it that this email is spam?” He starts from how common spam is (40%), multiplies in the evidence from each word, compares Spam with Ham, and says: “99.99% spam.” Correct — deleted in milliseconds.
That is Naïve Bayes. It is called “naïve” because it assumes every word gives its evidence independently of the others. That assumption is usually false, but the method still works remarkably well.
In real emails, “FREE” and “WINNER” are not independent — if you see one, the other becomes more likely. Naïve Bayes ignores all such links and treats every feature as a separate, independent clue. Statistically wrong. Practically powerful — especially for text.
Try It — Bayes the Intern
Click words in Bayes’s notebook, or play one of the example emails. Watch each word push the odds towards spam or ham.
इन interactive boxes को देखिए: Bayes the Intern (सेक्शन 01), Bayes’ Theorem with 1000 Emails (02), Underflow (03), Hand Calculator (04), Spam Filter Playground (05), Gaussian NB Explorer (07) और Double Counting (12)। इनका हर number आपके browser में live calculate होता है।
वह कहानी जो Naïve Bayes को समझाती है
“Word FREE 380 spam emails में आता है, पर सिर्फ़ 12 ham emails में।”
“Word meeting 420 ham emails में आता है, पर सिर्फ़ 3 spam emails में।”
“Word winner 350 spam emails में आता है, पर सिर्फ़ 2 ham emails में।”
एक नया email आता है: “You are a FREE WINNER — claim your prize now!”
Bayes इसे इंसान की तरह नहीं पढ़ता। वह सिर्फ़ एक ठंडा सवाल पूछता है: “इन words को देखते हुए, इस email के spam होने का कितना chance है?” वह इससे शुरू करता है कि spam कितना आम है (40%), फिर हर word का evidence गुणा करता है, Spam की तुलना Ham से करता है, और कहता है: “99.99% spam।” सही — milliseconds में delete।
यही है Naïve Bayes। इसे “naïve” इसलिए कहते हैं क्योंकि यह मान लेता है कि हर word अपना evidence बाक़ी words से independently देता है। यह मान्यता आमतौर पर ग़लत होती है, फिर भी यह तरीक़ा कमाल का काम करता है।
असली emails में “FREE” और “WINNER” independent नहीं हैं — अगर एक दिखे, तो दूसरे के आने का chance बढ़ जाता है। Naïve Bayes ऐसे सारे रिश्तों को नज़रअंदाज़ करता है और हर feature को एक अलग, independent सुराग़ मानता है। Statistics के हिसाब से ग़लत। Practice में बहुत ताक़तवर — ख़ासकर text के लिए।
ख़ुद आज़माइए — Bayes the Intern
Bayes की notebook में words पर click कीजिए, या कोई example email चलाइए। देखिए कि हर word odds को spam या ham की ओर कैसे धकेलता है।
请留意这些可以互动的方框:Bayes the Intern(第 01 节)、Bayes’ Theorem with 1000 Emails(02)、Underflow(03)、Hand Calculator(04)、Spam Filter Playground(05)、Gaussian NB Explorer(07)和 Double Counting(12)。里面的每一个数字都是在你的浏览器里实时算出来的。
一个能解释 Naïve Bayes 的故事
“FREE 这个词出现在 380 封 spam 里,但只出现在 12 封 ham 里。”
“meeting 这个词出现在 420 封 ham 里,但只出现在 3 封 spam 里。”
“winner 这个词出现在 350 封 spam 里,但只出现在 2 封 ham 里。”
一封新 email 来了:“You are a FREE WINNER — claim your prize now!”
Bayes 不像人那样读它。他只冷静地问一个问题: “有了这些词,这封 email 是 spam 的可能性有多大?” 他先看 spam 有多常见(40%),再把每个词的 evidence 乘进去,比较 Spam 和 Ham, 然后说:“99.99% 是 spam。”判断正确 —— 几毫秒就删掉了。
这就是 Naïve Bayes。它叫“naïve”(天真),是因为它假设每个词给出的 evidence 都和其他词互相独立。这个假设通常是错的,但这个方法仍然好用得惊人。
在真实的 email 里,“FREE”和“WINNER”并不独立 —— 看到其中一个,另一个出现的可能性就更大。 Naïve Bayes 忽略了所有这种联系,把每个 feature 都当作一条单独、独立的线索。 从统计上看,这是错的。但在实际中它很强大 —— 尤其是对文本。
动手试试 —— Bayes the Intern
点击 Bayes 笔记本里的词,或者播放一封示例 email。看每个词把 odds 推向 spam 或 ham。
The Foundation — Bayes’ Theorem
Everything in Naïve Bayes comes from one equation by the Reverend Thomas Bayes (18th century). It tells you how to update a belief when you see new evidence.
| Term | Name | Plain English | Spam Example |
|---|---|---|---|
P(Class | Features) |
Posterior | What we want — the probability of the class after seeing the evidence | P(Spam | “FREE”, “WIN”) |
P(Features | Class) |
Likelihood | How probable are these features if we already know the class? | P(“FREE”, “WIN” | Spam) |
P(Class) |
Prior | How common the class is in the training data, before looking at any features | P(Spam) = 400/1000 = 0.40 |
P(Features) |
Evidence | How common these features are overall. It is the same for every class | Only needed to turn scores into probabilities |
When we compare classes (Spam vs Ham), P(Features) is the same for both.
So to decide, we only compare P(Features | Class) × P(Class) and pick the largest.
This is the Maximum A Posteriori (MAP) rule. If we also want a probability (like “97% spam”),
we divide each score by the sum of all scores.
Try It — Bayes’ Theorem with 1000 Emails
Bayes’ theorem is just counting. Press Show only emails with FREE and count the red and green squares. Then try the “rare spam” preset to see why the prior matters.
नींव — Bayes’ Theorem
Naïve Bayes में सब कुछ एक ही equation से आता है, जो Reverend Thomas Bayes (18वीं सदी) ने दी थी। यह बताती है कि नया evidence देखकर अपना विश्वास कैसे update करें।
| Term | नाम | आसान भाषा में | Spam का उदाहरण |
|---|---|---|---|
P(Class | Features) |
Posterior | जो हमें चाहिए — evidence देखने के बाद class की probability | P(Spam | “FREE”, “WIN”) |
P(Features | Class) |
Likelihood | अगर class हमें पहले से पता हो, तो ये features कितने संभव हैं? | P(“FREE”, “WIN” | Spam) |
P(Class) |
Prior | कोई भी feature देखने से पहले, training data में class कितनी आम है | P(Spam) = 400/1000 = 0.40 |
P(Features) |
Evidence | ये features कुल मिलाकर कितने आम हैं। यह हर class के लिए एक जैसा है | सिर्फ़ scores को probabilities में बदलने के लिए चाहिए |
जब हम classes की तुलना करते हैं (Spam vs Ham), तो P(Features) दोनों के लिए एक जैसा होता है।
इसलिए फ़ैसला करने के लिए हम सिर्फ़ P(Features | Class) × P(Class) की तुलना करते हैं और सबसे बड़ा चुनते हैं।
यही Maximum A Posteriori (MAP) rule है। अगर हमें probability भी चाहिए (जैसे “97% spam”),
तो हम हर score को सारे scores के जोड़ से भाग देते हैं।
ख़ुद आज़माइए — Bayes’ Theorem with 1000 Emails
Bayes’ theorem बस गिनती है। सिर्फ़ FREE वाले emails दिखाएँ दबाइए और लाल और हरे squares गिनिए। फिर “rare spam” preset आज़माइए और देखिए कि prior क्यों मायने रखता है।
基础 —— Bayes’ Theorem
Naïve Bayes 的一切都来自一个公式,它出自 Thomas Bayes 牧师(18 世纪)。 它告诉你:看到新的 evidence 时,怎样更新一个信念。
| 术语 | 名称 | 通俗解释 | Spam 例子 |
|---|---|---|---|
P(Class | Features) |
Posterior | 我们想要的 —— 看到 evidence 之后,class 的 probability | P(Spam | “FREE”, “WIN”) |
P(Features | Class) |
Likelihood | 如果已经知道 class,这些 feature 出现的 probability 有多大? | P(“FREE”, “WIN” | Spam) |
P(Class) |
Prior | 还没看任何 feature 之前,这个 class 在 training data 里有多常见 | P(Spam) = 400/1000 = 0.40 |
P(Features) |
Evidence | 这些 feature 总体上有多常见。它对每个 class 都一样 | 只在把分数变成 probability 时才需要 |
比较各个 class(Spam vs Ham)时,P(Features) 对两者都一样。
所以要做决定,我们只需比较 P(Features | Class) × P(Class),选最大的那个。
这就是 Maximum A Posteriori (MAP) 规则。如果我们还想要一个 probability(比如“97% spam”),
就把每个分数除以所有分数的和。
动手试试 —— Bayes’ Theorem with 1000 Emails
Bayes’ theorem 其实就是数数。按 只显示含 FREE 的 email,数一数红色和绿色的方块。然后试试“少见的 spam”预设,看看为什么 prior 很重要。
The Naïve Independence Assumption
With many features, estimating P(word₁, word₂, word₃, … | Class) directly is impossible —
you would need to see every exact combination of words in the training data.
Naïve Bayes solves this with one bold simplification.
Multiplying hundreds of small probabilities — 0.001 × 0.003 × 0.0005 × … — gives numbers so tiny that the computer silently stores them as zero (floating-point underflow). Logarithms turn products into sums: log(a × b) = log(a) + log(b). Because log always increases, the class with the biggest log-score is also the class with the biggest product. scikit-learn does this for you, but you must do it yourself when you write Naïve Bayes from scratch.
Try It — Underflow
Press Play and watch both products fall towards the red zone. Once they hit it, the raw products are both 0 — but the log-scores still give the right answer.
Naïve Independence Assumption
बहुत सारे features हों, तो P(word₁, word₂, word₃, … | Class) को सीधे estimate करना नामुमकिन है —
आपको training data में words का हर exact combination देखना पड़ेगा।
Naïve Bayes इसे एक बड़े, साहसी simplification से हल करता है।
सैकड़ों छोटी probabilities का गुणा — 0.001 × 0.003 × 0.0005 × … — इतने छोटे numbers देता है कि computer चुपचाप उन्हें zero के रूप में रख देता है (floating-point underflow)। Logarithms products को sums में बदल देते हैं: log(a × b) = log(a) + log(b)। क्योंकि log हमेशा बढ़ता है, जिस class का log-score सबसे बड़ा है, उसी का product भी सबसे बड़ा है। scikit-learn यह आपके लिए करता है, पर जब आप Naïve Bayes शुरू से ख़ुद लिखते हैं, तो यह आपको ख़ुद करना होगा।
ख़ुद आज़माइए — Underflow
चलाएँ दबाइए और देखिए कि दोनों products लाल zone की ओर गिरते हैं। वहाँ पहुँचते ही दोनों raw products 0 हो जाते हैं — पर log-scores फिर भी सही जवाब देते हैं।
Naïve 的 Independence Assumption
feature 很多时,直接估计 P(word₁, word₂, word₃, … | Class) 是不可能的 ——
你得在 training data 里见过每一种确切的词组合。
Naïve Bayes 用一个大胆的简化解决了这个问题。
把几百个很小的 probability 乘在一起 —— 0.001 × 0.003 × 0.0005 × … —— 得到的数小到 计算机会悄悄地把它们存成零(floating-point underflow)。 log 把乘积变成和:log(a × b) = log(a) + log(b)。 因为 log 总是递增的,log-score 最大的 class,也就是乘积最大的 class。 scikit-learn 会帮你做这一步,但如果你从零开始写 Naïve Bayes,就必须自己做。
动手试试 —— Underflow
按 播放,看两个乘积都往红色区域掉。一碰到红色区域,两个原始乘积就都是 0 —— 但 log-score 仍然给出正确的答案。
Step-by-Step Manual Calculation
Let us classify one new email by hand. We use a tiny training set of 10 emails with three yes/no features.
| # | Contains “free” | Contains “winner” | Contains “meeting” | Label |
|---|---|---|---|---|
| 1 | ✅ | ✅ | ❌ | Spam |
| 2 | ✅ | ❌ | ❌ | Spam |
| 3 | ✅ | ✅ | ❌ | Spam |
| 4 | ❌ | ✅ | ❌ | Spam |
| 5 | ✅ | ❌ | ❌ | Spam |
| 6 | ❌ | ❌ | ✅ | Ham |
| 7 | ❌ | ❌ | ✅ | Ham |
| 8 | ❌ | ❌ | ✅ | Ham |
| 9 | ✅ | ❌ | ✅ | Ham |
| 10 | ❌ | ❌ | ❌ | Ham |
New email to classify: contains “free” ✅, “winner” ✅, “meeting” ❌. Spam or Ham?
= 0.5 × 0.800 × 0.600 × 1.000 = 0.240
= 0.5 × 0.200 × 0.000 × 0.200 = 0.000 ← one zero kills it!
The model predicted spam correctly. But the Ham score is exactly zero, because “winner” never appeared in a ham email during training. One unseen word cancelled all the other evidence for ham. This is the Zero Frequency Problem. Laplace smoothing fixes it in Section 06.
Try It — Hand Calculator
The same table, but live. Every factor is shown as a fraction. Click cells to change the training data, change the new email, and move α from 0 to 1 to see smoothing at work.
Step-by-Step हाथ से Calculation
चलिए एक नए email को हाथ से classify करते हैं। हम 10 emails का एक छोटा training set इस्तेमाल करेंगे, जिसमें तीन हाँ/ना features हैं।
| # | “free” है | “winner” है | “meeting” है | Label |
|---|---|---|---|---|
| 1 | ✅ | ✅ | ❌ | Spam |
| 2 | ✅ | ❌ | ❌ | Spam |
| 3 | ✅ | ✅ | ❌ | Spam |
| 4 | ❌ | ✅ | ❌ | Spam |
| 5 | ✅ | ❌ | ❌ | Spam |
| 6 | ❌ | ❌ | ✅ | Ham |
| 7 | ❌ | ❌ | ✅ | Ham |
| 8 | ❌ | ❌ | ✅ | Ham |
| 9 | ✅ | ❌ | ✅ | Ham |
| 10 | ❌ | ❌ | ❌ | Ham |
Classify करने के लिए नया email: इसमें “free” ✅, “winner” ✅, “meeting” ❌। Spam या Ham?
= 0.5 × 0.800 × 0.600 × 1.000 = 0.240
= 0.5 × 0.200 × 0.000 × 0.200 = 0.000 ← एक zero सब ख़त्म कर देता है!
Model ने spam को सही predict किया। पर Ham का score ठीक zero है, क्योंकि training में “winner” किसी भी ham email में नहीं आया। एक अनदेखे word ने ham के लिए बाक़ी सारा evidence ख़त्म कर दिया। यही Zero Frequency Problem है। सेक्शन 06 में Laplace smoothing इसे ठीक करता है।
ख़ुद आज़माइए — Hand Calculator
वही table, पर live। हर factor एक fraction के रूप में दिखता है। Training data बदलने के लिए cells पर click कीजिए, नया email बदलिए, और smoothing का असर देखने के लिए α को 0 से 1 तक खिसकाइए।
一步一步手算
我们来亲手给一封新 email 分类。我们用一个很小的 training set,只有 10 封 email,每封有三个“是 / 否” feature。
| # | 含“free” | 含“winner” | 含“meeting” | 标签 |
|---|---|---|---|---|
| 1 | ✅ | ✅ | ❌ | Spam |
| 2 | ✅ | ❌ | ❌ | Spam |
| 3 | ✅ | ✅ | ❌ | Spam |
| 4 | ❌ | ✅ | ❌ | Spam |
| 5 | ✅ | ❌ | ❌ | Spam |
| 6 | ❌ | ❌ | ✅ | Ham |
| 7 | ❌ | ❌ | ✅ | Ham |
| 8 | ❌ | ❌ | ✅ | Ham |
| 9 | ✅ | ❌ | ✅ | Ham |
| 10 | ❌ | ❌ | ❌ | Ham |
要分类的新 email:含“free” ✅、“winner” ✅、“meeting” ❌。是 Spam 还是 Ham?
= 0.5 × 0.800 × 0.600 × 1.000 = 0.240
= 0.5 × 0.200 × 0.000 × 0.200 = 0.000 ← 一个零就毁了它!
model 正确地预测出了 spam。但 Ham 的分数正好是零, 因为在训练时,“winner”从没在任何一封 ham email 里出现过。 一个没见过的词,抵消了支持 ham 的所有其他 evidence。 这就是 Zero Frequency Problem。第 06 节里的 Laplace smoothing 会修复它。
动手试试 —— Hand Calculator
还是同一张表,但这次是实时的。每个因子都显示成分数。点击格子来改变 training data,改变新 email,再把 α 从 0 移到 1,看 smoothing 怎么起作用。
The Variants of Naïve Bayes
Naïve Bayes is not one algorithm — it is a family. Choose the variant by the type of features in your data.
| Variant | Feature Type | Likelihood Model | Typical Use Cases |
|---|---|---|---|
| Gaussian NB | Real-valued, continuous | Gaussian density — uses μ, σ² | Iris, medical measurements, sensors |
| Multinomial NB | Non-negative counts (or TF-IDF) | Multinomial distribution over word counts | Spam, news topics, document tagging |
| Bernoulli NB | Binary 0 / 1 | One yes/no (Bernoulli) probability per feature | Short texts, binary feature sets |
| Complement NB | Non-negative counts (or TF-IDF) | Learns from the complement of each class | Imbalanced text classification |
| Categorical NB | Categories (colour, city…) | One probability per category value | Survey answers, encoded categories |
Try It — Spam Filter Playground
This simulator uses word counts from the real SMS Spam Collection (5,572 messages). Type any message, switch between Multinomial and Bernoulli, and see which words push towards spam.
Naïve Bayes के Variants
Naïve Bayes एक algorithm नहीं है — यह एक परिवार है। Variant अपने data के features के type के हिसाब से चुनिए।
| Variant | Feature Type | Likelihood Model | आम इस्तेमाल |
|---|---|---|---|
| Gaussian NB | Real-valued, continuous | Gaussian density — μ, σ² इस्तेमाल करता है | Iris, medical measurements, sensors |
| Multinomial NB | Non-negative counts (या TF-IDF) | Word counts पर Multinomial distribution | Spam, news topics, document tagging |
| Bernoulli NB | Binary 0 / 1 | हर feature के लिए एक हाँ/ना (Bernoulli) probability | छोटे texts, binary feature sets |
| Complement NB | Non-negative counts (या TF-IDF) | हर class के complement से सीखता है | Imbalanced text classification |
| Categorical NB | Categories (रंग, शहर…) | हर category value के लिए एक probability | Survey के जवाब, encoded categories |
ख़ुद आज़माइए — Spam Filter Playground
यह simulator असली SMS Spam Collection (5,572 messages) के word counts इस्तेमाल करता है। कोई भी message लिखिए, Multinomial और Bernoulli के बीच बदलिए, और देखिए कि कौन-से words spam की ओर धकेलते हैं।
Naïve Bayes 的几种变体
Naïve Bayes 不是一个算法 —— 它是一个家族。要根据数据里 feature 的类型来选变体。
| 变体 | Feature 类型 | Likelihood Model | 典型用途 |
|---|---|---|---|
| Gaussian NB | 实数,连续 | Gaussian 密度 —— 使用 μ、σ² | Iris、医疗测量值、传感器 |
| Multinomial NB | 非负计数(或 TF-IDF) | 词频计数上的 Multinomial 分布 | Spam、新闻主题、文档标注 |
| Bernoulli NB | 二值 0 / 1 | 每个 feature 一个“是 / 否”(Bernoulli)probability | 短文本、二值 feature 集 |
| Complement NB | 非负计数(或 TF-IDF) | 从每个 class 的补集中学习 | 不平衡的文本分类 |
| Categorical NB | 类别(颜色、城市…) | 每个类别值一个 probability | 问卷答案、编码后的类别 |
动手试试 —— Spam Filter Playground
这个模拟器使用的是真实的 SMS Spam Collection(5,572 条消息)里的词频。输入任意一条消息,在 Multinomial 和 Bernoulli 之间切换,看哪些词把结果推向 spam。
The Zero Frequency Problem — Laplace Smoothing
Score = 0.5 × 0.714 × 0.571 × 0.857 = 0.1749
Score = 0.5 × 0.286 × 0.143 × 0.286 = 0.0058
scikit-learn’s BernoulliNB gives exactly the same numbers:
Zero Frequency Problem — Laplace Smoothing
Score = 0.5 × 0.714 × 0.571 × 0.857 = 0.1749
Score = 0.5 × 0.286 × 0.143 × 0.286 = 0.0058
scikit-learn का BernoulliNB बिल्कुल यही numbers देता है:
Zero Frequency Problem —— Laplace Smoothing
分数 = 0.5 × 0.714 × 0.571 × 0.857 = 0.1749
分数 = 0.5 × 0.286 × 0.143 × 0.286 = 0.0058
scikit-learn 的 BernoulliNB 给出完全一样的数字:
import numpy as np
from sklearn.naive_bayes import BernoulliNB
# The 10 training emails from Section 04: [free, winner, meeting]
X = np.array([[1,1,0],[1,0,0],[1,1,0],[0,1,0],[1,0,0], # spam
[0,0,1],[0,0,1],[0,0,1],[1,0,1],[0,0,0]]) # ham
y = np.array(["spam"]*5 + ["ham"]*5)
new_email = [[1, 1, 0]] # has "free", has "winner", no "meeting"
for alpha in [1e-10, 1.0]: # almost no smoothing, then Laplace
nb = BernoulliNB(alpha=alpha, force_alpha=True).fit(X, y)
p = nb.predict_proba(new_email)[0]
print(f"alpha={alpha:g}: P(ham)={p[0]:.4f} P(spam)={p[1]:.4f} -> {nb.predict(new_email)[0]}")
# Learned P(word present | class) with alpha = 1
print("\nP(word | class), alpha=1:")
for cls, row in zip(nb.classes_, np.exp(nb.feature_log_prob_)):
print(f" {cls:4s} free={row[0]:.3f} winner={row[1]:.3f} meeting={row[2]:.3f}")
α = 1 → Laplace smoothing (add-one).
0 < α < 1 → Lidstone smoothing (gentler).
α = 0 → no smoothing (dangerous — scikit-learn even replaces it with a tiny number like 1e-10 unless you set force_alpha=True).
The default in scikit-learn is alpha=1.0.
Tune α between about 0.01 and 2 with cross-validation. Large datasets usually prefer small α; tiny datasets need more smoothing.
Gaussian NB — How Continuous Features Are Modelled
When features are continuous (age, glucose level, temperature), counting makes no sense. Gaussian NB instead models each feature as a bell curve inside each class — it estimates the mean μ and variance σ² from the training data.
| Patient | Age | Glucose (mg/dL) | BMI | Diabetes? |
|---|---|---|---|---|
| 1 | 50 | 180 | 33.6 | Yes |
| 2 | 58 | 200 | 35.0 | Yes |
| 3 | 45 | 165 | 30.5 | Yes |
| 4 | 25 | 90 | 22.1 | No |
| 5 | 30 | 85 | 23.5 | No |
| 6 | 28 | 100 | 24.0 | No |
scikit-learn divides by n (not n − 1) when it computes the variance, so its σ values are a bit smaller than a textbook “sample” standard deviation. With only 3 patients per class the σ values are tiny, so the model becomes extremely sure (here P(diabetic) ≈ 100%). Real models need far more data.
Try It — Gaussian NB Explorer
Click anywhere to place a new patient and see the bell curves and the log-score sums. Then try the three data shapes — the last one shows exactly where the naïve assumption breaks.
α = 1 → Laplace smoothing (add-one)।
0 < α < 1 → Lidstone smoothing (हल्की)।
α = 0 → कोई smoothing नहीं (ख़तरनाक — scikit-learn तो इसे 1e-10 जैसे छोटे number से बदल देता है, जब तक आप force_alpha=True set न करें)।
scikit-learn में default alpha=1.0 है।
Cross-validation से α को लगभग 0.01 और 2 के बीच tune कीजिए। बड़े datasets को आमतौर पर छोटा α पसंद आता है; बहुत छोटे datasets को ज़्यादा smoothing चाहिए।
Gaussian NB — Continuous Features कैसे Model होते हैं
जब features continuous हों (उम्र, glucose level, तापमान), तो गिनती का कोई मतलब नहीं। इसकी जगह Gaussian NB हर class के अंदर हर feature को एक bell curve के रूप में model करता है — यह training data से mean μ और variance σ² estimate करता है।
| मरीज़ | उम्र | Glucose (mg/dL) | BMI | Diabetes? |
|---|---|---|---|---|
| 1 | 50 | 180 | 33.6 | हाँ |
| 2 | 58 | 200 | 35.0 | हाँ |
| 3 | 45 | 165 | 30.5 | हाँ |
| 4 | 25 | 90 | 22.1 | नहीं |
| 5 | 30 | 85 | 23.5 | नहीं |
| 6 | 28 | 100 | 24.0 | नहीं |
Variance निकालते समय scikit-learn n से भाग देता है (n − 1 से नहीं), इसलिए उसकी σ values textbook वाले “sample” standard deviation से थोड़ी छोटी होती हैं। हर class में सिर्फ़ 3 मरीज़ हैं, इसलिए σ values बहुत छोटी हैं, और model बहुत ज़्यादा पक्का हो जाता है (यहाँ P(diabetic) ≈ 100%)। असली models को कहीं ज़्यादा data चाहिए।
ख़ुद आज़माइए — Gaussian NB Explorer
नया मरीज़ रखने के लिए कहीं भी click कीजिए और bell curves और log-score के जोड़ देखिए। फिर data के तीनों आकार आज़माइए — आख़िरी वाला ठीक दिखाता है कि naïve assumption कहाँ टूटता है।
α = 1 → Laplace smoothing(加一)。
0 < α < 1 → Lidstone smoothing(更温和)。
α = 0 → 不做 smoothing(很危险 —— 除非你设置 force_alpha=True,否则 scikit-learn 甚至会把它换成一个很小的数,比如 1e-10)。
scikit-learn 的默认值是 alpha=1.0。
用 cross-validation 在大约 0.01 到 2 之间调 α。大的 dataset 通常适合小的 α;很小的 dataset 需要更多的 smoothing。
Gaussian NB —— 怎样处理连续的 Feature
当 feature 是连续的(年龄、血糖水平、温度)时,数数就没有意义了。 Gaussian NB 换了一种做法:在每个 class 内部,把每个 feature 看成一条钟形曲线 —— 它从 training data 中估计 mean μ 和 variance σ²。
| 病人 | 年龄 | 血糖(mg/dL) | BMI | 糖尿病? |
|---|---|---|---|---|
| 1 | 50 | 180 | 33.6 | 是 |
| 2 | 58 | 200 | 35.0 | 是 |
| 3 | 45 | 165 | 30.5 | 是 |
| 4 | 25 | 90 | 22.1 | 否 |
| 5 | 30 | 85 | 23.5 | 否 |
| 6 | 28 | 100 | 24.0 | 否 |
scikit-learn 计算 variance 时除以 n(不是 n − 1),所以它的 σ 值比课本上的“sample”标准差小一点。 每个 class 只有 3 个病人,σ 值非常小,所以 model 会变得极其肯定(这里 P(diabetic) ≈ 100%)。真实的 model 需要多得多的数据。
动手试试 —— Gaussian NB Explorer
点击任意位置放一个新病人,看钟形曲线和 log-score 的总和。然后试试三种数据形状 —— 最后一种正好显示了 naïve 假设在哪里失效。
Python Implementation
Gaussian Naïve Bayes — Iris Classification
Python Implementation
Gaussian Naïve Bayes — Iris Classification
Python 实现
Gaussian Naïve Bayes —— Iris 分类
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import load_iris
# Iris: 4 continuous features -> Gaussian NB is a natural choice
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y)
gnb = GaussianNB(var_smoothing=1e-9) # adds 1e-9 x (largest variance) for stability
gnb.fit(X_train, y_train)
y_pred = gnb.predict(X_test)
print(f"Accuracy: {gnb.score(X_test, y_test):.4f}\n")
print(classification_report(y_test, y_pred, target_names=iris.target_names, digits=3))
# The learned mean (theta_) and variance (var_) for each class and feature
for i, cls in enumerate(iris.target_names):
print(f"{cls}:")
for j, feat in enumerate(iris.feature_names):
print(f" {feat:18s} mu={gnb.theta_[i, j]:.3f} var={gnb.var_[i, j]:.4f}")
96.7% accuracy (29 of 30 test flowers) with no tuning at all. Notice how small the setosa variances are for petal length and width — that is why setosa is so easy to separate.
Multinomial NB — A Tiny Spam Filter
बिना किसी tuning के 96.7% accuracy (30 में से 29 test फूल)। ध्यान दीजिए कि petal length और width के लिए setosa के variances कितने छोटे हैं — इसीलिए setosa को अलग करना इतना आसान है।
Multinomial NB — एक छोटा Spam Filter
完全不调参,就有 96.7% 的 accuracy(30 朵 test 花中对了 29 朵)。注意 setosa 在花瓣长度和宽度上的 variance 有多小 —— 这就是 setosa 很容易被分开的原因。
Multinomial NB —— 一个小小的 Spam Filter
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import Pipeline
emails = [
"Get free money now win prizes",
"Congratulations you are a winner claim your reward",
"Free entry in our lucky draw text WIN to 88888",
"Hi how are you doing today everything okay",
"Meeting scheduled for 3pm please confirm attendance",
"Project update attached please review the report",
"WINNER you have been selected for a cash prize",
"Lunch tomorrow at the usual place let me know",
"Urgent your account will be suspended click here now",
"Can we reschedule the team standup to Friday afternoon",
]
labels = [1, 1, 1, 0, 0, 0, 1, 0, 1, 0] # 1 = spam, 0 = ham
pipeline = Pipeline([
("tfidf", TfidfVectorizer(stop_words="english")),
("clf", MultinomialNB(alpha=1.0)), # Laplace smoothing
])
pipeline.fit(emails, labels) # only 10 emails, so we train on all of them
new_emails = [
"Claim your free cash prize now",
"Please confirm the meeting time for Friday",
"Free lunch at the team meeting tomorrow",
"Quarterly budget spreadsheet", # no known words at all
]
for email, prob in zip(new_emails, pipeline.predict_proba(new_emails)):
label = "SPAM" if prob[1] > 0.5 else "HAM "
print(f"[{label}] ({prob[1]*100:5.1f}% spam) {email}")
With only 10 training emails the model is weak, but it already gets the direction right. The last message has no known words at all, so the model can only return the prior: 50%. Unknown words are simply ignored.
Bernoulli NB — Binary Bag-of-Words
सिर्फ़ 10 training emails के साथ model कमज़ोर है, पर वह दिशा पहले से सही पकड़ता है। आख़िरी message में एक भी जाना-पहचाना word नहीं है, इसलिए model सिर्फ़ prior लौटा सकता है: 50%। अनजान words को बस छोड़ दिया जाता है।
Bernoulli NB — Binary Bag-of-Words
只有 10 封 training email,model 很弱,但它已经把方向判断对了。 最后一条消息里一个认识的词都没有,所以 model 只能返回 prior:50%。 不认识的词会被直接忽略。
Bernoulli NB —— 二值 Bag-of-Words
from sklearn.naive_bayes import BernoulliNB
from sklearn.feature_extraction.text import CountVectorizer
# binary=True: each word becomes 1 (present) or 0 (absent)
pipeline_bnb = Pipeline([
("bow", CountVectorizer(binary=True, stop_words="english")),
("clf", BernoulliNB(alpha=1.0, binarize=None)), # data is already 0/1
])
pipeline_bnb.fit(emails, labels)
print("Vocabulary size:", len(pipeline_bnb.named_steps["bow"].vocabulary_))
for email, prob in zip(new_emails, pipeline_bnb.predict_proba(new_emails)):
label = "SPAM" if prob[1] > 0.5 else "HAM "
print(f"[{label}] ({prob[1]*100:5.1f}% spam) {email}")
On the same data, BernoulliNB is much more confident — and it calls “Quarterly budget spreadsheet” spam (56%) even though none of its words were seen. Why? Bernoulli also uses absent words: the message lacks typical ham words such as “meeting”, “project” and “confirm”, and that absence counts as evidence.
Full Real-World Pipeline — SMS Spam Collection
Now a real dataset: the SMS Spam Collection — 5,572 real text messages, about 13% spam. We tune the pipeline with a grid search and judge it with macro-F1, because accuracy is misleading when one class is rare.
उसी data पर BernoulliNB कहीं ज़्यादा confident है — और वह “Quarterly budget spreadsheet” को spam (56%) कहता है, जबकि उसका कोई भी word पहले नहीं देखा गया था। क्यों? Bernoulli ग़ायब words को भी इस्तेमाल करता है: इस message में “meeting”, “project” और “confirm” जैसे आम ham words नहीं हैं, और उनका न होना भी evidence गिना जाता है।
पूरी Real-World Pipeline — SMS Spam Collection
अब एक असली dataset: SMS Spam Collection — 5,572 असली text messages, लगभग 13% spam। हम grid search से pipeline को tune करते हैं और macro-F1 से उसे परखते हैं, क्योंकि जब एक class rare हो तो accuracy धोखा देती है।
在同样的数据上,BernoulliNB 自信得多 —— 它把“Quarterly budget spreadsheet”判为 spam(56%),尽管其中没有一个词是见过的。 为什么?Bernoulli 也使用没出现的词:这条消息缺少“meeting”、“project”和“confirm”这些典型的 ham 词,而这种缺少也算作 evidence。
完整的真实 Pipeline —— SMS Spam Collection
现在来用一个真实的 dataset:SMS Spam Collection —— 5,572 条真实的短信,大约 13% 是 spam。 我们用 grid search 来调 pipeline,并用 macro-F1 来评判,因为当一个 class 很少见时,accuracy 会误导人。
import pandas as pd
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report, confusion_matrix
# SMS Spam Collection: 5,572 real text messages, about 13% spam
url = "https://raw.githubusercontent.com/justmarkham/pycon-2016-tutorial/master/data/sms.tsv"
sms = pd.read_csv(url, sep="\t", header=None, names=["label", "text"])
print(sms["label"].value_counts().to_dict())
X_train, X_test, y_train, y_test = train_test_split(
sms["text"], sms["label"], test_size=0.25, random_state=42, stratify=sms["label"])
pipe = Pipeline([("tfidf", TfidfVectorizer()), ("clf", MultinomialNB())])
param_grid = {
"tfidf__ngram_range": [(1, 1), (1, 2)],
"tfidf__sublinear_tf": [True, False],
"clf__alpha": [0.01, 0.1, 0.5, 1.0],
}
grid = GridSearchCV(pipe, param_grid, cv=5, scoring="f1_macro", n_jobs=-1)
grid.fit(X_train, y_train)
print("Best params:", grid.best_params_)
print(f"Best CV macro-F1: {grid.best_score_:.4f}\n")
y_pred = grid.predict(X_test)
print(classification_report(y_test, y_pred, digits=3))
print("Confusion matrix [ham, spam]:\n", confusion_matrix(y_test, y_pred))
Zero false alarms: not one real message was put in the spam folder. 20 of 187 spam messages got through (spam recall 0.893). For a spam filter that is usually the right trade-off — losing a real message is worse than seeing one spam. The grid search picked a small α (0.1), as expected for a dataset with thousands of messages.
Comparing the Variants with Cross-Validation
Zero false alarms: एक भी असली message spam folder में नहीं गया। 187 में से 20 spam messages बच निकले (spam recall 0.893)। Spam filter के लिए यह आमतौर पर सही trade-off है — एक असली message खोना एक spam देखने से ज़्यादा बुरा है। Grid search ने छोटा α (0.1) चुना, जैसी उम्मीद थी, क्योंकि dataset में हज़ारों messages हैं।
Cross-Validation से Variants की तुलना
零误报:没有一条真实消息被放进 spam 文件夹。187 条 spam 中有 20 条漏了过去(spam recall 0.893)。 对 spam filter 来说,这通常是正确的取舍 —— 丢掉一条真实消息,比看到一条 spam 更糟。 grid search 选了一个小的 α(0.1),对一个有几千条消息的 dataset 来说,这在意料之中。
用 Cross-Validation 比较各个变体
from sklearn.naive_bayes import BernoulliNB, ComplementNB
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
import time
models = {
"MultinomialNB": Pipeline([("v", TfidfVectorizer(sublinear_tf=True)), ("c", MultinomialNB(alpha=0.1))]),
"ComplementNB ": Pipeline([("v", TfidfVectorizer(sublinear_tf=True)), ("c", ComplementNB(alpha=0.1))]),
"BernoulliNB ": Pipeline([("v", CountVectorizer(binary=True)), ("c", BernoulliNB(alpha=0.1))]),
"LogisticReg ": Pipeline([("v", TfidfVectorizer(sublinear_tf=True)), ("c", LogisticRegression(C=10, max_iter=1000))]),
}
for name, model in models.items():
t0 = time.perf_counter()
f1 = cross_val_score(model, X_train, y_train, cv=5, scoring="f1_macro")
print(f"{name}: macro-F1 = {f1.mean():.3f} +/- {f1.std():.3f} ({time.perf_counter()-t0:.1f}s)")
All four models are close (macro-F1 0.955–0.977), and each trains in well under a second. On these short messages BernoulliNB is the best — presence or absence of a word matters more than its count. ComplementNB is made for imbalanced data, yet here it is slightly behind. Always test the variants on your own data.
When to Use Naïve Bayes
partial_fit without retraining from scratch.Naïve Bayes vs Other Classifiers
| Property | Naïve Bayes | Logistic Regression | Random Forest | SVM |
|---|---|---|---|---|
| Training speed | ⚡ Very fast (one pass) | Fast | Moderate | Slow on large N (kernel) |
| Prediction speed | ⚡ Very fast | Very fast | Moderate | Moderate |
| Text / NLP | Excellent baseline | Excellent | Weak on sparse text | Excellent (linear) |
| Probability calibration | Often overconfident | Usually good | Moderate | No probabilities by default |
| Missing values | Possible in theory (skip the feature); scikit-learn needs imputation | Needs imputation | Supported in scikit-learn ≥ 1.4 | Needs imputation |
| Feature scaling needed | No | Recommended | No | Yes |
| Correlated features | Assumption violated | Handles well | Handles well | Handles well |
| Data needed | Very little | Moderate | Moderate–High | Moderate |
Strengths vs Weaknesses
| Very fast to train — one pass over the data |
| Very fast predictions |
| Strong baseline for text and NLP tasks |
| Scales to millions of sparse features |
| Works with small training sets |
| Multi-class out of the box |
| Easy to inspect — you can read the learned probabilities |
| No feature scaling needed |
Can learn online with partial_fit |
| Independence assumption almost always false |
| Probabilities often too extreme (overconfident) |
| Zero frequency problem (needs smoothing) |
| Cannot model feature interactions |
| Gaussian NB struggles with non-bell-shaped features |
| Usually beaten by boosting on tabular data |
| Word order is ignored (bag-of-words) |
| Redundant features are double-counted |
Try It — Double Counting
Why are Naïve Bayes probabilities so extreme? Add copies of the same clue and watch Naïve Bayes become more and more sure — even though no new information was added.
चारों models पास-पास हैं (macro-F1 0.955–0.977), और हर एक एक second से काफ़ी कम में train होता है। इन छोटे messages पर BernoulliNB सबसे अच्छा है — word का होना या न होना उसके count से ज़्यादा मायने रखता है। ComplementNB imbalanced data के लिए बना है, फिर भी यहाँ यह थोड़ा पीछे है। Variants को हमेशा अपने data पर test कीजिए।
Naïve Bayes कब इस्तेमाल करें
partial_fit से जोड़े जा सकते हैं, शुरू से दोबारा train किए बिना।Naïve Bayes vs दूसरे Classifiers
| गुण | Naïve Bayes | Logistic Regression | Random Forest | SVM |
|---|---|---|---|---|
| Training speed | ⚡ बहुत तेज़ (एक pass) | तेज़ | ठीक-ठाक | बड़े N पर धीमा (kernel) |
| Prediction speed | ⚡ बहुत तेज़ | बहुत तेज़ | ठीक-ठाक | ठीक-ठाक |
| Text / NLP | बेहतरीन baseline | बेहतरीन | Sparse text पर कमज़ोर | बेहतरीन (linear) |
| Probability calibration | अक्सर overconfident | आमतौर पर अच्छा | ठीक-ठाक | Default में कोई probabilities नहीं |
| Missing values | Theory में मुमकिन (feature छोड़ दीजिए); scikit-learn को imputation चाहिए | Imputation चाहिए | scikit-learn ≥ 1.4 में supported | Imputation चाहिए |
| Feature scaling ज़रूरी | नहीं | सलाह दी जाती है | नहीं | हाँ |
| Correlated features | Assumption टूटता है | अच्छे से संभालता है | अच्छे से संभालता है | अच्छे से संभालता है |
| कितना data चाहिए | बहुत कम | ठीक-ठाक | ठीक-ठाक–ज़्यादा | ठीक-ठाक |
ख़ूबियाँ vs कमज़ोरियाँ
| Train करने में बहुत तेज़ — data पर एक ही pass |
| बहुत तेज़ predictions |
| Text और NLP tasks के लिए मज़बूत baseline |
| लाखों sparse features तक scale करता है |
| छोटे training sets के साथ काम करता है |
| Multi-class सीधे, बिना कुछ किए |
| जाँचना आसान — आप सीखी गई probabilities पढ़ सकते हैं |
| Feature scaling की ज़रूरत नहीं |
partial_fit से online सीख सकता है |
| Independence assumption लगभग हमेशा ग़लत |
| Probabilities अक्सर बहुत extreme (overconfident) |
| Zero frequency problem (smoothing चाहिए) |
| Feature interactions को model नहीं कर सकता |
| Gaussian NB को घंटी के आकार से अलग features में दिक़्क़त होती है |
| Tabular data पर आमतौर पर boosting से हार जाता है |
| Words का क्रम नज़रअंदाज़ होता है (bag-of-words) |
| Redundant features दो बार गिने जाते हैं |
ख़ुद आज़माइए — Double Counting
Naïve Bayes की probabilities इतनी extreme क्यों होती हैं? एक ही सुराग़ की copies जोड़िए और देखिए कि Naïve Bayes और ज़्यादा पक्का होता जाता है — जबकि कोई नई जानकारी नहीं जुड़ी।
四个 model 都很接近(macro-F1 0.955–0.977),每个的训练时间都远远不到一秒。 在这些短消息上,BernoulliNB 最好 —— 一个词有没有出现,比它出现几次更重要。 ComplementNB 是为不平衡数据设计的,但在这里它稍微落后。一定要在你自己的数据上测试这些变体。
什么时候用 Naïve Bayes
partial_fit 加进来,不用从头重新训练。Naïve Bayes vs 其他 Classifier
| 特点 | Naïve Bayes | Logistic Regression | Random Forest | SVM |
|---|---|---|---|---|
| 训练速度 | ⚡ 非常快(只扫一遍) | 快 | 中等 | N 很大时很慢(kernel) |
| 预测速度 | ⚡ 非常快 | 非常快 | 中等 | 中等 |
| 文本 / NLP | 出色的 baseline | 出色 | 在稀疏文本上弱 | 出色(linear) |
| Probability calibration | 常常 overconfident | 通常不错 | 中等 | 默认不给 probability |
| 缺失值 | 理论上可以(跳过这个 feature);scikit-learn 需要 imputation | 需要 imputation | scikit-learn ≥ 1.4 支持 | 需要 imputation |
| 需要 feature scaling | 不需要 | 建议使用 | 不需要 | 需要 |
| 相关的 feature | 违反了假设 | 处理得好 | 处理得好 | 处理得好 |
| 需要的数据 | 很少 | 中等 | 中等–多 | 中等 |
优点 vs 缺点
| 训练非常快 —— 只需扫一遍数据 |
| 预测非常快 |
| 文本和 NLP 任务的强大 baseline |
| 能扩展到几百万个稀疏 feature |
| training set 很小也能用 |
| 开箱即用,支持 multi-class |
| 容易检查 —— 你可以直接读出学到的 probability |
| 不需要 feature scaling |
可以用 partial_fit 在线学习 |
| Independence assumption 几乎总是不成立 |
| Probability 常常太极端(overconfident) |
| Zero frequency problem(需要 smoothing) |
| 无法描述 feature 之间的相互作用 |
| feature 不是钟形时,Gaussian NB 表现不好 |
| 在表格数据上通常输给 boosting |
| 忽略了词的顺序(bag-of-words) |
| 冗余的 feature 会被重复计算 |
动手试试 —— Double Counting
为什么 Naïve Bayes 的 probability 这么极端?加入同一条线索的副本,看 Naïve Bayes 变得越来越肯定 —— 尽管并没有加入任何新信息。
If you need reliable probabilities (risk scores, thresholds), wrap the model in scikit-learn’s
CalibratedClassifierCV: method='isotonic' for large datasets or 'sigmoid' for small ones.
For the class decision alone, the raw model is usually fine.
अगर आपको भरोसेमंद probabilities चाहिए (risk scores, thresholds), तो model को scikit-learn के
CalibratedClassifierCV में लपेटिए: बड़े datasets के लिए method='isotonic' या छोटे datasets के लिए 'sigmoid'।
सिर्फ़ class का फ़ैसला करना हो, तो raw model आमतौर पर ठीक है।
如果你需要可靠的 probability(风险分数、threshold),就用 scikit-learn 的
CalibratedClassifierCV 把 model 包起来:大的 dataset 用 method='isotonic',小的用 'sigmoid'。
如果只是判断 class,原始的 model 通常就够了。
import numpy as np
from sklearn.base import clone
from sklearn.calibration import CalibratedClassifierCV
from sklearn.metrics import brier_score_loss, log_loss
nb = grid.best_estimator_ # the tuned NB pipeline
cal = CalibratedClassifierCV(clone(nb), method="isotonic", cv=5).fit(X_train, y_train)
y01 = (y_test == "spam").astype(int)
for name, model in [("raw NB ", nb), ("calibrated", cal)]:
p = model.predict_proba(X_test)[:, 1]
print(f"{name} Brier = {brier_score_loss(y01, p):.4f} log loss = {log_loss(y01, p):.4f}")
Both scores are “lower is better”. Calibration improves them a little (Brier 0.0124 → 0.0110). On this easy dataset the gain is small; on harder data with many correlated words it is often larger.
Naïve Bayes in the Real World
- Made popular by Paul Graham’s “A Plan for Spam” (2002)
- SpamAssassin and other filters include a Bayes component
- Learns from each user’s own “spam / not spam” clicks
- Cheap enough to run on every incoming message
- Symptoms → likely conditions
- Probabilities support (never replace) clinicians
- Works with limited patient data
- Easy to explain: each symptom’s evidence is visible
- Product review classification
- Social media monitoring in real time
- News category tagging at scale
- Language detection from character n-grams
Golden Rules
alpha=1.0 is a safe start.
alpha with cross-validation — usually the most important setting.
Try values on a log scale: 0.001, 0.01, 0.1, 0.5, 1, 2.
Large datasets usually prefer small α; small or very sparse datasets need larger α.
CalibratedClassifierCV when you need reliable probabilities — risk scores, fraud thresholds, medical triage.
For a simple class decision, the raw output is fine.
log P(Class) + Σ log P(xᵢ | Class) — never multiply raw probabilities.
Underflow is silent and gives wrong answers with no warning.
दोनों scores “जितना कम, उतना अच्छा” वाले हैं। Calibration उन्हें थोड़ा सुधारता है (Brier 0.0124 → 0.0110)। इस आसान dataset पर फ़ायदा छोटा है; मुश्किल data पर, जहाँ बहुत सारे correlated words हों, यह अक्सर ज़्यादा होता है।
असली दुनिया में Naïve Bayes
- Paul Graham के “A Plan for Spam” (2002) से मशहूर हुआ
- SpamAssassin और दूसरे filters में एक Bayes हिस्सा होता है
- हर user के अपने “spam / not spam” clicks से सीखता है
- इतना सस्ता कि हर आने वाले message पर चल सके
- लक्षण → संभावित बीमारियाँ
- Probabilities doctors की मदद करती हैं (उनकी जगह कभी नहीं लेतीं)
- मरीज़ों के सीमित data के साथ काम करता है
- समझाना आसान: हर लक्षण का evidence दिखता है
- Product reviews की classification
- Real time में social media monitoring
- बड़े पैमाने पर news category tagging
- Character n-grams से language detection
Golden Rules
alpha=1.0 शुरुआत के लिए सुरक्षित है।
alpha tune कीजिए — आमतौर पर यही सबसे ज़रूरी setting है।
Log scale पर values आज़माइए: 0.001, 0.01, 0.1, 0.5, 1, 2।
बड़े datasets को आमतौर पर छोटा α पसंद आता है; छोटे या बहुत sparse datasets को बड़ा α चाहिए।
CalibratedClassifierCV इस्तेमाल कीजिए।
सिर्फ़ class का फ़ैसला करना हो, तो raw output ठीक है।
log P(Class) + Σ log P(xᵢ | Class) इस्तेमाल कीजिए — raw probabilities को कभी गुणा मत कीजिए।
Underflow चुपचाप होता है और बिना किसी warning के ग़लत जवाब देता है।
这两个分数都是“越低越好”。Calibration 让它们稍微变好了一点(Brier 0.0124 → 0.0110)。在这个简单的 dataset 上,提升很小;在更难、有很多相关词的数据上,提升常常更大。
真实世界中的 Naïve Bayes
- 因 Paul Graham 的“A Plan for Spam”(2002)而流行起来
- SpamAssassin 和其他 filter 都带有一个 Bayes 组件
- 从每个用户自己点击的“spam / 不是 spam”中学习
- 成本很低,每一条收到的消息都可以跑一遍
- 症状 → 可能的疾病
- probability 用来辅助(绝不取代)医生
- 病人数据有限时也能用
- 容易解释:每个症状的 evidence 都看得见
- 商品评论分类
- 实时监控社交媒体
- 大规模的新闻类别标注
- 用字符 n-gram 做语言检测
黄金法则
alpha=1.0 是一个安全的起点。
alpha —— 它通常是最重要的设置。
在 log 刻度上试这些值:0.001, 0.01, 0.1, 0.5, 1, 2。
大的 dataset 通常适合小的 α;小的或非常稀疏的 dataset 需要更大的 α。
CalibratedClassifierCV。
如果只是简单地判断 class,原始输出就够了。
log P(Class) + Σ log P(xᵢ | Class) —— 绝不要把原始的 probability 直接相乘。
Underflow 是悄无声息的,它会给出错误的答案,而且没有任何警告。