当前位置:   article > 正文

基于pandas python sklearn 的美团某商家的评论分类(文本分类)

根据提供的data.csv附件,对外卖评论进行分类,2分类,正向负向,两种方式:sklearn调

基于pandas python sklearn 的美团某商家的评论分类(文本分类)

美团店铺评价语言处理以及分类(NLP)

  • 第一篇 数据分析部分
  • 第二篇 可视化部分,
  • 本文是该系列第三篇,文本分类
  • 主要用到的包有jieba,sklearn,pandas,本篇博文主要先用的是词袋模型(bag of words),将文本以数值特征向量的形式来表示(每个文档构建一个特征向量,有很多的0,出现在特征向量中的值也叫做原始词频,tf(term frequency), 得到的矩阵为稀疏矩阵)
  • 后续的算法模型会陆续进行构建
导入数据分析常用库
  1. import pandas as pd
  2. import numpy as np
  • 读取文件
  1. df=pd.read_excel("all_data_meituan.xlsx")[["comment","star"]]
  2. df.head()

9ebd4c2bgy1fu9bm7nc6tj20qm0bijtc.jpg

  • 查看DataFrame的大小
df.shape
(17400, 2)
  1. df['sentiment']=df['star'].apply(lambda x:1 if x>30 else 0)
  2. df=df.drop_duplicates() ## 去掉重复的评论,剩余的文本1406条,我们将数据复制为原有数据的三倍
  3. df=df.dropna()
  1. X=pd.concat([df[['comment']],df[['comment']],df[['comment']]])
  2. y=pd.concat([df.sentiment,df.sentiment,df.sentiment])
  3. X.columns=['comment']
  4. X.reset_index
  5. X.shape
(3138, 1)
  1. import jieba # 导入分词库
  2. def chinese_word_cut(mytext):
  3. return " ".join(jieba.cut(mytext))
  4. X['cut_comment']=X["comment"].apply(chinese_word_cut)
  5. X['cut_comment'].head()
  1. Building prefix dict from the default dictionary ...
  2. DEBUG:jieba:Building prefix dict from the default dictionary ...
  3. Loading model from cache C:\Users\HUANG_~1\AppData\Local\Temp\jieba.cache
  4. DEBUG:jieba:Loading model from cache C:\Users\HUANG_~1\AppData\Local\Temp\jieba.cache
  5. Loading model cost 0.880 seconds.
  6. DEBUG:jieba:Loading model cost 0.880 seconds.
  7. Prefix dict has been built succesfully.
  8. DEBUG:jieba:Prefix dict has been built succesfully.
  9. 0 还行 吧 , 建议 不要 排队 那个 烤鸭 和 羊肉串 , 因为 烤肉 时间 本来 就 不够...
  10. 1 去过 好 几次 了 东西 还是 老 样子 没 增添 什么 新花样 环境 倒 是 ...
  11. 2 一个 字 : 好 ! ! ! # 羊肉串 # # 五花肉 # # 牛舌 # ...
  12. 3 第一次 来 吃 , 之前 看过 好多 推荐 说 这个 好吃 , 真的 抱 了 好 大 希望 ...
  13. 4 羊肉串 真的 不太 好吃 , 那种 说 膻 不 膻 说 臭 不 臭 的 味 。 烤鸭 还 行...
  14. Name: cut_comment, dtype: object
  • 导入sklearn中的数据分割模块,设定test数据集大小,shuffle默认Ture
  1. from sklearn.model_selection import train_test_split
  2. X_train,X_test,y_train,y_test= train_test_split(X,y,random_state=42,test_size=0.25)
  • 获取停用词
  1. def get_custom_stopwords(stop_words_file):
  2. with open(stop_words_file,encoding="utf-8") as f:
  3. custom_stopwords_list=[i.strip() for i in f.readlines()]
  4. return custom_stopwords_list
  1. stop_words_file = "stopwords.txt"
  2. stopwords = get_custom_stopwords(stop_words_file) # 获取停用词
  • 导入词袋模型
  1. from sklearn.feature_extraction.text import CountVectorizer
  2. vect=CountVectorizer() # 实例化
  3. vect # 查看参数
  1. CountVectorizer(analyzer='word', binary=False, decode_error='strict',
  2. dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
  3. lowercase=True, max_df=1.0, max_features=None, min_df=1,
  4. ngram_range=(1, 1), preprocessor=None, stop_words=None,
  5. strip_accents=None, token_pattern='(?u)\\b\\w\\w+\\b',
  6. tokenizer=None, vocabulary=None)
# dir(vect)  # 查看vect的属性
  • 将分割后的文本进行fit_transform,系数矩阵大小为2353*1965
vect.fit_transform(X_train["cut_comment"])
  1. <2353x1965 sparse matrix of type '<class 'numpy.int64'>'
  2. with 20491 stored elements in Compressed Sparse Row format>
vect.fit_transform(X_train["cut_comment"]).toarray().shape
(2353, 1965)
  1. pd.DataFrame(vect.fit_transform(X_train["cut_comment"]).toarray(),columns=vect.get_feature_names()).iloc[:,0:25].head()
  2. # print(vect.get_feature_names())
  3. # 数据维数1956,不算很大(未使用停用词)
  4. # 将其转化为DataFrame
  • 发现其中有很多的数字以及无效特征,随后传入实例化参数的同时,加入正则匹配取出这些无意义特征,同时取出停用词
    9ebd4c2bgy1fu9c1rlvn1j20mo05c74b.jpg
  1. vect = CountVectorizer(token_pattern=u'(?u)\\b[^\\d\\W]\\w+\\b',stop_words=frozenset(stopwords)) # 去除停用词,匹配以数字开头的非单词字符
  2. pd.DataFrame(vect.fit_transform(X_train['cut_comment']).toarray(), columns=vect.get_feature_names()).head()
  3. # 1691 columns,去掉以数字为特征值的列,减少了近三百列,由1965减小到1691
  4. # max_df = 0.8 # 在超过这一比例的文档中出现的关键词(过于平凡),去除掉(可以自行设定)
  5. # min_df = 3 # 在低于这一数量的文档中出现的关键词(过于独特),去除掉。(可以自行设定)
  • 取出数字特征之后

9ebd4c2bgy1fu9c4y3h26j20u5057wem.jpg

模型构建
  • 从sklearn 朴素贝叶斯中导入多维贝叶斯
  • 朴素贝叶斯通常用来处理文本分类垃圾短信,速度飞快,效果一般都不会差很多
  • MultinomialNB类可以选择默认参数,如果模型预测能力不符合要求,可以适当调整
  1. from sklearn.naive_bayes import MultinomialNB
  2. nb=MultinomialNB()
  1. from sklearn.pipeline import make_pipeline # 导入make_pipeline方法
  2. pipe=make_pipeline(vect,nb)
  3. pipe.steps # 查看pipeline的步骤(与pipeline相似)
  1. [('countvectorizer',
  2. CountVectorizer(analyzer='word', binary=False, decode_error='strict',
  3. dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
  4. lowercase=True, max_df=1.0, max_features=None, min_df=1,
  5. ngram_range=(1, 1), preprocessor=None,
  6. stop_words=frozenset({'', '范围', '但愿', 'vs', '为', '过去', '集中', '这般', '孰知', '认为', '论', '36', '前后', '每年', '长期以来', 'our', '要不', '使用', '好象', 'such', '不但', '一下', 'how', '召开', '6', '全体', '严格', '除开', 'get', '可好', '毕竟', 'but', '如前所述', '满足', 'your', 'keeps', '只', '大抵', '己', 'concerning', "they're", '再则', '有意的'...'reasonably', '绝对', '咧', '除此以外', '50', '得了', 'seeming', '只是', '背靠背', '弗', 'need', '其', '第二', '再者说'}),
  7. strip_accents=None, token_pattern='(?u)\\b[^\\d\\W]\\w+\\b',
  8. tokenizer=None, vocabulary=None)),
  9. ('multinomialnb', MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True))]
pipe.fit(X_train.cut_comment, y_train)
  1. Pipeline(memory=None,
  2. steps=[('countvectorizer', CountVectorizer(analyzer='word', binary=False, decode_error='strict',
  3. dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
  4. lowercase=True, max_df=1.0, max_features=None, min_df=1,
  5. ngram_range=(1, 1), preprocessor=None,
  6. stop_words=...e, vocabulary=None)), ('multinomialnb', MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True))])
测试集预测结果
  1. y_pred = pipe.predict(X_test.cut_comment)
  2. # 对测试集进行预测(其中包括了转化以及预测)
  1. # 模型对于测试集的准确率
  2. from sklearn import metrics
  3. metrics.accuracy_score(y_test,y_pred)
0.82929936305732488
  1. # 模型对于测试集的混淆矩阵
  2. metrics.confusion_matrix(y_test,y_pred)
  3. # 测试集中的预测结果:真阳性474个,假阳性112个,假阴性22个,真阴性为177个
  1. array([[177, 112],
  2. [ 22, 474]], dtype=int64)
  1. def get_confusion_matrix(conf,clas):
  2. import matplotlib.pyplot as plt
  3. fig,ax=plt.subplots(figsize=(2.5,2.5))
  4. ax.matshow(conf,cmap=plt.cm.Blues,alpha=0.3)
  5. tick_marks = np.arange(len(clas))
  6. plt.xticks(tick_marks,clas, rotation=45)
  7. plt.yticks(tick_marks, clas)
  8. for i in range(conf.shape[0]):
  9. for j in range(conf.shape[1]):
  10. ax.text(x=i,y=j,s=conf[i,j],
  11. va='center',
  12. ha='center')
  13. plt.xlabel("predict_label")
  14. plt.ylabel("true label")
  1. conf=metrics.confusion_matrix(y_test,y_pred)
  2. class_names=np.array(['0','1'])
  3. get_confusion_matrix(np.array(conf),clas=class_names)
  4. plt.show()

9ebd4c2bgy1fu9l64amzrj208807vq2x.jpg

对整个数据集进行预测分类
y_pred_all = pipe.predict(X['cut_comment'])
  1. metrics.accuracy_score(y,y_pred_all)
  2. # 对于整个样本集的预测正确率,整个数据集的准确率高于测试集,说明有些过拟合
0.85659655831739967
  1. metrics.confusion_matrix(y,y_pred_all)
  2. # 真个数据集的混淆矩阵
  1. array([[ 801, 369],
  2. [ 81, 1887]], dtype=int64)
  1. y.value_counts()
  2. # 初始样本中 正类与负类的数量
  1. 1 1968
  2. 0 1170
  3. Name: sentiment, dtype: int64
  1. metrics.f1_score(y_true=y,y_pred=y_pred_all)
  2. # f1_score 评价模型对于真个数据集
0.89346590909090906
  1. metrics.recall_score(y, y_pred_all)
  2. # 检出率,也就是正类总样本检出的比例 真正/假阴+真正
0.95884146341463417
  1. metrics.precision_score(y, y_pred_all)
  2. # 准确率, 检测出的来正类中真正类的比例 真正/假阳+真正
0.83643617021276595
  1. print(metrics.classification_report(y, y_pred_all))
  2. # 分类报告
  1. precision recall f1-score support
  2. 0 0.91 0.68 0.78 1170
  3. 1 0.84 0.96 0.89 1968
  4. avg / total 0.86 0.86 0.85 3138

posted on 2018-08-14 22:34 多一点 阅读(...) 评论(...) 编辑 收藏

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/47180?site
推荐阅读
相关标签
  

闽ICP备14008679号