草庐IT

matlab 朴素贝叶斯模型 代码及其案例

foddcusL 2023-04-05 原文

简介

朴素贝叶斯分类器(Naive Bayes Classifier 或 NBC)发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率。同时,NBC模型所需估计的参数很少,对缺失数据不太敏感,算法也比较简单。理论上,NBC模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为NBC模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,这给NBC模型的正确分类带来了一定影响。[1]

这里简单使用两张温州大学黄海广老师课件的截图来简要表示朴素贝叶斯的基本原理

X可以理解为可观测的参数,而Y则是我们所需预测的参数,利用统计学即某个确定Y的X属性占比分布来作为模型判断的基础。打个比方,我们通过一个人的体重(77kg)来预测其平均在一餐中摄入的热量,首先对建模集样本进行统计,发现75-80kg体重的人摄入热量分布600卡5%、700卡10%、800卡60%,基于这些建模集的样本统计,朴素贝叶斯给出答案:800卡(60%);在实际中案例中,这个模型还会有更多的参数,包括性别、身高、人种、生活气候等,通过各个属性概率的相乘,最后进行归一化对比,以可能性最高的情况作为预测结果。

朴素贝叶斯模型默认所有参数相互独立互补影响,但这对于日常生活中的模型是不切实际的,因此当建模对象的参数有明显的共线性问题时,使用朴素贝叶斯的方法就不太合适了。

下面提供参考的代码段:

代码脚本:

%Foddcus 2022.3
%朴素贝叶斯脚本
%输入:input 具有离散属性的数据、或已经分割好的数据 分类在第一列
%标准的贝叶斯数据处理,输出可以直接储存

clear all
input=xlsread("D:\同步空间\采集数据库\缺素\10.xlsx");
inform=[1111,1112,1113,1114];
errorF=CKOpatua(input,inform,20,0);
input=DLrow(input,errorF)
input=input(:,2:20);%删除序号

y=evaluatenNavieByes(input,inform);%测试最佳的分段数,y为分段数
[input2,D]=DSTparameter(input,y,0,0);%将离散的属性参数进行分段分类
maxnum=max(input2);

[XSelected,XRest,vSelectedRowIndex]=selectSam(input2,0.2);%提取20%的样本作为预测集,80%的样本为建模集
[modeIFMT,checkout,corr]=naviebyes(XRest,inform,maxnum);%建立朴素贝叶斯模型
[checkout2,corr2]=NbyesPre(XSelected,inform,modeIFMT,maxnum);%就模型对新的样本进行预测
Cmatrix=CFSmatrix(checkout2,inform);%就预测效果生成混淆矩阵

 其中运用到的自定义函数:

1.errorF=CKOpatua(input,inform,20,0);异常数据检验函数,

matlab 基于拉依达检验法(3σ准则) 实现多类别多参数的批量检验异常值与异常样本_foddcusL的博客-CSDN博客_拉依达检验法

2.input=DLrow(input,errorF);删除目标行(即异常样本)

 matlab 批量删除数组的行_foddcusL的博客-CSDN博客

3.y=evaluatenNavieByes(input,inform);

  因为案例中我输入的数据是一个连续的离散数据,而朴素贝叶斯的分类是基于属性分类的统计进行建模,所以我们要先尝试不同分段数下建模效果的准确率,取准确率最高的分段数作为建模分段数。

%评价当前数据用贝叶斯评价的的适合参数 评估范围是2:50
%xf,xe为参数的范围,xf一般从2开始取 第一列为标识码
%输入:input:excel文件夹, inform=[1111,1112,1113,1114,1115];
%输出:y:最佳的分割段数


function y=evaluatenNavieByes(input,inform);
for i=2:50
    for j=1:10
        disp([i,j]);
        [input2,D]=DSTparameter(input,i,0,0);
        maxnum=max(input2);
        [XSelected,XRest,vSelectedRowIndex]=selectSam(input2,0.2);
        [modeIFMT,checkout,corr]=naviebyes(XRest,inform,maxnum);%建模
        [checkout2,corr2]=NbyesPre(XSelected,inform,modeIFMT,maxnum);
        corrF(i,j)=corr;
        corrF2(i,j)=corr2;
    end
    disp('correct');
end
corrZ=mean(corrF,2);
corrZ2=mean(corrF2,2);
corrZ3=corrZ.*corrZ2;%预测集准确率与建模集集准确率相乘
for i=1:50
    corrZ3(i,1)=corrZ3(i,1)-0.2*i;%正则率取0.2%较佳
end
[x,y]=max(corrZ3);%取最高的准确率
end

4:[input2,D]=DSTparameter(input,i,0,0);将离散的参数分段

%%使用相对标准差将数据分割成数个区间,分成区间数为相对标准差*6
%第一列为识别码

%输入:excel数据:input xf,xe为参数的范围 一般第一列为识别码,xf从2开始取
%输出:分类后的数据:output D分割取值和最小值,方便后期对其他数据进行处理


function [output,D]=DSTparameter(input,muti,xfFxx,xeFxx)
[ys,xs]=size(input);
if xfFxx==0||xeFxx==0%这个判断会收到外部因素影响,所以加个后缀
    xfFxx=2;
    xeFxx=xs;
else
    input=[input(:,1),input(:,xfFxx:xeFxx)];%设定区间
end

S_row=std(input);
M_row=mean(input);
SBS=round(muti*S_row./M_row);%向上取整
Maxrow=max(input);
Minrow=min(input);
D=(Maxrow-Minrow)./SBS;
for i=xfFxx:xeFxx
    for j=1:ys
        for k=1:SBS(1,i)
            if (Minrow(1,i)+D(1,i)*(k-1))<=input(j,i)&&input(j,i)<=(Minrow(1,i)+D(1,i)*k)
                output(j,i)=k;
            end
        end
    end
end
output(:,1)=input(:,1);
D=[Minrow;D];
end

5:[XSelected,XRest,vSelectedRowIndex]=selectSam(input2,0.2);随机提取样本

 随机提取excel中的行 自定义函数_foddcusL的博客-CSDN博客

6: [modeIFMT,checkout,corr]=naviebyes(XRest,inform,maxnum);根据数据集进行朴素贝叶斯建模

%author LijiaYi FAFU  2022.3  
%朴素贝叶斯建模
% 输入:input 具有离散属性的数据、或已经分段判别好的数据 属性判别在第一列,且所有数据都在第一行
% inform数据标识(一行多列的矩阵) max:每个属性最大值的单行多列矩阵
% 输出:  modeIFMT模型内容,新内容加到3维阵的最后一列 checkout 输出本身的检查结果
% corr自检准确率
function [modeIFMT,checkout,corr]=naviebyes(input,inform,maxnum)
modeIFMT=[];
[yn,xn]=size(inform);
[ys,xs]=size(input);

for i=2:xs
    for j=1:maxnum(1,i)%j为属性值
        [indexF,input2]=DSTname(input,[j],i); %输出1维的矩阵 ,若未有其值,则输出空矩阵
        for ctg=1:xn
            if isempty(input2)%判断是否为空矩阵
                modeIFMT(j,i-1,ctg)=0;
            else
                name=inform(1,ctg);
                index=find(input2(:,1)==name);%判断这个属性各个于类别中的占比,转化为0-1之间的数
                [ys2,xs2]=size(index);
                modeIFMT(j,i-1,ctg)=ys2/ys;
            end
        end
    end
    %输出属性在某个类别的占比
end
%自检
dnum=modeIFMT(1,1,:);
for i=1:ys
    for j=2:xs
        for attri=1:maxnum(1,j)
            if find(input(i,j)==attri)
                for ctg=1:xn
                    build(ctg,j-1)=modeIFMT(attri,j-1,ctg);
                end
            end
        end
    end
    prob=ones(xn,1);
    for j=1:xs-1
        prob=prob.*build(:,j);
    end
    [pbb,ys3]=max(prob);
    checkout(i,2)=max(prob)/sum(prob);
    checkout(i,1)=inform(1,ys3);
end
n=0;
for i=1:ys
    if checkout(i,1)==input(i,1)
        n=n+1;
    end
end

corr=n/ys;
checkout=[input(:,1),checkout];

end

7:[checkout2,corr2]=NbyesPre(XSelected,inform,modeIFMT,maxnum);根据模型对预测集进行预测

%朴素贝叶斯预测
%输入:input 具有离散属性的数据、或已经分段判别好的数据 属性判别在第一列,且所有数据都在第一行
%inform数据标识(一行多列的矩阵) max:每个属性最大值的单行多列矩阵
%输出:  modeIFMT模型内容,新内容加到3维阵的最后一列 checkout 输出本身的检查结果
%corr自检准确率

% clear all
% load("D:\同步空间\算法汇总\机器学习\data\naviebyes1.mat")


function [checkout,corr]=NbyesPre(input,inform,modeIFMT,maxnum)
[yn,xn]=size(inform);
[ys,xs]=size(input);
dnum=modeIFMT(1,1,:);
nk=0;
for i=1:ys
    for j=2:xs
        for attri=1:maxnum(1,j)
            if find(input(i,j)==attri)%确定属性值,若为已存在在属性值
                for ctg=1:xn
                    build(ctg,j-1)=modeIFMT(attri,j-1,ctg);%buid为该样本在该条件下,各个种类可能值
                end
                nk=1;
            end
            
        end
        if nk==0%如果没有找到该位置的属性,为其赋值0
            build(ctg,j-1)=0
        end
        nk=0;
    end
    prob=ones(xn,1);
    errorP=max(build);
    for j=1:xs-1
        if find(errorP(1,j)==0)
            prob=prob.*ones(xn,1);
        else
            prob=prob.*build(:,j);
        end
    end
    [pbb,ys3]=max(prob);
    checkout(i,2)=max(prob)/sum(prob);
    checkout(i,1)=inform(1,ys3);
end
n=0;
for i=1:ys
    if checkout(i,1)==input(i,1)
        n=n+1;
    end
end
corr=n/ys;
checkout=[input(:,1),checkout];

end

8:Cmatrix=CFSmatrix(checkout2,inform);%就预测效果生成混淆矩阵

 matlab 混淆矩阵 自定义函数_foddcusL的博客-CSDN博客

9:[indexF,output]=DSTname(datadet,CTGname,where);根据样本名称分类的自定义函数

%输入
%datadet原始数据
%CTGname:分类名称(一行二维矩阵格式),类别名称应为第where列
%输出
%indexF:各类所在的行
%output:分好类的三维矩阵(按最大二维矩阵输出二维尺寸,其他会有含零的层

function [indexF,output]=DSTname(datadet,CTGname,where) 
output=[];
[ys,xs]=size(CTGname);
for i=1:xs
    indexForlist=find(datadet(:,where)==CTGname(1,i));
    [indexR,indexL]=size(indexForlist);
    indexF(1:indexR,i)=indexForlist(:,1);
    for j=1:indexR%将选中的数据分开存放
        output(j,:,i)=[datadet(indexForlist(j,1),:)];%数据开头是该行数据在原本excel中的行数
    end
end

案例展示:

输入表格:input:

第一列为样本的序号,第二列为样本的分类数值代号分别为1111,1112,1113、1114,对应inform的数据,后续皆为样本的参数。

输出:

corr、corr2;分别是建模集和预测集的准确率;朴素贝叶斯非常依赖建模样本的稳定程度,只有当样本参数够多,样本量较大,数据准确,才会有极高的预测准确度。

modelFMT:生成的模型;

checkout、checkout2:预测表,第一列为真实值;第二列为预测值,第三列为把握;

Cmatrix:生成的混合矩阵,4*4,表头对应inform的内容 

[1]朴素贝叶斯_百度百科 (baidu.com)

有关matlab 朴素贝叶斯模型 代码及其案例的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  4. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  5. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  6. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  7. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  8. ruby-on-rails - 如何将验证与模型分开 - 2

    我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:

  9. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  10. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

随机推荐