深度学习处理文本(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)​。

相关推荐
AngelPP2 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年2 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
AI探索者2 小时前
LangGraph StateGraph 实战:状态机聊天机器人构建指南
python
AI探索者2 小时前
LangGraph 入门:构建带记忆功能的天气查询 Agent
python
九狼2 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS2 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区3 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈3 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
FishCoderh3 小时前
Python自动化办公实战:批量重命名文件,告别手动操作
python
躺平大鹅3 小时前
Python函数入门详解(定义+调用+参数)
python