负面微博的识别,实际上可以理解为是文本分类的问题,正面还是负面微博?贝叶斯是文本分类的常用算法,对于中文文本来说,分词也是必不可少的步骤。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')