| 478 | return context, weights |
| 479 | |
| 480 | class AttnDecoderRNN(nn.Module): |
| 481 | def __init__(self, hidden_size, output_size, dropout_p=0.1): |
| 482 | super(AttnDecoderRNN, self).__init__() |
| 483 | self.embedding = nn.Embedding(output_size, hidden_size) |
| 484 | self.attention = BahdanauAttention(hidden_size) |
| 485 | self.gru = nn.GRU(2 * hidden_size, hidden_size, batch_first=True) |
| 486 | self.out = nn.Linear(hidden_size, output_size) |
| 487 | self.dropout = nn.Dropout(dropout_p) |
| 488 | |
| 489 | def forward(self, encoder_outputs, encoder_hidden, target_tensor=None): |
| 490 | batch_size = encoder_outputs.size(0) |
| 491 | decoder_input = torch.empty(batch_size, 1, dtype=torch.long, device=device).fill_(SOS_token) |
| 492 | decoder_hidden = encoder_hidden |
| 493 | decoder_outputs = [] |
| 494 | attentions = [] |
| 495 | |
| 496 | for i in range(MAX_LENGTH): |
| 497 | decoder_output, decoder_hidden, attn_weights = self.forward_step( |
| 498 | decoder_input, decoder_hidden, encoder_outputs |
| 499 | ) |
| 500 | decoder_outputs.append(decoder_output) |
| 501 | attentions.append(attn_weights) |
| 502 | |
| 503 | if target_tensor is not None: |
| 504 | # Teacher forcing: Feed the target as the next input |
| 505 | decoder_input = target_tensor[:, i].unsqueeze(1) # Teacher forcing |
| 506 | else: |
| 507 | # Without teacher forcing: use its own predictions as the next input |
| 508 | _, topi = decoder_output.topk(1) |
| 509 | decoder_input = topi.squeeze(-1).detach() # detach from history as input |
| 510 | |
| 511 | decoder_outputs = torch.cat(decoder_outputs, dim=1) |
| 512 | decoder_outputs = F.log_softmax(decoder_outputs, dim=-1) |
| 513 | attentions = torch.cat(attentions, dim=1) |
| 514 | |
| 515 | return decoder_outputs, decoder_hidden, attentions |
| 516 | |
| 517 | |
| 518 | def forward_step(self, input, hidden, encoder_outputs): |
| 519 | embedded = self.dropout(self.embedding(input)) |
| 520 | |
| 521 | query = hidden.permute(1, 0, 2) |
| 522 | context, attn_weights = self.attention(query, encoder_outputs) |
| 523 | input_gru = torch.cat((embedded, context), dim=2) |
| 524 | |
| 525 | output, hidden = self.gru(input_gru, hidden) |
| 526 | output = self.out(output) |
| 527 | |
| 528 | return output, hidden, attn_weights |
| 529 | |
| 530 | |
| 531 | ###################################################################### |
no outgoing calls
no test coverage detected