Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于encode和decode 字向量问题 #14

Open
liyonglion opened this issue Jun 4, 2018 · 8 comments
Open

关于encode和decode 字向量问题 #14

liyonglion opened this issue Jun 4, 2018 · 8 comments

Comments

@liyonglion
Copy link

liyonglion commented Jun 4, 2018

在encode阶段,使用tf.contrib.layers.embed_sequence函数来生成字向量。在decode阶段使用tf.random_uniform、tf.nn.embedding_lookup来生成和转换成字向量。
有两个疑问:
1.编码阶段和解码阶段不是同一个字向量,为什么需要这么做?不能是同一个字向量吗?
2.tf.contrib.layers.embed_sequence转换的字向量每次都不同,例如每次ids = [1,2,3,4],每次调用该函数,转换的字向量都是不一样的。这样会有一个问题,相同的字对应的不同的字向量。
先谢谢了

@NELSONZHAO
Copy link
Owner

1.编码端和解码端是不同的任务,并且是不同的语料。例如encoder端是英文,decoder端是法语,分别对应两个不同的embedding去捕捉不同的信息。
2.这个问题麻烦再稍微描述更具体一些哈,我没太看懂。

@liyonglion
Copy link
Author

例如第一次调用embed_sequence函数,传入的第一个参数是[1,2,3,4],返回的值为a。第二次再调用embed_sequence,同样传入[1,2,3,4],返回值b,此时a是不等于的b的吧~
在问一个问题:在训练解码端,为什么要在target前面添加呢?不能直接使用target作为解码端的input吗?

@NELSONZHAO
Copy link
Owner

关于embed_sequence我去查了一下官方文档,对这一点没说明,我自己再terminal里开了个sess跑了一下确实不一样,这个写法我也是参考了别人的代码,如果你找到了关于embed_sequence的具体解析欢迎提下issue。
第二个问题:在训练解码端,要在target前面添加,这是因为在预测的时候模型并不知道第一个input是什么。也就是说,训练时候我们有target数据,所以可以将其作为input直接输入,但是预测阶段模型是不知道第一个词的,所以要给一个初始化的token。

@liyonglion
Copy link
Author

我写的代码和你的差不多,但是我没有用tf.contrib.layers.embed_sequence,这个,而是使用tf.nn.embedding_lookup,第一个参数我使用变量共享。例如:
def get_embedding(ids): with variable_scope('embedding',reuse=tf.AUTO_REUSE) : embedding = tf.get_variable('vocab', [vocab_size, embedding_size]) return tf.nn.embedding_lookup(embedding, ids)
第二个问题:在预测阶段是无法知道target的,也不能添加token,而是直接把编码的最后一个时间步骤 output作为解码的的输入,然后预测的。还是无法理解为什么在训练解码端,给target开头添加一个token。

@NELSONZHAO
Copy link
Owner

添加token这个我是看吴恩达的实现和Youtute上的一个实现写的,我觉得是合理的。吴恩达写的时候也是在Decoder端添加了一个0向量作为输入。其实这个就是类似于LSTM的initial state一样的东西,你要告诉它怎么开始。但是我觉得用Encoder端最后一个时间步的output作为输入不合理呀,如果是翻译问题,最后一个output单词对于Decoder端是没啥意义的。个人见解,欢迎讨论哈~

@liyonglion
Copy link
Author

我并不认为最后的output 等效于单词,从LSTM的原型来看,当前的Ht = f(Ct,Xt),Ct = g(Ct-1,Xt),这里H表示输出,C表示状态,t表示时间步骤。可以从上面的简化公式理解:当前的输出,是综合了上一个状态(可以理解为记忆)和当前的输入,表示当从t0开始到tn输入的“理解”而已,当然可以用来预测当前的时间步输出单词而已,这里的预测也是用类似于全连接层,进行分类而已。

@NELSONZHAO
Copy link
Owner

Encoder-Decoder模型里面,本身学习到的context-vector就是对输入序列的信息抽取,我觉得你说的Encoder的输出和context-vector本身是高度相关的。从具体来说,如果给一个0向量作为Decoder的启动,那么其实相当于什么input信息都没给他,他能依赖的只有context-vector;如果按照你说的不加token,用Encoder的output给Decoder来启动,相当于增加了它的一部分启动信息,这么来看效果应该会好点,但是我始终认为这个output和context-vector是高度相关的。不过我还没尝试过,你这边用Encoder的output来启动Decoder有什么好的效果吗?

@liyonglion
Copy link
Author

目前我还没有测试。我也是在前天加了token,这个我后面再试。目前我正在做文本摘要,从目前的训练结果来看,可以提取文章的中心思想,但是有些重要的词抓的不准确,有些头疼。不知道如何改进。context-vector这个词用的好传神。如果给一个0向量作为Decoder的启动,那么其实相当于什么input信息都没给他,他能依赖的只有context-vector这句话说的很有些道理。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants