• 端到端机器学习项目:评论分类


    作者|Kiprono Elijah Koech
    编译|VK
    来源|Towards Data Science

    在本文中,我们将讨论一个分类问题,该问题涉及到将评论分为正面或负面。这里使用的评论是客户在ABC服务上所做的评论。

    数据收集和预处理

    在这个项目中使用的数据是从网上爬来的,数据清理在这个Notebook上完成:https://github.com/kipronokoech/Reviews-Classification/blob/master/data_collection.ipynb

    在我们抓取数据后被保存到一个.txt文件中,下面是一行文件的例子(代表一个数据点)

    {'socialShareUrl': 'https://www.abc.com/reviews/5ed0251025e5d20a88a2057d', 'businessUnitId': '5090eace00006400051ded85', 'businessUnitDisplayName': 'ABC', 'consumerId': '5ed0250fdfdf8632f9ee7ab6', 'consumerName': 'May', 'reviewId': '5ed0251025e5d20a88a2057d', 'reviewHeader': 'Wow - Great Service', 'reviewBody': 'Wow. Great Service with no issues.  Money was available same day in no time.', 'stars': 5}
    

    数据点是一个字典,我们对reviewBody和stars感兴趣。

    我们将把评论分类如下

    1 and 2 - Negative
    3 - Neutral
    4 and 5 - Positive
    

    在收集数据时,网站上有36456条评论。数据高度不平衡:94%的评论是正面的,4%是负面的,2%是中性的。在这个项目中,我们将在不平衡的数据和平衡的数据上拟合不同的Sklearn模型(我们去掉一些正面评论,这样我们就有相同数量的正面和负面评论。)

    下图显示了数据的组成:

    在上图中,我们可以看到数据是高度不平衡的。

    让我们从导入必要的包开始,并定义将用于对给定的评论进行分类的类Review

    #导入包
    import numpy as np
    import random
    import matplotlib.pyplot as plt
    from sklearn.model_selection import train_test_split
    from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
    from sklearn.metrics import f1_score #f1分数,一种评价指标
    import ast #将字符串转换为字典
    from IPython.display import clear_output
    from sklearn import svm #支持向量机分类器
    from sklearn.metrics import confusion_matrix
    from sklearn.linear_model import LogisticRegression #导入 logistic regression
    from sklearn.tree import DecisionTreeClassifier #导入 Decision tree
    from sklearn.naive_bayes import GaussianNB
    from sklearn.ensemble import RandomForestClassifier
    import pandas as pd
    import seaborn as sb
    
    
    # 将评论分为正面、负面或中性
    class Review:
        def __init__(self, text, score):
            self.text = text
            self.score = score
            self.sentiment = self.get_sentiment()
            
        def get_sentiment(self):
            if self.score <= 2:
                return "NEGATIVE"
            elif self.score == 3: 
                return "NEUTRAL"
            else: #4或5分
                return "POSITIVE"
    

    在这里,我们将加载数据并使用Review类将评论分类为正面、反面或中性

    # 大部分清理是在数据web爬取期间完成的
    # Notebook 链接
    # https://github.com/kipronokoech/Reviews-Classification/blob/master/data_collection.ipynb
    reviews = []
    with open("./data/reviews.txt") as fp:
        for index,line in enumerate(fp):
            # 转换为字典
            review = ast.literal_eval(line)
            #对评论进行分类并将其附加到reviews中
            reviews.append(Review(review['reviewBody'], review['stars']))
           
    # 打印出reviews[0]的情绪类别和文本
    print(reviews[0].text)
    print(reviews[0].sentiment)
    
    Wow. Great Service with no issues.  Money was available same day in no time.
    
    POSITIVE
    

    将数据拆分为训练集和测试集

    # 70%用于训练,30%用于测试
    training, test = train_test_split(reviews, test_size=0.30, random_state=42)
    
    # 定义X和Y
    train_x,train_y = [x.text for x in training],[x.sentiment for x in training]
    test_x,test_y = [x.text for x in test],[x.sentiment for x in test]
    
    print("Size of train set: ",len(training))
    print("Size of train set: ",len(test))
    
    Size of train set:  25519
    Size of train set:  10937
    

    在我们继续下一步之前,我们需要理解词袋的概念。

    词袋

    正如我们所知,一台计算机只理解数字,因此我们需要使用词袋模型将我们收到的评论信息转换成一个数字列表。

    词袋是一种文本表示形式。它包括两个方面:已知单词的词汇与已知单词存在程度的度量。

    词袋模型是一种用于文档分类的支持模型,其中每个词的出现频率作为训练分类器的特征。

    例子:

    考虑这两个评论

    • Excellent Services by the ABC remit team.Recommend.
    • Bad Services. Transaction delayed for three days.Don’t recommend.

    从以上两句话中,我们可以得出以下词典

    [Excellent, Services, by, the, ABC, remit, team, recommend, bad, transaction, delayed, for, three, days, don’t]

    我们现在将这个字典标记化以生成以下两个数据点,这些数据点现在可以用来训练分类器

    在python中,标记化的实现如下

    # 导入用于向量化的库
    from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
    
    # sklearn上的向量化——简单的例子
    corpus = [
        "Excellent Services by the ABC remit team.Recommend.",
        "Bad Services. Transaction delayed for three days.Don't recommend."]
    vectorizer = CountVectorizer()
    X = vectorizer.fit_transform(corpus)
    #print(X) #这是一个矩阵
    print(vectorizer.get_feature_names()) # 字典
    print(X.toarray())#显然是一个矩阵,每一行都是每个句子的标记值
    
    ['abc', 'bad', 'by', 'days', 'delayed', 'don', 'excellent', 'for', 'recommend', 'remit', 'services', 'team', 'the', 'three', 'transaction']
    [[1 0 1 0 0 0 1 0 1 1 1 1 1 0 0]
     [0 1 0 1 1 1 0 1 1 0 1 0 0 1 1]]
    

    现在我们已经理解了词袋的概念,现在让我们将这些知识应用到我们的训练和测试中

    vectorizer = TfidfVectorizer()
    train_x_vectors = vectorizer.fit_transform(train_x)
    test_x_vectors = vectorizer.transform(test_x)
    

    在不平衡数据中训练模型

    现在,我们拥有了向量,我们可以用来拟合模型,我们可以这样做

    支持向量机

    #训练支持向量机分类器
    clf_svm = svm.SVC(kernel='linear')
    
    clf_svm.fit(train_x_vectors, train_y)
    #基于SVM的随机预测
    
    i = np.random.randint(0,len(test_x))
    print("Review Message: ",test_x[i])
    print("Actual: ",test_y[i])
    print("Prediction: ",clf_svm.predict(test_x_vectors[i]))
    
    #支持向量机的混淆矩阵——你可以有其他分类器的混淆矩阵
    labels = ["NEGATIVE","NEUTRAL","POSITIVE"]
    pred_svm = clf_svm.predict(test_x_vectors)
    cm =confusion_matrix(test_y,pred_svm)
    
    df_cm = pd.DataFrame(cm, index=labels, columns=labels)
    
    sb.heatmap(df_cm, annot=True, fmt='d')
    plt.title("Confusion matrix from SVM [Imbalanced]")
    plt.savefig("./plots/confusion.png")
    
    Review Message:  easy efficient  first class
    Actual:  POSITIVE
    Prediction:  ['POSITIVE']
    

    训练的其他模型包括随机森林、朴素贝叶斯、决策树和Logistic回归。

    完整代码的链接:https://github.com/kipronokoech/Reviews-Classification

    基于不平衡数据的模型性能评估

    1. 准确度

    利用准确度对模型进行了评估,结果如下

    我们得到了90%的准确率,是正确还是有问题?答案是,出了点问题。

    数据是不平衡的,使用准确度作为评估指标不是一个好主意。以下是各类别的分布情况

    ----------TRAIN SET ---------------
    Positive reviews on train set: 23961 (93.89%)
    Negative reviews on train set: 1055 (4.13%)
    Neutral reviews on train set: 503 (1.97%)
    
    ----------TEST SET ---------------
    Positive reviews on test set: 10225 (93.48%)
    Negative reviews on test set: 499 (4.56%)
    Neutral reviews on test set: 213 (1.95%)
    

    如果分类器正确地预测了测试集中所有的正面评价,而没有预测到负面和中性评论,会发生什么?该分类器的准确率可达93.48%!!!!!!

    这意味着我们的模型将是93.48%的准确率,我们会认为模型是好的,但实际上,模型“只知道”如何预测一类(正面评价)。事实上,根据我们的结果,我们的支持向量机预测根本没有中性评论

    为了进一步理解这个问题,让我们引入另一个指标:F1分数,并用它来评估我们的模型。

    1. F1分数

    F1分数是精确和召回率的调和平均值。

    精确性和召回率衡量模型正确区分正面案例和负面案例的程度。

    当我们根据这个指标评估我们的模型时,结果如下

    从图中,我们现在知道这些模型在对正面评论进行分类时非常好,而在预测负面评论和中性评论方面则很差。

    使用平衡数据

    作为平衡数据的一种方法,我们决定随机删除一些正面评论,以便我们在训练模型时使用均匀分布的评论。这一次,我们正在训练1055个正面评论和1055个负面评论的模型。我们放弃中性评论。

    (你也可以考虑使用过采样技术来解决数据不平衡的问题)

    在训练了模型之后,我们得到了以下结果

    支持向量机的最佳结果是88.9%的准确率,在检查F1分数(如下)后,我们现在可以意识到模型预测负面评价和正面评价一样好。

    如果我们看一下显示支持向量机结果的混淆矩阵,我们会注意到该模型在预测两个类方面都很好

    在这里找到完整的代码:https://github.com/kipronokoech/Reviews-Classification

    结论

    在完成这个项目后,我希望你能够了解到:

    1. 在不平衡的数据上拟合一个或多个模型可能(在大多数情况下确实如此)会导致不良结果。

    2. 在处理不平衡数据时,准确度不是一个好的衡量标准。

    3. 大部分工作是在预处理阶段完成的。

    感谢阅读

    原文链接:https://towardsdatascience.com/end-to-end-machine-learning-project-reviews-classification-60666d90ec19

    欢迎关注磐创AI博客站:
    http://panchuang.net/

    sklearn机器学习中文官方文档:
    http://sklearn123.com/

    欢迎关注磐创博客资源汇总站:
    http://docs.panchuang.net/

  • 相关阅读:
    领域驱动模型DDD(二)——领域事件的订阅/发布实践
    领域驱动模型DDD(一)——服务拆分策略
    js创建对象的多种方式
    java.net.SocketException: Connection reset 异常处理
    hive从入门到放弃(四)——分区与分桶
    《前端运维》五、k8s3灰度发布、滚动更新与探针
    《前端运维》五、k8s2pod、services与Ingress部署
    《前端运维》三、Docker2其他
    《前端运维》三、Docker1镜像与容器
    《前端运维》二、Nginx3静态资源服务、跨域与其他
  • 原文地址:https://www.cnblogs.com/panchuangai/p/13893562.html
Copyright © 2020-2023  润新知