基于朴素贝叶斯分类器的文本分类

一、什么是朴素贝叶斯

朴素贝叶斯:它是一系列以假设特征特征之间强独立下运用的贝叶斯定理为基础的简单概率分类器,它的核心思想就是,假设有一篇文章,它属于A类文章的概率为P(A)属于B类文章的概率为P(B),如果P(A)>P(B),则这篇文章属于A类,否则这篇文章属于B类。

优点:在数据较少的情况下仍然有效,可以处理多分类问题

缺点:对于输入数据的准备方式较为敏感

二、程序实现流程图

运行环境要求:jieba(安装方法:pip install jieba)+numpy


三、具体实现代码如下

#encoding:utf8
import jieba,numpy
import jieba.analyse
import math
import os

'''
使用jieba分词,采用TF-IDF算法来提取文档中的前10个关键词
'''
def extractWordsTop30(file_path):
    #读取文档中的所有内容
    contents = open(file_path,"rb").read()
    #对文档进行分词,获取文档的前10个关键词
    #wordsTop30 = jieba.analyse.extract_tags(contents,topK=30) TF-IDF算法提取关键词   allowPOS=('ns', 'n', 'vn', 'v')
    wordsTop30 = jieba.analyse.textrank(contents, topK=30, withWeight=False, allowPOS=('ns', 'n')) #textrank算法提取关键词
    return wordsTop30

'''
将所有文档的关键词,进行合并,去掉重复的关键词
'''
def mergeKeyWords(listKeyWords):
    allWords = set([])
    for words in listKeyWords:
        allWords = allWords | set(words)
    return list(allWords)

'''
将输入的关键词,转换为与所有词对应的一个词向量
'''
def setOfWords2Vec(allWords,inputWords):
    resultWords = [0] * len(allWords)
    for word in inputWords:
        if word in allWords:
            resultWords[allWords.index(word)] = 1
    return resultWords

'''
将输入的关键词,转换与所有词相对应的一个词袋
词袋模型与词向量模型的区别在于,词袋模型中的每个词可以出现多次
词向量模型中的词只能出现一次
'''
def bagOfwords2Vec(allWords,inputWords):
    resultWords = [0] * len(allWords)
    for word in inputWords:
        if word in allWords:
            resultWords[allWords.index(word)] += 1
    return resultWords

'''
朴素贝叶斯的训练函数
'''
def trainNB(trainMatrix,trainCategory):
    #计算出训练文档的个数
    numTrainDocs = len(trainMatrix)
    #计算总共词的个数
    numWords = len(trainMatrix[0])
    #计算属于1类的概率
    pCorrect = sum(trainCategory)/numTrainDocs

    print("sum(trainCategory):",sum(trainCategory))
    print("numTrainDocs:",numTrainDocs)

    p0Num = numpy.ones(numWords)
    p1Num = numpy.ones(numWords)
    p0Denom = 2.0
    p1Denom = 2.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
    p0Vect = p0Num / p0Denom
    return p0Vect,p1Vect,pCorrect

'''
分类器
vec2Classify:输入向量
'''
def ClassifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    p1 = sum(vec2Classify * p1Vec) + math.log(pClass1)
    p0 = sum(vec2Classify * p0Vec) + math.log(1-pClass1)
    if p1 > p0:
        return 1
    else:
        return 0

def test():
    docList = []
    classList = []
    cars = os.listdir("../C000007/")
    for file in cars:
        docList.append(extractWordsTop30("../C000007/"+file))
        classList.append(0)
        docList.append(extractWordsTop30("../C000008/" + file))
        classList.append(1)
    allWords = mergeKeyWords(docList)
    trainingSet = [x for x in range(598)]
    testSet = []
    import random
    for i in range(198):
        randIndex = int(random.uniform(0,len(trainingSet)))
        testSet.append(trainingSet[randIndex])
        del trainingSet[randIndex]
    trainMat = []
    trainClasses = []
    for docIndex in trainingSet:
        trainMat.append(setOfWords2Vec(allWords,docList[docIndex]))
        trainClasses.append(classList[docIndex])
    p0V,p1V,p = trainNB(trainMat,trainClasses)
    print("p:",p)
    errorCount = 0
    for docIndex in testSet:
        wordVector = setOfWords2Vec(allWords,docList[docIndex])
        if ClassifyNB(wordVector,p0V,p1V,p) != classList[docIndex]:
            errorCount += 1
    print("errorCount:",errorCount)
    print("len(testSet):",len(testSet))
    print("错误率:",errorCount/len(testSet))

if __name__=="__main__":
    test()
四、总结
在运行的时候会发现每次的运行结果的错误率不一样,原因在每一次的训练数据和测试数据都是从数据集中随机抽取的,所以每一次的运行结果会不一致,观察结果可以发现分类的效果并不是很理想,最好的错误率在10%左右,大的可能到50%。而且,在利用朴素贝叶斯进行分类文本的时候可以发现,如果我需要的分类文本既不属于1类也不属于0类的时候,分类器还是会把它分为属于1类或者是0类,这样显然是不合理的,为了避免这种情况的发生,我们可以多设置一种类别,但是对于这种类别的文档我们应该如何选择,这也是一个问题。整个项目我已经上传到了CSDN,下载地址 http://download.csdn.net/download/sinat_29957455/9956328,数据集采用的是搜狗的新闻词库,其中的C000007文件夹中的类别属于汽车,C000008属于财经。在使用TF-IDF算法和textrank算法分类的时候,对比结果发现textrank算法的准确率要高于TF-IDF算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

修炼之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值