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

关于实现细节存在的问题 #28

Closed
wengyuyuan opened this issue Jan 17, 2022 · 7 comments
Closed

关于实现细节存在的问题 #28

wengyuyuan opened this issue Jan 17, 2022 · 7 comments

Comments

@wengyuyuan
Copy link

您好,感谢您公开您的代码。代码实现似乎和我对GAT的理解不太相同,所以请教一下您。
在用GAT计算word和sentence之间的边注意力权重的时候,做法是将边的头结点和尾结点的embedding拼接起来再做变换,但是在您的实现中当结点是word时,传入的向量为【0,0,0,0,0,0,0,0】,不知道这里是您有意设计还是实现方面遗漏了?
感谢您的回复!

@dqwang122
Copy link
Owner

在您的实现中当结点是word时,传入的向量为[0,0,0,0,0,0,0,0]

不知道这边你具体指的是什么?传入向量具体是指node节点的哪一个feature?

不过我在检查相关代码的时候,确实发现实现上有一些遗漏。在WSGATLayer有一个edge_attention函数,针对edges.src['z'], edges.dst['z']进行attention weight的计算,但是在apply_edges之前只对其中一种类型(word)的z进行赋值。

g.nodes[wnode_id].data['z'] = z

实际上由于edges是连接word和sent的,因此src和dst必然有一个z是默认赋值的(也就可能是你提到的默认0的向量赋值)。因此这里其实没有很好的用到两端的信息。这个问题影响WSGATLayer和WSGATLayer,对两端节点类型相同的SGATLayer没有影响。

因为代码涉及到checkpoint的更改,因此对于此问题的修复我放在dev分支中,并且会在readme中注明。感谢你的提醒~

@wengyuyuan
Copy link
Author

在您的实现中当结点是word时,传入的向量为[0,0,0,0,0,0,0,0]

不知道这边你具体指的是什么?传入向量具体是指node节点的哪一个feature?

不过我在检查相关代码的时候,确实发现实现上有一些遗漏。在WSGATLayer有一个edge_attention函数,针对edges.src['z'], edges.dst['z']进行attention weight的计算,但是在apply_edges之前只对其中一种类型(word)的z进行赋值。

g.nodes[wnode_id].data['z'] = z

实际上由于edges是连接word和sent的,因此src和dst必然有一个z是默认赋值的(也就可能是你提到的默认0的向量赋值)。因此这里其实没有很好的用到两端的信息。这个问题影响WSGATLayer和WSGATLayer,对两端节点类型相同的SGATLayer没有影响。

因为代码涉及到checkpoint的更改,因此对于此问题的修复我放在dev分支中,并且会在readme中注明。感谢你的提醒~

感谢您的回复,对于您的修复还有一点困惑,word结点和sent结点向量的维度并不相同,似乎无法在GAT计算中通过同一个映射函数,不知是否是我漏掉了您将他们word结点和sent结点处理为同一个维度的步骤了

@dqwang122
Copy link
Owner

word结点和sent结点向量的维度并不相同,似乎无法在GAT计算中通过同一个映射函数

我猜你指的是不是这个:

sent_feature = self.n_feature_proj(self.set_snfeature(graph)) # [snode, n_feature_size]

在HSG和HDSG里面分别存在n_feature_proj和dn_feature_proj函数将节点维度映射到同一纬度

@wengyuyuan
Copy link
Author

word结点和sent结点向量的维度并不相同,似乎无法在GAT计算中通过同一个映射函数

我猜你指的是不是这个:

sent_feature = self.n_feature_proj(self.set_snfeature(graph)) # [snode, n_feature_size]

在HSG和HDSG里面分别存在n_feature_proj和dn_feature_proj函数将节点维度映射到同一纬度

我的疑惑是word和sent结点的维度似乎不相同,word的维度是300,sent的维度是64,,在HSG和HDSG里面分别存在n_feature_proj和dn_feature_proj函数将sent节点维度映射到64,这使得word和sent结点的维度不同,想问您的解决方案是把修改n_feature_proj和dn_feature_proj函数将sent节点映射到300吗,和word节点维度一致

@dqwang122
Copy link
Owner

在这里GAT的实现,word和sent/doc不需要维度一致,在self.word2sent和self.sent2word的初始化可以看到,对应的in_dim和out_dim是不一样的:

# word -> sent
embed_size = hps.word_emb_dim
self.word2sent = WSWGAT(in_dim=embed_size,
                       out_dim=hps.hidden_size,
                       num_heads=hps.n_head,
                       attn_drop_out=hps.atten_dropout_prob,
                       ffn_inner_hidden_size=hps.ffn_inner_hidden_size,
                       ffn_drop_out=hps.ffn_dropout_prob,
                       feat_embed_size=hps.feat_embed_size,
                       layerType="W2S"
                       )

# sent -> word
self.sent2word = WSWGAT(in_dim=hps.hidden_size,
                       out_dim=embed_size,
                       num_heads=6,
                       attn_drop_out=hps.atten_dropout_prob,
                       ffn_inner_hidden_size=hps.ffn_inner_hidden_size,
                       ffn_drop_out=hps.ffn_dropout_prob,
                       feat_embed_size=hps.feat_embed_size,
                       layerType="S2W"
                       )

在更新过程中word始终保持embed_size=300,而sent/doc则是hidden_size=64。当然你也可以添加额外的proj layer或者更改hidden_size使得他们的维度一致,但是这里维度不统一实际不影响实现。

当初设置这个超参数是基于过大的hidden_size和num_layer会使得模型更容易oversmoothing而性能下降的考虑,而embed_size则是考虑保持Glove词向量的维度,不一定是最佳的参数设置。你可以探究更好的超参组。

@wengyuyuan
Copy link
Author

可是,在您的dev中WSGATLayer更新函数中,为了用边两端的信息进行更新,您把word结点和sent结点都经过同一个映射函数self.fc,这不就需要word结点和sent结点具有相同的维度吗
g.nodes[wnode_id].data['z'] = self.fc(srch)
g.nodes[snode_id].data['z'] = self.fc(dsth)
我尝试过将word节点和sent节点映射为具有同一维度(300维或64维),效果有些降低。

@dqwang122
Copy link
Owner

是的,如果你指的是dev分支中的更新,那么确实需要统一word和sent的维度。抱歉,我以为你指的是master分支的实现。
在dev中,需要将hidden size统一成embed_size确保word和sent都可以通过WSGATLayer和SWGATLayer同一个fc函数来映射。
不过更好的实现可能是再添加一个fc函数来进行out_dim和out_dim之间的映射,比如在WSGATLayer中:

# init
self.wsfc = nn.Linear(in_dim, out_dim, bias=False)
self.ssfc = nn.Linear(out_dim, out_dim, bias=False)

# forward
g.nodes[wnode_id].data['z'] = self.wsfc(srch)
g.nodes[snode_id].data['z'] = self.ssfc(dsth)

由于实现上的区别,在可能在超参设置上需要进行一定调整。

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