TensorFlow深度学习实战——基于循环神经网络的情感分析模型

TensorFlow深度学习实战——基于循环神经网络的情感分析模型

    • 0. 前言
    • 1. 数据处理
    • 2. 模型构建与训练
    • 3. 模型评估
    • 相关链接

0. 前言

情感分析 (Sentiment Analysis) 是自然语言处理中的一项技术,旨在识别和提取文本中的情感信息,通常是分析一段文本中是否存在积极、消极或中立的情绪,广泛应用于社交媒体监控、客户反馈分析、产品评论分析等领域。我们已经学习了使用 TensorFlow 构建简单情感分析模型,在本节中,将实现基于循环神经网络的情感分析模型,进一步提高情感分析性能。

1. 数据处理

本节构建的基于循环神经网络的情感分析模型属于多对一结构,以句子为输入并预测其情感是正面还是负面。数据集是来自 UCI 机器学习库上的 Sentiment-labeled sentences 数据集,包含来自亚马逊、IMDbYelp3,000 条评论句子,句子标记为 0 表示评论表达了负面情感,标记为 1 表示评论表达了正面情感。

(1) 首先,导入所需库:

import numpy as np
import os
import shutil
import tensorflow as tf
from sklearn.metrics import accuracy_score, confusion_matrix

(2) 数据集以压缩文件提供,解压后包含三个文件,每个文件包含一个提供者的标记句子,每行包含一个句子和一个标签,句子和标签之间用制表符分隔。首先下载压缩文件,然后将文件解析为(句子, 标签)对的列表:

def clean_logs(data_dir):logs_dir = os.path.join(data_dir, "logs")shutil.rmtree(logs_dir, ignore_errors=True)return logs_dirdef download_and_read(url):local_file = url.split('/')[-1]local_file = local_file.replace("%20", " ")p = tf.keras.utils.get_file(local_file, url, extract=True, cache_dir=".")local_folder = os.path.join("datasets", local_file.split('.')[0])labeled_sentences = []for labeled_filename in os.listdir(local_folder):if labeled_filename.endswith("_labelled.txt"):with open(os.path.join(local_folder, labeled_filename), "r") as f:for line in f:sentence, label = line.strip().split('\t')labeled_sentences.append((sentence, label))return labeled_sentences# clean up log area
data_dir = "./data"
logs_dir = clean_logs(data_dir)# download and read data into data structures
labeled_sentences = download_and_read("https://archive.ics.uci.edu/ml/machine-learning-databases/00331/sentiment%20labelled%20sentences.zip")
sentences = [s for (s, l) in labeled_sentences]
labels = [int(l) for (s, l) in labeled_sentences]

(3) 模型训练的目标是,使其能够根据输入的句子预测相应的情感标签。每个句子都是一个单词序列。然而,为了将其输入模型,我们必须将其转换为一个整数序列。序列中的每个整数指向一个单词,整数与单词的映射称为词汇表。因此,我们需要对句子进行词元化 (tokenize) 并生成词汇表:

# tokenize sentences
tokenizer = tf.keras.preprocessing.text.Tokenizer()
tokenizer.fit_on_texts(sentences)
vocab_size = len(tokenizer.word_counts)
print("vocabulary size: {:d}".format(vocab_size))word2idx = tokenizer.word_index
idx2word = {v:k for (k, v) in word2idx.items()}

本节的词汇表包含 5,271 个唯一的单词。可以通过丢弃出现次数低于某个阈值的单词来缩小词汇表的大小,该阈值可以通过检查 tokenizer.word_counts 字典确定。在这种情况下,我们需要为词汇表添加一个用于表示未知单词 (UNK) 的项,用以替换所有在词汇表中未找到的单词。
构建查找字典,以便在单词和索引之间进行转换。第一个字典在训练期间用于构建整数序列,以供网络使用。第二个字典用于将单词索引转换回单词,以便在后续的预测代码中使用。

(4) 每个句子的单词数可能不同。我们的模型需要为每个句子提供相同长度的整数序列。为了满足这个要求,通常会选择一个足够大的最大序列长度,以容纳训练集中大多数句子。较短的句子将用零填充,而较长的句子将被截断。选择最大序列长度的一个简单方法是查看不同百分位数位置的句子长度(即单词数):

seq_lengths = np.array([len(s.split()) for s in sentences])
print([(p, np.percentile(seq_lengths, p)) for p in [75, 80, 90, 95, 99, 100]])

输出结果如下所示:

[(75, 16.0), (80, 18.0), (90, 22.0), (95, 26.0), (99, 36.0), (100, 71.0)]

可以看到,最大句子长度为 71 个单词,但 99% 的句子长度都在 36 个单词以下,如果选择 64 作为阈值,大多数情况下不需要截断句子。可以多次交互式地运行以上代码块,以选择合适的词汇表大小和最大序列长度的值。在本节中,我们选择保留所有单词(即 vocab_size = 5271),并将 max_seqlen 设置为 64

(5) 接下来,创建模型可用的数据集。首先使用训练好的词元分析器 (tokenizer),将每个句子从单词序列 (sentences) 转换为整数序列 (sentences_as_ints),其中每个整数对应于词元分析器中单词的索引 (tokenizer.word_index),然后对其进行截断并用 0 进行填充。标签同样转换为 NumPy 数组 labels_as_ints,最后,将张量 sentences_as_intslabels_as_ints 合并为一个 TensorFlow 数据集:

max_seqlen = 64# create dataset
sentences_as_ints = tokenizer.texts_to_sequences(sentences)
sentences_as_ints = tf.keras.preprocessing.sequence.pad_sequences(sentences_as_ints, maxlen=max_seqlen)
labels_as_ints = np.array(labels)
dataset = tf.data.Dataset.from_tensor_slices((sentences_as_ints, labels_as_ints))

(6) 将数据集的三分之一用于模型评估,剩余数据中,使用 10% 作为验证数据集,验证数据集将用于在训练过程中评估模型的进展,剩余部分作为训练数据集。最后,将每个数据集的批大小设为 64

# split into train and test
dataset = dataset.shuffle(10000)
test_size = len(sentences) // 3
val_size = (len(sentences) - test_size) // 10
test_dataset = dataset.take(test_size)
val_dataset = dataset.skip(test_size).take(val_size)
train_dataset = dataset.skip(test_size + val_size)batch_size = 64
train_dataset = train_dataset.batch(batch_size)
val_dataset = val_dataset.batch(batch_size)
test_dataset = test_dataset.batch(batch_size)

2. 模型构建与训练

定义模型。模型的每个输入句子是一个大小为 max_seqlen (64) 的整数序列,该序列输入到嵌入层中,该层将每个单词转换为一个向量,大小为 (vocab_size + 1), 其中 vocab_size 表示词汇表大小。额外的单词用于处理在 pad_sequences() 调用中引入的填充整数 0。每个时间步的 64 个向量送入一个双向长短期记忆 (Long Short Term Memory, LSTM) 层,该层将每个单词转换为大小为 (64,) 的向量。LSTM 在每个时间步的输出送入一个使用 ReLU 激活的全连接层,生成一个大小为 (64, ) 的向量。这个全连接层的输出再送入另一个全连接层,该层通过 sigmoid 激活在每个时间步输出一个大小为 (1, ) 的向量。模型使用二元交叉熵损失函数和 Adam 优化器编译,然后训练 10epochs

class SentimentAnalysisModel(tf.keras.Model):def __init__(self, vocab_size, max_seqlen, **kwargs):super(SentimentAnalysisModel, self).__init__(**kwargs)self.embedding = tf.keras.layers.Embedding(vocab_size, max_seqlen)self.bilstm = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(max_seqlen))self.dense = tf.keras.layers.Dense(64, activation="relu")self.out = tf.keras.layers.Dense(1, activation="sigmoid")def call(self, x):x = self.embedding(x)x = self.bilstm(x)x = self.dense(x)x = self.out(x)return xmodel = SentimentAnalysisModel(vocab_size+1, max_seqlen)
model.build(input_shape=(batch_size, max_seqlen))
model.summary()# compile
model.compile(loss="binary_crossentropy",optimizer="adam", metrics=["accuracy"]
)# train
best_model_file = os.path.join(data_dir, "best_model.h5")
checkpoint = tf.keras.callbacks.ModelCheckpoint(best_model_file,save_weights_only=True,save_best_only=True)
tensorboard = tf.keras.callbacks.TensorBoard(log_dir=logs_dir)
num_epochs = 10
history = model.fit(train_dataset, epochs=num_epochs, validation_data=val_dataset,callbacks=[checkpoint, tensorboard])

可以看到,模型在训练集上的准确率达到了 99.17%,验证集的准确率约为 99.00%。观察训练过程的损失变化情况,以了解模型何时开始在训练集上过拟合。可以看到,训练损失持续下降,但验证损失在经历最初的下降后开始上升。当验证损失开始上升时,模型在训练集上出现过拟合。

训练过程

模型训练过程中在训练集和验证集上的准确率和损失变化情况如下所示:

训练过程监测

3. 模型评估

(1) 检查点回调根据最低验证集损失值保存最佳模型,可以重新加载保存的最佳模型评估保留的测试集:

# evaluate with test set
best_model = SentimentAnalysisModel(vocab_size+1, max_seqlen)
best_model.build(input_shape=(batch_size, max_seqlen))
best_model.load_weights(best_model_file)
best_model.compile(loss="binary_crossentropy",optimizer="adam", metrics=["accuracy"]
)

(2) 对模型进行评估的最简单方法是调用 model.evaluate()

test_loss, test_acc = best_model.evaluate(test_dataset)
print("test loss: {:.3f}, test accuracy: {:.3f}".format(test_loss, test_acc))

输出结果如下所示:

test loss: 0.044, test accuracy: 0.990

(3) 还可以使用 model.predict() 获取预测结果,将它们与标签逐个比较,并使用外部工具(如 scikit-learn )评估模型预测结果:

# predict on batches
labels, predictions = [], []
idx2word[0] = "PAD"
is_first_batch = True
for test_batch in test_dataset:inputs_b, labels_b = test_batchpred_batch = best_model.predict(inputs_b)predictions.extend([(1 if p > 0.5 else 0) for p in pred_batch])labels.extend([l for l in labels_b])if is_first_batch:for rid in range(inputs_b.shape[0]):words = [idx2word[idx] for idx in inputs_b[rid].numpy()]words = [w for w in words if w != "PAD"]sentence = " ".join(words)print("{:d}\t{:d}\t{:s}".format(labels[rid], predictions[rid], sentence))is_first_batch = Falseprint("accuracy score: {:.3f}".format(accuracy_score(labels, predictions)))
print("confusion matrix")
print(confusion_matrix(labels, predictions))

对于测试数据集中第一个批次的 64 个句子,我们重建句子并显示标签(第一列)以及模型的预测(第二列)。可以看到,模型在大多数句子中的预测都正确:

预测结果

评估整个测试数据集的结果。可以看到,测试准确率与调用 evaluate() 方法的结果相同。生成混淆矩阵,在 1000 个测试样本中,情感分析网络正确预测了987次,错误预测了 13 次:

accuracy score: 0.987
confusion matrix
[[497   4][  9 490]]

相关链接

TensorFlow深度学习实战(1)——神经网络与模型训练过程详解
TensorFlow深度学习实战(2)——使用TensorFlow构建神经网络
TensorFlow深度学习实战(3)——深度学习中常用激活函数详解
TensorFlow深度学习实战(4)——正则化技术详解
TensorFlow深度学习实战(5)——神经网络性能优化技术详解
TensorFlow深度学习实战(7)——分类任务详解
TensorFlow深度学习实战(8)——卷积神经网络
TensorFlow深度学习实战(12)——词嵌入技术详解
TensorFlow深度学习实战(13)——神经嵌入详解
TensorFlow深度学习实战(14)——循环神经网络详解
TensorFlow深度学习实战——基于循环神经网络的文本生成模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/903896.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

eslint相关报错收集

[vue/no-multiple-template-root]The template root requires exactly one element.eslint-plugin-vuejsx报错:jsx报错Parsing error: Unexpected token <eslint;ts报错:Parsing error: Unexpected token {eslintmodule报错 ‘mod…

【论文推荐】深度学习赋能地质灾害分析:数据、模型、应用与机遇(用于地质灾害分析的深度学习:数据源)

【论文推荐】深度学习赋能地质灾害分析:数据、模型、应用与机遇(用于地质灾害分析的深度学习:数据源) 【论文推荐】深度学习赋能地质灾害分析:数据、模型、应用与机遇(用于地质灾害分析的深度学习&#xf…

判断用户选择的Excel单元格区域是否跨页?

VBA应用程序开发过程中,经常需要处理用户选中的单元格区域,有的应用场景中,需要限制用户选中区域位于同一页中(以打印预览显示的分页划分),但是VBA对象模型中并没有提供相应的接口,用于快速查询…

题解:洛谷 CF2091E Interesting Ratio

思路推导 我们先对 32 32 32 和 96 96 96 进行二进制拆分。 相同部分(用 α \alpha α 表示): 5 5 5 个 2 2 2。 不同部分(用 β \beta β 表示): 1 1 1 和 3 3 3。 gcd ⁡ ( 32 , 96 ) \gcd(32,9…

linux安装配置PostgreSQL

环境:centos7、SpringBoot、PostgreSQL15 PostgreSQL: Linux downloads (Red Hat family) PostgreSQL安装 1.安装 PostgreSQL Yum 仓库 RPM 包 sudo rpm -ivh https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noar…

docker安装jenkins v2.504.1集群

1 概述 Jenkins是一款开源的、基于Java开发的持续集成(CI)与持续交付(CD)工具,旨在通过自动化构建、测试和部署流程,提升软件开发效率与质量。 ‌ 1.1 核心功能与特点 持续集成与交付‌ Jenkins支持自动化…

5月2日日记

今天看了爸爸推荐的书,叫:“高效能人士的七个习惯” 现在刚看完50页,感觉确实有点东西, 七个习惯分别是: 个人层面1积极主动 2要事第一 3以终为始 社交层面 4知彼解己5 统效综合 6双赢思维 7不断更新 目前还没有…

Aws S3上传优化

上传大约 3.4GB 的 JSON 文件,zip算法压缩后约为 395MB,上传至 S3 效率优化,有一些优化方案可以提高上传速率。下面是几种可能的优化方式,包括选择压缩算法、调整上传方式、以及其他可能的方案。 方案 1. 选择更好的压缩算法 压…

CAD(计算机辅助设计)基础知识点整理

以下是CAD(计算机辅助设计)的基础知识点整理,涵盖核心概念、操作技巧和行业规范,适合新手学习和参考: 一、CAD基本概念 什么是CAD • 利用计算机技术进行设计和绘图的工具,广泛应用于机械、建筑、电子等领…

重构之道:识别并替换不合适使用的箭头函数

1、引言 JavaScript 自 ES6 引入了箭头函数(Arrow Function)后,因其简洁的语法和对 this 的词法绑定机制,迅速成为开发者喜爱的写法之一。然而,并不是所有场景都适合使用箭头函数。 在实际开发中,我们常常会因为追求代码简洁而忽视其潜在问题,例如: this 指向错误不适…

[英语单词] from under

最近在看RCU的资料,读到下面的一句,感觉总是特别怪怪的,就是从单词的组合角度,记录一下。 Use rcu_read_lock() and rcu_read_unlock() to ensure that the structure does not get deleted out from under us。 意思是我们还在使…

Python 中 DAO 层使用泛型的探索

方法一: from types import UnionType from typing import TypeVar, Generic, TypeModelT TypeVar(ModelT)def _new_cls_with_grm_generic_args(cls, __item):new_cls type(f"{cls.__name__}[{__item.__name__}]", (cls,), {})new_cls._grm_generic_ar…

Cesium 环境搭建

一、前提条件 1. **安装 Node.js** - 访问 [Node.js 官方网站](https://nodejs.org/),下载并安装适合你操作系统的版本。Node.js 用于运行本地开发服务器和安装依赖。 2. **安装 Vue CLI** - Vue CLI 是一个用于快速开发 Vue.js 项目的工具。在终端中运行以下…

DarkGS:论文解读与全流程环境配置及数据集测试【基于Ubuntu20.04 】【2025最新实战无坑版!!】

一、背景及意义 DarkGS是一个创新性的研究项目,旨在解决机器人在黑暗或低光照环境中探索的问题。传统的3D重建和视觉定位系统在光照条件不佳时表现不佳,这严重限制了机器人在黑暗环境中的应用,如夜间救援、深海探索或洞穴勘测等场景。 这项工…

(八)RestAPI 毛子(Unit Testing/Integration)

文章目录 项目地址一、Unit Testing1.1 创建X unit 测试项目1. 创建项目目录2. 管理包1.2 创建CreateEntryDtoValidator测试1.3 创建CreateEntryDtoValidator测试二、Integration test2.1 创建Integration test环境1. 安装所需要的包2.2 配置基础设置1. 数据库链接DevHabitWebA…

设计模式--桥接模式详解

桥接模式(bridge pattern) 桥接模式时将抽象部分与它的实现部分分离,使他们可以独立的变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或者接口(interface)模式&…

关于 live555延迟优化之缓存区优化“StreamParser::afterGettingBytes() warning: read”” 的解决方法

若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/146354088 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…

Vite 动态导入静态资源与自动依赖发现实战解析

一、Vite 动态导入静态资源的实现方案 在 Vite 中,动态加载图片、JSON 等静态资源是高频需求,但动态路径拼接可能导致构建失败或资源未识别。以下结合示例代码,分析三种实现方案: 1. 方案一:new URL 动态路径转换 通…

在matlab中使用UAV123官方toolkits测试自己的数据集

一、前言 最近需要将自己的跟踪代码在自己拍摄的数据集上进行测试,这里我选择使用 UAV123 官方 toolkits 进行配置。首先需要搞清楚这部分代码是如何运行的,精度图和成功率图是如何绘制出来的,然后再将自己的数据集加进去进行测试。 二、UA…

9.idea中创建springboot项目_jdk1.8

9. idea中创建springboot项目_jdk1.8 步骤 1:打开 IntelliJ IDEA 并创建新项目 启动 IntelliJ IDEA。在欢迎界面,点击 New Project(或通过菜单栏 File > New > Project)。 步骤 2:选择 Maven 项目类型 在左侧…