tf.nn.embedding_lookup()函数的原理

tf.nn.embedding_lookup()函数

  • 这个函数有什么作用?看起来像查找表,也就是返回每个ID对应的参数(以ID为单位)?
  • 例如,在Skip-Gram模型中,如果我们使用tf.nn.embedding_lookup(embeddings, train_inputs),那么对于每个train_input,它会找到对应的嵌入(Embedding)?

简单来说

embedding_lookup函数检索params张量的行。该行为类似于对numpy中的数组使用索引。
例如:

matrix = np.random.random([1024, 64])  # 64-dimensional embeddings
ids = np.array([0, 5, 17, 33])
# matrix中按照行取,索引为0,5,17,33
print(matrix[ids].shape)  # prints a matrix of shape [4, 64]

进阶说明

最简单的形式类似于tf.gather。它根据ids指定的索引返回params的元素。
例如:

params = tf.constant([10,20,30,40])
ids = tf.constant([0,1,2,3])
with tf.Session() as sess:
    a = tf.nn.embedding_lookup(params, ids)
    print(a.eval())     # 输出为  [10 20 30 40]

将返回[10 20 30 40],因为params的第一个元素(索引0)是10,params的第二个元素(索引1)是20,依此类推

那么同理:下面则返回 [20 20 40]

params = tf.constant([10,20,30,40])
ids = tf.constant([1,1,3])
with tf.Session() as sess:
    a = tf.nn.embedding_lookup(params, ids)
    print(a.eval())     # 输出为  [20 20 40]

但是embedding_lookup不仅限于此。
params参数可以是张量列表,而不是单个张量。

params1 = tf.constant([1,2])
params2 = tf.constant([10,20])
ids = tf.constant([2,0,2,1,2,3])
with tf.Session() as sess:
    result = tf.nn.embedding_lookup([params1, params2], ids)
    print(result.eval())        # [ 2  1  2 10  2 20]

在这种情况下,在ids中指定的索引根据分区策略对应于张量的元素,其中默认分区策略为’mod’。在’mod’策略中,
索引0对应于列表中第一个张量的第一个元素。
索引1对应于第二张量的第一元素。
索引2对应于第三张量的第一个元素,
依此类推。对于所有索引0…(n-1),假设参数是n张量的列表,则简单地将索引i对应于第**(i + 1)**张量的第一个元素。

现在,索引n不能对应于张量n + 1,因为列表params仅包含n张量。因此索引n对应于第一个张量的第二个元素。类似地,索引n+1对应于第二张量的第二个元素,依此类推。

因此,在上一个代码中
下标0对应于第一个张量的第一个元素:1

索引1对应于第二张量的第一个元素:10

索引2对应于第一个张量的第二个元素:2

索引3对应于第二张量的第二个元素:20
因此,结果将是:[ 2 1 2 10 2 20]

实际的例子

以文本嵌入(Embedding)为例,tf.nn.embedding_lookup()函数的目的是在嵌入矩阵中执行查找并返回单词的嵌入(或简单地说是矢量表示)。

一个简单的嵌入矩阵(形状:vocabulary_size x embedding_dimension)如下所示。 (即,每个单词将由一个数字向量表示;也就是word2vec)


嵌入矩阵

the 0.418 0.24968 -0.41242 0.1217 0.34527 -0.044457 -0.49688 -0.17862
like 0.36808 0.20834 -0.22319 0.046283 0.20098 0.27515 -0.77127 -0.76804
between 0.7503 0.71623 -0.27033 0.20059 -0.17008 0.68568 -0.061672 -0.054638
did 0.042523 -0.21172 0.044739 -0.19248 0.26224 0.0043991 -0.88195 0.55184
just 0.17698 0.065221 0.28548 -0.4243 0.7499 -0.14892 -0.66786 0.11788
national -1.1105 0.94945 -0.17078 0.93037 -0.2477 -0.70633 -0.8649 -0.56118
day 0.11626 0.53897 -0.39514 -0.26027 0.57706 -0.79198 -0.88374 0.30119
country -0.13531 0.15485 -0.07309 0.034013 -0.054457 -0.20541 -0.60086 -0.22407
under 0.13721 -0.295 -0.05916 -0.59235 0.02301 0.21884 -0.34254 -0.70213
such 0.61012 0.33512 -0.53499 0.36139 -0.39866 0.70627 -0.18699 -0.77246
second -0.29809 0.28069 0.087102 0.54455 0.70003 0.44778 -0.72565 0.62309 

我拆分了上述嵌入矩阵,并仅将单词vocab装入我们的词汇表,并将相应的向量装入emb数组。

vocab = ['the','like','between','did','just','national','day','country','under','such','second']

emb = np.array([[0.418, 0.24968, -0.41242, 0.1217, 0.34527, -0.044457, -0.49688, -0.17862],
   [0.36808, 0.20834, -0.22319, 0.046283, 0.20098, 0.27515, -0.77127, -0.76804],
   [0.7503, 0.71623, -0.27033, 0.20059, -0.17008, 0.68568, -0.061672, -0.054638],
   [0.042523, -0.21172, 0.044739, -0.19248, 0.26224, 0.0043991, -0.88195, 0.55184],
   [0.17698, 0.065221, 0.28548, -0.4243, 0.7499, -0.14892, -0.66786, 0.11788],
   [-1.1105, 0.94945, -0.17078, 0.93037, -0.2477, -0.70633, -0.8649, -0.56118],
   [0.11626, 0.53897, -0.39514, -0.26027, 0.57706, -0.79198, -0.88374, 0.30119],
   [-0.13531, 0.15485, -0.07309, 0.034013, -0.054457, -0.20541, -0.60086, -0.22407],
   [ 0.13721, -0.295, -0.05916, -0.59235, 0.02301, 0.21884, -0.34254, -0.70213],
   [ 0.61012, 0.33512, -0.53499, 0.36139, -0.39866, 0.70627, -0.18699, -0.77246 ],
   [ -0.29809, 0.28069, 0.087102, 0.54455, 0.70003, 0.44778, -0.72565, 0.62309 ]])


emb.shape
# (11, 8)

在TensorFlow中查找嵌入(Embedding)。现在,我们将看到如何对某些任意输入语句执行嵌入查找。

In [54]: from collections import OrderedDict

# embedding as TF tensor (for now constant; could be tf.Variable() during training)
In [55]: tf_embedding = tf.constant(emb, dtype=tf.float32)

# input for which we need the embedding
In [56]: input_str = "like the country"

# build index based on our `vocabulary`
In [57]: word_to_idx = OrderedDict({w:vocab.index(w) for w in input_str.split() if w in vocab})

# lookup in embedding matrix & return the vectors for the input words
In [58]: tf.nn.embedding_lookup(tf_embedding, list(word_to_idx.values())).eval()
Out[58]: 
array([[ 0.36807999,  0.20834   , -0.22318999,  0.046283  ,  0.20097999,
         0.27515   , -0.77126998, -0.76804   ],
       [ 0.41800001,  0.24968   , -0.41242   ,  0.1217    ,  0.34527001,
        -0.044457  , -0.49687999, -0.17862   ],
       [-0.13530999,  0.15485001, -0.07309   ,  0.034013  , -0.054457  ,
        -0.20541   , -0.60086   , -0.22407   ]], dtype=float32)

观察我们如何使用词汇表中的单词索引从原始嵌入矩阵(带单词)中获取嵌入。
通常,此类嵌入查找是由第一层(称为嵌入层)执行的,然后将这些嵌入传递到RNN /LSTM /GRU层以进行进一步处理。

嵌入的图示

这是描述嵌入查找过程的图示。
简而言之,它获取由ID列表指定的嵌入层的相应行,并将其提供为张量。它是通过以下过程实现的。在这里插入图片描述

  • 定义一个占位符lookup_ids = tf.placeholder([10])
  • 定义嵌入层embeddings = tf.Variable([100,10],...)
  • 定义张量流操作embed_lookup = tf.embedding_lookup(embeddings, lookup_ids)
  • 通过运行lookup = session.run(embed_lookup, feed_dict={lookup_ids:[95,4,14]})获取结果

高维embedding_lookup例子

当参数张量为高维时,id仅指最大维。

embeddings = tf.constant([
    [
        [1,1],
        [2,2],
        [3,3],
        [4,4]
    ],
    [
        [11,11],
        [12,12],
        [13,13],
        [14,14]
    ],
    [
        [21,21],
        [22,22],
        [23,23],
        [24,24]
    ]
])
ids=tf.constant([0,2,1])
embed = tf.nn.embedding_lookup(embeddings, ids, partition_strategy='div')
with tf.Session() as session:
    result = session.run(embed)
    print(result)

仅尝试’div’策略,对于一个张量,这没有什么区别。

#下面是输出
[[[ 1  1]
  [ 2  2]
  [ 3  3]
  [ 4  4]]

 [[21 21]
  [22 22]
  [23 23]
  [24 24]]

 [[11 11]
  [12 12]
  [13 13]
  [14 14]]]

参考资料:https://vimsky.com/article/4298.html

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
tf.nn.embedding_lookup是一个用于选取张量中索引对应元素的函数。它的用法是tf.nn.embedding_lookup(tensor, id),其中tensor是输入张量,id是要查找的索引。根据id在tensor中找到对应的元素并返回。 举个例子,假设我们有一个嵌入矩阵embedding和一个输入id列表input_ids。我们可以使用tf.nn.embedding_lookup(embedding, input_ids)来找到embedding中与input_ids中的id对应的向量。如果input_ids=[1, 2, 3],则函数会返回embedding中下标为1, 2, 3的向量组成的矩阵。 需要注意的是,tf.nn.embedding_lookup不仅仅是简单地查表,查到的向量是可以训练的,也就是说它是一种全连接层,训练参数的个数是类别数乘以嵌入向量的大小。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [tf.nn.embedding_lookup()函数](https://blog.csdn.net/yql_617540298/article/details/88394120)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [tf.nn.embedding_lookup()的用法](https://blog.csdn.net/yangfengling1023/article/details/82910951)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

年少无为呀!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值