《机器学习(周志华)》Chapter7 贝叶斯分类

一、贝叶斯决策论

    贝叶斯分类器通俗点理解就是在给定样本的情况下使得分类正确的概率越大,则分类器越好。反之分类错误的概率越小分类器越好。举个例子:以西瓜数据3.0为例,对编号为1的数据进行预测,预测是好瓜的概率越大分类器越好,这很容易理解。


我们可以将问题转化为最小化分类错误的概率,对于多分类类别我们考虑分类成所有不同类别期望损失(可以简单考虑为类别的平均值),假设有N种可能的假设,即y={c1, c2, ......cN},λij是将一个真实标记为cj的样本误分类为ci所产生的损失,就可以得出给定样本x的期望损失为(条件风险):


我们训练的目的是通过训练数据寻找一个判定准则h使得整体样本期望损失最小:


显然若h能使每个样本x都能最小化条件风险R(h(x)|x),则总体风险R(h)也将被最小化。


如果将λij写成:


即分类正确为0,分类错误为1

因为x分类为所有类别的概率为1,分类正确的概率只真实类别p(c|x),则条件风险为:



我们知道p(c|x)为后验概率,显示任务中通常难以直接获得,通过贝叶斯定位可得到后验概率:


但是又引出了求p(x|c)的问题,显示中的总体空间远大于样本空间,很多样本取值在训练集中根本没有出现,直接用评率来估计p(x|c)显然不行,因为“未被观测到”与“出现概率为零”通常是不同的。极大似然估计是解决该问题的方式之一。


二、极大似然估计:

    要求条件概率p(x|c)先假定其具有某种确定的概率分布形式,再机遇训练样本对概率分布的参数进行估计。假设p(x|c)具有确定的形式并且被参数θc唯一确定,则我们的任务就是利用训练集D估计参数θc。将p(x|c)标记为p(x|θc)。

注意:(若对极大似然估计不熟悉的同学可以参考浙江大学的《概率论与数理统计》,这里只做简单记录)




对LL(θc)求导等于零即可解出最大似然估计



可解出:


进而可以求出p(x|c)。


三、朴素贝叶斯分类器:

    计算P(x|c)的方式不同,朴素贝叶斯分类器采用了属性条件独立性假设,类条件概率P(x|c)是所有属性上的联合概率,可得:









但是需要注意对未出现过的属性集会造成概率为0:


常用拉普拉斯修正:



四、半朴素贝叶斯分类器:

    朴素贝叶斯分类器采用了属性条件独立性假设,但现实任务中这个假设往往很难成立,由此产生了半朴素贝叶斯分类器。

    基本思想是适当考虑一部分属性间的相互依赖信息。“独依赖估计”(ODE)是半朴素贝叶斯分类器最常用的一种策略。


其中pai为属性xi所依赖的属性,称为xi的父属性。如何确定pai这个父属性产生了如下几种算法法:


AODE计算公式如下:




其中TAN最大带权生成树算法,通过以下步骤生成树:



五、贝叶斯网:

    贝叶斯网用来刻画属性间的依赖关系,简单点说就是假设将相关属性用有向线段链接起来表示属性相互关联,而相互独立独立属性不连接,形成的图称为贝叶斯网,然后计算出属性的联合概率分布。而这个贝叶斯网的结构是未知的,通过训练数据来确定结构,如下图:


上图表示x1、x2独立、x3和x4在给定x1的情况下独立、x4和x5在给定x2的情况下独立。

为根蒂的条件概率表,例如:

一个贝叶斯网B由结构G和参数θ两部分构成,即B=(G,θ),G是一个有向无环图,参数θ包含了每个属性的条件概率表



由图可以看出贝叶斯网中三个变量之间的典型依赖关系:



就生成了道德图:


为了通过训练数据确定贝叶斯网结构,常用评分函数

其中|B|是贝叶斯网的参数个数,f(θ)表示描述每个参数θ所需的字节数;


是贝叶斯网B的对数似然。目标就是最小化s(B|D)。

f(θ)=1得到AIC评分函数:


得到BIC评分函数:


贝叶斯网络训练好之后就能通过一些属性变量的观测值来推测其他属性变量的取值。

对于属性值不完整的训练样本通常使用EM算法。



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值