使用朴素贝叶斯分类器,对一片文章进行分类处理
贝叶斯分类器的优缺点:
优点:
- 速度相对较快,因为针对每个分类的特征词不会太多
- 算法比较简单
- 可以动态的添加训练数据集合
- 分类的过程可以查看
缺点:
- 无法处理基于特征组合所产生的变化结果
贝叶斯—文本分类的步骤:
- 对中文进行分词处理 —jieba分词
- 对分开的词语进行处理,去除重复词汇,去除标点和单个虚拟词汇如:你,我,他。。。
- 选择特征词,很重要,要总结出符合某一类型的关键特征词
- 对分类器进行训练,即传入一些已经分好类的文章,让分类器可以知道其中的一些特征词。
- 计算出特征词在各个分类中出现的概率。
- 为每个特征词设置权重值
- 计算整篇文档的概率,将每个特征值的概率相乘,即求出了在某一分类条件下,这篇文章出现的概率P(Document|Category)
- 根据P(Document|Category)应用贝叶斯定理求出P(Category|Document)
- 判定文章所属的分类
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嵌入式数据库。