贝叶斯用于文档分类

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))


 

你可能感兴趣的:(机器学习)