• 基于C++的朴素贝叶斯分类器


    基于C++的朴素贝叶斯分类器

    github链接
    使用c++编写的朴素贝叶斯分类器,其中似然中的离散分量,以及先验概率使用拉普拉斯平滑,连续分量为正态分布。

    警告,此代码仅为初学学习之用,请勿用作任何工程项目!

    一、跑起来

    方式一

    使用vscode+cmake插件或者Clion打开目录。然后直接编译运行。

    方式二

    1、确保安装cmake环境,没有请先装cmake。
    2、在工程目录下键入:

    mkdir build
    cd build
    cmake ..
    make
    
    • 1
    • 2
    • 3
    • 4

    3、运行build目录下的程序Bayers_classifier程序

    二、用起来

    1、建立模型

    Simple_Bayes_Classifier::Info info;
    /**
        struct Info {
            int sample_num; // 样例数量
            std::vector header; // 样例格式,
                                     // 如当前分量为离散值则为样例可能取值的数量,
                                     // 如为连续值则填0,
                                     // 例如,现有样例格式为这样 :
                                     //           x0 属于 {"东","南","西","北"}
                                     //           x1 属于 {"左","右"}
                                     //           x2 属于 {x|0
    Simple_Bayes_Classifier model(info);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2、读取文件,训练模型

    model.train("data/1.txt"); // 文件格式为:每行一个样例,每个样例n个分量用空格隔开,最后为该样例所属分类
    
    • 1

    示例文件格式:

    3、开始分类, 构造出一个待分类的样例,然后分类结果赋值到样例的belong_to字段

    Sample s;
    s.add_parameter(x); s.add_parameter(y);
    model.classify(s);
    std::cout << s.belong_to << std::endl;
    
    • 1
    • 2
    • 3
    • 4

    三、学起来

    贝叶斯分类器的基石为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)=\frac{P(B|A_i)P(A_i)}{\sum_{j=1}^nP(B|A_j)P(A_j)} P(AiB)=j=1nP(BAj)P(Aj)P(BAi)P(Ai)

    若现在存在样例的向量为 x \boldsymbol{x} x,而其所属分类为 c c c的概率为:

    P ( c ∣ x ) = p ( c ) p ( x ∣ c ) p ( x ) P(c|\boldsymbol{x})=\frac{p(c)p(\boldsymbol{x}|c)}{p(\boldsymbol{x})} P(cx)=p(x)p(c)p(xc)

    其中,我们把 p ( c ) p(c) p(c)称为先验概率(prior),而 p ( x ∣ c ) p(\boldsymbol{x}|c) p(xc)则为似然(likelihood)而 p ( x ) p(\boldsymbol{x}) p(x)称为证据(evidence)。当分类器工作时,遵循 h ( x ) h(\boldsymbol{x}) h(x),我们需要比较 n n n种分类,选择概率最大的分类。
    h ( x ) = a r g m a x c ∈ Y P ( c ∣ x ) h(\boldsymbol{x})=argmax_{c\in Y}P(c|\boldsymbol{x}) h(x)=argmaxcYP(cx)

    P ( c ∣ x ) ∝ p ( c ) p ( x ∣ c ) P(c|\boldsymbol{x}) \propto p(c)p(\boldsymbol{x}|c) P(cx)p(c)p(xc)

    所以我们可以忽略证据,针对每个待分类的样例,对每种分类计算先验概率和似然即可。

    先验概率 p ( c ) p(c) p(c)一般直接进行数量统计,即:
    p ( c ) = ∣ D c ∣ ∣ D ∣ p(c)=\frac{|D_c|}{|D|} p(c)=DDc

    其中 D c D_c Dc为训练集中。所属类别 c c c的样例集,而 ∣ D ∣ |D| D为全体训练集。

    而计算较为困难的是似然 p ( x ∣ c ) p(\boldsymbol{x}|c) p(xc),在朴素贝叶斯中,我们认为向量 x \boldsymbol{x} x的所有分量的取值是独立的,此时有:
    p ( x ∣ c ) = ∏ i = 0 n p ( x i ∣ c ) p(\boldsymbol{x}|c)=\prod_{i=0}^np(x_i|c) p(xc)=i=0np(xic)

    此时即可进行运算,这里如果 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(xic)=DcDi,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)=\frac{1}{\sqrt{2\pi}\sigma_{i,c}}e^{-\frac{(x_i-\mu_{i,c} )^2}{2\sigma_{i,c}^2}} p(xic)=2π σi,c1e2σ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 \boldsymbol{x} 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(\boldsymbol{x})=\frac{1}{(2\pi)^{\frac{d}{2}}|\Sigma|^{\frac{1}{2}}}exp\left ( -\frac{1}{2} (\boldsymbol{x}-\boldsymbol{\mu} )^T\Sigma^{-1}(\boldsymbol{x}-\boldsymbol{\mu} ) \right ) p(x)=(2π)2d∣Σ211exp(21(xμ)TΣ1(xμ))

    其中

    μ i = E [ x i ] \mu_i=E[x_i] μi=E[xi]
    Σ i , j = E [ ( x i − μ i ) ( x j − μ j ) ] \Sigma_{i,j}=E[(x_i-\mu_i)(x_j-\mu_j)] Σi,j=E[(xiμi)(xjμj)]

    这里我们将结果取对数

    g i ( x ) = l n ( p ( x ∣ c i ) p ( c i ) ) = l n p ( x ∣ c i ) + l n p ( c i ) g_i(\boldsymbol{x})=ln(p(\boldsymbol{x}|c_i)p(c_i))=lnp(\boldsymbol{x}|c_i)+lnp(c_i) gi(x)=ln(p(xci)p(ci))=lnp(xci)+lnp(ci)

    g i ( x ) = − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) − d 2 l n 2 π − 1 2 l n ∣ Σ i ∣ + l n p ( c i ) g_i(\boldsymbol{x})=-\frac{1}{2} (\boldsymbol{x}-\boldsymbol{\mu} )^T\Sigma^{-1}(\boldsymbol{x}-\boldsymbol{\mu} )-\frac{d}{2}ln2\pi -\frac{1}{2}ln|\Sigma_i|+lnp(c_i) gi(x)=21(xμ)TΣ1(xμ)2dln2π21lnΣi+lnp(ci)

    此时有决策函数:

    g i , j ( x ) = g i ( x ) − g j ( x ) g_{i,j}(x)=g_i(x)-g_j(x) gi,j(x)=gi(x)gj(x)

    g i , j ( x ) = 0 g_{i,j}(x)=0 gi,j(x)=0为决策界,当 g i , j ( x ) ≥ 0 g_{i,j}(x)\ge 0 gi,j(x)0归为 i i i类,否则归为 j j j。至此,我们讨论了贝叶斯分类器中,样例各分量满足多维正态分布的情况。

  • 相关阅读:
    频频刷屏朋友圈,白酒如何越来越年轻化?来聊聊白酒企业数字化
    攻防世界Check
    Java实现分片上传(前端分,后端合并)
    22ccpc桂林E - Draw a triangle 向量求三角形面积,exgcd
    海思开机画面
    NSSCTF Round#4
    Spring-AOP 讲解
    代码都成屎山了,还在用if-else?不如试试我的这套工厂模式+Map+自定义注解+枚举
    centos编译安装opencv,生成opencv-2413.jar
    ESP32-C3入门教程 IoT篇⑥——微软云 Microsoft Azure 物联网 IoT Central EspAzureIoT 实战
  • 原文地址:https://blog.csdn.net/qq_35802619/article/details/126841418