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

相关推荐
CoovallyAIHub2 分钟前
全球OCR新标杆!百度0.9B小模型斩获四项SOTA,读懂复杂文档像人一样自然
深度学习·算法·计算机视觉
weixin_377634844 分钟前
【强化学习】RLMT强制 CoT提升训练效果
人工智能·算法·机器学习
Francek Chen12 分钟前
【深度学习计算机视觉】14:实战Kaggle比赛:狗的品种识别(ImageNet Dogs)
人工智能·pytorch·深度学习·计算机视觉·kaggle·imagenet dogs
dxnb2216 分钟前
Datawhale25年10月组队学习:math for AI+Task3线性代数(下)
人工智能·学习·线性代数
波诺波27 分钟前
通用装饰器示例
开发语言·python
渡我白衣32 分钟前
《未来的 AI 操作系统(四)——AgentOS 的内核设计:调度、记忆与自我反思机制》
人工智能·深度学习·机器学习·语言模型·数据挖掘·人机交互·语音识别
飞哥数智坊1 小时前
Claude Skills 实测体验:不用翻墙,GLM-4.6 也能玩转
人工智能·claude·chatglm (智谱)
程序员爱钓鱼1 小时前
Python编程实战 · 基础入门篇 | 变量与命名规范
后端·python
007php0071 小时前
猿辅导Java面试真实经历与深度总结(二)
java·开发语言·python·计算机网络·面试·职场和发展·golang
惊鸿.Jh1 小时前
C++可变参数模板
开发语言·python