深度学习处理文本(5)

导出能够处理原始字符串的模型

在前面的例子中,我们将文本标准化、拆分和建立索引 都作为tf.data管道的一部分。但如果想导出一个独立于这个管道的模型,我们应该确保模型包含文本预处理(否则需要在生产环境中重新实现,这可能很困难,或者可能导致训练数据与生产数据之间的微妙差异)​。幸运的是,这很简单。我们只需创建一个新的模型,复用TextVectorization层,并将其添加到刚刚训练好的模型中。

python 复制代码
inputs = keras.Input(shape=(1,), dtype="string")  ←----每个输入样本都是一个字符串
processed_inputs = text_vectorization(inputs)  ←----应用文本预处理
outputs = model(processed_inputs)  ←----应用前面训练好的模型
inference_model = keras.Model(inputs, outputs)  ←----将端到端的模型实例化

我们得到的模型可以处理原始字符串组成的批量,如下所示。

python 复制代码
import tensorflow as tf
raw_text_data = tf.convert_to_tensor([
    ["That was an excellent movie, I loved it."],
])
predictions = inference_model(raw_text_data)
print(f"{float(predictions[0] * 100):.2f} percent positive")

将单词作为序列处理:序列模型方法

前面几个例子清楚地表明,词序 很重要。基于顺序的手动特征工程(比如二元语法)可以很好地提高精度。现在请记住:深度学习的历史就是逐渐摆脱手动特征工程 ,让模型仅通过观察数据来自己学习特征。如果不手动寻找基于顺序的特征,而是让模型直接观察原始单词序列并自己找出这样的特征,那会怎么样呢?这就是序列模型(sequence model)的意义所在。要实现序列模型,首先需要将输入样本表示为整数索引序列(每个整数代表一个单词)​。然后,将每个整数映射为一个向量,得到向量序列。最后,将这些向量序列输入层的堆叠,这些层可以将相邻向量的特征交叉关联,它可以是一维卷积神经网络、RNN或Transformer。

2016年~2017年,双向RNN(特别是双向LSTM)被认为是最先进的序列模型。你已经熟悉了这种架构,所以第一个序列模型示例将用到它。然而,如今的序列模型几乎都是用Transformer实现的,我们稍后会介绍。奇怪的是,一维卷积神经网络在NLP中一直没有很流行,尽管根据我自己的经验,一维深度可分离卷积的残差堆叠通常可以实现与双向LSTM相当的性能,而且计算成本大大降低。

第一个实例

我们来看一下第一个序列模型实例。首先,准备可以返回整数序列的数据集,如代码清单11-12所示。

代码清单11-12 准备整数序列数据集

python 复制代码
from tensorflow.keras import layers

max_length = 600
max_tokens = 20000
text_vectorization = layers.TextVectorization(
    max_tokens=max_tokens,
    output_mode="int",
    output_sequence_length=max_length,  ←----为保持输入大小可控,我们在前600个单词处截断输入。这是一个合理的选择,因为评论的平均长度是233个单词,只有5%的评论超过600个单词
)
text_vectorization.adapt(text_only_train_ds)

int_train_ds = train_ds.map(
    lambda x, y: (text_vectorization(x), y),
    num_parallel_calls=4)
int_val_ds = val_ds.map(
    lambda x, y: (text_vectorization(x), y),
    num_parallel_calls=4)
int_test_ds = test_ds.map(
    lambda x, y: (text_vectorization(x), y),
    num_parallel_calls=4)

下面来创建模型。要将整数序列转换为向量序列,最简单的方法是对整数进行one-hot编码(每个维度代表词表中的一个单词)​。在这些one-hot向量之上,我们再添加一个简单的双向LSTM,如代码清单11-13所示。

代码清单11-13 构建于one-hot编码的向量序列之上的序列模型

python 复制代码
import tensorflow as tf
inputs = keras.Input(shape=(None,), dtype="int64")  ←----每个输入是一个整数序列
embedded = tf.one_hot(inputs, depth=max_tokens)  ←----将整数编码为20 000维的二进制向量
x = layers.Bidirectional(layers.LSTM(32))(embedded)  ←----添加一个双向LSTM
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(1, activation="sigmoid")(x)  ←----最后添加一个分类层
model = keras.Model(inputs, outputs)
model.compile(optimizer="rmsprop",
              loss="binary_crossentropy",
              metrics=["accuracy"])
model.summary()

下面我们来训练模型,如代码清单11-14所示。

代码清单11-14 训练第一个简单的序列模型

python 复制代码
callbacks = [
    keras.callbacks.ModelCheckpoint("one_hot_bidir_lstm.keras",
                                    save_best_only=True)
]
model.fit(int_train_ds, validation_data=int_val_ds, epochs=10,
          callbacks=callbacks)
model = keras.models.load_model("one_hot_bidir_lstm.keras")
print(f"Test acc: {model.evaluate(int_test_ds)[1]:.3f}")

我们得到两个观察结果。第一,这个模型的训练速度非常慢,尤其是与轻量级模型相比。这是因为输入很大:每个输入样本被编码成尺寸为(600, 20000)的矩阵(每个样本包含600个单词,共有20 000个可能的单词)​。一条影评就有12 000 000个浮点数。双向LSTM需要做很多工作。第二,这个模型的测试精度只有87%,性能还不如一元语法二进制模型,后者的速度还很快。显然,使用one-hot编码将单词转换为向量,这是我们能做的最简单的事情,但这并不是一个好主意。有一种更好的方法:词嵌入(word embedding)​。

相关推荐
Wilber的技术分享4 分钟前
【机器学习实战笔记 14】集成学习:XGBoost算法(一) 原理简介与快速应用
人工智能·笔记·算法·随机森林·机器学习·集成学习·xgboost
巴里巴气5 分钟前
selenium基础知识 和 模拟登录selenium版本
爬虫·python·selenium·爬虫模拟登录
19899 分钟前
【零基础学AI】第26讲:循环神经网络(RNN)与LSTM - 文本生成
人工智能·python·rnn·神经网络·机器学习·tensorflow·lstm
JavaEdge在掘金15 分钟前
Redis 数据倾斜?别慌!从成因到解决方案,一文帮你搞定
python
ansurfen19 分钟前
我的第一个AI项目:从零搭建RAG知识库的踩坑之旅
python·llm
前端付豪24 分钟前
20、用 Python + API 打造终端天气预报工具(支持城市查询、天气图标、美化输出🧊
后端·python
burg_xun24 分钟前
【Vibe Coding 实战】我如何用 AI 把一张草图变成了能跑的应用
人工智能
前端付豪30 分钟前
19、用 Python + OpenAI 构建一个命令行 AI 问答助手
后端·python
酌沧1 小时前
AI做美观PPT:3步流程+工具测评+避坑指南
人工智能·powerpoint
狂师1 小时前
啥是AI Agent!2025年值得推荐入坑AI Agent的五大工具框架!(新手科普篇)
人工智能·后端·程序员