预测的程序就很简单了:1. 计算输入样本的特征向量与模型的特征向量的向量内积;2. 在多个类别中,选择概率最大的类别。不过,贝努利模型和多项式模型的区别也就在此,在1——对那些在输入样本中没有出现的特征类型,那些取值为0的特征类型,如何处理。从前说过,我写的是贝努利模型,所以,这些特征类型的条件概率也计算进去了。
计算向量内积的代码如下:
double NaiveBayes::CalcProbLogByFeaVec (vector<int> & FeaIdVec, vector<FeaProbNode> & FeaVec)
{
double dProbLog = 0.0;
vector<int>::iterator pFeaId = FeaIdVec.begin();
vector<FeaProbNode>::iterator pFea = FeaVec.begin();
while (pFeaId != FeaIdVec.end() && pFea != FeaVec.end())
{
if (*pFeaId == pFea->iFeadId)
{
dProbLog += log (pFea->dProb + DBL_MIN);
pFeaId++;
pFea++;
}
else if (*pFeaId < pFea->iFeadId)
pFeaId++; // it's not a selected feature in Bayes model, skip it
else
{
// strictly speaking, we should do this in naive bayes:
// there are two value for a feature type: 1 and 0
// It is 1 when the feature occurs in input sample; otherwise, 0.
#if 1
dProbLog += log (1.0 - pFea->dProb + DBL_MIN);
#endif
pFea++;
}
}
return dProbLog;
}
关键的那个地方我用宏夹住了,并在代码里写了相对多的注释。想要变换算法的时候,随时禁止这个宏就行了。当然,更标准的做法是,起一个名字,在某个头文件里面定义这个宏的值是0还是1。不过,我就不搞那么“严肃”的了,毕竟这个东西代码量也不大,不至于那么难维护。
接下来,确定类别的代码:
bool NaiveBayes::PredictByInputFeas (vector<int> & FeaIdVec, int & iClassId)
{
if (FeaIdVec.empty())
return false;
int iClassNum = ClassFeaVec.size();
if (iClassNum <= 0)
return false;
vector<double> PredProbLogVec (iClassNum, 0.0); // the predicting probability for each class
for (int i=0; i<iClassNum; i++)
{
PredProbLogVec.at(i) = CalcProbLogByFeaVec (FeaIdVec, ClassFeaVec.at(i).FeaVec);
}
// select the class with max probability
double dMaxProbLog = -DBL_MAX;
for (int i=0; i<iClassNum; i++)
{
if (dMaxProbLog < PredProbLogVec.at(i))
{
dMaxProbLog = PredProbLogVec.at(i);
iClassId = ClassFeaVec.at(i).iClassId;
}
}
return true;
}
没啥可说的了。就朴素贝叶斯模型本身,还有一些代码,如:load模型,计算错误率等,都很简单,不罗列了。其实还有很大一部分代码,代码量可能更多,就是数据准备。尤其是分词,分词算法很多,不是这里的主题,以后有时间慢慢细说。还有停用词过滤,等等。呵呵。
【分类效果】
最后说一下我实际使用过程中的分类效果吧。前面的软文说过了,我要做的是文本过滤,也就是二值分类问题。正例样本比较多,反例样本比较少。整体上的错误率(误分率)大概9%;正例样本的误分率是7%,反例样本的误分率是15%。同时用了一下svm,结果svm效果远超过朴素贝叶斯。哎,这时候才体会到,知识就是生产力啊。不过朴素贝叶斯也不是没用了,svm只能处理小量的数据,而且并行化训练很困难。朴素贝叶斯在这些方面都是强项。
【后记】
其实还有些工作是可以做的,或者说有些问题是可以继续思考的。以上这些程序,其中一个缺点是就是模型训练算法与特征选择算法耦合的非常紧。这样做有好处,因为模型训练和特征选择都要对一些统计量进行计数,这种紧耦合的设计,能够在只扫描一遍样本集合的情况下完成任务,这对于大样本集合的问题来讲是比较有利的。但是缺点也很明显,就是耦合的太紧,不够灵活,如果想要换一个特征选择算法,就要直接改变Train函数的代码。如何解耦合?其实也简单,就是将训练过程和特征选择过程分开,分别放到两个类当中,再用聚合的方法将他们放在一起工作。特征选择类可以用工厂模式,来动态选择用哪个特征选择算法。选择的特征,可以用文本文件的形式暂时存储,供训练类读取使用。不过相应地,特征选择过程和训练过程也就分开了,也就是说要分别统计各自的统计量,也就是说至少扫描两遍样本集合。各有各自的优缺点,大家视自己的情况而定。
不说了。完。
分享到:
相关推荐
1、内容概要:本资源主要基朴素贝叶斯算法实现新闻分类,适用于初学者学习文本分类使用。 2、新闻分类源码实现过程:将数据集划分为训练集和测试集;使用jieba模块进行分词,词频统计,停用词过滤,文本特征提取,将...
基于朴素贝叶斯分类器的文本分类程序 python
朴素贝叶斯实战代码,含注释,分为两个模块,第一模型实现,第二进行文本分类。事实上利用的是词袋模型的朴素贝叶斯,也就是多项式事件模型。利用python3进行编程实现。
朴素贝叶斯分类器,使用MATLAB语言编写,对文档进行自动分类
这个主要是利用spark的api,朴素贝叶斯算法,来预测股票,其中包含的股票的原始数据和处理后适合spark api处理的训练模型
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法 。最为广泛的两种分类模型是决策树模型(Decision Tree Model)和朴素贝叶斯模型(Naive Bayesian Model,NBM)。和决策树模型相比,朴素贝叶斯分类器...
编写的关于三维点云的朴素贝叶斯分类,能够根据训练实例,分成不同类别,是一种监督分类
基于朴素贝叶斯方法的文本分类研究_姚严志.caj
朴素贝叶斯java代码参考朴素贝叶斯java代码参考
朴素贝叶斯伪代码,就是一般的伪代码,好好看看把
1、内容概要:本资源主要基朴素贝叶斯算法实现垃圾邮件过滤分类,适用于初学者学习文本分类使用。 2、主要内容:邮件数据集email,email文件夹下有两个文件夹ham和spam,其中ham文件夹下的txt文件为正常邮件,spam...
编写朴素贝叶斯分类器,对测试集进行分类预测,并计算分类精度
朴素贝叶斯算法,完成垃圾邮件分类。首先把每个邮件的单词抽取出来,组成单词表,放在列表中,去掉重复单词,然后将每个单词对应的标签放在另一个列表中,正例为1,反例为0。
用matlab实现的朴素贝叶斯分类器,比较简单,有助于理解朴素贝叶斯。代码直接可用。
朴素贝叶斯python版本,内容很详细,直接可用,可以从代码更容易理解朴素贝叶斯背后的原理。
java实现朴素贝叶斯分类算法
朴素贝叶斯算法实现分类以及matlab实现
能实现对相应数据集进行分类,并计算出准确率
朴素贝叶斯包含数据文档,朴素贝叶斯算法在文字识别, 图像识别方向有着较为重要的作用。 可以将未知的一种文字或图像,根据其已有的分类规则来进行分类,最终达到分类的目的。
实现朴素贝叶斯分类器算法基本功能,代码有注释,还包括一个垃圾邮件过滤的实例。另外我这次用的是python2.7版,如果用python3的可能需要根据提示修改几个语法(sorted函数的参数)。