使用朴素贝叶斯分类器,对一片文章进行分类处理


贝叶斯分类器的优缺点:

优点:

  • 速度相对较快,因为针对每个分类的特征词不会太多
  • 算法比较简单
  • 可以动态的添加训练数据集合
  • 分类的过程可以查看

缺点:

  • 无法处理基于特征组合所产生的变化结果

贝叶斯—文本分类的步骤:

  1. 对中文进行分词处理 —jieba分词
  2. 对分开的词语进行处理,去除重复词汇,去除标点和单个虚拟词汇如:你,我,他。。。
  3. 选择特征词,很重要,要总结出符合某一类型的关键特征词
  4. 对分类器进行训练,即传入一些已经分好类的文章,让分类器可以知道其中的一些特征词。
  5. 计算出特征词在各个分类中出现的概率。
  6. 为每个特征词设置权重值
  7. 计算整篇文档的概率,将每个特征值的概率相乘,即求出了在某一分类条件下,这篇文章出现的概率P(Document|Category)
  8. 根据P(Document|Category)应用贝叶斯定理求出P(Category|Document)
  9. 判定文章所属的分类

python代码实现

#-*_coding:utf8-*-
import jieba
from sqlite3 import dbapi2 as sqlite


#将传入文档分词,并去除重复和不必要的词汇。
def getwords(doc):
    doc1 = list(jieba.cut(doc))
    words = []
    for s in doc1:
        if(len("".join(s))>1):
            if(s not in words):
                words.append(s)
    return words


class classifier:
    def __init__(self, getfeatures, filename='test1.db'):
        #记录位于各分类中不同特征值的数量
        self.fc = {}
        #统计每个分类中的文档数量(即各分类被使用的次数)
        self.cc = {}
        #从即将被归类的内容项中提取特征出来
        self.getfeatures = getfeatures
        #链接数据库
        self.con = sqlite.connect(filename)
        self.con.execute('create table if not exists fc(feature,category,count)')
        self.con.execute('create table if not exists cc(category,count)')


    #增加对特征/分类组合的计数值
    def incf(self,f,cat):
        count = self.fcount(f,cat)
        if(count==0):
            self.con.execute("insert into fc values ('%s','%s',1)" % (f,cat))
        else:
            self.con.execute("update fc set count=%d where feature='%s' and category='%s'" % (count+1,f,cat))

    #增加对某一分类的技术值
    def incc(self,cat):
        count = self.catcount(cat)
        if(count==0):
            self.con.execute("insert into cc values ('%s',1)" % (cat))
        else:
            self.con.execute("update cc set count=%d where category='%s'" % (count+1,cat))

    #某一特征出现于某一分类的的次数
    def fcount(self,f,cat):
        res = self.con.execute("select count from fc where feature='%s' and category='%s'" % (f,cat)).fetchone()
        if(res==None):return 0
        else: return float(res[0])

    #某一种分类的内容项数量
    def catcount(self,cat):
        res = self.con.execute("select count from cc where category='%s'" % (cat)).fetchone()
        if(res==None):return 0
        else:return float(res[0])

    #所有内容向的数量
    def totalcount(self):
        res = self.con.execute("select sum(count) from cc").fetchone()
        if(res==None):return 0
        return res[0]

    #所有分类的列表
    def categories(self):
        cur = self.con.execute("select category from cc")
        return [d[0] for d in cur]

    #训练
    def train(self,item,cat):
        features=self.getfeatures(item)
        #针对该分类为每一个特征增加计数值
        for f in features:
            self.incf(f,cat)
        #增加针对该分类的计数值
        self.incc(cat)
        #向数据库提交数据
        self.con.commit()

    #计算概率
    def fprob(self,f,cat):
        if self.catcount(cat)==0: return 0
        #特征在分类总出现的总次数,除以分类中包含内容项的总数
        return self.fcount(f,cat)/self.catcount(cat)

    #加入概率的权重值
    def weightedprob(self,f,cat,prf,weight=1.0,ap=0.5):
        #计算当前的概率值
        basicprob=prf(f,cat)
        #统计特征在所有分类中出现的次数
        totals = sum([self.fcount(f,c) for c in self.categories()])
        # print("所有次数:")
        # print(totals)
        #计算加权平均
        bp = ((weight*ap)+(totals*basicprob))/(weight+totals)
        return bp

    #最终的分类方法
    def classify(self,item,default=None):
        probs={}
        #寻找概率最大的分类
        max=0.0
        for cat in self.categories():
            probs[cat] = self.prob(item,cat)
            if probs[cat] > max:
                max = probs[cat]
                best = cat
        return best




#新建一个classifier的子类
class naivebayes(classifier):
    #提取特征词,并将所有单词的概率相乘,以求出整体的概率。P(Document|Category)
    def docprob(self,item,cat):
        features = self.getfeatures(item)
        #将所有的特征概率相乘
        p=1
        for f in features:p *= self.weightedprob(f,cat,self.fprob)
        return p

    #已知P(Document|Category)应用贝叶斯定理求出P(Category|Document)
    def prob(self,item,cat):
        catprob=self.catcount(cat)/self.totalcount()
        docprob = self.docprob(item,cat)
        return docprob * catprob

调用方法:

import docClass
    cl = docClass.naivebayes(docClass.getwords)
    cl.train('训练的文章1')
    cl.train('训练的文章2')
    cl.train('...')
    cl.train('训练的文章n')
    print(cl.classify('待分类的文章', default='unknow'))

ok,以上的代码就实现了贝叶斯的分类器,代码中用到了jieba分词模块,sqlite嵌入式数据库。