负面微博的识别,实际上可以理解为是文本分类的问题,正面还是负面微博?贝叶斯是文本分类的常用算法,对于中文文本来说,分词也是必不可少的步骤。python可以非常方便的实现,以下是具体过程及代码。
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import unicode_literals
import pandas as pd
import numpy as np
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.cross_validation import cross_val_predict
from sklearn.metrics import classification_report
from sklearn.pipeline import Pipeline
from random import shuffle
from sklearn.externals import joblib
# 读取标记数据-----------
# 微博文本在weibo.xlsx文件中,一行一条微博。
# 字段content为微博内容文本,
# 字段isaction为微博标识,1为负面微博,否则为0
s1 = pd.read_excel('weibo.xlsx')
s1['isaction'] = s1['isaction'].fillna(0)
# 分类数量
# 查看微博类别分布,发现数据不平衡,负面微博占比不到1/10
print(s1.groupby('isaction').size())
# 不平衡数据过采样处理----------
# 处理不平衡数据,以提升模型质量
s1_1 = s1[s1['isaction'] == 1]
# 将正类复制扩大至4份,不宜过大,否则容易过拟合
for n in range(0, 3):
s1 = pd.concat([s1, s1_1], ignore_index=True)
# 打乱数据-------------
r = np.arange(0, s1.shape[0])
shuffle(r)
s1 = s1.iloc[r, :]
#分词,使用jieba分词----------
s1['class'] = s1['content'].apply(lambda x: " ".join(jieba.cut(x)))
#词袋-----------------------
# 首先统计词频,再进行Tf-idf转换,TfidfVectorizer()封装了这两步
vectorizer = TfidfVectorizer()
vec = vectorizer.fit(s1['class'])
t1 = vec.transform(s1['class'])
# 算法-------------------
# 朴素贝叶斯常见的有高斯贝叶斯、多项式贝叶斯、伯努利贝叶斯,这里显然多项式贝叶斯更合适
nb = MultinomialNB()
# 训练及评估------------
# 这里简化处理,仅通过5折交叉验证。
# 在数据量足够的情况下,还是建议将数据集分为训练集、验证集和测试集,仅在最后检验时使用测试集
# 调节算法的alpha值,并通过循环自动评估
for n in np.arange(0.1, 1.1, 0.1):
pre = cross_val_predict(
nb.set_params(alpha=n), t1.toarray(), s1['isaction'], cv=5, n_jobs=-1)
print(nb.alpha)
print(classification_report(s1['isaction'], pre))
# 生成最终模型管道-----------
# 经过验证,alpha=0.6时效果最好,用这个参数对全部数据进行训练,生成最终模型
nb = MultinomialNB(alpha=0.6)
nb.fit(t1.toarray(), s1['isaction'])
vec_nb = Pipeline([('vec', vec), ('nb', nb)])
# 保存模型管道,下次可以直接载入使用-------
joblib.dump(vec_nb, 'vec_nb.pkl')