机器学习数学基础——全概率公式与贝叶斯公式

概率论在机器学习中有很重要的地位,本篇总结一下我对贝叶斯公式和全概率公式的理解。

1、全概率公式的定义

因为公式本身就比较抽象,一开始就列举公式很不友好,因此先举个栗子抛砖引玉:

【问题1】现追捕某犯罪嫌疑人,据分析他外逃、市内藏匿和自首的概率依次为0.3,0.5,0.2。并且在外逃以及市内藏匿成功缉拿的概率依次是0.4,0.7。问该犯罪嫌疑人最终归案的概率是多少?

【解答】设该犯罪嫌疑人最终归案为事件A,外逃、市内藏匿和自首分别为事件B1,B2,B3。则在外逃的情况下被成功缉拿的概率为P(A|B_1)=0.4,在市内藏匿被成功缉拿的概率为P(A|B_2)=0.7,自首则肯定被成功缉拿概率为P(A|B_3)=1,最终被成功缉拿归案的概率为以上三者相加:P(A)=P(A|B_1)P(B_1)+P(A|B_2)P(B_2)+P(A|B_3)P(B_3)=0.67

在这个例子里,B_1\bigcup B_2\bigcup B_3包含了这个逃犯所有的选择情况,且各个选择之间互不相关,即B_i \bigcap Bj=\varnothing ,i\neq j

从上面的问题1可以总结出全概率公式的定义:

设B1,B2,...为有限或者无限个事件,它们两两互斥且在每次实验中至少发生一个,即满足:B_i \bigcap Bj=\varnothing ,i\neq j,且B_1\bigcup B_2\bigcup...= \Omega,A为任一事件(下图中红圈内部)。形象的如下图表示:

则事件A发生的概率为:

P(A)=\sum_{i=1}^{n}P(A|B_i)P(B_i)

上面的公式就叫做全概率公式。

 

2、全概率公式的意义

全概率公式的意义在于,当直接计算P(A)较为困难,而P(Bi), P(A|Bi) (i=1,2,...)的计算较为简单的时候,可以使用全概率公式计算P(A)。思想就是将事件A分解成若干小时间,通过求每个小事件的概率相加后求得事件A的概率。

我们可以将事件A看作问题的结果,将事件Bi看作问题的原因i。那么全概率公式是将可能引起事件A发生的所有可能原因{B1, B2, ... Bn}均看作单一的事件,通过将这个问题拆分,分别求出不同的起因情况下事件发生的概率之后,再汇总起来的。仍是是由原因到结果的一种解法。

 

3、贝叶斯公式的定义

【问题2】接着问题1,加入现在已知该逃犯被抓捕,求他是因为自首被抓捕归案的概率是多少?

【解答】在问题1中已经知道,嫌疑人最终可以因为三种情况被抓捕归案,分别是外逃、市内藏匿和投案自首。现在已经知道他被抓捕了,那么肯定是这三种情况之中的一种,现在题目求的是因为自首被抓捕归案的概率(在“因为自首而被抓捕归”案这个事件中,被抓捕归案是条件)这个事件的概率为:

P(B_3|A) =\frac{P(A|B_3)P(B_3)}{\sum_{i=1}^{3}P(A|B_i)P(B_i) } = \frac{0.2*1}{0.3*0.4+0.5*0.7+0.2*1}=0.2985

与全概率公式解决的问题相反,贝叶斯公式是建立在条件概率的基础上寻找事情发生的原因,设B1,B2,...是样本空间S的一个划分,则对任意事件A(P(A)>0)有:

P(Bi|A)=\frac{P(B_i)P(A|B_i)}{\sum_{j=1}^{n}P(B_j)P(A|B_j)}

上面的公式即为贝叶斯公式,Bi常被认为是导致A放生的原因,因此P(Bi)(i=1,2,...)表示各种原因发生的可能性大小,因此称之为先验概率(权重);而P(Bi|A)(i=1,2,...)则反映了当产生了结果A之后,再对各种原因概率的新认识,称为后验概率。

 

4、贝叶斯公式的理解

贝叶斯公式恰好和全概率公式相反,作用在于“由结果推原因”:现在结果A已经发生了,再众多的原因中,某个原因导致事件发生的概率是多少呢?这个过程是反过来的。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是朴素贝叶斯分类器的伪代码: 1. 训练阶段: (1)对于每个类别 i,计算先验概率P(Y=i)。 (2)对于每个特征 j,计算在每个类别 i 下该特征的条件概率P(Xj=x|Y=i)。 2. 测试阶段: (1)对于输入样本 x,计算该样本属于每个类别 i 的条件概率P(Y=i|X=x)。 (2)将样本分到概率最大的类别中。 下面是朴素贝叶斯分类器的 C++ 代码实现,其中假设特征和类别都是离散的: ``` #include <iostream> #include <vector> #include <map> #include <cmath> using namespace std; // 计算先验概率 map<int, double> cal_prior_prob(vector<int>& labels) { map<int, double> prior_prob; int total = labels.size(); for (int i = 0; i < total; i++) { int label = labels[i]; if (prior_prob.find(label) == prior_prob.end()) { prior_prob[label] = 0.0; } prior_prob[label] += 1.0; } for (auto iter = prior_prob.begin(); iter != prior_prob.end(); iter++) { iter->second /= total; } return prior_prob; } // 计算条件概率 map<int, map<int, double>> cal_cond_prob(vector<vector<int>>& features, vector<int>& labels) { map<int, map<int, double>> cond_prob; int total = labels.size(); int feature_num = features[0].size(); for (int i = 0; i < total; i++) { int label = labels[i]; if (cond_prob.find(label) == cond_prob.end()) { cond_prob[label] = map<int, double>(); } for (int j = 0; j < feature_num; j++) { int feature = features[i][j]; if (cond_prob[label].find(j) == cond_prob[label].end()) { cond_prob[label][j] = map<int, double>(); } if (cond_prob[label][j].find(feature) == cond_prob[label][j].end()) { cond_prob[label][j][feature] = 0.0; } cond_prob[label][j][feature] += 1.0; } } for (auto iter1 = cond_prob.begin(); iter1 != cond_prob.end(); iter1++) { int label = iter1->first; for (auto iter2 = iter1->second.begin(); iter2 != iter1->second.end(); iter2++) { int feature = iter2->first; int feature_total = iter2->second.size(); for (auto iter3 = iter2->second.begin(); iter3 != iter2->second.end(); iter3++) { iter3->second /= feature_total; } } } return cond_prob; } // 预测 int predict(vector<int>& feature, map<int, double>& prior_prob, map<int, map<int, double>>& cond_prob) { int label = -1; double max_prob = -1.0; for (auto iter = prior_prob.begin(); iter != prior_prob.end(); iter++) { int cur_label = iter->first; double cur_prob = log(iter->second); for (int i = 0; i < feature.size(); i++) { cur_prob += log(cond_prob[cur_label][i][feature[i]]); } if (cur_prob > max_prob) { max_prob = cur_prob; label = cur_label; } } return label; } // 测试 void test(vector<vector<int>>& features, vector<int>& labels, map<int, double>& prior_prob, map<int, map<int, double>>& cond_prob) { int total = labels.size(); int correct = 0; for (int i = 0; i < total; i++) { int predict_label = predict(features[i], prior_prob, cond_prob); if (predict_label == labels[i]) { correct++; } } cout << "Accuracy: " << (double)correct / total << endl; } int main() { // 读取数据,features存放特征,labels存放类别 vector<vector<int>> features; vector<int> labels; // 训练 map<int, double> prior_prob = cal_prior_prob(labels); map<int, map<int, double>> cond_prob = cal_cond_prob(features, labels); // 测试 test(features, labels, prior_prob, cond_prob); return 0; } ``` 注意:这里的代码只是朴素贝叶斯分类器的一种实现方式,可能还有其他实现方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值