程序简述
将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%的准确率,勉强合格