此文旨在把trainNB0这个函数详细讲清楚。
def trainNB0(trainMatrix,trainCategory): numTrainDocs = len(trainMatrix) numWords = len(trainMatrix[0]) pAbusive = sum(trainCategory)/float(numTrainDocs) #? (以下两行)初始化概率 p0Num = zeros(numWords); p1Num = zeros(numWords) p0Denom = 0.0; p1Denom = 0.0 for i in range(numTrainDocs): if trainCategory[i] == 1: #?(以下两行)向量相加 p1Num += trainMatrix[i] p1Denom += sum(trainMatrix[i]) else: p0Num += trainMatrix[i] p0Denom += sum(trainMatrix[i]) p1Vect = p1Num/p1Denom #change to log() #? 对每个元素做除法 p0Vect = p0Num/p0Denom #change to log() return p0Vect,p1Vect,pAbusive
下面把这个函数逐步分解:
1.参数
此函数的参数有两个,一个是trainMatrix,另一个是trainCategory,这两个参数是一步一步的数据处理产生的结果,过程如下:
1.1第一步 创建实验样本
可能是为了简化操作,突出重点,作者在这里设置了手工设置类别,在应用场景中,应当是自动判断自动生成的。
listOPosts,listClasses = bayes.loadDataSet()
这一句产生了listOPosts和listClasses
详细内容分别是:
listOPosts:
[[‘my‘,‘dog‘,‘dog‘,‘has‘,‘flea‘,‘problems‘,‘help‘,‘please‘],
[‘maybe‘,‘not‘,‘take‘,‘him‘,‘to‘,‘dog‘,‘park‘,‘stupid‘],
[‘my‘,‘dalmation‘,‘is‘,‘so‘,‘cute‘,‘I‘,‘love‘,‘him‘],
[‘stop‘,‘posting‘,‘stupid‘,‘worthless‘,‘garbage‘],
[‘mr‘,‘licks‘,‘ate‘,‘my‘,‘steak‘,‘how‘,‘to‘,‘stop‘,‘him‘],
[‘quit‘,‘buying‘,‘worthless‘,‘dog‘,‘food‘,‘stupid‘]
]
listClasses:
[0,1,0,1,0,1]
其中的listOPosts即list Of Posts,文档列表,就是帖子列表、邮件列表等等。你可以认为列表中的一元素就是一个帖子或者回复,
在此例中一共6个文档、帖子、回复(以后统称文档)。
分别是:
[‘my‘,‘dog‘,‘dog‘,‘has‘,‘flea‘,‘problems‘,‘help‘,‘please‘]
[‘maybe‘,‘not‘,‘take‘,‘him‘,‘to‘,‘dog‘,‘park‘,‘stupid‘]
[‘my‘,‘dalmation‘,‘is‘,‘so‘,‘cute‘,‘I‘,‘love‘,‘him‘]
[‘stop‘,‘posting‘,‘stupid‘,‘worthless‘,‘garbage‘]
[‘mr‘,‘licks‘,‘ate‘,‘my‘,‘steak‘,‘how‘,‘to‘,‘stop‘,‘him‘]
[‘quit‘,‘buying‘,‘worthless‘,‘dog‘,‘food‘,‘stupid‘]
可以看到,2、4、6句标红部分,存在侮辱性词条,第1、3、5个句子,不存在侮辱性词条,所以,对应的类别标签设置为
listClasses = [0,1,0,1,0,1]
1.2第二步 创建包含所有不重复词条的集合(词汇表)
这一步是为了产生一个大而全的集合,这个集合包括了所有文档(即第一步产生的6个文档)中的词条,但每个词条都不重复。
#创建一个所有文档中的不重复单词列表 def createVocabList(dataSet): vocabSet = set([]) #创建一个空集 n = 0 for document in dataSet: vocabSet = vocabSet | set(document) #创建两个集合的并集 n += 1 # print(‘vocabSet:‘,n,vocabSet) # print(‘文档集合的总长度:‘,len(vocabSet)) a = list(vocabSet) a.sort()
return a
Python中的集合(set)具有消除重复元素的功能。
书中代码没有排序。为了看得更清楚,我加上了排序。
上述代码中的
vocabSet = vocabSet | set(document)
并集操作,相当于 += 操作
此函数的参数dataSet,即是上一步产生的listOPosts
调用方式:
myVocablList = createVocabList(listOfPosts)
运行结果是:
[‘I‘, ‘ate‘, ‘buying‘, ‘cute‘, ‘dalmation‘, ‘dog‘, ‘flea‘, ‘food‘, ‘garbage‘, ‘has‘, ‘help‘, ‘him‘, ‘how‘, ‘is‘, ‘licks‘, ‘love‘,
‘maybe‘, ‘mr‘, ‘my‘, ‘not‘, ‘park‘, ‘please‘, ‘posting‘, ‘problems‘, ‘quit‘, ‘so‘, ‘steak‘, ‘stop‘, ‘stupid‘, ‘take‘, ‘to‘, ‘worthless‘]
1.3第三步 文档向量
获得词汇表后,便可以使用函数setOfWords2Vec(),该函数的输入参数为词汇表及某个文档,输出的是文档向量,向量的每一元素为1或0,分别表示词汇表中的单词在输入文档中是否出现。
def setOfWords2Vec(vocabList, inputSet): returnVec = [0] * len(vocabList)
for word in inputSet: if word in vocabList: # print("word:",word) returnVec[vocabList.index(word)] = 1 else: print("the word:%s is not in my Vocabulary!" % word) return returnVec # 返回一个list
vocabList即上一步产生的词汇表,inputSet可以是任意一篇文档,此处为了简化操作,在6篇文档中选取。
调用方式:
listOfPosts,listClasses = loadDataSet() print(listOfPosts) myVocablList = createVocabList(listOfPosts) print(myVocablList) l = listOfPosts[0] l.append("中华人民共和国") l.append("kk") print("listOfPosts:", listOfPosts[0]) b = setOfWords2Vec(myVocablList, listOfPosts[0]) print(b)
得到:
[0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]