python调用sklearn模块实现朴素贝叶斯(NBC)——以新闻分类为例

程序简述

将9类新闻语料切割为训练集和数据集,对新闻进行分词、去停用词、句向量构建后,调用sklearn模块提供的朴素贝叶斯接口建模,对新闻分类,最终实现的接口为
输入:新闻字符串
输出:新闻分类

朴素贝叶斯分类(NBC)是以贝叶斯定理为基础并且假设特征条件之间相互独立的方法,先通过已给定的训练集,以特征词之间独立作为前提假设,学习从输入到输出的联合概率分布,再基于学习到的模型,输入X求出使得后验概率最大的输出Y。

数据集截图

图1,共9类新闻,每一类2000条数据

图2,中文停用词

程序/数据集下载

点击进入下载地址

核心代码解析

Module/BuildModel.py

读取数据后,语料保存在data变量中,首先对所有新闻利用jieba模块进行分词,然后过滤掉停用词

def clearpara(para):
    '''
    清理段落,分词,删除停用词
    '''
    words = jieba.cut(para)#分词
    #过滤
    words = [word for word in words if len(word)>1]
    words = [word for word in words if word not in stopWords]
    return words
print('正在对语料分词,请耐心...')
data['words'] = data['content'].apply(clearpara)

得到各条新闻词组后,需要构建新闻句向量,首先统计词频,在排序后,词典中保留前topWordNum个高频词

#词频统计,保留top N
print('正在进行词频统计')
items = data['words'].values.tolist()
words = []
for item in items:
    words.extend(item)
wordCount = pd.Series(words).value_counts()[0:topWordNum]
wordCount = wordCount.index.values.tolist()

现在词组可以根据词典构建句向量,即将各词转为数字表达,在这里只是简单的将1个词转为1个数字,但是效果也不错

def wordsToVec(words):
    '''
    将词组转为向量,此处向量的数为高频词出现次数
    '''
    vec = map(lambda word:words.count(word),wordCount)
    vec = list(vec)
    return vec
print('正在将词组转为句向量,请耐心...')
data['vec'] = data['words'].apply(wordsToVec)

分割数据为测试集和训练集,建模,sklearn模块有朴素贝叶斯模型接口

#数据集分割
xTrain,xTest,yTrain,yTest = train_test_split(data['vec'].tolist(),data['flag'].tolist(),test_size=testRate,random_state=seed)
#建模
model = MultinomialNB()
model.fit(xTrain,yTrain)
#预测
yPred = model.predict(xTest)
yTest = np.array(yTest)
yPred = np.array(yPred)
print('模型测试集准确率:%.2f'%accuracy_score(yTest,yPred))

Module/NewsPredict.py

这个函数整合了上述各步,最后调用训练好的模型,只需要输入新闻字符串,即可输出分类,效果如图4所示

def predict(para):
    '''
    输入文章,输出分类标签
    '''
    words = clearpara(para)#分词
    vec = wordsToVec(words)#句向量
    vec = np.array(vec)[np.newaxis,:]
    flagIndex = model.predict(vec)[0]
    flag = flags[flagIndex]
    return flag

接口调用、运行效果

Main.py

简单粗暴,封装的predict函数,输入为一条新闻字符串,输出为字符串的分类

# -*- coding: utf-8 -*-
from Module.NewsPredict import predict
#一则体育新闻
para = '明天凌晨,欧洲杯C组将展开第二轮的争夺。拥有意大利、法国、荷兰与罗马尼亚的C组在赛前就被认为是“死亡之组”,而首轮的结果也印证了这一点。意大利意外惨败给荷兰后,将在本轮对阵实力相对较弱的罗马尼亚,只有取胜蓝衣军团才能保留出线的希望。'
#预测分类
flag = predict(para)
print('该则新闻分类为%s\n'%flag)
print(para)

图3,这里输入为1条体育新闻,输出为sports分类

图4,在测试集的表现为79.3%的准确率,勉强合格

猜你喜欢

转载自www.cnblogs.com/boom-meal/p/12368496.html
今日推荐