Python `for`循环到PyTorch中的多维数组
我想用注意力机制来实施问答系统。我有两个输入<代码>上下文和Python `for`循环到PyTorch中的多维数组,python,deep-learning,pytorch,Python,Deep Learning,Pytorch,我想用注意力机制来实施问答系统。我有两个输入上下文和查询哪些形状是(批量大小、上下文大小、embd大小)和(批量大小、查询大小、embd大小) 我正在看下面的文章。 使用匹配LSTM和应答指针进行机器理解 然后,我想得到一个注意矩阵,其形状是(批大小、上下文大小、查询大小、embd大小)。在论文中,他们计算每一行的值(在论文中是指每一个上下文单词,G_i,alpha_i) 我的代码在下面,它正在运行。但我不确定我的方式是否好。例如,我使用For loop生成序列数据(For I in range
查询
哪些形状是(批量大小、上下文大小、embd大小)
和(批量大小、查询大小、embd大小)
我正在看下面的文章。
使用匹配LSTM和应答指针进行机器理解
然后,我想得到一个注意矩阵,其形状是(批大小、上下文大小、查询大小、embd大小)
。在论文中,他们计算每一行的值(在论文中是指每一个上下文单词,G_i,alpha_i)
我的代码在下面,它正在运行。但我不确定我的方式是否好。例如,我使用For loop
生成序列数据(For I in range(T):
)。为了获得每一行,我使用了像G[:,I,:,:]
,embd_context[:,I,:]这样的就地操作符。clone()在pytorch中是一种很好的方式吗?如果没有,我应该在哪里更改代码
如果你注意到其他要点,请告诉我。我是这个领域的新手,也是个新手。对不起,我的问题模棱两可
class MatchLSTM(nn.Module):
def __init__(self, args):
super(MatchLSTM, self).__init__()
self.embd_size = args.embd_size
d = self.embd_size
self.answer_token_len = args.answer_token_len
self.embd = WordEmbedding(args)
self.ctx_rnn = nn.GRU(d, d, dropout = 0.2)
self.query_rnn = nn.GRU(d, d, dropout = 0.2)
self.ptr_net = PointerNetwork(d, d, self.answer_token_len) # TBD
self.w = nn.Parameter(torch.rand(1, d, 1).type(torch.FloatTensor), requires_grad=True) # (1, 1, d)
self.Wq = nn.Parameter(torch.rand(1, d, d).type(torch.FloatTensor), requires_grad=True) # (1, d, d)
self.Wp = nn.Parameter(torch.rand(1, d, d).type(torch.FloatTensor), requires_grad=True) # (1, d, d)
self.Wr = nn.Parameter(torch.rand(1, d, d).type(torch.FloatTensor), requires_grad=True) # (1, d, d)
self.match_lstm_cell = nn.LSTMCell(2*d, d)
def forward(self, context, query):
# params
d = self.embd_size
bs = context.size(0) # batch size
T = context.size(1) # context length
J = query.size(1) # query length
# LSTM Preprocessing Layer
shape = (bs, T, J, d)
embd_context = self.embd(context) # (N, T, d)
embd_context, _h = self.ctx_rnn(embd_context) # (N, T, d)
embd_context_ex = embd_context.unsqueeze(2).expand(shape).contiguous() # (N, T, J, d)
embd_query = self.embd(query) # (N, J, d)
embd_query, _h = self.query_rnn(embd_query) # (N, J, d)
embd_query_ex = embd_query.unsqueeze(1).expand(shape).contiguous() # (N, T, J, d)
# Match-LSTM layer
G = to_var(torch.zeros(bs, T, J, d)) # (N, T, J, d)
wh_q = torch.bmm(embd_query, self.Wq.expand(bs, d, d)) # (N, J, d) = (N, J, d)(N, d, d)
hidden = to_var(torch.randn([bs, d])) # (N, d)
cell_state = to_var(torch.randn([bs, d])) # (N, d)
# TODO bidirectional
H_r = [hidden]
for i in range(T):
wh_p_i = torch.bmm(embd_context[:,i,:].clone().unsqueeze(1), self.Wp.expand(bs, d, d)).squeeze() # (N, 1, d) -> (N, d)
wh_r_i = torch.bmm(hidden.unsqueeze(1), self.Wr.expand(bs, d, d)).squeeze() # (N, 1, d) -> (N, d)
sec_elm = (wh_p_i + wh_r_i).unsqueeze(1).expand(bs, J, d) # (N, J, d)
G[:,i,:,:] = F.tanh( (wh_q + sec_elm).view(-1, d) ).view(bs, J, d) # (N, J, d) # TODO bias
attn_i = torch.bmm(G[:,i,:,:].clone(), self.w.expand(bs, d, 1)).squeeze() # (N, J)
attn_query = torch.bmm(attn_i.unsqueeze(1), embd_query).squeeze() # (N, d)
z = torch.cat((embd_context[:,i,:], attn_query), 1) # (N, 2d)
hidden, cell_state = self.match_lstm_cell(z, (hidden, cell_state)) # (N, d), (N, d)
H_r.append(hidden)
H_r = torch.stack(H_r, dim=1) # (N, T, d)
indices = self.ptr_net(H_r) # (N, M, T) , M means (start, end)
return indices
我认为你的代码很好。您无法避免循环:对于范围(t)中的i:
,因为在本文()的等式(2)中,有一个隐藏状态来自Match LSTM单元,该单元涉及计算gi
和alpha_i
向量,并用于计算Match LSTM下一个时间步的输入。因此,您需要为匹配LSTM的每个时间步运行循环,我看不到任何替代方法可以避免for
循环。您应该将此提交给。所以,这并不是审查工作代码质量的正确地方。哦,我不知道那个网站。我搬到了那个地方。非常感谢。没问题。你可能应该从这里删除这个问题。谢谢你每一次。是的,我想是的。但我是这一领域的新手,也是一个新手。听到你这么说,我感到很欣慰。我相信这个答案是正确的;任何循环架构的一个问题是,它依赖于以前的时间步骤,因此需要一个for循环来展开