🖋️【深度学习原理与PyTorch实战】实验三:使用神经网络识别文字中的情感信息
00 分钟
2023-5-13
2023-9-1
type
status
date
slug
summary
tags
category
icon
password
Last edited time
Sep 1, 2023 04:40 AM
Created time
May 24, 2023 07:23 AM
本文将介绍一个基于神经网络的实验,该实验旨在识别文字中的情感信息。在这个实验中,我们将使用不同的网络结构,包括前馈网络、普通 RNN 和 LSTM 网络,并使用词袋模型对评论进行分类。此外,我们还会详细讨论如何使用 PyTorch 来保存和加载训练好的模型。我们将会谈到如何进行超参数调整,如何处理不平衡数据集,并且会展示如何通过可视化工具来分析训练过程。最后,我们将探讨这些技术如何应用于实际生活中的情境,例如如何使用这些技术来分析社交媒体上的用户评论,以及如何将这些技术应用于金融和医疗行业中的数据分析。

实验介绍

实验内容

在上一次的实验中,介绍了如何训练一个人工神经网络来对共享单车使用量来进行预测。 本次实验将重点介绍如何采用人工神经网络来进行分类。 在本实验中将结合一个具体的问题来看分类问题,这就是识别一段文字中的情绪,从而判断出这句话是称赞还是抱怨。 例如,给你这样两句话:
  • 老熟客了,东西还是一如既往的好,货真价实的日货尾单,性价比突出。
  • 一星都不想给,当时把包装袋随手扔了,现在退货还不知道退不退得了。
这是两句出现在京东购物平台上客户对店家的评语。很显然,前面一句充满了溢美之词,而后一句则充满了抱怨和诟病。作为一个懂得中文的人类,你一眼就能识别出句子中蕴含的情绪,但是机器能做到这一点吗? 你可能会非常困惑,为什么非要教会机器识别一段文字中的情绪呢? 答案就在于,因为机器一旦学会了这个本事,那么它能够帮助人类做的事情就多了。例如,可以根据一支股票的关键词以及网络上包含这些关键词的句子所蕴含的情绪,而自动判别这支股票的走势,从而让机器帮我们快速进行股票的买卖。在本次实验中,首先会编写一个自动爬虫程序,并使用它从在线商城的大量商品评论中抓取评论文本以及分类标签(评论得分)。然后,将根据文本的词袋(Bag of Word)模型来对文本进行建模,然后利用一个神经网络来对这段文本进行分类。

实验知识点

  • 使用 Python 从网络上爬取信息的基本方法
  • 处理语料“洗数据”的基本方法
  • 词袋模型搭建方法
  • 简单 RNN 的搭建方法
  • 简单 LSTM 的搭建方法

实验环境

  • Jupyter Notebook
  • Python 3.7
  • PyTorch 1.4.0

从网络中抓取并处理数据

引入相关包

首先导入相关软件包。这次使用了JSON与Http请求相关的包,是在从网上抓取商品评论信息时使用的。另外还有包含正则表达式相关功能的包re,用于从抓取的商品评论文本中去除标点符号。以及分词工具jieba,用于在评论文本的句子中进行中文分词。

从在线商城中抓取评论数据

我们的数据来源于在线商城中的商品评论,每一条评论都会配合有一个评分。 评分就是用户给出的星级,星级越高用户对这个商品的评价也就越正面。 根据评分的高低,我们可以将评论文本划分成积极的(情感)和消极的(情感)两组。 这些评论信息都可以通过调用网络接口获得。下面这段代码可以向指定URL发送请求,并从请求返回的文本中分析出评论文本。
下面是抓取“积极评论”的来源地址。
其中 productId 为商品的 id,score 为评分,page 为对应的评论翻页的页码,pageSize 为总页数。
这里,我们设定只获得3星的商品评价,即score=3表示好的评分。
注意在下面每条 URL 中,都预留了page={},用于后面的程序指定页号。
下面对上述商品的 URL 进行抓取操作,每个 URL 模拟翻页 100 次,每次翻页可以获取 10 条评论文本,理论上共可爬取 8000 条积极情绪的评论文本(实际情况往往爬不到那么多)。爬取成功后将评论文本保存在data/good.txt文件中。
可以通过同样的方法获取负面情绪倾向的评论文本。 指定score=1即表示用户在提交这条评论时只打了一星,也就代表负面评论,商品的 URL 如下:
负向评论也如法炮制,在获取足够的负向评论文本后,保存到data/bad.txt文件中。

数据预处理(洗数据)

我们提供了爬取好的评论文本在以及中。
data/good.txt
data/bad.txt
下面的代码将对评论文本进行预处理,去除其中的标点符号等无意义的字符。这样可以使词袋模型预测的更加准确。首先编写一个去除标点符号的正则匹配函数,它可以将设定好的标点符号等文本替换为空,也就是去除标点符号。
在下面的函数代码中,首先会循环文本文件中的每行评论,过滤标点符号,分词。
将分词好的评论分别放置在pos_sentences与neg_sentences中。
注意这个函数中同时建立好了词典,词典中包含评论中出现的每一种单词。
上面函数返回的diction就是“字典”了,其中包含从评论文本中切分出的所有词。“字典”是个集合,所以每个词在字典中只出现一次。字典的每一项为。有了字典的内容,还需封装两个函数来“查字典”。这两个函数一个是用“词”来查“索引号”,一个是用“索引号”来查“词”。
下面将读取包含商品评论信息的两个文本文件。

基于词袋模型的简单文本分类器

词袋模型就是一种简单而有效的对文本进行向量化表示的方法。早在1954年的时候,泽里格.哈里斯(Zellig Harris)就提出了这个模型。
简单来理解,词带模型就是将一句话中的所有单词都放进一个袋子里(单词表),而忽略掉语法、语义,甚至单词之间的顺序这些所有的信息。
我们最终只关心每一个单词的数量,然后根据这个数量来建立对句子进行表征的向量。

训练数据准备

输入一个句子和相应的词典,得到这个句子的向量化表示。
句子向量的尺寸为词典中词汇的个数,句子向量在第i位置上面的数值为第i个单词在sentence中出现的频率。
利用上面编写的函数,以句子为单位,将所有的积极情感的评论文本,全部转化为句子向量,并保存到数据集dataset中。
对于消极情绪的评论如法炮制,全部转化为句子向量保存到数据集 中。
dataset
下面进行数据集的切分。 与上一个实验不同的是,在这里我们定义了三种数据集:训练集,校验集(称为 validation 或 develop),测试集。其中训练集占大多数,校验集包含在测试集当中。通常情况下,这三种数据集的尺寸比例大概是 10:1:1 的关系。
为什么要多出来这么一个校验数据集呢?这就是为了检验模型是否会产生过拟合的现象。
通俗地说,过拟合现象就是指模型太过于“死记硬背”,而无法将学到的知识活学活用,做到“举一反三”。在神经网络中,这种“死记硬背”就体现为网络可以很好地拟合训练集数据,但却无法泛化到测试集,这就是过拟合。
那么校验数据集是怎样起到检验模型过拟合的作用的?
首先,在训练模型的时候,校验数据集是不被使用的。其次,在一组超参数下,当模型训练好后,可以利用校验集的数据来监测模型的表现。如果误差同训练数据同样低或差不多,那么就说明模型泛化的能力很强,否则就是模型出现了过拟合的现象。

模型定义

上面已经将文本数据进行了向量化,并且对数据集进行了划分。
终于可以开始搭建神经网络了,它包括一个输入层(大小与词典相同,图中以7133为例)、一个隐含层(10个单元),以及一个输出层(2个单元)。
notion image
在这里,仍然是使用PyTorch自带的Sequential命令来建立多层前馈网络。其中,Sequential中的每一个部件都是PyTorch的nn.Module模块继承而来的对象。
下面要编写的是计算预测错误率的函数。
其中predictions是模型给出的一组预测结果,batch_size行num_classes列的矩阵,labels是数据之中的正确答案。

训练模型

建立好神经网络之后,就可以进行训练了。
首先,定义损失函数cost,以及优化器optimizer,然后即可开始训练循环。
单独把训练模型的主要语句封装到一个函数中。
下面是专门来验证模型的函数,与训练不同,它没有梯度反传和优化的操作。
函数会返回模型预测的结果、正确率、损失值。
下面是训练循环部分,与上一章实验没有太大的区别。

绘制图像观察模型训练情况

使用下面代码将损失函数和准确度的曲线画出来:
可以看到,随着训练周期的增加,训练数据和校验数据的损失函数曲线都快速下降。
笔者实验时是大概到达第 15 个周期的时候,训练数据的损失函数已经低于校验数据的损失函数值了。
因此,15 步训练已经足可以把模型训练好了,更多的训练可能导致神经网络产生一定程度的过拟合。
除此之外,校验数据上的分类准确率也快速提高,达到了 90% 左右的水平。
进一步,通过下面的代码,可以看到模型在测试数据上的准确率。
下面将模型在整个测试集上运行,记录预测结果,并计算总的正确率。
计算输出的分类准确度可以达到 90% 左右。
至此,我们已经训练好了一个可以比较准确地识别电商产品评论中情绪的分类神经网络了。
当然,神经网络仅针对京东这样的网上购物评论工作的很好,它并不一定能够判断更一般的自然语言中的情绪。
这是因为,神经网络的工作是非常严重地依赖于训练数据的。因此,如果换过一套新的不同风格的数据,它的准确度也会有所下降。

保存模型

可以将训练好的模型以文件的形式保存下来。
这样即使 Python 内核停止运行,下次只需要从文件中加载这个模型即可,无需重新训练。

基于RNN的简单文本分类器

除了最简单的词袋模型,下面的内容中还对比了另外两种 RNN 模型的效果,一个是普通的 RNN 模型,另一个是 LSTM RNN。
本章节的主要目的是了解 RNN 模型如何实现,以及考察它们在测试数据集上的分类准确度。
本次实验只是演示 RNN 的用法,不做过多的讲解。关于 RNN 以及 LSTM 更多的内容,会在后面的几次实验中再专门详细讲解。

普通RNN模型

正如词袋模型那样,首先加载并预处理数据。
与词袋模型不同,在这次 RNN 的实验中,不去除评论语料中的标点符号。
采用与词袋模型相似的方法,将评论语料向量化,变成句子向量。
每一个句子向量在词袋模型中都被表示为了固定长度的向量,其中长度为字典的尺寸。
与词袋模型不同的是,在 RNN 中,每一个句子就是被单独当成词语的序列来处理的,因此序列的长度是与句子等长的。
PyTorch 内部其实已经封装了很多常用的神经网络模型供开发者使用。
但是在本次实验中还是采用手动编写模型的方式,以熟悉 RNN 的结构与工作流程。
本次要搭建的 RNN 模型结构如下:
notion image
下面开始训练这个 RNN 网络。
同样,绘制 RNN 模型的误差曲线。
在测试集上运行,并计算准确率。
将模型保存下来。

基于LSTM的简单文本分类器

普通 RNN 的效果并不好,可以尝试利用改进型的 RNN,即 LSTM。
LSTM 与 RNN 最大的区别就是在于每个神经元中多增加了3个控制门:遗忘门、输入门和输出门。
另外,在每个隐含层神经元中,LSTM 多了一个 cell 的状态,起到了记忆的作用。
这就使得 LSTM 可以记忆更长时间的 Pattern。
下面的代码搭建了一个简单的 LSTM 模型,用来判断评论信息的情感倾向。
与上面编写的普通 RNN 模型一样,本次只是演示 LSTM 模型的搭建方法,对比与其它模型的效果。
在后面的实验中会有单独详细讲解 LSTM 的部分。
下面开始训练LSTM模型。
绘制误差与准确率的曲线。
在测试集上计算总的正确率。
保存模型

实验总结

首先,在本实验中我们了解了如何写一个简单的爬虫程序从网上扒文章。
其次,我们设计了一个简单的前馈网络,利用词袋模型获得每一个评论的向量表示,并输入进前馈网络得到很好的分类效果。
然后,我们尝试了两种 RNN 网络,一种是普通的 RNN,另一种是 LSTM。
在本次实验中展示了它们在处理同样的文本分类问题上的用法。
👌🏼
若您有更好的见解,请您在评论区评论!

评论