from numpy import *
def loadDataSet():
# 词条切分后的文档集合,列表每一行代表一个文档
postingList = [['my', 'dog', 'has', 'flea', 'please'],
['not', 'take', 'him', 'to', 'dog', 'stupid'],
['my', 'is', 'cute', 'love', 'him'],
['stop', 'posting', 'stupid', 'worthless', 'garbage'],
['my', 'licks', 'my', 'to', 'stop', 'him'],
['quit', 'worthless', 'dog', 'stupid']]
# 由人工标注的每篇文档的类标签
classVec = [0, 1, 0, 1, 0, 1]
return postingList, classVec
# 统计所有文档中出现的词条列表
def createVocabList(dataSet):
# 新建一个存放词条的集合
vocabSet = set([])
# 遍历文档集合中的每一篇文档
for document in dataSet:
# 将文档列表转为集合的形式,保证每个词条的唯一性
# 然后与vocabSet取并集,向vocabSet中添加没有出现
# 的新的词条
vocabSet = vocabSet | set(document)
# 再将集合转化为列表,便于接下来的处理
return list(vocabSet)
# 根据词条列表中的词条是否在文档中出现(出现1,未出现0),将文档转化为词条向量
def setOfWords2Vec(vocabSet, inputSet):
# 新建一个长度为vocabSet的列表,并且各维度元素初始化为0
returnVec = [0] * len(vocabSet)
# 遍历文档中的每一个词条
for word in inputSet:
# 如果词条在词条列表中出现
if word in vocabSet:
# 通过列表获取当前word的索引(下标)
# 将词条向量中的对应下标的项由0改为1
returnVec[vocabSet.index(word)] += 1
else:
print('the word: %s is not in my vocabulary! ' % 'word')
# 返回inputet转化后的词条向量
return returnVec
# 训练算法,从词向量计算概率p(w0|ci)...及p(ci)
# @trainMatrix:由每篇文档的词条向量组成的文档矩阵
# @trainCategory:每篇文档的类标签组成的向量
def trainNB0(trainMatrix, trainCategory):
# 获取文档矩阵中文档的数目
numTrainDocs = len(trainMatrix) # 6
# 获取词条向量的长度
numWords = len(trainMatrix[0]) # 19
# 所有文档中属于类1所占的比例p(c=1)
pAbusive = sum(trainCategory) / float(numTrainDocs) # 3/6=0.5,先验
# 创建一个长度为词条向量等长的列表
p0Num = zeros(numWords)
p1Num = zeros(numWords)
p0Denom = 0.0
p1Denom = 0.0
# 遍历每一篇文档的词条向量
for i in range(numTrainDocs):
# 如果该词条向量对应的标签为1
if trainCategory[i] == 1:
# 统计所有类别为1的词条向量中各个词条出现的次数
p1Num += trainMatrix[i]
# 统计类别为1的词条向量中出现的所有词条的总数
# 即统计类1所有文档中出现单词的数目
p1Denom += sum(trainMatrix[i])
else:
# 统计所有类别为0的词条向量中各个词条出现的次数
p0Num += trainMatrix[i]
# 统计类别为0的词条向量中出现的所有词条的总数
# 即统计类0所有文档中出现单词的数目
p0Denom += sum(trainMatrix[i])
# 利用NumPy数组计算p(wi|c1)
p1Vect = p1Num / p1Denom # 为避免下溢出问题,后面会改为log()
# 利用NumPy数组计算p(wi|c0)
p0Vect = p0Num / p0Denom # 为避免下溢出问题,后面会改为log()
return p0Vect, p1Vect, pAbusive
# 朴素贝叶斯分类函数
# @vec2Classify:待测试分类的词条向量
# @p0Vec:类别0所有文档中各个词条出现的频数p(wi|c0)
# @p0Vec:类别1所有文档中各个词条出现的频数p(wi|c1)
# @pClass1:类别为1的文档占文档总数比例
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
# 根据朴素贝叶斯分类函数分别计算待分类文档属于类1和类0的概率
print(vec2Classify)
p1 = sum(vec2Classify * p1Vec) + log(pClass1)
p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
if p1 > p0:
return 1
else:
return 0
# 分类测试整体函数
# 由数据集获取文档矩阵和类标签向量
allfile, fileClasses = loadDataSet()
# 统计所有文档中出现的词条,存入词条列表
VocabSet = createVocabList(allfile)
# 创建新的列表
trainMat = []
for singlefile in allfile:
# 将每篇文档利用words2Vec函数转为词条向量,存入文档矩阵中
trainMat.append(setOfWords2Vec(VocabSet, singlefile))
# 将文档矩阵和类标签向量转为NumPy的数组形式,方便接下来的概率计算
# 调用训练函数,得到相应概率值
p0V, p1V, pAb = trainNB0(array(trainMat), array(fileClasses))
# 测试文档
testEntry = ['love', 'my', 'cute']
# 将测试文档转为词条向量,并转为NumPy数组的形式
thisDoc = array(setOfWords2Vec(VocabSet, testEntry))
# 利用贝叶斯分类函数对测试文档进行分类并打印
print(testEntry, 'classified as:', classifyNB(thisDoc, p0V, p1V, pAb))
# 第二个测试文档
testEntry1 = ['stupid', 'garbage']
# 同样转为词条向量,并转为NumPy数组的形式
thisDoc1 = array(setOfWords2Vec(VocabSet, testEntry1))
print(testEntry1, 'classified as:', classifyNB(thisDoc1, p0V, p1V, pAb))