如何训练一个用于情感分析的神经网络

开头

情感分析与文本挖掘和自然语言处理密切相关,从书面评论中提取出了定性评价。很多人阅读电影评论,以评估一部电影在普通观众中的好坏程度。虽然给一部电影评分或星级评价可能并不能准确反映其成功或失败的数量层面,但是一系列电影评论能够提供对这些电影的定性观点。通过文本电影评论,我们可以了解观众认为哪些方面是好的,哪些方面不足。更深入地审查评论往往能揭示电影是否达到了评论者的期望。情感分析能够用于评估评论者对主题或评论的整体极性方面的观点。

进行情感分析,您可以运行计算程序,识别和分类文本中的观点,例如判断作者(或评论者)对给定主题(在本例中是一部电影)持有积极还是消极的态度。作为意见挖掘的一个子领域,情感分析侧重于从结构化、半结构化或非结构化的文本数据中提取对特定主题的情感和观点。与其他意见挖掘模型一样,您可能会使用情感分析来监测品牌和产品观点并了解客户需求。情感分析侧重于文本的极性(积极、消极或中性),以及检测评论者的具体情感和感情(由模型定义的愤怒、快乐、悲伤等),紧迫性,甚至意图(感兴趣与否)。

在这个教程中,您将使用Keras构建一个神经网络,用于预测电影评论的情感。您的模型将使用国际电影数据库(IMDb)的评论数据集将评论分类为两个类别(积极或消极),该数据集包含50000条电影评论。在本教程结束时,您将创建一个深度学习模型并训练一个神经网络来进行情感分析。

前提条件

  • One Ubuntu 22.04 server instance with at least 8GB RAM. This server will need a non-root user with sudo privileges and a firewall configured, which you can set up by following our initial server setup guide.
  • Python 3, pip, and the Python venv module installed on the server, which you can set up by following Steps 1 and 2 of our tutorial on How To Install Python 3 and Set Up a Programming Environment.
  • Jupyter notebook installed and running on a remote server, which you can set up with How to Install, Run, and Connect to Jupyter Notebook on a Remote Server.
  • A modern web browser that you will use to access Jupyter Notebook.
  • A fundamental understanding of machine learning and deep learning models. Learn more in An Introduction to Machine Learning.

步骤1 – 准备您的Jupyter Notebook环境

Jupyter Notebook提供了一个交互式的计算环境,因此经常用于运行深度学习模型,而不是在命令行终端中使用Python。使用Jupyter Notebook,命令和输出会出现在同一个笔记本中,使您能够在开发分析过程时记录您的思考。

要在您的Jupyter Notebook中按照本教程进行操作,您需要打开一个新的Notebook并安装所需的依赖项,在本步骤中完成。

Note

注意:如果您正在使用远程服务器的教程,则可以使用端口转发在本地机器的浏览器中访问您的Jupyter Notebook。
打开一个终端并输入以下命令:
ssh -L 8888:localhost:8888 您的非根用户@您的服务器IP

连接到服务器后,导航到输出中提供的链接以访问您的Jupyter Notebook。在本教程的其余部分中,请保持此终端打开。

在先决条件中,您在服务器上设置了一个Jupyter Notebook环境。一旦您登录到服务器上,激活虚拟环境。

  1. source ~/environments/my_env/bin/activate

 

然后运行Jupyter Notebook应用程序来启动应用。

  1. jupyter notebook

 

运行并连接后,您将在浏览器中访问到一个用户界面。从“New”下拉菜单中选择Python3(ipykernel)选项,这将打开一个未命名的Python笔记本的新标签页。将文件命名为neural_network.ipynb,因为您将在此文件中运行代码。

然后,在浏览器的Jupyter Notebook的第一个单元格中,使用pip安装处理数据所需的依赖项。

神经网络.ipynb
!pip install numpy
!pip install tensorflow

numpy依赖于线性代数中的数组操作。在本教程中,您将使用它来通过调用以下函数来操作以数组形式存在的IMDb数据集:
使用concatenate函数将测试数据数组序列连接到训练数据数组中。
使用unique函数在数据集数组中找到独特的元素。
在对数据集进行向量化时,使用zeros函数返回一个由零填充的新数组。

TensorFlow依赖库允许你在Python中训练和部署深度学习模型。安装TensorFlow也会同时安装Keras,Keras运行在TensorFlow之上,并为用户和TensorFlow之间引入了一个抽象层,以便快速开发深度学习模型。本教程使用TensorFlow和Keras完成整个情感分析的训练和部署过程。

在将这两个命令添加到你的Jupyter Notebook后,点击运行按钮来运行它们。

你的Jupyter Notebook将会提供一个运行输出来指示每个依赖项正在被下载。在这个输出下方会有一个新的输入单元格,你可以在其中运行接下来的代码行。

当依赖项下载完成后,您将导入它们。请将以下代码添加到下一个单元格中,然后按运行按钮。

神经网络.ipynb
import numpy as np
from keras.utils import to_categorical
from keras import models
from keras import layers

Note

注:当运行这些命令时,您可能会收到有关TensorFlow和TensorRT库的警告。通常,Tensorflow可以与CPU、GPU和TPU一起工作。警告错误说明安装的TensorFlow版本可以使用AVX和AVX2操作,从而加快处理速度。这个警告不是错误,而是一个提示,表示TensorFlow将利用您的CPU提供额外的速度。

Keras工具的安装包含了内置的IMDB数据库。该数据集有50/50的训练集和测试集划分。为了避免过度训练神经网络,在本教程中,你将设置一个80/20的划分比例。因此,在下载数据后,你将合并数据和目标,以便在教程的后续部分进行80/20的划分。请将以下行添加到一个新的单元格中并点击运行:

神经网络.ipynb
from keras.datasets import imdb
(training_data, training_targets), (testing_data, testing_targets) = imdb.load_data(num_words=10000)
data = np.concatenate((training_data, testing_data), axis=0)
targets = np.concatenate((training_targets, testing_targets), axis=0)

这个代码单元导入了IMDb数据集,并将训练数据和测试数据进行连接。默认情况下,数据集被划分为训练数据、训练目标、测试数据和测试目标。

您的Jupyter笔记本将包含一个活动日志,并且需要一些时间来下载数据集。

Output

Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/imdb.npz 17464789/17464789 [==============================] – 0s 0us/step

在这一步中,您准备了Jupyter Notebook环境,以便您可以调查此数据集的模式、假设和异常测试。接下来,您将对整个数据集进行探索性数据分析。

第二步——分析数据集

现在你将评估数据集,确定如何使用这些数据来训练你的模型。对数据集进行探索性数据分析将揭示数据集的潜在结构。这个过程可能会发现不容易察觉的趋势、模式和关系。这些信息可以帮助你检测错误、驳斥假设,并理解关键变量之间的关系。这些洞察力最终可能会导致选择一种合适的预测模型。

你在处理这个数据集时的第一个任务是获取输出类型和不重复单词的数量。要获取这些信息,请在一个新的单元格中运行以下代码行:

神经网络.ipynb .ipynb)
print("The output categories are", np.unique(targets))
print("The number of unique words is", len(np.unique(np.hstack(data))))

此单元格打印数据集中唯一情感(积极[1]或消极[0])的数量,以及评论中使用的唯一单词数量。

下面的输出将打印:

Output

The output categories are [0 1] The number of unique words is 9998

这个输出的第一行说明电影被标记为积极(1)或消极(0)。第二行说明数据集中有9998个独特的单词。

接下来,你将确定电影评论的平均词长和词的标准差。为此,请在新单元格中运行以下代码行:

神经网络.ipynb
length = [len(i) for i in data]
print("The Average Review length is", np.mean(length))
print("The Standard Deviation is", round(np.std(length)))

这个单元格将打印数据集的平均评价长度和标准差。

Output

The Average Review length is 234.75892 The Standard Deviation is 173

这项评估表明,平均评价长度为234个字,标准偏差为173。

接下来,您可以通过在新的单元格中运行以下代码来打印数据集中的一个元素(第一个索引)。

神经网络.ipynb
print("Label:", targets[0])
print(data[0])

数据集中第一个元素的电影评论 – 标签对将输出:

Output

Label: 1 [1, 14, 22, 16, 43, 530, 973, 1622, 1385, 65, 458, 4468, 66, 3941, 4, 173, 36, 256, 5, 25, 100, 43, 838, 112, 50, 670, 2, 9, 35, 480, 284, 5, 150, 4, 172, 112, 167, 2, 336, 385, 39, 4, 172, 4536, 1111, 17, 546, 38, 13, 447, 4, 192, 50, 16, 6, 147, 2025, 19, 14, 22, 4, 1920, 4613, 469, 4, 22, 71, 87, 12, 16, 43, 530, 38, 76, 15, 13, 1247, 4, 22, 17, 515, 17, 12, 16, 626, 18, 2, 5, 62, 386, 12, 8, 316, 8, 106, 5, 4, 2223, 5244, 16, 480, 66, 3785, 33, 4, 130, 12, 16, 38, 619, 5, 25, 124, 51, 36, 135, 48, 25, 1415, 33, 6, 22, 12, 215, 28, 77, 52, 5, 14, 407, 16, 82, 2, 8, 4, 107, 117, 5952, 15, 256, 4, 2, 7, 3766, 5, 723, 36, 71, 43, 530, 476, 26, 400, 317, 46, 7, 4, 2, 1029, 13, 104, 88, 4, 381, 15, 297, 98, 32, 2071, 56, 26, 141, 6, 194, 7486, 18, 4, 226, 22, 21, 134, 476, 26, 480, 5, 144, 30, 5535, 18, 51, 36, 28, 224, 92, 25, 104, 4, 226, 65, 16, 38, 1334, 88, 12, 16, 283, 5, 16, 4472, 113, 103, 32, 15, 16, 5345, 19, 178, 32]

此输出为数据集的第一条评论,标记为正面(1),并将全文作为整数索引提供。默认情况下,文本评论以数值编码形式给出,作为基于整数的单词索引列表。评论中的单词索引基于它们在整个数据集中的出现频率。例如,数据中出现次数第二多的术语由整数2进行编码。

接下来,您将检索字典,将单词索引映射回原始单词,以便您可以阅读文本评论。请在新单元格中运行这些代码。

神经网络.ipynb
index = imdb.get_word_index()
reverse_index = dict([(value, key) for (key, value) in index.items()])
decoded = " ".join( [reverse_index.get(i - 3, "#") for i in data[0]] )
print(decoded)

这段代码将数字形式解码为可读文本。通过 get_word_index() 函数,您可以检索将单词映射到其在 IMDb 数据集中的索引的字典。然后,reverse_index 变量保存将单词索引反转后,将索引映射到单词的字典。dict() 函数创建一个以键值对形式存储数据值的字典。代码的最后两行将解码并打印数据集中的第一个序列。

使用get_word_index()函数,您将收到以下输出:

Output

# this film was just brilliant casting location scenery story direction everyone’s really suited the part they played and you could just imagine being there robert # is an amazing actor and now the same being director # father came from the same scottish island as myself so i loved the fact there was a real connection with this film the witty remarks throughout the film were great it was just brilliant so much that i bought the film as soon as it was released for # and would recommend it to everyone to watch and the fly fishing was amazing really cried at the end it was so sad and you know what they say if you cry at a film it must have been good and this definitely was also # to the two little boy’s that played the # of norman and paul they were just brilliant children are often left out of the # list i think because the stars that play them all grown up are such a big profile for the whole film but these children are amazing and should be praised for what they have done don’t you think the whole story was so lovely because it was true and was someone’s life after all that was shared with us all

get_word_index() 函数将该评论的数字数据解码为可读的单词,并将每个无法识别的单词替换为 #。

在这一步中,您已经对数据集进行了评估,审查了每个评论的准备情况。有了这些信息,现在您将准备数据进行训练。

第三步 – 为训练准备数据

在这一步骤中,您将为训练准备数据集。深度学习模型一般是根据它们所训练的数据逐渐发展的。

在准备数据时,您需要以精确的方式对其进行格式化,以产生有价值的洞见,从而得到更准确的模型结果。一些数据准备的技术包括特征选择(选择与模型相关的特征)、特征工程(使用编码方法将数据集中的变量转换为有用的特征)以及将数据集分割为训练集和测试集。

在这个教程中,你将把数据分成测试集和训练集,并通过将数据向量化进行特征工程。

在下一个单元格中,运行以下代码以将数据集中的每个评论转化为向量。

神经网络.ipynb
def vectorize(sequences, dimension = 10000):
    results = np.zeros((len(sequences), dimension))
    for i, sequence in enumerate(sequences):
        results[i, sequence] = 1
    return results

data = vectorize(data)
targets = np.array(targets).astype("float32")

首先,你将每个评论向量化并填充,确保每个评论都包含10,000个数字。通过这个过程,你会填充每个短于10,000字的评论,因为数据集中最长的评论大约是这个长度,神经网络要求每个输入都是相同的大小。

vectorize()函数接受两个参数:一个数组和一个预设的维度10000。这个函数调用numpy库中的zeros()方法,该方法返回一个由零填充的新数组,然后对剩余的数据进行编码。通过最后两行代码,您将在数据集上调用定义的函数,然后将数据集的目标列转换为32位浮点数。32位浮点数是具有大约七位有效数字的浮点数。将目标列转换为32位浮点数将增加列的精确度,并进而提升深度学习模型的性能。

作为准备数据的最后一步,您将把数据分成训练集和测试集。您将把40,000个评论放入训练集中,将10,000个评论放入测试集中,实现之前提到的80/20的分割比例。

在新的单元格中运行这些命令来拆分你的数据集。

神经网络.ipynb可以改写为:神经网络笔记本.ipynb
test_x = data[:10000]
test_y = targets[:10000]
train_x = data[40000:]
train_y = targets[40000:]

数据集已经按照1:4的比例分成测试集和训练集。其中,训练集和测试集的目标变量分别保存为train_y和test_y,训练集和测试集的评论分别保存为train_x和test_y。此外,除了使用新数据测试和评估模型外,数据集的分割还可以防止模型过拟合,即算法过于拟合训练数据。

在这一步中,您准备了数据并将数据集分为训练集和测试集。您将原始数据转换为可用于深度学习模型的特征。准备好训练数据后,您现在将构建并训练神经网络,该神经网络将用于您的深度学习模型。

第四步——构建和训练神经网络

现在你可以构建你的神经网络了。

你将会从定义你想要构建的模型类型开始。在keras中有两种可用的模型类型:顺序模型API和函数式API。在本教程中,你将使用顺序模型API,因为它允许你逐层创建模型。

Note

注意:对于更复杂的深度学习模型,你应该使用功能API,因为顺序API不允许你创建共享层或具有多个输入或输出的模型。然而,对于本教程来说,顺序API就足够了。

在新的单元格中运行以下命令,将你的模型设置为序列模型。

神经网络.ipynb
model = models.Sequential()

Note

注意:在此阶段您可能会遇到另一个TensorFlow错误,提示您使用适当的编译器标签重新构建TensorFlow。这个错误与之前的错误相关,因为TensorFlow 2.x软件包同时支持CPU和GPU,所以TensorFlow正在寻找GPU驱动程序。您可以安全地忽略这个警告,因为它不会影响教程的结果。

由于层是深度学习模型的基础,下一步你将添加输入层、隐藏层和输出层。在它们之间,你将在每一层上使用dense,并使用dropout来防止过拟合。

在一个新的单元格中运行这些代码以添加图层:

神经网络.ipynb
# Input - Layer
model.add(layers.Dense(50, activation = "relu", input_shape=(10000, )))
# Hidden - Layers
model.add(layers.Dropout(0.3, noise_shape=None, seed=None))
model.add(layers.Dense(50, activation = "relu"))
model.add(layers.Dropout(0.2, noise_shape=None, seed=None))
model.add(layers.Dense(50, activation = "relu"))
# Output- Layer
model.add(layers.Dense(1, activation = "sigmoid"))
model.summary()

因为它产生了令人满意的结果,所以你会在隐藏层中使用relu函数。relu代表修正线性单元,该函数在接收到任何负输入时返回0,并在接收到任何正值时返回该值。将此函数添加到您的第一层中,通过返回0去掉了负值。在本教程中,relu函数确保所有进入输入层的值都是必要的神经输入的正值。

在输出层,你将使用sigmoid函数,该函数将值映射为0和1。由于输出是正数(1)或负数(0),sigmoid函数将确保输出层产生的输出是0或1。

最后,你将让Keras打印一份你刚刚构建的模型摘要。

您将收到您刚训练的模型的特性摘要。

Output

Model: “sequential” _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense (Dense) (None, 50) 500050 dropout (Dropout) (None, 50) 0 dense_1 (Dense) (None, 50) 2550 dropout_1 (Dropout) (None, 50) 0 dense_2 (Dense) (None, 50) 2550 dense_3 (Dense) (None, 1) 51 ================================================================= Total params: 505,201 Trainable params: 505,201 Non-trainable params: 0 _________________________________________________________________ ​

接下来,您将编译并配置用于训练的模型。您将使用Adam优化器,它是一种在训练过程中改变权重和偏差的算法,并将二元交叉熵作为损失函数、准确率作为评估指标。损失函数将计算模型在训练期间应该寻求最小化的量。在这种情况下,您选择了二元交叉熵,因为真实标签和预测标签之间的交叉熵损失是二元(0或1)分类应用的一个优秀度量指标。

要编译模型,请在下一个单元格中运行以下命令。

神经网络.ipynb
model.compile(
optimizer = "adam",
loss = "binary_crossentropy",
metrics = ["accuracy"]
)

compile()函数定义了模型的架构。在这个定义中,你使用adam算法作为模型的优化器。这个算法是基于近似一阶和二阶矩的梯度下降方法。度量标准和损失参数非常密切相关。度量标准参数定义了如何评判模型的性能,而损失参数定义了模型在训练过程中寻求最小化的量。这里的度量标准是准确率(模型正确预测的预测数量的比例),损失函数是二元交叉熵(在只有两个标签类别(正类别1和负类别0)时,标签和预测之间的度量标准)。

现在,你将能够训练你的模型。为了做到这一点,你将使用一个批量大小为32,并且只进行两个周期。批量大小是通过神经网络传播的样本数量,而周期是对整个训练数据的迭代。较大的批量大小通常意味着训练速度更快,但有时收敛较慢。相反,较小的批量大小在训练时较慢,但可以更快地收敛。

你现在将开始训练模型,以获取所有参数的正确值,将输入映射到你的输入。请在下一个单元格中运行这些代码。

神经网络.ipynb luò.ipynb)
results = model.fit(
train_x, train_y,
epochs= 2,
batch_size = 32,
validation_data = (test_x, test_y)
)

你将使用.fit()函数来训练你的模型。这个函数在数据集上对深度学习模型进行固定次数的迭代训练。该函数有两个必需的参数。

  • train_x refers to the input data.
  • train_y refers to the target data for the training set on which the data will be trained and can take other parameters.

其他参数包括以下内容:

  • epochs (the number of epochs to train the model where an epoch is an iteration over the entire data provided).
  • batch_size (the number of samples per gradient update).
  • validation_data (the data on which the model will evaluate the loss at the end of each epoch).

这段代码使用两个轮次和批大小为32来训练模型,这意味着整个数据集将通过神经网络两次,并且每次迭代中使用32个训练样例。验证数据用作test_x和test_y。

Note

注意:训练情感分析模型需要大量内存。如果你在一台只有8GB内存的服务器上运行本教程,可能会收到以下警告:分配的x超过了可用系统内存的10%。当出现这个警告时你可以忽略它并继续进行教程,因为它只是说明训练过程占用了相当数量的空闲系统内存,对教程的其他部分没有影响。

在这一步中,你构建了深度学习模型,并在你准备的数据集上进行了训练。接下来,你将使用在这一步中生成的验证数据,评估模型对另一个数据集的性能。

第五步 — 评估模型

在这一步骤中,您将对模型进行评估。模型评估是机器学习改进和发展过程中不可或缺的一部分。该评估有助于找到最能代表您的数据和最适合的模型,并评估所选择模型的表现效果。

机器学习分类模型有四个主要的模型评估指标:准确率、精确度、召回率和F1得分。

准确率是一个常用的性能指标,因为它评估了模型预测正确的比例。准确率通过将正确预测的数量除以总预测数量来确定。在本教程中,您将使用准确率来评估您的模型。

在该模型的背景下,精确度指的是预测准确的正面电影评论与总预测正面电影评论的比例。召回率是正确预测的正面电影评论与数据集中评估的总电影评论数量的比例。精确度回答了这个问题:你的模型标记为正面的所有电影评论中,有多少实际上是正面的?相反,召回率回答了这个问题:所有真正正面的电影评论中,你的模型标记为正面的有多少?F1得分是精确度和召回率结果的加权平均值。因此,它考虑了被错误分类的任何评论。

在这个教程中,您将使用准确率评估模型的性能。在下一个单元格中运行以下代码行。

神经网络.ipynb
scores = model.evaluate(test_x, test_y, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))

这段代码将模型的准确率分数存储在一个名为scores的变量中,并将其打印到屏幕上。.evaluate函数接受三个参数。

  • x_test: the feature column for the test dataset.
  • y_test: the target column for the test dataset.
  • verbose: the mode of verbosity.

以下结果将以精确率打印出来。

Output

Accuracy: 86.59%

这个训练模型的准确率为86.59%。

这个准确度分数表明,该模型在十次中有九次能准确预测出评论是积极还是消极的。你可以继续改进你的代码,尝试提高分类器的准确性。为了使你的模型表现更好并提高准确度,你可以增加模型的迭代次数或批处理大小。

深度学习模型(和机器学习模型)的强大程度取决于所输入的数据。因此,通过增加更多的数据来提高模型的准确性是常见的做法。然而,用于该模型的数据是内置的,无法修改。在这种情况下,您可以通过在第四步中增加更多的层或增加迭代次数(将整个数据集通过神经网络传递的次数)来提高模型的准确性。

为了增加纪元数目,在 model.fit() 的代码块中将纪元数从2更改为3(或其他数字),然后重新运行该代码块及其后续代码块。

神经网络.ipynb
results = model.fit(
train_x, train_y,
epochs= 3,
batch_size = 32,
validation_data = (test_x, test_y)
)

增加了训练轮次的数量,意味着训练数据将总共经过神经网络三次,模型将有额外的机会从数据中学习。当您重新运行model.evaluate()函数时,将会得到一个更新的准确率新输出。

在这个步骤中,你通过计算准确率评估了你构建的模型。在初始计算之后,你增加了轮次的数量来改善模型,并重新评估准确率得分。

总结

在这个教程中,你使用keras训练了一个神经网络,用于将电影评论的情感分类为积极或消极。你使用了由斯坦福大学研究人员收集的IMDb情感分类数据集。该数据集是keras预下载的二元情感分类数据集之一。你可以访问这个数据集,其中包含了25,000条高度极化的电影评论用于训练,以及另外25,000条用于测试。你对这个数据集进行了回顾,以开发一个适用于情感分析的大型神经网络模型。

既然你已经构建并训练了一个神经网络,你可以使用自己的数据来尝试这个实现,或者在其他流行的数据集上进行测试。你可以尝试使用其他的Keras数据集,或者尝试不同的算法。

为了加强您在Keras和TensorFlow方面的经验,您可以根据我们的教程,使用Keras和TensorFlow构建深度学习模型来预测员工保留情况。

发表回复 0

Your email address will not be published. Required fields are marked *


广告
将在 10 秒后关闭
bannerAds