基于C++的朴素贝叶斯分类器
Posted Kalzn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于C++的朴素贝叶斯分类器相关的知识,希望对你有一定的参考价值。
基于C++的朴素贝叶斯分类器
github链接
使用c++编写的朴素贝叶斯分类器,其中似然中的离散分量,以及先验概率使用拉普拉斯平滑,连续分量为正态分布。
警告,此代码仅为初学学习之用,请勿用作任何工程项目!
一、跑起来
方式一
使用vscode+cmake插件或者Clion打开目录。然后直接编译运行。
方式二
1、确保安装cmake环境,没有请先装cmake。
2、在工程目录下键入:
mkdir build
cd build
cmake ..
make
3、运行build目录下的程序Bayers_classifier程序
二、用起来
1、建立模型
Simple_Bayes_Classifier::Info info;
/**
struct Info
int sample_num; // 样例数量
std::vector<int> header; // 样例格式,
// 如当前分量为离散值则为样例可能取值的数量,
// 如为连续值则填0,
// 例如,现有样例格式为这样 :
// x0 属于 "东","南","西","北"
// x1 属于 "左","右"
// x2 属于 x|0<x<100 为连续值
// 则 header=4, 2, 0
int class_num; // 分类数量
int sample_size; // 样例分量维度大小
*/
Simple_Bayes_Classifier model(info);
2、读取文件,训练模型
model.train("data/1.txt"); // 文件格式为:每行一个样例,每个样例n个分量用空格隔开,最后为该样例所属分类
示例文件格式:
3、开始分类, 构造出一个待分类的样例,然后分类结果赋值到样例的belong_to字段
Sample s;
s.add_parameter(x); s.add_parameter(y);
model.classify(s);
std::cout << s.belong_to << std::endl;
三、学起来
贝叶斯分类器的基石为Bayes公式:
P ( A i ∣ B ) = P ( B ∣ A i ) P ( A i ) ∑ j = 1 n P ( B ∣ A j ) P ( A j ) P(A_i|B)=\\fracP(B|A_i)P(A_i)\\sum_j=1^nP(B|A_j)P(A_j) P(Ai∣B)=∑j=1nP(B∣Aj)P(Aj)P(B∣Ai)P(Ai)
若现在存在样例的向量为 x \\boldsymbolx x,而其所属分类为 c c c的概率为:
P ( c ∣ x ) = p ( c ) p ( x ∣ c ) p ( x ) P(c|\\boldsymbolx)=\\fracp(c)p(\\boldsymbolx|c)p(\\boldsymbolx) P(c∣x)=p(x)p(c)p(x∣c)
其中,我们把
p
(
c
)
p(c)
p(c)称为先验概率(prior),而
p
(
x
∣
c
)
p(\\boldsymbolx|c)
p(x∣c)则为似然(likelihood)而
p
(
x
)
p(\\boldsymbolx)
p(x)称为证据(evidence)。当分类器工作时,遵循
h
(
x
)
h(\\boldsymbolx)
h(x),我们需要比较
n
n
n种分类,选择概率最大的分类。
h
(
x
)
=
a
r
g
m
a
x
c
∈
Y
P
(
c
∣
x
)
h(\\boldsymbolx)=argmax_c\\in YP(c|\\boldsymbolx)
h(x)=argmaxc∈YP(c∣x)
而
P ( c ∣ x ) ∝ p ( c ) p ( x ∣ c ) P(c|\\boldsymbolx) \\propto p(c)p(\\boldsymbolx|c) P(c∣x)∝p(c)p(x∣c)
所以我们可以忽略证据,针对每个待分类的样例,对每种分类计算先验概率和似然即可。
先验概率
p
(
c
)
p(c)
p(c)一般直接进行数量统计,即:
p
(
c
)
=
∣
D
c
∣
∣
D
∣
p(c)=\\frac|D_c||D|
p(c)=∣D∣∣Dc∣
其中 D c D_c Dc为训练集中。所属类别 c c c的样例集,而 ∣ D ∣ |D| ∣D∣为全体训练集。
而计算较为困难的是似然
p
(
x
∣
c
)
p(\\boldsymbolx|c)
p(x∣c),在朴素贝叶斯中,我们认为向量
x
\\boldsymbolx
x的所有分量的取值是独立的,此时有:
p
(
x
∣
c
)
=
∏
i
=
0
n
p
(
x
i
∣
c
)
p(\\boldsymbolx|c)=\\prod_i=0^np(x_i|c)
p(x∣c)=i=0∏np(xi∣c)
此时即可进行运算,这里如果 x i x_i xi为离散值,则可以直接进行统计:
p ( x i ∣ c ) = ∣ D i , c ∣ ∣ D c ∣ p(x_i|c)=\\frac|D_i,c||D_c| p(xi∣c)=∣Dc∣∣Di,c∣
其中 D i , c D_i,c Di,c是训练集中满足:所属类别为 c c c且 i i i分量为 x i x_i xi的集合。
而如果 x i x_i xi为连续值,则这里可以将其看成正态分布:
p ( x i ∣ c ) = 1 2 π σ i , c e − ( x i − μ i , c ) 2 2 σ i , c 2 p(x_i|c)=\\frac1\\sqrt2\\pi\\sigma_i,ce^-\\frac(x_i-\\mu_i,c )^22\\sigma_i,c^2 p(xi∣c)=2πσi,c1e−2σi,c2(xi−μi,c)2
其中 σ i , c 2 , μ i , c \\sigma_i,c^2,\\mu_i,c σi,c2,μi,c分别为所属类别为 c c c的训练集的 i i i分量的方差和均值。
至此我们解决了朴素贝叶斯分类器。
在有些时候,向量 x \\boldsymbolx x的分量不是独立的,一种常见的情况是所有分量满足多维正态分布 N ( μ , Σ ) N(\\mu, \\Sigma) N(μ,Σ)。为了清晰设置 e x p ( x ) = e x exp(x)=e^x exp(x)=ex
p ( x ) = 1 ( 2 π ) d 2 ∣ Σ ∣ 1 2 e x p ( − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) ) p(\\boldsymbolx)=\\frac1(2\\pi)^\\fracd2|\\Sigma|^\\frac12exp\\left ( -\\frac12 (\\boldsymbolx-\\boldsymbol\\mu )^T\\Sigma^-1(\\boldsymbolx-\\boldsymbol\\mu ) \\right ) p(x)=(2π)2d∣Σ∣211exp(−以上是关于基于C++的朴素贝叶斯分类器的主要内容,如果未能解决你的问题,请参考以下文章