8
朴素贝叶斯与 KNN
Naive Bayes & K-Nearest Neighbors
两个"老古董"但依然在某些场景无敌:朴素贝叶斯做文本分类快到飞起;KNN 是最直观的"看邻居是谁"。
朴素贝叶斯
论贝叶斯定理 + 条件独立假设
朴素两个字是关键:假设所有特征在给定类别时条件独立(实际不成立,但效果往往不错)。这样 P(特征 | 类别) 可以拆成每个特征的乘积,计算量从指数级降到线性。拉普拉斯平滑:避免某个词没在某类出现过导致概率为 0。
P(类别 | 特征) = P(特征 | 类别) · P(类别) / P(特征)
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score
# 垃圾邮件分类:TF-IDF + 多项式朴素贝叶斯
texts = ["免费 中奖 点击 领奖", "会议 下午 项目 进度", ...]
labels = [1, 0, ...] # 1=垃圾, 0=正常
clf = Pipeline([
("tfidf", TfidfVectorizer()),
("nb", MultinomialNB(alpha=0.1))
])
scores = cross_val_score(clf, texts, labels, cv=5, scoring="f1")
print(f"F1: {scores.mean():.3f} ± {scores.std():.3f}")
# F1: 0.972 ± 0.008
KNN:惰性学习
论看你邻居是谁
KNN 不训练——训练阶段啥也不干,所有数据存下来。预测时找离测试样本最近的 K 个邻居,投票决定类别(分类)或平均它们的 y(回归)。距离度量:欧氏距离、曼哈顿距离、余弦相似度。K 值选择:K 太小容易过拟合(被噪声带跑),K 太大欠拟合(把邻居都包进来)。一般交叉验证选 K。KD 树 / 球树:加速最近邻搜索,不用和所有样本算距离。
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
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)
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)
# 不同 K 值对比
for k in [1, 3, 5, 11, 21]:
knn = KNeighborsClassifier(n_neighbors=k, weights="distance")
knn.fit(X_train_s, y_train)
print(f"K={k:2d}: 准确率 {knn.score(X_test_s, y_test):.3f}")
# K= 1: 准确率 0.933
# K= 3: 准确率 1.000
# K= 5: 准确率 1.000
# K=11: 准确率 1.000
# K=21: 准确率 1.000
三种朴素贝叶斯模型对比
| 模型 | 假设 | 什么时候用 |
| GaussianNB | 特征服从正态分布 | 连续数值特征(如身高、体重)。 |
| MultinomialNB | 特征是计数/频率 | 文本分类(TF-IDF、词袋)。 |
| BernoulliNB | 特征是 0/1 出现与否 | 短文本、二值特征。 |
TF-IDF 原理
论为什么 TF-IDF 比词频好
TF(词频):这个词在文档里出现多少次。但"的、是、在"出现频率最高,没区分度。IDF(逆文档频率):词越少见,权重越大(log(N / df))。TF-IDF = TF × IDF,让"罕见但有信息量的词"权重高。"机器学习"在 1000 篇文档里出现 5 篇,IDF 很高;"的"在所有文档出现,IDF≈0。
本章面试题
面试 · NB / KNN
Q1. 朴素贝叶斯为什么"朴素"?
查看答案
假设特征在给定类别下条件独立,现实不成立但好用。计算上把联合概率拆成边缘概率乘积。
Q2. 拉普拉斯平滑干什么?
查看答案
某个词在某类没出现过时 P(词|类)=0,会让整个乘积变 0。拉普拉斯平滑给分子加 1、分母加词汇数,避免概率为 0。
Q3. KNN 为什么必须标准化?
查看答案
KNN 用距离,量纲大的特征会主导距离。不标准化等于让"收入(万元)"比"年龄(岁)"权重高 1000 倍。
Q4. KNN 缺点?
查看答案
预测慢(每个测试样本要和所有训练样本算距离)、内存大、高维数据效果差(维度灾难)。KD 树能加速但不解决高维问题。