使用词嵌入
将单词与向量相关联还有另一种常用的强大方法,就是使用密集的词向量(word vector),也叫词嵌入(word embedding)。one-hot 编码得到的向量是二进制的、稀疏的(绝大部分元素都是 0)、维度很高的(维度大小等于词表中的单词个数),而词嵌入是低维的浮点数向量(即密集向量,与稀疏向量相对)
获取词嵌入有两种方法
- 在完成主任务(比如文档分类或情感预测)的同时学习词嵌入。在这种情况下,一开始是随机的词向量,然后对这些词向量进行学习,其学习方式与学习神经网络的权重相同。
- 在不同于待解决问题的机器学习任务上预计算好词嵌入,然后将其加载到模型中。这些词嵌入叫作预训练词嵌入(pretrained word embedding)。
利用 Embedding 层学习词嵌入
要将一个词与一个密集向量相关联,最简单的方法就是随机选择向量。这种方法的问题在于,得到的嵌入空间没有任何结构。
词向量之间的几何关系应该表示这些词之间的语义关系。词嵌入的作用应该是将人类的语言映射到几何空间中。例如,在一个合理的嵌入空间中,同义词应该被嵌入到相似的词向量中,一般来说,任意两个词向量之间的几何距离(比如 L2 距离)应该和这两个词的语义距离有关(表示不同事物的词被嵌入到相隔很远的点,而相关的词则更加靠近)。除了距离,你可能还希望嵌入空间中的特定方向也是有意义的。为了更清楚地说明这一点,我们来看一个具体示例。
四个词被嵌入在二维平面上,这四个词分别是 cat(猫)、dog(狗)、wolf(狼)和 tiger(虎)。对于我们这里选择的向量表示,这些词之间的某些语义关系可以被编码为几何变换。例如,从 cat 到 tiger 的向量与从 dog 到 wolf 的向量相等,这个向量可以被解释为“从宠物到野生动物”向量。同样,从 dog 到 cat 的向量与从 wolf 到 tiger 的向量也相等,它可以被解释为“从犬科到猫科”向量。
在真实的词嵌入空间中,常见的有意义的几何变换的例子包括“性别”向量和“复数”向量。例如,将 king(国王)向量加上 female(女性)向量,得到的是 queen(女王)向量。将 king(国王)向量加上 plural(复数)向量,得到的是 kings 向量。词嵌入空间通常具有几千个这种可解释的、并且可能很有用的向量。
有没有一个理想的词嵌入空间,可以完美地映射人类语言,并可用于所有自然语言处理任务?可能有,但我们尚未发现。此外,也不存在人类语言(human language)这种东西。
将一个 Embedding 层实例化
from keras.layers import Embedding
# Embedding 层至少需要两个参数:标记的个数(这里是 1000,即最大单词索引 +1)和嵌入的维度(这里是 64)
embedding_layer = Embedding(1000, 64)
最好将 Embedding 层理解为一个字典,将整数索引(表示特定单词)映射为密集向量。它接收整数作为输入,并在内部字典中查找这些整数,然后返回相关联的向量。Embedding 层实际上是一种字典查找。
Embedding 层的输入是一个二维整数张量,其形状为 (samples, sequence_length),每个元素是一个整数序列。
Embedding 层,你可以输入形状为 (32, 10)(32 个长度为 10 的序列组成的批量)
Embedding 层返回一个形状为 (samples, sequence_length, embedding_dimensionality) 的三维浮点数张量。
将一个 Embedding 层实例化时,它的权重(即标记向量的内部字典)最开始是随机的,与其他层一样。在训练过程中,利用反向传播来逐渐调节这些词向量,改变空间结构以便下游模型可以利用。一旦训练完成,嵌入空间将会展示大量结构,这种结构专门针对训练模型所要解
决的问题。
Embedding 实例
>>> model = tf.keras.Sequential()
>>> model.add(tf.keras.layers.Embedding(1000, 64, input_length=10))
>>> # The model will take as input an integer matrix of size (batch,
>>> # input_length), and the largest integer (i.e. word index) in the input
>>> # should be no larger than 999 (vocabulary size).
>>> # Now model.output_shape is (None, 10, 64), where `None` is the batch
>>> # dimension.
>>> input_array = np.random.randint(1000, size=(32, 10))
>>> model.compile