内容目录

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

项目目的

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

数据集

字段名称 字段类型 字段说明
label 整型 情感标签(1为正面,0为负面)。
review 字符型 评论内容。
  • 数据集样例:

    label review
    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

代码实现思路

整体代码实现的解决思路如上图所示:

1、首先,我们需要读取csv文件并且将标签和特征数据切分出来。

2、其次,我们需要解决:如何将汉字转换为数字编码这个问题;

3、接着,通过与GPT沟通词袋模型,我们了解到需要构建一个词汇表,然后根据词汇表数个数,所以这个问题可以分解为两个子问题:如何将数据集汉字建立成字典?如何根据字典数文字出现的个数?

4、对于如何将数据集汉字建立成字典?这个问题,我们通过与GPT沟通了解到,可以使用一个双层循环,逐行逐字遍历数据集,然后把字加入到一个set变量中。(因为set数据类型有滤重功能)

5、对于如何根据字典数文字出现的个数?这个问题,我们通过与GPT沟通了解到,需要下面几个小步骤:

  • ①生成一个长度为字典长度,内容都为0的bow_vector。
  • ②将原始的文本数据,以字的维度转成二维数组vector。
  • ③根据上面②生成的vector,继续使用双层循环遍历,在字典vocab中找当前遍历的字地索引值
  • ④根据索引值,在bow_vector同样的位置进行计数+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)
  • 第三步:生成词汇表

    # 原始文本数据
    data = [
      "很快,好吃,味道足,量大",
      "没有送水没有送水没有送水"
    ]
    
    # 构建词汇表
    vocab = set()
    for text in data:
      for char in text:
          vocab.add(char)
    # 输出结果
    print("词汇表:", vocab)

运行结果:

  • 第四步:生成向量化数据

    # 原始文本数据
    data = [
      "很快,好吃,味道足,量大",
      "没有送水没有送水没有送水"
    ]
    
    # 向量化处理
    vector = []
    for text in data:
      words = list(text)  # 将每个文本按字拆分为单个字,并转换为列表
      vector.append(words)
    print("向量化后的结果:", vector)

    运行结果:

  • 第五步:生成一个长度为字典长度,内容都为0的bow_vector;遍历vector,在vocab字典中找到当前遍历字符的index,然后在bow_vector的同样index位置进行+1计数

    # 原始文本数据
    data = [
      "很快,好吃,味道足,量大",
      "没有送水没有送水没有送水"
    ]
    
    # 向量化处理
    vector = []
    for text in data:
      words = list(text)  # 将每个文本按字拆分为单个字,并转换为列表
      vector.append(words)
    
    # 向量化处理(生成词袋模型)
    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)
    # 输出向量化后的结果
    print("向量化后的结果(词袋模型):", vectorized_data)

    运行结果:

至此,一个基本的数据预处理过程雏形已经完成。

接下来,

1、我们需要对上面的过程封装为一个function,然后将示例代码中的data替换为从文件读取切分出来的n_data,详细过程不再赘述。

2、最终生成的向量化数据,可以保存在内存中,在下面的运行模型中直接使用;也可以将向量化数据保存到本地文件,然后在模型方法中读取后使用。

我使用的方法是保存到本地后,在下面的decision_tree来读取使用。处理后的数据保存在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编码和词袋模型

参考资料

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

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

分类文章

personal_logo
Dongming
自由职业者

推荐活动

推荐文章

【项目实战】基于Agent的金融问答系统:RAG的检索增强之上下文重排和压缩
【项目实战】基于Agent的金融问答系统:RAG的检索增强之ElasticSearch
【项目实战】基于Agent的金融问答系统:前后端流程打通
【项目实战】基于Agent的金融问答系统:代码重构
【项目实战】基于Agent的金融问答系统:Agent框架的构建
【项目实战】基于Agent的金融问答系统:RAG检索模块初建成
【项目实战】基于Agent的金融问答系统:项目简介
【课程总结】day29:大模型之深入了解Retrievers解析器
【课程总结】day28:大模型之深入探索RAG流程
【课程总结】day30:大模型之Agent的初步了解
内容目录
滚动至顶部