Python与机器学习 贝叶斯算法

朴素贝叶斯分类时一种十分简单的分类算法,称其朴素是因为其思想基础的简单性,对文本分类而言,它认为词袋中的两两词之间的关系是相互独立的,即一个对象的特征向量中每个维度都是相互独立的。

Python与机器学习 贝叶斯算法

一、定义

(1)设x={a1,a2,…,am}为一个待分类项,而每个a为x的一个特征属性;
(2)有类别集合C={y1,y2,…,yn};
(3)计算P(y1|x),P(y2|x),…,P(yn|x);
(4)如果P(yk|x)=max{P(y1|x),P(y2|x),…,P(yn|x)},则x属于yk。

上述定义给出了对x样本进行分类的准则,分类的关键是计算各个条件概率。可以按以下步骤计算。
(1)找到一个已知分类的待分类项集合,也就是训练集;
(2)统计得到在各类别下各个特征属性的条件概率估计;
(3)如果各个特征属性是条件独立的(或者假设它们是相互独立的),则根据贝叶斯定义有如下推论:

二、分类流程

(1)训练数据生成训练样本集:TF-IDF
(2)对每个类别计算P(yi)
(3)对每个特征属性计算所有划分的条件概率
(4)对每个类别计算P(x|yi)P(yi)
(5)以(x|yi)P(yi)的最大项判断x的所属类别

三、算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def loadDataSet():
postingList=[['my','dog','has','flea','poblems','help','please'],['maybe','not','take','him','to','dog','park','stupid'],['my','dalmation','is','so','cute','I','love','him','my'],['stop','posting','stupid','worthless','garbage'],['mr','licks','ate','my','steak','how','to','stop','to','stop','him'],['quit','buying','worthles','dog','food','stupid']]
classVec=[0,1,0,1,0,1]
return postingList,classVec
#这里postingList,classVec分别为训练集和对应的分类


#编写一个bayes算法类,实现该算法
#默认构造方法
class NBayes(object):
def __init__(self):
self.vocabulary=[] #词典
self.idf=0 #词典的IDF权值向量
self.tf=0 #训练集中的权值矩阵
self.tdm=0 #P(x|yi)
self.Pcates={} #P(yi)是一个类别字典
self.lables=[] #对应每个文本的分类,是一个外部导入的列表
self.doclength=0 #训练集文本数
self.vocablen=0 #词典词长
self.testset=0 #测试集

#导入和训练集数据,生成算法必需的参数和数据结构
def train_set(self,trainset,classVec):
self.cate_prob(classVec) #计算每个分类在数据集中的概率P(yi)
self.doclength=len(trainset)
tempset=set()
[tempset.add(word) for doc i trainset for word in doc] #生成词典
self.vocabulary=list(tempset)
self.vocablen=len(self.vocabulary)
self.calc_wordfreq(trainset) #计算词频数据集
self.built_tdm() #按分类累计向量空间的每维值P(x|yi)

#cate_prob函数,计算在数据集中每个分类的概率P(yi)
def cate_prob(self,classVec):
self.lables=classVec
labletemps=set(self.lables) #全部分类
for labletemp in labletemps:
self.lables.count(labletemp)
self.Pcates[labletemp]=float(self.lables.count(labletemp))/float(len(self.lables))

#calc_wordfreq函数,生成普通的词频向量
def calc_wordfreq(self,trainset):
self.idf=np.zeros([1,self.vocablen])
self.tf=np.zeros(self.doclength,self.vocablen)
for indx in xrange(self.doclength):
for word in trainset[indx]:
self.tf[indx,self.vocabulary.index(word)]+=1
for signleword in set(trainset[indx]):
self.idf[0,self.vocabulary.index(signleword)]+=1

#built_tdm函数,按分类累计计算向量空间的每维值
def built_tdm(self):
self.tdm=np.zeros([len(self.Pcates),self.vocablen])
sumlist=np.zeros([len(self.Pcates),1]) #统计每个分类的总值
for indx in xrange(self.doclength):
#将同一类别的词向量空间值相加
self.tdm[self.lables[indx]]+=self.tf[indx]
#统计每个分类的总值,它为一个标量
sumlist[self.lables[indx]]=np.sum(self.tdm[self.lables[indx]])
self.tdm=self.tdm/sumlist

#map2vocab函数,将测试集映射到当前词典
def map2vovocab(self,testdata):
self.testdata=np.zeros([1,self.vocablen])
for word in testdata:
self.testdata[0,self.vocabulary.index(word)]+=1

#predict函数,预测分类结果,输出预测的分类类别
def predict(self,testdata):
if np.shape(testdata)[1]!=self.vocablen: #测试集长度与词典长度不相等,则退出
print "Error input"
exit(0)

predvalue=0 #初始化类别概率
predclass="" #初始化类别名称
for tdm_vect,keyclass in zip(self.tdm,self.Pcates):
temp=np.sum(testset*tdm_vect*self.Pcates[keyclass])
if temp>predvalue:
predvalue=temp
predclass=keyclass

return predclass
1