1616 register_model_architecture ,
1717)
1818from fairseq .modules import AdaptiveSoftmax
19+ from torch import Tensor
20+ from typing import Dict , List , Optional , Tuple
21+
1922
2023DEFAULT_MAX_SOURCE_POSITIONS = 1e5
2124DEFAULT_MAX_TARGET_POSITIONS = 1e5
2225
26+
2327@register_model ('lstm' )
2428class LSTMModel (FairseqEncoderDecoderModel ):
2529 def __init__ (self , encoder , decoder ):
@@ -176,6 +180,19 @@ def load_pretrained_embedding_from_file(embed_path, dictionary, embed_dim):
176180 )
177181 return cls (encoder , decoder )
178182
183+ def forward (
184+ self ,
185+ src_tokens ,
186+ src_lengths ,
187+ prev_output_tokens ,
188+ incremental_state : Optional [Dict [str , Dict [str , Optional [Tensor ]]]] = None ,
189+ ):
190+ encoder_out = self .encoder (src_tokens , src_lengths = src_lengths )
191+ decoder_out = self .decoder (
192+ prev_output_tokens , encoder_out = encoder_out , incremental_state = incremental_state
193+ )
194+ return decoder_out
195+
179196
180197class LSTMEncoder (FairseqEncoder ):
181198 """LSTM encoder."""
@@ -213,13 +230,17 @@ def __init__(
213230 if bidirectional :
214231 self .output_units *= 2
215232
216- def forward (self , src_tokens , src_lengths ):
233+ def combine_bidir (self , outs , bsz : int ):
234+ out = outs .view (self .num_layers , 2 , bsz , - 1 ).transpose (1 , 2 ).contiguous ()
235+ return out .view (self .num_layers , bsz , - 1 )
236+
237+ def forward (self , src_tokens , src_lengths : Tensor ):
217238 if self .left_pad :
218239 # nn.utils.rnn.pack_padded_sequence requires right-padding;
219240 # convert left-padding to right-padding
220241 src_tokens = utils .convert_padding_direction (
221242 src_tokens ,
222- self .padding_idx ,
243+ torch . zeros_like ( src_tokens ). fill_ ( self .padding_idx ) ,
223244 left_to_right = True ,
224245 )
225246
@@ -233,7 +254,7 @@ def forward(self, src_tokens, src_lengths):
233254 x = x .transpose (0 , 1 )
234255
235256 # pack embedded source tokens into a PackedSequence
236- packed_x = nn .utils .rnn .pack_padded_sequence (x , src_lengths .data . tolist () )
257+ packed_x = nn .utils .rnn .pack_padded_sequence (x , src_lengths .data )
237258
238259 # apply LSTM
239260 if self .bidirectional :
@@ -245,34 +266,32 @@ def forward(self, src_tokens, src_lengths):
245266 packed_outs , (final_hiddens , final_cells ) = self .lstm (packed_x , (h0 , c0 ))
246267
247268 # unpack outputs and apply dropout
248- x , _ = nn .utils .rnn .pad_packed_sequence (packed_outs , padding_value = self .padding_idx )
269+ x , _ = nn .utils .rnn .pad_packed_sequence (packed_outs , padding_value = self .padding_idx * 1.0 )
249270 x = F .dropout (x , p = self .dropout_out , training = self .training )
250271 assert list (x .size ()) == [seqlen , bsz , self .output_units ]
251272
252273 if self .bidirectional :
253274
254- def combine_bidir (outs ):
255- out = outs .view (self .num_layers , 2 , bsz , - 1 ).transpose (1 , 2 ).contiguous ()
256- return out .view (self .num_layers , bsz , - 1 )
257-
258- final_hiddens = combine_bidir (final_hiddens )
259- final_cells = combine_bidir (final_cells )
275+ final_hiddens = self .combine_bidir (final_hiddens , bsz )
276+ final_cells = self .combine_bidir (final_cells , bsz )
260277
261278 encoder_padding_mask = src_tokens .eq (self .padding_idx ).t ()
262279
263280 return {
264281 'encoder_out' : (x , final_hiddens , final_cells ),
265- 'encoder_padding_mask' : encoder_padding_mask if encoder_padding_mask . any () else None
282+ 'encoder_padding_mask' : ( encoder_padding_mask , torch . empty ( 0 ), torch . empty ( 0 )),
266283 }
267284
268- def reorder_encoder_out (self , encoder_out , new_order ):
269- encoder_out ['encoder_out' ] = tuple (
270- eo .index_select (1 , new_order )
271- for eo in encoder_out ['encoder_out' ]
272- )
273- if encoder_out ['encoder_padding_mask' ] is not None :
274- encoder_out ['encoder_padding_mask' ] = \
275- encoder_out ['encoder_padding_mask' ].index_select (1 , new_order )
285+ def reorder_encoder_out (self , encoder_out : Dict [str , Tuple [Tensor , Tensor , Tensor ]], new_order ):
286+ encoder_out ['encoder_out' ] = (
287+ encoder_out ['encoder_out' ][0 ].index_select (1 , new_order ),
288+ encoder_out ['encoder_out' ][1 ].index_select (1 , new_order ),
289+ encoder_out ['encoder_out' ][2 ].index_select (1 , new_order ))
290+ if encoder_out ['encoder_padding_mask' ][0 ] is not None :
291+ encoder_out ['encoder_padding_mask' ] = (
292+ encoder_out ['encoder_padding_mask' ][0 ].index_select (1 , new_order ),
293+ encoder_out ['encoder_padding_mask' ][1 ],
294+ encoder_out ['encoder_padding_mask' ][2 ])
276295 return encoder_out
277296
278297 def max_positions (self ):
@@ -329,6 +348,7 @@ def __init__(
329348 self .share_input_output_embed = share_input_output_embed
330349 self .need_attn = True
331350 self .max_target_positions = max_target_positions
351+ self .num_layers = num_layers
332352
333353 self .adaptive_softmax = None
334354 num_embeddings = len (dictionary )
@@ -369,36 +389,51 @@ def __init__(
369389 elif not self .share_input_output_embed :
370390 self .fc_out = Linear (out_embed_dim , num_embeddings , dropout = dropout_out )
371391
372- def forward (self , prev_output_tokens , encoder_out = None , incremental_state = None , ** kwargs ):
392+ def get_cached_state (self , incremental_state : Optional [Dict [str , Dict [str , Optional [Tensor ]]]]):
393+
394+ cached_state = self .get_incremental_state (incremental_state , 'cached_state' )
395+ assert cached_state is not None
396+ prev_hiddens_ = cached_state ["prev_hiddens" ]
397+ assert prev_hiddens_ is not None
398+ prev_cells_ = cached_state ["prev_cells" ]
399+ assert prev_cells_ is not None
400+ prev_hiddens = [prev_hiddens_ [i ] for i in range (self .num_layers )]
401+ prev_cells = [prev_cells_ [j ] for j in range (self .num_layers )]
402+ input_feed = cached_state ["input_feed" ]
403+ assert input_feed is not None
404+ return prev_hiddens , prev_cells , input_feed
405+
406+ def forward (self , prev_output_tokens , encoder_out : Dict [str , Tuple [Tensor , Tensor , Tensor ]],
407+ incremental_state : Optional [Dict [str , Dict [str , Optional [Tensor ]]]]):
373408 x , attn_scores = self .extract_features (
374409 prev_output_tokens , encoder_out , incremental_state
375410 )
376411 return self .output_layer (x ), attn_scores
377412
378413 def extract_features (
379- self , prev_output_tokens , encoder_out , incremental_state = None
414+ self , prev_output_tokens , encoder_out : Dict [str , Tuple [Tensor , Tensor , Tensor ]],
415+ incremental_state : Optional [Dict [str , Dict [str , Optional [Tensor ]]]] = None
380416 ):
381417 """
382418 Similar to *forward* but only return features.
383419 """
384420 if encoder_out is not None :
385- encoder_padding_mask = encoder_out ['encoder_padding_mask' ]
421+ encoder_padding_mask , _ , _ = encoder_out ['encoder_padding_mask' ]
386422 encoder_out = encoder_out ['encoder_out' ]
387423 else :
388424 encoder_padding_mask = None
389425 encoder_out = None
390426
391- if incremental_state is not None :
427+ if incremental_state is not None and len ( incremental_state ) > 0 :
392428 prev_output_tokens = prev_output_tokens [:, - 1 :]
429+
393430 bsz , seqlen = prev_output_tokens .size ()
394431
395432 # get outputs from encoder
433+ srclen = 0
396434 if encoder_out is not None :
397435 encoder_outs , encoder_hiddens , encoder_cells = encoder_out [:3 ]
398436 srclen = encoder_outs .size (0 )
399- else :
400- srclen = None
401-
402437 # embed tokens
403438 x = self .embed_tokens (prev_output_tokens )
404439 x = F .dropout (x , p = self .dropout_in , training = self .training )
@@ -407,27 +442,25 @@ def extract_features(
407442 x = x .transpose (0 , 1 )
408443
409444 # initialize previous states (or get from cache during incremental generation)
410- cached_state = utils . get_incremental_state ( self , incremental_state , 'cached_state' )
411- if cached_state is not None :
412- prev_hiddens , prev_cells , input_feed = cached_state
445+
446+ if incremental_state is not None and len ( incremental_state ) > 0 :
447+ prev_hiddens , prev_cells , input_feed = self . get_cached_state ( incremental_state )
413448 elif encoder_out is not None :
414449 # setup recurrent cells
415- num_layers = len (self .layers )
416- prev_hiddens = [encoder_hiddens [i ] for i in range (num_layers )]
417- prev_cells = [encoder_cells [i ] for i in range (num_layers )]
450+ prev_hiddens = [encoder_hiddens [i ] for i in range (self .num_layers )]
451+ prev_cells = [encoder_cells [i ] for i in range (self .num_layers )]
418452 if self .encoder_hidden_proj is not None :
419- prev_hiddens = [self .encoder_hidden_proj (x ) for x in prev_hiddens ]
420- prev_cells = [self .encoder_cell_proj (x ) for x in prev_cells ]
453+ prev_hiddens = [self .encoder_hidden_proj (y ) for y in prev_hiddens ]
454+ prev_cells = [self .encoder_cell_proj (y ) for y in prev_cells ]
421455 input_feed = x .new_zeros (bsz , self .hidden_size )
422456 else :
423457 # setup zero cells, since there is no encoder
424- num_layers = len (self .layers )
425458 zero_state = x .new_zeros (bsz , self .hidden_size )
426- prev_hiddens = [zero_state for i in range (num_layers )]
427- prev_cells = [zero_state for i in range (num_layers )]
459+ prev_hiddens = [zero_state for i in range (self . num_layers )]
460+ prev_cells = [zero_state for i in range (self . num_layers )]
428461 input_feed = None
429462
430- assert srclen is not None or self .attention is None , \
463+ assert srclen > 0 or self .attention is None , \
431464 "attention is not supported if there are no encoder outputs"
432465 attn_scores = x .new_zeros (srclen , seqlen , bsz ) if self .attention is not None else None
433466 outs = []
@@ -451,6 +484,7 @@ def extract_features(
451484
452485 # apply attention using the last layer's hidden state
453486 if self .attention is not None :
487+ assert attn_scores is not None
454488 out , attn_scores [:, j , :] = self .attention (hidden , encoder_outs , encoder_padding_mask )
455489 else :
456490 out = hidden
@@ -463,11 +497,14 @@ def extract_features(
463497 # save final output
464498 outs .append (out )
465499
466- # cache previous states (no-op except during incremental generation)
467- utils .set_incremental_state (
468- self , incremental_state , 'cached_state' ,
469- (prev_hiddens , prev_cells , input_feed ),
470- )
500+ # Stack all the necessary tensors together and store
501+ prev_hiddens_tensor = torch .stack (prev_hiddens )
502+ prev_cells_tensor = torch .stack (prev_cells )
503+ cache_state = torch .jit .annotate (
504+ Dict [str , Optional [Tensor ]],
505+ {"prev_hiddens" : prev_hiddens_tensor , "prev_cells" : prev_cells_tensor , "input_feed" : input_feed })
506+ self .set_incremental_state (
507+ incremental_state , 'cached_state' , cache_state )
471508
472509 # collect outputs across time steps
473510 x = torch .cat (outs , dim = 0 ).view (seqlen , bsz , self .hidden_size )
@@ -478,9 +515,9 @@ def extract_features(
478515 if hasattr (self , 'additional_fc' ) and self .adaptive_softmax is None :
479516 x = self .additional_fc (x )
480517 x = F .dropout (x , p = self .dropout_out , training = self .training )
481-
482518 # srclen x tgtlen x bsz -> bsz x tgtlen x srclen
483519 if not self .training and self .need_attn and self .attention is not None :
520+ assert attn_scores is not None
484521 attn_scores = attn_scores .transpose (0 , 2 )
485522 else :
486523 attn_scores = None
@@ -495,22 +532,22 @@ def output_layer(self, x):
495532 x = self .fc_out (x )
496533 return x
497534
498- def reorder_incremental_state (self , incremental_state , new_order ):
499- super ().reorder_incremental_state (incremental_state , new_order )
500- cached_state = utils .get_incremental_state (self , incremental_state , 'cached_state' )
501- if cached_state is None :
502- return
503-
504- def reorder_state (state ):
505- if isinstance (state , list ):
506- return [reorder_state (state_i ) for state_i in state ]
507- elif state is not None :
508- return state .index_select (0 , new_order )
509- else :
510- return None
535+ def reorder_state (self , state : List [Tensor ], new_order ):
536+ return [state_i .index_select (0 , new_order ) for state_i in state ]
511537
512- new_state = tuple (map (reorder_state , cached_state ))
513- utils .set_incremental_state (self , incremental_state , 'cached_state' , new_state )
538+ def reorder_incremental_state (self , incremental_state : Optional [Dict [str , Dict [str , Optional [Tensor ]]]], new_order ):
539+ if incremental_state is None or len (incremental_state ) == 0 :
540+ return
541+ prev_hiddens , prev_cells , input_feed = self .get_cached_state (incremental_state )
542+ cached_state = (prev_hiddens , prev_cells , [input_feed ])
543+ new_state = [self .reorder_state (state , new_order ) for state in cached_state ]
544+ prev_hiddens_tensor = torch .stack (new_state [0 ])
545+ prev_cells_tensor = torch .stack (new_state [1 ])
546+ cached_state_new = torch .jit .annotate (
547+ Dict [str , Optional [Tensor ]],
548+ {"prev_hiddens" : prev_hiddens_tensor , "prev_cells" : prev_cells_tensor , "input_feed" : new_state [2 ][0 ]})
549+ self .set_incremental_state (incremental_state , 'cached_state' , cached_state_new ),
550+ return
514551
515552 def max_positions (self ):
516553 """Maximum output length supported by the decoder."""
0 commit comments