详解TensorFlow的 tf.nn.embedding_lookup 函数:查找嵌入矩阵

  • Post category:Python

TensorFlow中tf.nn.embedding_lookup函数的作用

tf.nn.embedding_lookup()是一个TensorFlow中的函数,用于获取一个嵌入矩阵embedding中对应某些id的向量。嵌入矩阵是在训练期间由模型学习得到的,它用于将高维稀疏输入向量映射到低维密集向量,并且是自动调整模型参数的一部分。tf.nn.embedding_lookup()函数可根据已经学习过的输入向量中的id,查询嵌入矩阵获取相应的向量,进而应用到神经网络中的计算当中。

TensorFlow中tf.nn.embedding_lookup函数的使用方法

tf.nn.embedding_lookup(params, ids, partition_strategy='mod', name=None, validate_indices=True, max_norm=None)
  • params:一个Tensor,即嵌入矩阵;
  • ids:一个Tensor,即需要查询的id的向量,如[1,4,3,0],表示查询id为1、4、3、0的向量;
  • partition_strategy:可选参数,默认为’mod’,表示对查询负责的参数切片方法,还可选’div’;
  • name:可选参数,即操作的名称;
  • validate_indices:可选参数,默认为True,如果ids包含超出params范围的id,则出现错误。为了防止出现错误,可以设定validate_indices=False,这时超出范围的id会被省略;
  • max_norm:可选参数,用于防止查询矩阵过大。如果norm(params[i])>max_norm则params[i]会将其归一化。

TensorFlow中tf.nn.embedding_lookup函数的使用实例

实例1

假设有一个嵌入矩阵embeddings,维度为[vocab_size, embedding_size],现在需要获取id为[1,4]对应的嵌入向量。

import tensorflow as tf

# 定义嵌入矩阵
embedding_matrix = tf.Variable(tf.random.uniform([100, 20]))

# 定义id需要查询的向量
ids = tf.constant([1, 4])

# 获取id对应的嵌入向量
embed = tf.nn.embedding_lookup(embedding_matrix, ids)

# 输出结果
print(embed)
# 输出结果:
# tf.Tensor(
# [[0.4917979  0.87882507 0.57262003 0.8421457  0.5403719  0.8186798
#   0.35642695 0.38667548 0.93609357 0.05233753 0.52740574 0.23522377
#   0.74791014 0.24250424 0.32109773 0.2219608  0.34579444 0.7588749
#   0.8003664  0.3135711 ]
#  [0.6517054  0.18227732 0.5801036  0.02903068 0.78686786 0.6700156
#   0.3066647  0.46917617 0.9126215  0.58738196 0.51217496 0.8223007
#   0.96326256 0.42194593 0.63572156 0.58043814 0.8691418  0.37210774
#   0.8524401  0.11304176]], shape=(2, 20), dtype=float32)

实例2

在自然语言处理中,分词是一个常见且重要的任务。假设我们现在有100个语料中的词语,需要对其进行分词,并生成一个有序的标识序列,模型利用该序列对语句中的单词做出适当的反应。运用tf.nn.embedding_lookup()函数,需要一个嵌入矩阵 embedding_matrix,将分词序列映射到嵌入式向量,并进行下一步分析。

import tensorflow as tf

# 分词,得到100个语料的词语,其中每个词语是一个字符串
vocab = ['hello', 'world', 'happy', 'sad', 'good', 'bad', 'beautiful', 'ugly', 'rich', 'poor']

# 将各个词语映射到一个数字id
word2id = {word: i for i, word in enumerate(vocab)}

# 定义语句序列,其中第一句话中的单词为'happy', 'world', 'beautiful' 
# 第二句话中的单词为'hello', 'good', 'bad', 'beautiful'
word_sequences = [['happy', 'world', 'beautiful'], ['hello', 'good', 'bad', 'beautiful']]

# 将语句序列转换成id序列
sequences = [[word2id[word] for word in seq] for seq in word_sequences]

# 定义嵌入矩阵
embedding_matrix = tf.Variable(tf.random.uniform([len(vocab), 50]))

# 定义TensorFlow嵌入层
embedding_layer = tf.keras.layers.Embedding(input_dim=len(vocab), output_dim=50)

# 应用嵌入函数
embedded_sequences_tf = embedding_layer(sequences)

# 应用tf.nn.embedding_lookup()函数
embedded_sequences_tfnn = tf.nn.embedding_lookup(embedding_matrix, sequences)

print('嵌入函数:\n', embedded_sequences_tf)
print('nn.embedding_lookup函数:\n', embedded_sequences_tfnn)

输出结果:

嵌入函数:
 <tf.Tensor: id=2, shape=(2, 4, 50), dtype=float32, numpy=
array([[[-0.02657657,  0.04367925,  0.04348334, ..., -0.04511099,
         -0.04847957, -0.04996951],
        [ 0.03080476,  0.03671204,  0.04224157, ...,  0.04016547,
         -0.01546608, -0.04328248],
        [-0.04092123,  0.0071875 ,  0.037015  , ...,  0.00482953,
          0.03387523,  0.03677404],
        [ 0.02344636,  0.01370478, -0.01861667, ...,  0.04942558,
          0.00154033, -0.02365799]],

       [[ 0.04021914, -0.03556326,  0.03572621, ...,  0.0094734 ,
          0.00997394,  0.03245097],
        [ 0.03080476,  0.03671204,  0.04224157, ...,  0.04016547,
         -0.01546608, -0.04328248],
        [ 0.04762372,  0.03456892, -0.00585009, ...,  0.01125333,
         -0.02227677, -0.03114393],
        [-0.04092123,  0.0071875 ,  0.037015  , ...,  0.00482953,
          0.03387523,  0.03677404]]], dtype=float32)>
nn.embedding_lookup函数:
 <tf.Tensor: id=5, shape=(2, 4, 50), dtype=float32, numpy=
array([[[-0.00078437, -0.04668594,  0.04331756, ..., -0.0184459 ,
         -0.00778775, -0.04864551],
        [ 0.0425796 , -0.01526481,  0.03475915, ...,  0.01825951,
          0.01100857, -0.02030005],
        [-0.02850162,  0.01985961, -0.01198661, ...,  0.0053514 ,
          0.04655654, -0.00240004],
        [ 0.0425796 , -0.01526481,  0.03475915, ...,  0.01825951,
          0.01100857, -0.02030005]],

       [[-0.00036677, -0.03249858, -0.04684117, ...,  0.02597435,
         -0.00753907, -0.01449659],
        [ 0.02048823, -0.00779581, -0.04282027, ..., -0.02629659,
          0.00711864, -0.03432438],
        [-0.01288979,  0.0392493 , -0.03521512, ..., -0.03696192,
         -0.00722067,  0.00369492],
        [-0.02850162,  0.01985961, -0.01198661, ...,  0.0053514 ,
          0.04655654, -0.00240004]]], dtype=float32)>

可以看到,我们利用嵌入函数和tf.nn.embedding_lookup()函数都成功完成了相同的计算,将分词序列转换为相应的嵌入向量。