21

我不明白 Keras 的嵌入层。虽然有很多文章解释它,但我仍然感到困惑。例如,下面的代码来自于 imdb 情感分析:

top_words = 5000
max_review_length = 500
embedding_vecor_length = 32    

model = Sequential()
model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length))
model.add(LSTM(100))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
model.fit(X_train, y_train, nb_epoch=3, batch_size=64)

在这段代码中,嵌入层到底在做什么?嵌入层的输出是什么?如果有人可以用一些例子来解释它,那就太好了!

4

2 回答 2

13

嵌入层从输入单词中创建嵌入向量(我自己仍然不懂数学),就像 word2vec 或预先计算的手套一样。

在我开始你的代码之前,让我们做一个简短的例子。

texts = ['This is a text','This is not a text']

首先,我们将这些句子转换为整数向量,其中每个单词都是分配给字典中单词的数字,向量的顺序创建单词的序列。

from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences 
from keras.utils import to_categorical

max_review_length = 6 #maximum length of the sentence
embedding_vecor_length = 3
top_words = 10

#num_words is tne number of unique words in the sequence, if there's more top count words are taken
tokenizer = Tokenizer(top_words)
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)
word_index = tokenizer.word_index
input_dim = len(word_index) + 1
print('Found %s unique tokens.' % len(word_index))

#max_review_length is the maximum length of the input text so that we can create vector [... 0,0,1,3,50] where 1,3,50 are individual words
data = pad_sequences(sequences, max_review_length)

print('Shape of data tensor:', data.shape)
print(data)

[Out:] 
'This is a text' --> [0 0 1 2 3 4]
'This is not a text' --> [0 1 2 5 3 4]

现在您可以将这些输入到嵌入层

from keras.models import Sequential
from keras.layers import Embedding

model = Sequential()
model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length,mask_zero=True))
model.compile(optimizer='adam', loss='categorical_crossentropy')
output_array = model.predict(data)

output_array 包含大小为 (2, 6, 3) 的数组:在我的情况下,2 个输入评论或句子,6 是每个评论中的最大单词数 (max_review_length),3 是 embedding_vecor_length。例如

array([[[-0.01494285, -0.007915  ,  0.01764857],
    [-0.01494285, -0.007915  ,  0.01764857],
    [-0.03019481, -0.02910612,  0.03518577],
    [-0.0046863 ,  0.04763055, -0.02629668],
    [ 0.02297204,  0.02146662,  0.03114786],
    [ 0.01634104,  0.02296363, -0.02348827]],

   [[-0.01494285, -0.007915  ,  0.01764857],
    [-0.03019481, -0.02910612,  0.03518577],
    [-0.0046863 ,  0.04763055, -0.02629668],
    [-0.01736645, -0.03719328,  0.02757809],
    [ 0.02297204,  0.02146662,  0.03114786],
    [ 0.01634104,  0.02296363, -0.02348827]]], dtype=float32)

在您的情况下,您有一个 5000 个单词的列表,它可以创建最多 500 个单词的评论(更多将被修剪)并将这 500 个单词中的每一个转换为大小为 32 的向量。

您可以通过运行以下命令获得词索引和嵌入向量之间的映射:

model.layers[0].get_weights()

在下面的例子中,top_words 是 10,所以我们有 10 个单词的映射,你可以看到 0、1、2、3、4 和 5 的映射等于上面的 output_array。

[array([[-0.01494285, -0.007915  ,  0.01764857],
    [-0.03019481, -0.02910612,  0.03518577],
    [-0.0046863 ,  0.04763055, -0.02629668],
    [ 0.02297204,  0.02146662,  0.03114786],
    [ 0.01634104,  0.02296363, -0.02348827],
    [-0.01736645, -0.03719328,  0.02757809],
    [ 0.0100757 , -0.03956784,  0.03794377],
    [-0.02672029, -0.00879055, -0.039394  ],
    [-0.00949502, -0.02805768, -0.04179233],
    [ 0.0180716 ,  0.03622523,  0.02232374]], dtype=float32)]

https://stats.stackexchange.com/questions/270546/how-does-keras-embedding-layer-work中所述,这些向量是随机启动的,并由网络优化器进行优化,就像网络的任何其他参数一样。

于 2017-10-23T18:48:11.797 回答
4

我同意之前的详细回答,但我想尝试给出更直观的解释。

要了解 Embedding 层的工作原理,最好先退后一步,了解为什么我们首先需要 Embedding。

通常 ML 模型将向量(数字数组)作为输入,在处理文本时,我们将字符串转换为数字。最简单的方法之一是单热编码,您将每个字符串视为分类变量。但是第一个问题是,如果您使用 10000 个单词的字典(词汇表),那么 one-hot 编码非常浪费空间(内存)。

此外,由于离散实体被映射到表示特定类别的 0 或 1,因此 one-hot 编码无法捕获单词之间的任何关系。因此,如果您熟悉IMDB 电影数据集,单热编码对于情感分析毫无用处。因为,如果您使用余弦距离测量相似度,那么对于不同索引之间的每次比较,相似度始终为零。

这应该指导我们找到一种方法,其中——

  • 相似的词可以有相似的编码,
  • 为了表示分类变量,我们的数字将少于唯一类别的数量。

进入嵌入..

嵌入是浮点值的密集向量,这些数字是随机生成的,在训练期间这些值通过反向传播更新,就像密集层中的权重在训练期间更新一样。如TensorFlow 文档
中所定义

Embedding 层可以理解为从整数索引(代表特定单词)映射到密集向量(它们的嵌入)的查找表。

在使用顺序构建模型之前,您已经使用了Keras Tokenizer API,并且输入数据已经进行了整数编码。现在,一旦您提到嵌入维度的数量(例如 16、32、64 等),查找表的列数将由其确定。

嵌入层的输出总是一个二维数组,这就是为什么它通常在连接到密集层之前被展平。在上一个答案中,您还可以看到第 0 层的二维权重数组,列数 = 嵌入向量长度。

这就是我对 Keras 中嵌入层的看法。希望这能带来更多的启示,我认为这可能是@Vaasha发布的答案的一个很好的伴奏。

参考: TensorFlow 词嵌入教程

于 2019-10-30T05:26:44.490 回答