【再学Tensorflow2】TensorFlow2的建模流程:电影评论分析

news2025/1/18 10:02:22

TensorFlow2的建模流程:电影评论分析

  • 词嵌入技术
  • 数据准备
  • 定义模型
  • 训练模型
  • 评估模型
  • 使用模型
  • 保存模型
  • 参考资料

情感分析无处不在,它是一种基于自然语言处理的分类技术。其主要解决的问题是给定一段话,判断这段话是正面的还是负面的。情感分析的本质就是根据已知的文字和情感符号,推测文字是正面的还是负面的。

进行情感分析有如下难点:第一,文字非结构化,有长有短,很难适合经典的机器学习分类模型;第二,特征不容易提取。文字可能是谈论的某个主题,也可能是某个人物、商品或事件。人工提取特征耗时费力。第三,词与词之间有联系,把这部分信息纳入模型不容易。

深度学习适合做文字处理和语义理解,是因为深度学习结构灵活,其底层利用词嵌入技术可以避免文字长短不均带来的处理困难。本文将使用电影评论文字为例进行分析。

词嵌入技术

词嵌入,简单地说,就是给每个词赋一个向量,向量代表空间里的点,含义接近的词,其向量也接近,这样对于词的操作就可以转换为对于向量的操作了。在深度学习中,这被叫做张量(Tensor)。
用张量表示词的好处在于:

  1. 可以克服文字长短不均的问题
  2. 词本身无法形成特征,但是张量就是抽象的量化,它是通过多层神经网络层层抽象计算出来的
  3. 文本是有词组成的,文本的特征可以由词的张量组合。

词的嵌入最经典的方法是Word2Vec

数据准备

IMDB数据集的目标是根据电影评论的文本内容预测评论的情感标签。训练集有20000条电影评论文本,测试集有5000条电影评论文本,其中正面评论和负面评论都各占一半。
电影评论
文本数据预处理较为繁琐,包括中文切词(本示例不涉及),构建词典,编码转换,序列填充,构建数据管道等等。

在Tensorflow2中完成文本数据预处理的常用方案有两种

  • 第一种是利用tf.keras.preprocessing中的Tokenizer词典构建工具和tf.keras.utils.Sequence构建文本数据生成器管道。
  • 第二种是使用tf.data.Dataset搭配tf.keras.layers.experimental.preprocessing.TextVectorization预处理层。

第二种方法为TensorFlow原生方式,相对也更加简单一些,这里选择第二种方法:
导入依赖库

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

import tensorflow as tf
from tensorflow.keras import models, layers, preprocessing, optimizers, losses, metrics
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization
import re, string

数据路径

train_data_path = '../DemoData/imdb/train.csv'
test_data_path = '../DemoData/imdb/test.csv'

默认参数

MAX_WORDS = 10000 # 仅考虑最高频的10000个词
MAX_LEN = 200 # 每个样本保留200个词的长度
BATCH_SIZE = 20

构建管道

# 构建管道
def split_line(line):
    arr = tf.strings.split(line, '\t')
    label = tf.expand_dims(tf.cast(tf.strings.to_number(arr[0]), tf.int32), axis=0)
    text = tf.expand_dims(arr[1], axis=0)
    return text, label

ds_train_raw = tf.data.TextLineDataset(filenames=[train_data_path]).map(split_line, num_parallel_calls=tf.data.experimental.AUTOTUNE).shuffle(buffer_size=1000).batch(BATCH_SIZE).prefetch(tf.data.experimental.AUTOTUNE)

ds_test_raw = tf.data.TextLineDataset(filenames=[test_data_path]).map(split_line, num_parallel_calls=tf.data.experimental.AUTOTUNE).batch(BATCH_SIZE).prefetch(tf.data.experimental.AUTOTUNE)

构建词典

def clean_text(text):
    lowercase = tf.strings.lower(text)
    stripped_html = tf.strings.regex_replace(lowercase, '<br />', ' ')
    cleaned_punctuation = tf.strings.regex_replace(stripped_html,
                                                   '[%s]' % re.escape(string.punctuation), '')
    return cleaned_punctuation


vectorize_layer = TextVectorization(
    standardize=clean_text,
    split='whitespace',
    max_tokens=MAX_WORDS - 1,  #有一个留给占位符
    output_mode='int',
    output_sequence_length=MAX_LEN)

ds_text = ds_train_raw.map(lambda text, label: text)
vectorize_layer.adapt(ds_text)
print(vectorize_layer.get_vocabulary()[0:100])

输出:

['', '[UNK]', 'the', 'and', 'a', 'of', 'to', 'is', 'in', 'it', 'i', 'this', 'that', 'was', 'as', 'for', 'with', 'movie', 'but', 'film', 'on', 'not', 'you', 'his', 'are', 'have', 'be', 'he', 'one', 'its', 'at', 'all', 'by', 'an', 'they', 'from', 'who', 'so', 'like', 'her', 'just', 'or', 'about', 'has', 'if', 'out', 'some', 'there', 'what', 'good', 'more', 'when', 'very', 'she', 'even', 'my', 'no', 'would', 'up', 'time', 'only', 'which', 'story', 'really', 'their', 'were', 'had', 'see', 'can', 'me', 'than', 'we', 'much', 'well', 'get', 'been', 'will', 'into', 'people', 'also', 'other', 'do', 'bad', 'because', 'great', 'first', 'how', 'him', 'most', 'dont', 'made', 'then', 'them', 'films', 'movies', 'way', 'make', 'could', 'too', 'any']

单词编码

ds_train = ds_train_raw.map(lambda text,label:(vectorize_layer(text),label)).prefetch(tf.data.experimental.AUTOTUNE)
ds_test = ds_test_raw.map(lambda text, label:(vectorize_layer(text), label)).prefetch(tf.data.experimental.AUTOTUNE)

定义模型

使用Keras接口有以下3种方式构建模型:

  1. 使用Sequential按层顺序构建模型
  2. 使用函数式API构建任意结构模型
  3. 继承Model基类构建自定义模型
tf.keras.backend.clear_session()


class CNNModel(models.Model):
    def __init__(self):
        super(CNNModel, self).__init__()

    def build(self, input_shape):
        self.embedding = layers.Embedding(MAX_WORDS, 7, input_length=MAX_LEN)
        self.conv_1 = layers.Conv1D(16, kernel_size=5, name='conv_1', activation='relu')
        self.pool_1 = layers.MaxPool1D(name='pool_1')
        self.conv_2 = layers.Conv1D(128, kernel_size=2, name='conv_2', activation='relu')
        self.pool_2 = layers.MaxPool1D(name='pool_2')
        self.flatten = layers.Flatten()
        self.dense = layers.Dense(1, activation='sigmoid')
        super(CNNModel, self).build(input_shape)

    def call(self, x):
        x = self.embedding(x)
        x = self.conv_1(x)
        x = self.pool_1(x)
        x = self.conv_2(x)
        x = self.pool_2(x)
        x = self.flatten(x)
        x = self.dense(x)
        return x

    # 用于显示Output shape
    def summary(self):
        x_input = layers.Input(shape=MAX_LEN)
        output = self.call(x_input)
        model = tf.keras.Model(inputs=x_input, outputs=output)
        model.summary()


model = CNNModel()
model.build(input_shape=(None, MAX_LEN))
model.summary()

模型概况:

Model: "model"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 200)]             0         
                                                                 
 embedding (Embedding)       (None, 200, 7)            70000     
                                                                 
 conv_1 (Conv1D)             (None, 196, 16)           576       
                                                                 
 pool_1 (MaxPooling1D)       (None, 98, 16)            0         
                                                                 
 conv_2 (Conv1D)             (None, 97, 128)           4224      
                                                                 
 pool_2 (MaxPooling1D)       (None, 48, 128)           0         
                                                                 
 flatten (Flatten)           (None, 6144)              0         
                                                                 
 dense (Dense)               (None, 1)                 6145      
                                                                 
=================================================================
Total params: 80,945
Trainable params: 80,945
Non-trainable params: 0
_________________________________________________________________

训练模型

训练模型通常有3种方法:内置fit方法,内置train_on_batch方法,以及自定义训练循环。
这里我们选择通过自定义训练循环来训练模型:

#打印时间分割线
@tf.function
def printbar():
    today_ts = tf.timestamp()%(24*60*60)

    hour = tf.cast(today_ts//3600+8,tf.int32)%tf.constant(24)
    minite = tf.cast((today_ts%3600)//60,tf.int32)
    second = tf.cast(tf.floor(today_ts%60),tf.int32)

    def timeformat(m):
        if tf.strings.length(tf.strings.format("{}",m))==1:
            return(tf.strings.format("0{}",m))
        else:
            return(tf.strings.format("{}",m))

    timestring = tf.strings.join([timeformat(hour),timeformat(minite),
                timeformat(second)],separator = ":")
    tf.print("=========="*8+timestring)

定义训练和测试步骤:

optimizer = optimizers.Nadam()
loss_func = losses.BinaryCrossentropy()

train_loss = metrics.Mean(name='train_loss')
train_metric = metrics.BinaryAccuracy(name='train_accuracy')

valid_loss = metrics.Mean(name='valid_loss')
valid_metric = metrics.BinaryAccuracy(name='valid_accuracy')


@tf.function
def train_step(model, features, labels):
    with tf.GradientTape() as tape:
        predictions = model(features,training = True)
        loss = loss_func(labels, predictions)
    gradients = tape.gradient(loss, model.trainable_variables)
    optimizers.apply_gradients(zip(gradients, model.trainable_variables))

    train_loss.update_state(loss)
    train_metric.update_state(labels, predictions)


@tf.function
def valid_step(model, features, labels):
    predictions = model(features,training = False)
    batch_loss = loss_func(labels, predictions)
    valid_loss.update_state(batch_loss)
    valid_metric.update_state(labels, predictions)


def train_model(model,ds_train,ds_valid,epochs):
    for epoch in tf.range(1,epochs+1):

        for features, labels in ds_train:
            train_step(model,features,labels)

        for features, labels in ds_valid:
            valid_step(model,features,labels)

        #此处logs模板需要根据metric具体情况修改
        logs = 'Epoch={},Loss:{},Accuracy:{},Valid Loss:{},Valid Accuracy:{}' 

        if epoch%1==0:
            printbar()
            tf.print(tf.strings.format(logs,
            (epoch,train_loss.result(),train_metric.result(),valid_loss.result(),valid_metric.result())))
            tf.print("")

        train_loss.reset_states()
        valid_loss.reset_states()
        train_metric.reset_states()
        valid_metric.reset_states()

train_model(model,ds_train,ds_test,epochs = 6)

注意:运行失败!莫名其妙地重启Kernel。

评估模型

通过自定义训练循环训练的模型没有经过编译,无法直接使用model.evaluate(ds_valid)方法:

def evaluate_model(model,ds_valid):
    for features, labels in ds_valid:
         valid_step(model,features,labels)
    logs = 'Valid Loss:{},Valid Accuracy:{}' 
    tf.print(tf.strings.format(logs,(valid_loss.result(),valid_metric.result())))

    valid_loss.reset_states()
    train_metric.reset_states()
    valid_metric.reset_states()

评估模型:

evaluate_model(model,ds_test)

使用模型

可以使用以下方法:

  • model.predict(ds_test)
  • model(x_test)
  • model.call(x_test)
  • model.predict_on_batch(x_test)

推荐优先使用model.predict(ds_test)方法,既可以对Dataset,也可以对Tensor使用。

model.predict(ds_test)

或者

for x_test,_ in ds_test.take(1):
    print(model(x_test))
    #以下方法等价:
    #print(model.call(x_test))
    #print(model.predict_on_batch(x_test))

保存模型

推荐使用TensorFlow原生方式保存模型。

model.save('../../data/tf_model_savedmodel', save_format="tf")
print('export saved model.')

model_loaded = tf.keras.models.load_model('../../data/tf_model_savedmodel')
model_loaded.predict(ds_test)

参考资料

  1. [Keras快速上手:基于Python的深度学习实战]
  2. 30天吃掉那只Tensorflow2

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

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

相关文章

KDE桌面环境下电源管理对应的文件及选项

在KDE桌面环境下&#xff0c;“系统设置”—>“电源管理”—>“高级电源设置”的界面如下&#xff1a; 点击界面中的“配置通知”选项&#xff0c;界面如下所示&#xff1a; 其中图形界面下的各项设置对应的文件为~/.config/powerdevil.notifyrc。上图状态下&#xff0c…

Elasticsearch8.X入门实战(七)Java API操作:员工信息

Elasticsearch本身使用Java开发,因此对Java的支持能力是最好的。本节通过对员工信息建立索引,并对索引数据进行添加、修改等,讲解Elasticsearch的相关Java客户端 API的操作。 1.新建项目 在Eclipse中新建Maven项目elasticsearch_demo,在pom.xml文件中加入项目的依赖库,…

vue2[webpack]中接入vue3[vite]的qiankun微前端服务

本文记录在 vue2[webpack]老项目中&#xff0c;使用qiankun.js微前端服务&#xff0c;接入vue3[vite]新项目。 纯vue2[webpack]技术项目可参考以前的文章&#xff1a; vue项目落地(qiankun.js)微前端服务-zhanghaoran’s blog vue2为基座主应用&#xff1b; vue3为子应用。 改造…

cursor:pin S wait on X故障诊分析

1. 故障概述 7:15&#xff0c;二节点出现大量的“cursor: pin S wait on X”等待事件&#xff0c;数据库性能下降&#xff0c;持续到7:19分恢复正常&#xff0c;持续时间4分钟左右。下面是详细的故障分析诊断过程。2. 故障分析 2.1. 故障现象 7:15,系统出现大量“curs…

Lexical Simplification with Pretrained Encoders 论文精读

Lexical Simplification with Pretrained Encoders 论文精读InformationAbstract1 Introduction2 Related Work3 Unsupervised Lexical Simplification3.1 The BERT model3.2 Simplification Candidate generation3.3 Substitution Ranking3.4 Simplification Algorithm4 Exper…

【半监督医学图像分割 ISBI】2022-ICT-MedSeg

【半监督医学图像分割 ISBI】2022-ICT-MedSeg 论文题目&#xff1a;AN EMBARRASSINGLY SIMPLE CONSISTENCY REGULARIZATION METHOD FOR SEMI-SUPERVISED MEDICAL IMAGE SEGMENTATION 中文题目&#xff1a;一种简单的一致性正则化半监督医学图像分割方法 论文链接&#xff1a;ht…

基于redis缓存查询店铺

基于redis缓存查询店铺 Overridepublic Result queryById(Long id) {//从redis中查询商铺缓存String shopJson stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY id);//判断缓存是否命中if (StrUtil.isNotBlank(shopJson)){//命中&#xff0c;则返回店铺信息Shop shop …

统计同成绩学生

目录 1038:统计同成绩学生 输入格式&#xff1a; 输出格式&#xff1a; 样例&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 代码长度限制: 时间限制: 内存限制: 思路: 1.暴力法 1.1查找函数 1.1.2查找函数代码 1.2main函数 1.2.1main函数代码 1.3完整代码…

亚马逊云科技Build On - 使用Serverless搭建创新零售应用的惊喜体验

近日有幸参加了亚马逊云科技Build On第三季的学习培训&#xff0c;深刻感受到亚马逊在云服务方面技术的先进性。在培训后进行了实操体验&#xff0c;通过Serverless 的事件驱动架构搭建一个快消行业场景的应用——咖啡店的订餐系统。只用了短短的几小时&#xff0c;就完成了整个…

学生管理系统(Python实现)

文章目录学生管理系统介绍学生管理系统效果展示代码实现入口函数打印菜单新增学生信息显示学生信息查找学生信息删除学生信息实现存档读档打包成exe程序学生管理系统介绍 学生管理系统是为了对学校学生信息进行管理而开发的一款软件&#xff0c;下面我们来实现一个命令行版本的…

【UE4 第一人称射击游戏】12-全自动步枪并显示剩余弹药量

上一篇&#xff1a; 【UE4 第一人称射击游戏】11-武器跟随鼠标移动并添加开火音效 本篇效果&#xff1a; 步骤&#xff1a; 1.打开“Weapon_Base”&#xff0c;添加一个整数类型&#xff0c;名为“Ammo”的变量&#xff0c;用来表示弹药量。编译后默认值设为30 再添加一个浮点…

操作系统~Linux~线程控制,POSIX线程库的使用

1.POSIX线程库 与线程有关的函数构成了一个完整的系列&#xff0c;绝大多数函数的名字都是以“pthread_”开头的要使用线程库中的函数&#xff0c;要通过引入头文件<pthread.h>链接这些线程函数库时要使用编译器命令的“-lpthread”选项2.创建线程-pthread_create() 功…

在HTML页面中引用Markdown编辑器(Editor.md)

目录 1、下载Ediotor.md 2、引入Ediotor.md 3、确定Ediotor.md在哪里显示 最近写博客项目&#xff0c;用到了Markdown编辑器&#xff0c;这里介绍一款国内好用的Markdown编辑器&#xff1a;Editor.md&#xff0c;下面介绍一下该编辑器以及如果在页面中引用。 1、下载Edioto…

【TypeScript】类型兼容性与相关类型讲解

目录 类型兼容性 对象类型兼容性 接口类型兼容性 函数类型兼容性 索引签名类型 映射类型 索引查询类型 交叉类型 类型兼容性 在TS中&#xff0c;类型采用的是结构化类型系统&#xff0c;也叫做 duck typing&#xff08;鸭子类型&#xff09;&#xff0c;类型检查关注的…

电脑c盘备份怎么操作?备份C盘的6个步骤

电脑出现问题&#xff0c;想要修复又不知该怎么操作。可能你会想要重装电脑的系统&#xff0c;但是在操作之前&#xff0c;一定要对电脑重要的数据做好备份。尤其是电脑C盘里面存储着我们很多重要的数据&#xff0c;电脑c盘备份怎么进行&#xff1f;跟着下面6个操作步骤进行&am…

<Linux线程池、线程安全(单例模式、STL、智能指针)、读者写者问题及线程扩展与总结>——《Linux》

目录 1.线程池 1.1 线程池: 1.2 线程池的应用场景&#xff1a; 1.3 线程池的种类&#xff1a; 1.4 线程池示例&#xff1a; 1.5 线程池编程模拟实现&#xff1a; 2. 线程安全的单例模式 2.1 什么是单例模式 2.2 什么是设计模式 2.3 单例模式的特点 2.3.1 饿汉实现方…

驱动相关基础

1.程序分类 1.1 裸机程序&#xff1a;直接运行在对应硬件的的程序 1.2 应用程序&#xff1a;只能运行在对应操作系统上的程序 2. 计算机系统的层次结构 2.1 无操作系统的简单的两层结构 2.2 有操作系统的四层层次结构 3. 操作系统 狭义&#xff1a;给应用程序提供运行环…

Python图像处理【7】采样、卷积与离散傅里叶变换

采样、卷积与离散傅里叶变换0. 前言1. 图像傅里叶变换1.1 傅里叶变换基础1.2 傅里叶变换应用1.3 逆傅里叶变换应用2. 利用采样改变图像分辨率2.1 上采样2.2 下采样小结系列链接0. 前言 采样 (Sampling) 是用于选择/丢弃图像像素的空间操作&#xff0c;通常用于增加/减小图像大…

(byte)1658385462>>16=-40,怎么算的?

正文 在 Github 项目mongo-java-driver有一个类ObjectId.java&#xff0c;它的作用是生成唯一 id 的&#xff0c;它的核心实现是下面这样一段代码 [1]&#xff1a; public void putToByteBuffer(final ByteBuffer buffer) {notNull("buffer", buffer);isTrueArgume…

【数据结构Java版】树与二叉树的相关知识全解

目录 一、树型结构 &#xff08;1&#xff09;树的定义 &#xff08;2&#xff09;树的基本术语 &#xff08;3&#xff09;树的存储结构 二、二叉树 &#xff08;1&#xff09;二叉树的定义 &#xff08;2&#xff09;两种特殊二叉树 1.满二叉树 2.完全二叉树 &…