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

相关推荐
用户835629078051几秒前
使用Python自动化移除Excel公式,保留纯净数值
后端·python
Pocker_Spades_A几秒前
Python快速入门专业版(五十):Python异常处理:try-except语句(捕获单一与多个异常)
开发语言·python
大囚长5 分钟前
从AI角度深入解析和论述哲学的终极答案‘语言即世界‘
人工智能·搜索引擎
北京地铁1号线30 分钟前
机器学习笔试选择题:题组2
人工智能·算法·机器学习
Gerlat小智1 小时前
【Python精讲 16】实战项目演练(二):用Flask/FastAPI发布你的第一个Web API
python·flask·fastapi
算家云1 小时前
OpenAI秘密测试ChatGPT安全路由,情感对话触发GPT-5严格审查
人工智能·chatgpt·算家云·openai秘密测试安全路由·算家计算·租算力,就到算家云
新加坡内哥谈技术1 小时前
OpenAI近日推出了一项名为 ChatGPT Pulse 的全新功能
人工智能·chatgpt
hunteritself1 小时前
DeepSeek V3.1-Terminus、阿里 Qwen3-Max、ChatGPT Pulse 同周登场!| AI Weekly 9.22-9.28
人工智能·ios·chatgpt·语音识别·iphone
ai_xiaogui1 小时前
ChatGPT开源模型发布!部署20B/120B AI模型实战指南
人工智能·chatgpt·20b 120b模型部署教程·本地部署chatgpt模型实战·高性能加速开源ai模型开发·开源模型windows配置方法
春末的南方城市1 小时前
阿里开源视频修复方法Vivid-VR:以独特策略与架构革新,引领生成视频修复高质量可控新时代。
人工智能·深度学习·机器学习·计算机视觉·aigc