zoukankan      html  css  js  c++  java
  • 基于pandas python sklearn 的美团某商家的评论分类(文本分类)

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

    • 第一篇 数据分析部分
    • 第二篇 可视化部分,
    • 本文是该系列第三篇,文本分类
    • 主要用到的包有jieba,sklearn,pandas,本篇博文主要先用的是词袋模型(bag of words),将文本以数值特征向量的形式来表示(每个文档构建一个特征向量,有很多的0,出现在特征向量中的值也叫做原始词频,tf(term frequency), 得到的矩阵为稀疏矩阵)
    • 后续的算法模型会陆续进行构建

    导入数据分析常用库

    import pandas as pd
    import numpy as np
    
    • 读取文件
    df=pd.read_excel("all_data_meituan.xlsx")[["comment","star"]]
    df.head()
    

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

    模型构建

    • 从sklearn 朴素贝叶斯中导入多维贝叶斯
    • 朴素贝叶斯通常用来处理文本分类垃圾短信,速度飞快,效果一般都不会差很多
    • MultinomialNB类可以选择默认参数,如果模型预测能力不符合要求,可以适当调整
    from sklearn.naive_bayes import MultinomialNB
    nb=MultinomialNB()  
    
    from sklearn.pipeline import make_pipeline # 导入make_pipeline方法
    pipe=make_pipeline(vect,nb)
    pipe.steps #  查看pipeline的步骤(与pipeline相似)
    
    [('countvectorizer',
      CountVectorizer(analyzer='word', binary=False, decode_error='strict',
              dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
              lowercase=True, max_df=1.0, max_features=None, min_df=1,
              ngram_range=(1, 1), preprocessor=None,
              stop_words=frozenset({'', '范围', '但愿', 'vs', '为', '过去', '集中', '这般', '孰知', '认为', '论', '36', '前后', '每年', '长期以来', 'our', '要不', '使用', '好象', 'such', '不但', '一下', 'how', '召开', '6', '全体', '严格', '除开', 'get', '可好', '毕竟', 'but', '如前所述', '满足', 'your', 'keeps', '只', '大抵', '己', 'concerning', "they're", '再则', '有意的'...'reasonably', '绝对', '咧', '除此以外', '50', '得了', 'seeming', '只是', '背靠背', '弗', 'need', '其', '第二', '再者说'}),
              strip_accents=None, token_pattern='(?u)\b[^\d\W]\w+\b',
              tokenizer=None, vocabulary=None)),
     ('multinomialnb', MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True))]
    
    pipe.fit(X_train.cut_comment, y_train)
    
    Pipeline(memory=None,
         steps=[('countvectorizer', CountVectorizer(analyzer='word', binary=False, decode_error='strict',
            dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
            lowercase=True, max_df=1.0, max_features=None, min_df=1,
            ngram_range=(1, 1), preprocessor=None,
            stop_words=...e, vocabulary=None)), ('multinomialnb', MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True))])
    

    测试集预测结果

    y_pred = pipe.predict(X_test.cut_comment) 
    # 对测试集进行预测(其中包括了转化以及预测)
    
    # 模型对于测试集的准确率
    from sklearn import  metrics
    metrics.accuracy_score(y_test,y_pred)
    
    0.82929936305732488
    
    # 模型对于测试集的混淆矩阵
    metrics.confusion_matrix(y_test,y_pred)
    # 测试集中的预测结果:真阳性474个,假阳性112个,假阴性22个,真阴性为177个
    
    array([[177, 112],
           [ 22, 474]], dtype=int64)
    
    def get_confusion_matrix(conf,clas):
        import  matplotlib.pyplot as  plt
        fig,ax=plt.subplots(figsize=(2.5,2.5))
        ax.matshow(conf,cmap=plt.cm.Blues,alpha=0.3)
        tick_marks = np.arange(len(clas))
        plt.xticks(tick_marks,clas, rotation=45)
        plt.yticks(tick_marks, clas)
        for i in range(conf.shape[0]):
            for j in range(conf.shape[1]):
                ax.text(x=i,y=j,s=conf[i,j],
                       va='center',
                       ha='center')
        plt.xlabel("predict_label")
        plt.ylabel("true label")
    
    conf=metrics.confusion_matrix(y_test,y_pred)
    class_names=np.array(['0','1'])
    get_confusion_matrix(np.array(conf),clas=class_names)
    plt.show()
    
    

    对整个数据集进行预测分类

    y_pred_all = pipe.predict(X['cut_comment'])
    
    metrics.accuracy_score(y,y_pred_all)
    # 对于整个样本集的预测正确率,整个数据集的准确率高于测试集,说明有些过拟合
    
    
    0.85659655831739967
    
    metrics.confusion_matrix(y,y_pred_all)
    #  真个数据集的混淆矩阵
    
    array([[ 801,  369],
           [  81, 1887]], dtype=int64)
    
    y.value_counts()
    # 初始样本中 正类与负类的数量
    
    1    1968
    0    1170
    Name: sentiment, dtype: int64
    
    metrics.f1_score(y_true=y,y_pred=y_pred_all)
    # f1_score 评价模型对于真个数据集
    
    0.89346590909090906
    
    metrics.recall_score(y, y_pred_all)
    # 检出率,也就是正类总样本检出的比例   真正/假阴+真正
    
    0.95884146341463417
    
    metrics.precision_score(y, y_pred_all)
    #  准确率,  检测出的来正类中真正类的比例  真正/假阳+真正
    
    0.83643617021276595
    
    print(metrics.classification_report(y, y_pred_all))
    # 分类报告
    
                 precision    recall  f1-score   support
    
          0       0.91      0.68      0.78      1170
          1       0.84      0.96      0.89      1968
    
    avg / total       0.86      0.86      0.85      3138
  • 相关阅读:
    从Oracle提供两种cube产品说开
    Sql Server DWBI的几个学习资料
    Unload Oracle data into text file
    初学Java的几个tips
    我常用的Oracle知识点汇总
    benefits by using svn
    如何在windows上使用putty来显示远端linux的桌面
    building commercial website using Microsoft tech stack
    Understand Thread and Lock
    Update google calendar by sunbird
  • 原文地址:https://www.cnblogs.com/onemorepoint/p/9478429.html
Copyright © 2011-2022 走看看