贝叶斯文本分类例子和原理

来源:互联网 发布:迷宫生成算法 编辑:程序博客网 时间:2024/04/28 19:47

   基本定义:

贝叶斯分类方法是一种基于统计的学习方法,利用概率统计进行学习分类,如预测一个数据对象属于某类的概率。主要算法有朴素贝叶斯分类算法,贝叶斯信念网络分类算法。

一个事物具有很多属性,把它的众多属性看作一个向量,即x=(x1,x2,x3,…,xn),用x这个向量来代表这个事物,x的集合记为X,称为属性集。类别也有很多种,用集合C={c1,c2,…cm}表示。一般XC的关系是不确定的,可以将XC看作是随机变量,P(C|X)称为C的后验概率,与之相对的,P(C)称为C的先验概率。

根据贝叶斯公式,后验概率P(C|X)=P(X|C)P(C)/P(X),但在比较不同C值的后验概率时,分母P(X)总是常数,忽略掉,后验概率P(C|X)=P(X|C)P(C),先验概率P(C)可以通过计算训练集中属于每一个类的训练样本所占的比例,容易估计,对类条件概率P(X|C)的估计,这里我只说朴素贝叶斯分类器方法,因为朴素贝叶斯假设事物属性之间相互条件独立,P(X|C)=∏P(xi|ci)。

文本分类过程

例如文档:Good good study Day day up可以用一个文本特征向量来表示,x=(Good, good, study, Day, day , up)

在文本分类中,假设我们有一个文档dX,类别c又称为标签。我们把一堆打了标签的文档集合作为训练样本,X×C。例如:={Beijing joins the World Trade Organization, China}对于这个只有一句话的文档,我们把它归类到 China,即打上china标签。

朴素贝叶斯分类器是一种有监督学习,常见有两种模型,多项式模型(Multinomial Model)即为词频型和伯努利模型(Bernoulli Model)即文档型。二者的计算粒度不一样,多项式模型以单词为粒度,伯努利模型以文件为粒度,因此二者的先验概率和类条件概率的计算方法都不同。

计算后验概率时,对于一个文档d多项式模型中,只有在d中出现过的单词,才会参与后验概率计算,伯努利模型中,没有在d中出现,但是在全局单词表中出现的单词,也会参与计算,不过是作为反方参与的。这里暂不考虑特征抽取、为避免消除测试文档时类条件概率中有为0现象而做的取对数等问题。

多项式模型

基本原理

在多项式模型中, 设某文档d=(t1,t2,…,tk)tk是该文档中出现过的单词,允许重复,则:

先验概率P(c)= c下单词总数/整个训练样本的单词总数

类条件概率P(tk|c)=(c下单词tk在各个文档中出现过的次数之和+1)/(c下单词总数+|V|)(采用了拉普拉斯平滑,吊塔取1)

V是训练样本的单词表(即抽取单词,单词出现多次,只算一个),|V|则表示训练样本包含多少种单词。 P(tk|c)可以看作是单词tk在证明d属于类c上提供了多大的证据,而P(c)则可以认为是类别c在整体上占多大比例(有多大可能性)

伯努利模型

   在多变量伯努利事件模型中文本向量是布尔权重,也就是说,如果特征词在文本中出现则权重为1,否则权重为0,而不考虑特征词出现的顺序,忽略特征在文本出现的次数。
        若特征在文本中出现,相乘的项是P(Tj|Ci),若不出现,相乘的项是1-P(Tj|Ci);
  P(Tj|Ci)的估计采用文档频次:
P(Tj|Ci)=特征tj在Ci类中出现的文本数量/Ci类的文本数量

程序例子

前期准备,训练集采用搜狗语料库提供的数据集合http://www.sogou.com/labs/dl/c.html,分词直接采用了中科院的分词库http://www.ictclas.org/ 具体怎么配置到vs2010,里面有个例子可以参考,主要是配置一些lib路径还有把相关配置文件放到运行目录

 分词

       
string Split::split(char * sentence){  string result;  char* sRst=0;  int nPaLen=strlen(sentence);  sRst=(char *)malloc(nPaLen*6);  ICTCLAS_ParagraphProcess(sentence,nPaLen,sRst,CODE_TYPE_UNKNOWN,1);//导入用户字典后分词处理  result=sRst;  free(sRst);  return result;}
       接着对词进行切割出词和词性,本文采用动词和名字作为特征词
void Split::toWord(string src,vector<Word> &words){int start=0;const char * match=" ";int end=0;int index=0;end=src.find(match,start+1);while(end>0&&end<=src.length()){string temp=src.substr(start,end-start);Word word;index=temp.find("/",0);word.word=temp.substr(0,index);word.word=trim(word.word);word.prop=temp.substr(index+1,temp.length()-index);if(IsGoodWord(word))words.push_back(word);start=end+1;end=src.find(match,start+1);}}

特征提取

     文本特征选择是根据某种原则从原始特征中选择部分最有区分类别能力的特征,即从一组特征中选取一些最有效的特征,以降低特征空间维数的过程。

本文采用tf-idf来提取特征,即每个类别提取前1000个词,建议保存到硬盘上。

在这里,我直接使用wordFre*docFre 作为特征词选取的标准,因为对于一个类,包含该词的文档数越多,该词就越有代表性。

从训练集中获取模型

1.    首先定义WordInfo类该类包含了文档数目和该词的数目,还有在哪篇文章包含了vector<pair<string,int>>来记录

2.    读取该类下的所有文章,对每一篇文章进行分词,统计每个单词的数目和文档频率,建议使用map来操作

  pair< map<string,int>::iterator,bool> ret =tf.insert(make_pair((*it_word).word,1)); if(!ret.second){  (ret.first->second)++; }

3.    计算单词的tf-idf,按大小进行排序,取前1000个作为该类的特征词

使用模型对未知文档进行分类

1.    输入文章,对文章进行分词,并统计词频

2.    计算x文章对于A类文章的后验概率,由于很小的概率相乘,会接近于0,于是对其取log,相加就是属于A的概率

如果Xi单词在A类的特征词上出现(建议使用map.find(string))


3.    比较每类的概率,最小的就是最接近

具体的代码在这里可以下载,写的不是很好,如有错误,请留言指出来。



0 0