跳到主要内容

朴素贝叶斯

一、直观理解:用“条件独立”把贝叶斯公式算到底​

朴素贝叶斯(Naive Bayes)先问:在看到特征 xx 之后,样本更像哪一类?贝叶斯公式给出

P(y∣x)∝P(y) P(x∣y)P(y\mid x)\propto P(y)\,P(x\mid y)

难点是 P(x∣y)P(x\mid y) 在高维下难以估计。朴素假设是:给定类别后,各特征相互独立,于是

P(x∣y)=∏j=1pP(xj∣y)P(x\mid y)=\prod_{j=1}^{p}P(x_j\mid y)

联合分布拆成一堆一维分布,统计上粗糙,但在文本分类、垃圾邮件、简单传感器组合等问题上往往出奇地好用——偏差大,方差小,校准有时还不错。

可以把它想成:每位“特征证人”独立作证,法官按先验与各证人的似然连乘更新信念。

二、适用场景与优缺点​

类型说明
适用场景文本词频/TF-IDF;高维稀疏计数特征;需要快速基线与概率输出;特征近似条件独立;在线/流式更新。
核心优点训练极快(只需计频率或高斯参数);对高维友好;实现简单;小样本也可估;天然多分类。
局限与缺点条件独立常不成立,概率可能过尖;特征相关时决策仍可能准但概率失真;高斯版对非正态敏感;零概率需要平滑。

使用前:选择合适的事件模型(高斯/多项式/伯努利);做拉普拉斯平滑;标准化对高斯 NB 有时有用,对多项式 NB 通常保持计数。

三、核心原理​

1. 决策规则​

y^=arg⁡max⁡c log⁡P(y=c)+∑j=1plog⁡P(xj∣y=c)\hat y=\arg\max_c\ \log P(y=c)+\sum_{j=1}^{p}\log P(x_j\mid y=c)

取对数把连乘变求和,数值更稳。

2. 常见事件模型​

模型特征假设典型数据
高斯 NBxj∣y∼N(μcj,σcj2)x_j\mid y\sim\mathcal{N}(\mu_{c j},\sigma_{c j}^2)连续测量
多项式 NB词频多项分布文本计数
伯努利 NB特征是否出现二值词袋

3. 拉普拉斯平滑(多项式)​

P^(t∣c)=Nct+αNc+α∣V∣\hat P(t\mid c)=\frac{N_{c t}+\alpha}{N_c+\alpha |V|}

α=1\alpha=1 即加一平滑,避免某词在某类未出现导致整个后验为 0。

尽管独立假设很强,分类只关心后验的排序,因此即使概率估计有偏,argmax 仍可能正确。

四、关键决策​

决策点建议
分布族连续 → 高斯;文本计数 → 多项式;0/1 → 伯努利
平滑 α\alpha文本默认 1,可用 CV 微调
先验默认用训练频率;可按业务设类先验
特征去掉近乎恒定的列;文本去停用词、可 IDF
相关特征强相关可合并或降维,减轻“重复计票”
评价看校准与 Brier;不只看准确率

五、MATLAB 示例​

% 连续特征 + 高斯朴素贝叶斯
X = [
5.1 3.5 1.4;
4.9 3.0 1.4;
6.2 3.4 5.4;
5.9 3.0 5.1;
5.5 2.3 4.0;
6.5 3.0 5.5;
4.8 3.4 1.6;
5.7 2.8 4.5
];
y = [1;1;3;3;2;3;1;2]; % 三类

Mdl = fitcnb(X, y, ...
"DistributionNames", "normal", ...
"Prior", "empirical");

% 查看各类各特征均值
for c = 1:numel(Mdl.ClassNames)
fprintf("类 %s 的均值:\n", string(Mdl.ClassNames(c)));
disp(Mdl.DistributionParameters{c,1}); % 结构因版本而异,可检查文档
end

[label, posterior, cost] = predict(Mdl, X);
disp("混淆矩阵:");
disp(confusionmat(y, label));
disp("后验概率(前 5 行):");
disp(posterior(1:5, :));

% 交叉验证
cv = crossval(Mdl, "KFold", 4);
fprintf("CV loss = %.3f\n", kfoldLoss(cv));

% 若特征是计数型文本,可设置
% Mdl = fitcnb(Xcount, y, "DistributionNames", "mvmn"); % 或按文档使用 multinomial
% 对高斯 NB 也可指定不同特征不同分布:
% Mdl = fitcnb(X, y, "DistributionNames", {"normal","normal","kernel"});

简单手写高斯 NB(便于论文公式对照):

classes = unique(y);
[n, p] = size(X);
mu = zeros(numel(classes), p);
sg = zeros(numel(classes), p);
pri = zeros(numel(classes), 1);
for i = 1:numel(classes)
Xi = X(y == classes(i), :);
mu(i, :) = mean(Xi);
sg(i, :) = std(Xi, 0); % 可用平滑避免 0 方差
sg(i, sg(i,:) < 1e-6) = 1e-6;
pri(i) = size(Xi, 1) / n;
end

x = X(1, :);
logPost = log(pri);
for i = 1:numel(classes)
logPost(i) = logPost(i) + sum( ...
-log(sqrt(2*pi)*sg(i,:)) - 0.5*((x - mu(i,:))./sg(i,:)).^2 );
end
[~, idx] = max(logPost);
fprintf("手写 NB 预测类 = %d\n", classes(idx));

六、如何解释结果​

  1. 类条件均值/方差(高斯):某类在哪些特征上整体偏高;
  2. 似然比:某特征值使哪一类的 P(xj∣y)P(x_j\mid y) 显著更大;
  3. 后验概率:给出“有多有把握”,但若特征相关,概率值可能过度自信;
  4. 先验影响:小样本下先验会拉动结果;
  5. 报告:事件模型、平滑、类先验、CV 指标、与 Logistic 对比。

七、常见误区​

1. 条件独立当真理​

它是计算假设,不是世界规律;相关特征会重复放大证据。

2. 零概率“一票否决”​

不加平滑时,未见过的词会把整类后验打成 0。

3. 把后验当成精确风险​

需要可靠概率时做校准或换模型。

4. 连续特征硬套多项式,或文本硬套高斯​

事件模型与数据类型匹配比调参更重要。

5. 忽略类先验与采样偏差​

训练类比例若与部署不同,应调整先验。

八、小结​

朴素贝叶斯在特征条件独立假设下,用先验乘类条件似然做分类,是最快、最干净的概率基线之一。

它特别适合高维稀疏与文本类问题,也适合作为复杂模型的对照。写论文时诚实说明独立假设,用混淆矩阵与校准检查“准”和“信”是否同步。