“嵌入”在大语言模型中是解决把句子转换成向量表示的技术
上一篇:《人工智能是这样理解“情绪”的》
序言:这段话要优化吗?““嵌入”是一种将句子、单词或其他语言单位转换为向量表示的技术。这个向量通常位于高维空间中,它以一种能够表达相似性的方式编码出文本的含义或上下文。嵌入层的作用就在于把离散的语言符号(如单词或句子)转换成连续的向量,使得模型能更好地理解和处理语言之间的关系。其实我们人类的大脑也是这样干的,只是我们自己无法感知而已,我们最终得到的就是某个“记忆”,可以供人类随时使用的“记忆”也就是特征,所以让人工智能来识别人类说话中包含的情绪也只是将整句话转换成了向量后才能通过计算得到结论。
在 TensorFlow 人工智能开发框架中使用“嵌入”层
正如你在 Dense 和 Conv2D 中所见,tf.keras 使用嵌入层来实现嵌入。这会创建一个查找表,将一个整数映射到一个嵌入表,其中的内容是表示该整数对应单词的向量系数。例如,在上个章节的《傲慢与偏见》示例中,x 和 y 坐标会为我们提供某个书中人物的嵌入。当然,在实际的 NLP 问题中,我们会使用远多于两个维度。因此,向量空间中的向量方向可以视为编码了单词的“含义”,而那些指向大致相同方向的相似向量所代表的单词则可以被认为是与该单词相关的。
嵌入层将被随机初始化——也就是说,向量的坐标一开始是完全随机的,在训练过程中通过反向传播学习得到。当训练完成时,嵌入会粗略编码出单词之间的相似性,使我们可以基于这些单词的向量方向识别出某种程度上相似的单词。
这些内容相当抽象,所以我认为理解嵌入的最佳方式是动手实践。让我们从使用第五章的讽刺数据集来构建一个讽刺检测器开始。
使用”嵌入”技术设计一个讽刺情绪检测器
在第五章中,你加载并对一个名为《讽刺检测新闻标题数据集》的 JSON 数据集(简称讽刺数据集)进行了预处理。处理完成后,你会得到训练和测试数据及标签的列表。这些列表可以使用以下代码转换为 TensorFlow 训练所用的 Numpy 格式:
import numpy as np
training_padded = np.array(training_padded)
training_labels = np.array(training_labels)
testing_padded = np.array(testing_padded)
testing_labels = np.array(testing_labels)
这些数据是通过一个指定了最大词汇量和词汇外(OOV)标记的分词器生成的:
tokenizer = Tokenizer(num_words=vocab_size, oov_token=oov_tok)
要初始化嵌入层,你需要词汇量大小和指定的嵌入维度:
tf.keras.layers.Embedding(vocab_size, embedding_dim),
这将为每个单词初始化一个具有 embedding_dim 个点的数组。比如,如果 embedding_dim 为 16,那么词汇表中的每个单词都会被分配一个 16 维的向量。
随着时间推移,这些维度将通过反向传播学习得到,因为网络在学习如何将训练数据与标签匹配。
接下来一个重要步骤是将嵌入层的输出传递到一个全连接层。最简单的方法是像在卷积神经网络中一样使用池化。在这种情况下,嵌入的维度会被平均化,以产生一个固定长度的输出向量。
例如,考虑以下模型架构:
model = tf.keras.Sequential([
tf.keras.layers.Embedding(10000, 16),
tf.keras.layers.GlobalAveragePooling1D(),
tf.keras.layers.Dense(24, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(loss='binary_crossentropy',
optimizer='adam', metrics=['accuracy'])
这里定义了一个嵌入层,给定词汇量大小(10000)和一个 16 维的嵌入。让我们使用 model.summary 查看网络中的可训练参数数量:
Model: "sequential_2"
Layer (type) Output Shape Param #
=================================================================
embedding_2 (Embedding) (None, None, 16) 160000
global_average_pooling1d_2 ( (None, 16) 0
dense_4 (Dense) (None, 24) 408
dense_5 (Dense) (None, 1) 25
=================================================================
Total params: 160,433
Trainable params: 160,433
Non-trainable params: 0
由于嵌入层有一个 10,000 个单词的词汇表,且每个单词将是 16 维的向量,因此总的可训练参数数将为 160,000。平均池化层的可训练参数为 0,因为它只是将嵌入层中的参数平均,以获得一个 16 值的向量。
该向量随后被输入到 24 个神经元的全连接层。请记住,一个全连接神经元实际上是通过权重和偏置计算的,因此它将需要学习 (24 × 16) + 16 = 408 个参数。
该层的输出随后传递到最终的单神经元层,其中将有 (1 × 24) + 1 = 25 个参数需要学习。
如果我们训练该模型,在 30 个训练周期(epoch)后,我们可以获得 99%以上的训练准确率,但验证准确率仅为约 81%(图 6-2)。
这看起来似乎是合理的曲线,因为验证数据可能包含许多训练数据中不存在的单词。然而,如果你检查 30 个训练周期中训练和验证的损失曲线,就会发现一个问题。尽管你预期训练准确率高于验证准确率,但一个明显的过拟合指标是验证准确率随着时间略微下降(在图 6-2 中),而验证损失却急剧增加,如图 6-3 所示。
像这样的过拟合在 NLP 模型中很常见,因为语言具有某种不可预测的特性。在接下来的章节中,我们将探讨如何使用一些技术来减轻这一影响。
总结:嵌入技术通过将句子或单词转化为高维空间中的向量,使模型能更好地理解文本含义和上下文。在 TensorFlow 中,嵌入层通过查找表实现词向量表示,并在训练中逐渐学习文本之间的相似性。本书将通过讽刺情绪检测器的构建实例,演示嵌入层如何应用在 NLP 任务中,并揭示如何利用模型架构和训练技巧来优化文本分析效果。