【课程总结】Day6(上):机器学习项目实战--外卖点评情感分析预测

机器学习项目实战:外卖点评情感分析预测

项目目的

基于中文外卖评论数据集,通过机器学习算法,对评论内容进行情感预测。

数据集

  • 地址:http://idatascience.cn/dataset-detail?table_id=429
  • 数据集字段
字段名称字段类型字段说明
label整型情感标签(1为正面,0为负面)。
review字符型评论内容。
  • 数据集样例:

    labelreview
    1很快,好吃,味道足,量大
    1没有送水没有送水没有送水
    1非常快,态度好。
    1方便,快捷,味道可口,快递给力
    1菜味道很棒!送餐很及时!
    1今天师傅是不是手抖了,微辣格外辣!
    1送餐快,态度也特别好,辛苦啦谢谢
    1超级快就送到了,这么冷的天气骑士们辛苦了。谢谢你们。麻辣香锅依然很好吃。
    1经过上次晚了2小时,这次超级快,20分钟就送到了……
    1最后五分钟订的,卖家特别好接单了,谢谢。

解决思路

《【课程总结】Day1:人工智能的核心概念》一文中,初步梳理过人工智能的开展流程,在本次实战项目中,我们将结合实战深入理解项目流程。

分析输入/输出

通过分析,本次项目我们要解决的问题:给定一段中文评论,判断其是正面评论还是负面评论。

该问题是一个典型的分类问题,分析相关输入/输出如下:

  • 输入:一段中文评论
  • 输出:1为正面,0为负面
构建数据集
机器学习数据集特点

一般来说,机器学习的特征数据具有以下特点:

  • 特征与特征之间相互独立
  • 数据集是一个表格类数据
  • 数据成行成列
  • 一行一个样本,一列一个特征

通过分析上述的数据集,可以看到该数据集基本满足上述特点,但是仍然存在一个比较大的问题:数据集是汉字,机器无法处理(因为机器学习底层是对数字的处理),所以我们首先需要对数据数字化(也叫汉字向量化)。

汉字向量化

在机器学习中,汉字向量化是将汉字表示为计算机可识别的数值形式的过程。常用的方法有:

  • One-Hot 编码

    这是传统机器学习中常用的一种向量化方法。在这种方法中,每个汉字被表示为一个固定长度的向量,向量的大小等于字典的大小,每个条目对应于预定义单词字典中的一个单词,其中只有一个位置是1,其余为0。

  • 词袋模型

    在词袋模型中,文本中的每个汉字被看作是独立的,没有关联性,然后根据字典统计单词出现的频数。这种方法虽然简单,但在文本向量化中具有一定的实用性。

以词袋模型为例:

如果将文本"方便,快捷,味道可口,快递给力"以字为单位进行切分,并使用词袋模型进行向量化,向量化过程如下:

  1. 构建字汇表:首先,将文本中的所有不重复的字作为字汇表。在这个例子中,字汇表为[“方”, “便”, “,”, “快”, “捷”, “味”, “道”, “可”, “口”, “快”, “递”, “给”, “力”]。

  2. 向量化过程:对于每个文本,统计字汇表中每个字在文本中出现的次数,形成一个向量表示。

在这个例子中,"方便,快捷,味道可口,快递给力"的向量表示如下:

"方"出现1次
"便"出现1次
","出现3次
"快"出现2次
"捷"出现1次
"味"出现1次
"道"出现1次
"可"出现1次
"口"出现1次
"递"出现1次
"给"出现1次
"力"出现1次
因此,根据字汇表的顺序,该文本的词袋模型向量化结果为:
1,1,3,2,1,1,1,1,1,1,1,1

代码实现
  • 第一步:读取csv文件

    import csv
    import numpy as np
    def read_file(file_path, skip_header=True):
        """
        读取CSV文件的内容。
        参数:
            file_path (str): CSV文件的路径。
            skip_header (bool): 是否跳过表头数据,默认为True。
        返回:
            list: 包含CSV文件内容的列表。
        """
        print(f'读取原始数据集文件: {file_path}')
        with open(file_path, 'r', encoding='utf-8') as f:
            if skip_header:
                # 跳过表头数据
                f.readline()
            reader = csv.reader(f)
            return [row for row in reader]  # 读取csv文件的内容
    
    read_file("./中文外卖评论数据集.csv")
    
  • 第二步:切分标签和数据

    def split_data(data):
        """
        将数据分割为标签和数据。
        参数:
            data (list): 数据行的列表,第一个元素是标签。
        返回:
            numpy.ndarray: 标签数组。
            numpy.ndarray: 连接元素后的数据数组。
        """
        label = [row[0] for row in data]
        data = [','.join(row[1:]) for row in data]
    
        # 转换为numpy数组
        n_label = np.array(label)
        n_data = np.array(data)
    
        return n_label, n_data
    
    listdata = read_file('./中文外卖评论数据集.csv')
    label, data = split_data(listdata)
    print(label)
    print(data)
    
  • 第三步:对汉字进行向量化处理

    
    def load_stop_words(file_path):
        """
        读取停用词文件。
        参数:
            file_path (str): 停用词文件的路径。
        返回:
            list: 包含停用词的列表。
        """
        print(f'读取停用词文件: {file_path}')
        # 从csv文件中读取停用词
        stopwords = []
        with open(file_path, 'r', encoding='utf-8') as f:
            # 跳过第一行表头
            f.readline()
            reader = csv.reader(f)
            for row in reader:
                stopwords.append(row[0])
        return stopwords
    
    def text_to_vector(data, stopwords=None):
        """
        将数据中的汉字向量化。
        参数:
            data (numpy.ndarray): 包含汉字的数组。
            stopwords (list): 包含停用词的列表。
        返回:
            list: 使用词袋模型向量化的数据。
        """
    
        print('开始数据集汉字的向量化处理')
        # 逐个汉字进行分词
        vector = []
        for review in data:
            words = []
            for word in review:
                if word not in stopwords:
                    words.append(word)
            vector.append(words)
    
        # 词袋模型的向量化
        # 举个例子,假设有以下数据:
        # 词汇表: {方, 便, 快, 捷, 味, 道, 可, 口, 递, 给, 力}
        # 初始向量: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        # 向量化过程:
        # 第一次: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]  # '方'出现1次
        # 第二次: [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]  # '快'出现1次
        # 第三次: [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]  # '味'出现1次
        # 第四次: [1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0]  # '可', '口'各出现1次
    
        # 第一步:构建词汇表
        vocab = set([word for sublist in vector for word in sublist])
        vectorized_data = []
    
        # 第二步:遍历字的内容
        for words in vector:
            # 第三步:生成一个长度为len(vocab),内容都为0的向量
            bow_vector = [0] * len(vocab)
            # 第四步:找到词语在词汇表中的索引,然后在对应的位置上加1
            for word in words:
                if word in vocab:
                    index = list(vocab).index(word)
                    bow_vector[index] += 1
            vectorized_data.append(bow_vector)
    
        return vectorized_data
    
    
  • 第四步:保存向量数据到本地文件

    
    def process_data(label, vector, file_path_save):
        """
        处理数据的函数,包括读取文件、切分数据、向量化和保存向量化后的数据到新文件中。
        参数:
            label (numpy.ndarray): 标签数组。
            vector (list): 向量化数据。
            file_path_save (str): 向量化数据保存的路径。
        """
    
        print(f'向量化处理完毕,保存至: {file_path_save}')
        # 将向量化的数据保存到新文件中
        with open(file_path_save, 'w', encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerow(['label'] + ['x' + str(i) for i in range(len(vector[0]))])
            for i in range(len(label)):
                writer.writerow([label[i]] + vector[i])
    process_data(label, vector, 'vectorized_data.csv')
    

    至此,数据的预处理已经完成,处理后的数据保存在vectorized_data.csv文件,其内容如下:


- label为标签

- x0~xn为特征数据
遴选算法

为了跑通逻辑,我们先选择决策树来验证上述数据集是否可用。

from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier


def decision_tree(train_data_file_path='vectorized_data.csv', test_size=0.2):
    """
    决策树模型的训练和评估。
    参数:
        train_data_file_path (str): 向量化数据的文件路径。
        test_size (float): 测试集的比例,默认为0.2。
    """
    print('开始加载训练数据...')
    # 读取文件
    with open(train_data_file_path, 'r', encoding='utf-8') as f:
        reader = csv.reader(f)
        data = [row for row in reader]

    # 数据切分
    label = [row[0] for row in data[1:]]
    vector = [row[1:] for row in data[1:]]

    # 训练集和测试集切分
    X_train, X_test, y_train, y_test = train_test_split(vector, label, test_size=0.2)

    print('开始训练决策树模型...')
    # 数据预测
    clf = DecisionTreeClassifier()
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)

    # 评估
    print('开始决策树预测...')
    accuracy = np.mean(y_pred == y_test)
    print(f'预测准确率:{accuracy}')

运行结果:

工程优化

通过上述验证数据集已经可以使用,整体流程已经没有问题。接下来我们对代码进行重构:

1、将整体代码使用面向对象封装为类实现

2、在汉字向量化处理中使用jieba的分词方式

3、在模型预测部分加入KNN、贝叶斯、线性回归、随机森林、SVC向量机的方式

由于重构的代码内容较多,本篇文章不再赘述,详情请见Github仓库

遴选算法

通过运行上述工程优化后的代码,执行结果如下:

  • 通过对比准确率,线性回归、SVC、随机森林的准确率较高。
  • 通过分析日志中的执行时间,SVC在使用jieba分词时的训练时间大概有9分钟,训练速度比较慢。
  • 因此,综合下来线性回归和随机森林是较为合适的机器学习模型。

内容小结

  • 机器学习时,数据一般有如下特点

    • 特征与特征之间相互独立
    • 数据集是一个表格类数据
    • 数据成行成列
    • 一行一个样本,一列一个特征
  • 如果数据是汉字,机器是无法处理的,其底层都是处理数字,我们需要将汉字向量化为数字

  • 汉字的向量化方法一般来说有OneHot编码和词袋模型

参考资料

知乎:文本表示之词袋模型

  • 10
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值