【朴素贝叶斯】实战朴素贝叶斯_代码实现_预测
预测的程序就很简单了:1. 计算输入样本的特征向量与模型的特征向量的向量内积;2. 在多个类别中,选择概率最大的类别。不过,贝努利模型和多项式模型的区别也就在此,在1——对那些在输入样本中没有出现的特征类型,那些取值为0的特征类型,如何处理。从前说过,我写的是贝努利模型,所以,这些特征类型的条件概率也计算进去了。
计算向量内积的代码如下:
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 classfor (int i=0; i<iClassNum; i++){PredProbLogVec.at(i) = CalcProbLogByFeaVec (FeaIdVec, ClassFeaVec.at(i).FeaVec);}// select the class with max probabilitydouble 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函数的代码。如何解耦合?其实也简单,就是将训练过程和特征选择过程分开,分别放到两个类当中,再用聚合的方法将他们放在一起工作。特征选择类可以用工厂模式,来动态选择用哪个特征选择算法。选择的特征,可以用文本文件的形式暂时存储,供训练类读取使用。不过相应地,特征选择过程和训练过程也就分开了,也就是说要分别统计各自的统计量,也就是说至少扫描两遍样本集合。各有各自的优缺点,大家视自己的情况而定。
不说了。完。