基于weka平台手工实现朴素贝叶斯分类

这篇具有很好参考价值的文章主要介绍了基于weka平台手工实现朴素贝叶斯分类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、贝叶斯定理

B事件发生后,A事件发生的概率可以如下表示:

p ( A ∣ B ) = p ( A ∩ B ) P ( B ) (1) p(A|B)=\frac{p(A\cap B)}{P(B)}\tag{1} p(AB)=P(B)p(AB)(1)

A事件发生后,B事件发生的概率可以如下表示:

p ( B ∣ A ) = p ( A ∩ B ) P ( A ) (2) p(B|A)=\frac{p(A\cap B)}{P(A)}\tag{2} p(BA)=P(A)p(AB)(2)

二者做比:

P ( A ∣ B ) P ( B ∣ A ) = P ( A ) P ( B ) (3) \frac{P(A|B)}{P(B|A)}=\frac{P(A)}{P(B)}\tag{3} P(BA)P(AB)=P(B)P(A)(3)

P ( B ∣ A ) P(B|A) P(BA) 乘到等式右边后,我们就叨叨了如下贝叶斯定理:

P ( A ∣ B ) = P ( B ∣ A ) P ( A ) P ( B ) (4) P(A|B)=\frac{P(B|A)P(A)}{P(B)}\tag{4} P(AB)=P(B)P(BA)P(A)(4)

二、贝叶斯分类

将贝叶斯定理的变量名称稍作变换,我们就得到了贝叶斯公式:

P ( c ∣ x ) = P ( x ∣ c ) P ( c ) P ( x ) (5) P(c|\bm{x})=\frac{P(\bm{x}|c)P(c)}{P(\bm{x})}\tag{5} P(cx)=P(x)P(xc)P(c)(5)

其中, P ( c ) P(c) P(c) 表示数据集中 l a b e l label label c c c 类样本的概率, x \bm{x} x 是输入属性, P ( x ) P(\bm{x}) P(x) 表示输入 x \bm{x} x 发生的概率, P ( x ∣ c ) P(\bm{x}|c) P(xc) c c c 发生条件下 x \bm{x} x 发生的概率。

我们通过公式5,来表示我们把输入 x \bm{x} x 分为 c c c 类的概率,这就是贝叶斯分类

进一步理解, P ( c ) P(c) P(c)叫做先验概率 P ( x ∣ c ) P(x|c) P(xc)叫做似然概率,二者相乘,最终的结果就可以很好的表征样本为某个类别的可能性大小。

三、朴素贝叶斯

从上面的式5可以看出,我们如果想要预测一个输入 x \bm{x} x的类别,我们只需要得到训练数据集中的 P ( c ) P(c) P(c) P ( x ∣ c ) P(\bm{x}|c) P(xc) 就可以了, P ( x ) P(x) P(x)不需要。

因为我们的预测过程是,给出一个样本输入 x x x,假设这个样本可能的类别为 C = { c ∣ c 0 , c 1 , . . . , c n } C=\{c|c_0,c_1,...,c_n\} C={cc0,c1,...,cn}

我们根据贝叶斯公式,计算 P ( c 0 ) P(c_0) P(c0) P ( c 1 ) P(c_1) P(c1),……, P ( c n ) P(c_n) P(cn)

最后,我们选择一个最大的 P ( c ) P(c) P(c)作为我们最终的预测类别 c ′ c' c,模型预测结束。

而在这个过程中,我们的输入 x x x 是相同的,因此 P ( x ) P(\bm{x}) P(x) 也是相同的,所以我们不需要管它,就选择分子最大的就可以了。

3.1 计算 P ( c ) P(c) P(c)

这个很好计算,我们直接统计一下,数据集中不同类别的数据的频率就可以了,大数定律告诉我们,当数据集足够大的时候,我们可以使用频率来逼近概率。

3.2 计算 P ( x ∣ c ) P(\bm{x}|c) P(x∣c)

这个思路也很简单,同样是统计,统计数据集中,label属于 c c c 的,同时输入属性为 x \bm{x} x 的数据的频率,在数据量比较大的情况下,同样使用频率逼近概率。

但是,这里的 x \bm{x} x 是由不同的输入属性组合到一起最终合成的,它具有非常多种的情况,是组合问题,这种问题统计起来是会出现复杂度爆炸的情况的,无法在多项式的时间内完成程序的运算,换言之为一种 NP 难问题。

3.3 属性独立假设

为了解决这种 NP 难问题,我们采用了属性条件独立假设,进而就诞生了朴素贝叶斯

朴素贝叶斯分类通过属性独立假设,近似求解了 P ( x ∣ c ) P(\bm{x}|c) P(xc)这个NP难问题,而且近似的效果非常好,可以取得很棒的分类效果。

假设所有属性为独立分布的,我们可以得到如下式子:

P ( x ∣ c ) = ∏ i = 0 d P ( x i ∣ c ) (6) P(\bm{x}|c)=\prod_{i=0}^dP(x_i|c)\tag{6} P(xc)=i=0dP(xic)(6)

其中d为属性数目, x i x_i xi x \bm{x} x 在第 i i i 个属性上的取值。

将式(6)带入式(5)可以得到如下结果:

P ( c ∣ x ) = P ( x ∣ c ) P ( c ) P ( x ) = P ( c ) P ( x ) ∏ i = 0 d P ( x i ∣ c ) (7) P(c|\bm{x})=\frac{P(\bm{x}|c)P(c)}{P(\bm{x})}=\frac{P(c)}{P(\bm{x})}\prod_{i=0}^dP(x_i|c)\tag{7} P(cx)=P(x)P(xc)P(c)=P(x)P(c)i=0dP(xic)(7)

这里面的 P ( x i ∣ c ) P(x_i|c) P(xic) 是很有限的,它的数量可以表示为 ∑ i = 1 n n u m A t t r i b u t e s V a l u e s ( i ) × n u m C l a s s V a l u e s \sum_{i=1}^n numAttributesValues(i)\times numClassValues i=1nnumAttributesValues(i)×numClassValues。在程序设计中我们可以采用一个二维的List数组、三维double数组或者二维数组表示三维数组等多种方法来存储这个变量。(具体可以看下面代码,为了代码的可读性和简洁性,我是采用二维List来进行表示的)

其中 n n n表示输入 x \bm{x} x的属性数量, n u m A t t r i b u t e s V a l u e s ( i ) numAttributesValues(i) numAttributesValues(i) 表示第i个属性的可能取值的数量, n u m C l a s s V a l u e s numClassValues numClassValues 表示 label 有多少个类别。

从上面也可以看出,贝叶斯分类器天然是用来处理名词性属性的,如果我们遇到了数值型属性,就需要进行一下数据离散化处理,才能采用贝叶斯进行分类。数据离散化处理方法有很多,比如:等高分箱、等宽分享,以及基于概率分布的划分等。文章来源地址https://www.toymoban.com/news/detail-543978.html

四、基于weka的代码实现

package weka.classifiers.myf;

import weka.classifiers.Classifier;
import weka.core.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * @author YFMan
 * @Description 朴素贝叶斯 分类器
 * @Date 2023/5/14 18:48
 */
public class myNaiveBayes extends Classifier {

    // 用于存储 朴素贝叶斯 属性参数
    protected List<Integer>[][] m_Distributions;

    // 用于存储 朴素贝叶斯 类别参数
    protected List<Integer> m_ClassDistribution;

    // 类别参数 的 种类数量
    protected int m_NumClasses;

    // 存储训练数据
    protected Instances m_Instances;

    /*
     * @Author YFMan
     * @Description 训练分类器,初始化 属性参数 和 类别参数
     * @Date 2023/5/14 21:42
     * @Param [instances 训练数据]
     * @return void
     **/
    public void buildClassifier(Instances instances) throws Exception {
        // 初始化训练数据
        m_Instances = instances;
        // 初始化类别参数 的 种类数量
        m_NumClasses = instances.numClasses();

        // 初始化 属性参数
        m_Distributions = new List[instances.numAttributes() - 1][m_NumClasses];
        for(int i=0;i<instances.numAttributes() - 1;i++){
            for(int j=0;j<m_NumClasses;j++){
                m_Distributions[i][j] = new ArrayList<>();
            }
        }
        // 初始化 类别参数
        m_ClassDistribution = new ArrayList<>();
        for(int i=0;i<m_NumClasses;i++){
            m_ClassDistribution.add(0);
        }

        // 获取属性参数的枚举类型
        Enumeration attributeEnumeration = instances.enumerateAttributes();
        // 遍历属性参数
        while (attributeEnumeration.hasMoreElements()) {
            // 获取属性参数
            Attribute attribute = (Attribute) attributeEnumeration.nextElement();
            // 获取属性参数的索引
            int attributeIndex = attribute.index();
            // 获取属性参数的值的枚举类型
            Enumeration attributeValueEnumeration = attribute.enumerateValues();
            // 遍历属性参数的值
            while (attributeValueEnumeration.hasMoreElements()) {
                // 获取属性参数的值
                String attributeValue = (String) attributeValueEnumeration.nextElement();
                // 遍历类别参数
                for (int classIndex = 0; classIndex < m_NumClasses; classIndex++) {
                    // 初始化 属性参数 的 某个值 的 某个类别参数 的 计数
                    m_Distributions[attributeIndex][classIndex].add(0);
                }
            }
        }

        // 遍历训练数据
        for (int instanceIndex = 0; instanceIndex < instances.numInstances(); instanceIndex++) {
            // 获取训练数据的实例
            Instance instance = instances.instance(instanceIndex);
            // 获取训练数据的类别参数的值
            int classValue = (int) instance.classValue();
            // 遍历属性参数
            for (int attributeIndex = 0; attributeIndex < instances.numAttributes() - 1; attributeIndex++) {
                // 获取训练数据的属性参数的值
                int attributeValue = (int) instance.value(attributeIndex);
                // 计数
                m_Distributions[attributeIndex][classValue].set(attributeValue,
                        m_Distributions[attributeIndex][classValue].get(attributeValue) + 1);
            }
            // 计数
            m_ClassDistribution.set(classValue, m_ClassDistribution.get(classValue) + 1);
        }
    }

    /*
     * @Author YFMan
     * @Description 根据给定的实例,预测其类别
     * @Date 2023/5/14 21:43
     * @Param [instance 给定的实例]
     * @return double[]
     **/
    public double[] distributionForInstance(Instance instance)
            throws Exception {
        // 初始化预测概率数组
        double[] predictionProbability = new double[m_NumClasses];
        // 遍历类别参数
        for (int classIndex = 0; classIndex < m_NumClasses; classIndex++) {
            // 初始化预测概率
            double prediction = 1;
            // 遍历属性参数
            for (int attributeIndex = 0; attributeIndex < m_Instances.numAttributes() - 1; attributeIndex++) {
                // 获取属性参数的值
                int attributeValue = (int) instance.value(attributeIndex);
                // 获取 当前属性 可能的取值数
                int attributeValueCount = m_Distributions[attributeIndex][classIndex].size();
                // 计算条件概率P(x|c) (当前属性值在当前类别下占的比例) (拉普拉斯平滑)
                double p_x_c =  (double) (m_Distributions[attributeIndex][classIndex].get(attributeValue) + 1) /
                        (m_ClassDistribution.get(classIndex) + attributeValueCount);
                // 计算预测概率
                prediction *= p_x_c;
            }
            // 计算先验概率P(c) (当前类别占总类别的比例) (拉普拉斯平滑)
            double p_c = (double) (m_ClassDistribution.get(classIndex) + 1) /
                    (m_Instances.numInstances() + m_NumClasses);
            // 计算预测概率
            predictionProbability[classIndex] = prediction * p_c;
        }
        // 归一化
        Utils.normalize(predictionProbability);
        // 返回预测概率数组
        return predictionProbability;
    }

    /*
     * @Author YFMan
     * @Description 主函数
     * @Date 2023/5/14 21:54
     * @Param [argv 命令行参数]
     * @return void
     **/
    public static void main(String[] argv) {
        runClassifier(new myNaiveBayes(), argv);
    }
}

到了这里,关于基于weka平台手工实现朴素贝叶斯分类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【机器学习实战】-基于概率论的分类方法:朴素贝叶斯

    【机器学习实战】读书笔记 **朴素贝叶斯:**称为“ 朴素 ”的原因,整个形式化过程只做最原始、最简单的假设,特征之间没有关联,是统计意义上的独立。 **优点:**在数据较少的情况下仍然有效,可以处理多类别问题。 **缺点:**对于输入数据的准备方式较为敏感。 **适

    2024年03月25日
    浏览(40)
  • 基于机器学习算法:朴素贝叶斯和SVM 分类-垃圾邮件识别分类系统(含Python工程全源码)

    本项目采用朴素贝叶斯和支持向量机(SVM)分类模型作为基础,通过对垃圾邮件和正常邮件的数据进行训练,旨在实现垃圾邮件的自动识别功能。 通过训练这两个分类模型,我们的目标是建立一个高效准确的垃圾邮件识别系统。当接收到新的邮件时,系统将对邮件文本进行预

    2024年02月09日
    浏览(38)
  • 机器学习——使用朴素贝叶斯分类器实现垃圾邮件检测(python代码+数据集)

    机器学习——scikit-learn库学习、应用 机器学习——最小二乘法拟合曲线、正则化 机器学习——使用朴素贝叶斯分类器实现垃圾邮件检测(python代码+数据集) 贝叶斯公式: P ( A ∣ B ) = P ( A ) P ( B ∣ A ) P ( B ) P(A mid B)=frac{P(A) P(B mid A)}{P(B)} P ( A ∣ B ) = P ( B ) P ( A ) P ( B ∣ A )

    2024年02月10日
    浏览(34)
  • 基于朴素贝叶斯的垃圾邮件分类Python实现

    垃圾邮件的问题一直困扰着人们,传统的垃圾邮件分类的方法主要有\\\"法\\\"和\\\"校验码法\\\"等,然而这两种方法效果并不理想。其中,如果使用的是“”法,垃圾邮件中如果这个被拆开则可能识别不了,比如,“中奖”如果被拆成“中 ~~~ 奖”可能会识别不了。

    2024年02月02日
    浏览(35)
  • 机器学习算法——贝叶斯分类器3(朴素贝叶斯分类器)

    基于贝叶斯公式来估计后验概率P(c|x)的主要困难在于:类条件概率P(x|c)是所有属性上的联合概率,难以从有限的训练样本直接估计而得。 为避开这个障碍,朴素贝叶斯分类器(Naive Bayes classfier)采用了“ 属性条件独立性假设 ”:对已知类别,假设所有属性相互独立。换句话

    2023年04月22日
    浏览(44)
  • 机器学习--朴素贝叶斯分类器

    第1关:条件概率 什么是条件概率 概率指的是某一事件 A 发生的可能性,表示为 P(A) 。而条件概率指的是某一事件 A 已经发生了条件下,另一事件 B 发生的可能性,表示为 P(B|A) ,举个例子: 今天有 25% 的可能性下雨,即 P(下雨)=0.25 ; 今天 75% 的可能性是晴天,即 P(晴天)=0.7

    2024年02月08日
    浏览(49)
  • 机器学习之朴素贝叶斯分类器原理详解、公式推导(手推)、面试问题、简单实例(python实现,sklearn调包)

    朴素贝叶斯是一种有监督学习算法,这种算法基于贝叶斯的一个朴素的假设——每对特征和样本数据都是独立同分布的。最终可以推出朴素贝叶斯分类器的判定准则: h n b ( x ) = a r g   m a x c ∈ Υ   P ( c ) ∏ i = 1 d P ( x i   ∣   c ) h_{nb}(x)=mathop{arg max}limits_{cin varUpsilon} P(

    2024年02月08日
    浏览(36)
  • 机器学习实验 - 朴素贝叶斯分类器

    报告内容仅供学习参考,请独立完成作业和实验喔~ 1.1 实验要求 (1)了解朴素贝叶斯与半朴素贝叶斯的区别与联系,掌握高斯分布、多项式分布和伯努利分布的朴素贝叶斯计算方法。 (2)编程实现朴素贝叶斯分类器,基于多分类数据集,使用朴素贝叶斯分类器实现多分类预

    2024年02月09日
    浏览(39)
  • 机器学习笔记07---朴素贝叶斯分类器

    贝叶斯决策论是概率框架下实施决策的基本方法。对分类任务来说,在所有相关概率都已知的理想情形下,贝叶斯决策论考虑如何基于这些概率和误判损失来选择最优的类别标记。     贝叶斯公式:  其中,P(c)是类\\\"先验\\\"概率;P(x|c)是样本x相对于类标记c的类条件概率,或称

    2024年02月07日
    浏览(49)
  • 【机器学习】分类算法 - 朴素贝叶斯 MultinomialNB

    「作者主页」: 士别三日wyx 「作者简介」: CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」: 对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 md5() 可以计算字符串的 「MD5散列值」 。 语法 参数 $str :需要计算的字符串

    2024年02月14日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包