tensorflow中有一个函数embedding_lookup可以很方便地将输入转化为嵌入矩阵。一般方便起见,我们会使用一个由随机数组成的embedding矩阵,但效果个人觉得和one-hot差不太多。这个矩阵仅仅是初始化矩阵,在更新权重的时候是会改变的。
实现很简单:
inputs = tf.placeholder(tf.int32, name='inputs')
with tf.variable_scope("embedding", reuse=tf.AUTO_REUSE):
embedding = tf.get_variable('embedding', [vocab_size, embedding_size])
inputs_embedded = tf.nn.embedding_lookup(embedding, inputs)
with tf.Session() as sess:
init = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
sess.run(init)
print(sess.run(embedding))
print(sess.run(encoder_inputs_embedded,feed_dict={encoder_inputs:inputs}))
embedding是一个词典维度x词向量维度的矩阵,每一行代表一个词的词向量,列的索引值代表词在字典中的索引值。inputs是已经根据字典转化为向量的一个列表。embedding_lookup就是根据inputs中的向量,即该词在字典中的索引值,在embedding中找到对应行,读取该行,也就是这个词的词向量。
值得注意的是embedding_lookup不简单只是一个转换成词向量的字典,可以视为一个全连接网络,也就是说在更新的过程中是可以当做权重进行训练的。
一个简单的例子:
embedding = [[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]]
inputs = [1,2,2,1,0,3]
inputs_embedded = [[0 1 0 0 0],
[0 0 1 0 0],
[0 0 1 0 0],
[0 1 0 0 0],
[1 0 0 0 0],
[0 0 0 1 0]]
知道这个原理之后,我们就很容易改进embedding矩阵,使用我们自己通过word2vec训练的矩阵作为初始值,见word2vec训练中文词向量中文词向量。