# Buggy code
def _add_embeddings_internal(self, sentences: Union[List[Sentence], Sentence]):
    """Add embeddings to all sentences in the given list of sentences. If embeddings are already added, update
    only if embeddings are non-static."""

    # TODO: remove in future versions
    if not hasattr(self, "locked_dropout"):
        self.locked_dropout = None
    if not hasattr(self, "word_dropout"):
        self.word_dropout = None

    if type(sentences) is Sentence:
        sentences = [sentences]

    self.rnn.zero_grad()

    # embed words in the sentence
    self.embeddings.embed(sentences)

    lengths: List[int] = [len(sentence.tokens) for sentence in sentences]
    longest_token_sequence_in_batch: int = max(lengths)

    # initialize zero-padded word embeddings tensor
    # sentence_tensor = torch.zeros(
    #     [
    #         len(sentences),
    #         longest_token_sequence_in_batch,
    #         self.embeddings.embedding_length,
    #     ],
    #     dtype=torch.float,
    #     device=flair.device,
    # )
    #
    # for s_id, sentence in enumerate(sentences):
    #     # fill values with word embeddings
    #     all_embs = list()
    #
    #     for index_token, token in enumerate(sentence):
    #         embs = token.get_each_embedding()
    #         if not all_embs:
    #             all_embs = [list() for _ in range(len(embs))]
    #         for index_emb, emb in enumerate(embs):
    #             all_embs[index_emb].append(emb)
    #
    #     concat_word_emb = [torch.stack(embs) for embs in all_embs]
    #     concat_sentence_emb = torch.cat(concat_word_emb, dim=1)
    #     sentence_tensor[s_id][: len(sentence)] = concat_sentence_emb

    pre_allocated_zero_tensor = torch.zeros(
        self.embeddings.embedding_length * longest_token_sequence_in_batch,
        dtype=torch.float,
        device=flair.device,
    )

    all_embs: List[torch.Tensor] = list()
    for sentence in sentences:
        all_embs += [emb for token in sentence for emb in token.get_each_embedding()]
        nb_padding_tokens = longest_token_sequence_in_batch - len(sentence)

        if nb_padding_tokens > 0:
            t = pre_allocated_zero_tensor[
                : self.embeddings.embedding_length * nb_padding_tokens
            ]
            all_embs.append(t)

    sentence_tensor = torch.cat(all_embs).view(
        [
            len(sentences),
            longest_token_sequence_in_batch,
            self.embeddings.embedding_length,
        ]
    )

    # before-RNN dropout
    if self.dropout:
        sentence_tensor = self.dropout(sentence_tensor)
    if self.locked_dropout:
        sentence_tensor = self.locked_dropout(sentence_tensor)
    if self.word_dropout:
        sentence_tensor = self.word_dropout(sentence_tensor)

    # reproject if set
    if self.reproject_words:
        sentence_tensor = self.word_reprojection_map(sentence_tensor)

    # push through RNN
    packed = pack_padded_sequence(
        sentence_tensor, lengths, enforce_sorted=False, batch_first=True
    )
    rnn_out, hidden = self.rnn(packed)
    outputs, output_lengths = pad_packed_sequence(rnn_out, batch_first=True)

    # after-RNN dropout
    if self.dropout:
        outputs = self.dropout(outputs)
    if self.locked_dropout:
        outputs = self.locked_dropout(outputs)

    # extract embeddings from RNN
    for sentence_no, length in enumerate(lengths):
        last_rep = outputs[sentence_no, length - 1]

        embedding = last_rep
        if self.bidirectional:
            first_rep = outputs[sentence_no, 0]
            embedding = torch.cat([first_rep, last_rep], 0)

        if self.static_embeddings:
            embedding = embedding.detach()

        sentence = sentences[sentence_no]
        sentence.set_embedding(self.name, embedding)


# Traceback (AttributeError)
AttributeError                            Traceback (most recent call last)
<ipython-input-4-f517a501f1cf> in <module>
----> 1 classifier = TextClassifier.load('en-sentiment')

~/Desktop/flair/flair/nn.py in load(cls, model)
86             state = torch.load(f, map_location=flair.device)
87
---> 88         model = cls._init_model_with_state_dict(state)
89
90         model.eval()

~/Desktop/flair/flair/models/text_classification_model.py in _init_model_with_state_dict(state)
129             multi_label=state["multi_label"],
130             beta=beta,
--> 131             loss_weights=weights,
132         )
133

~/Desktop/flair/flair/models/text_classification_model.py in __init__(self, document_embeddings, label_dictionary, multi_label, multi_label_threshold, beta, loss_weights)
90
91         # auto-spawn on GPU if available
---> 92         self.to(flair.device)
93
94     def _init_weights(self):

~/.local/lib/python3.6/site-packages/torch/nn/modules/module.py in to(self, *args, **kwargs)
423             return t.to(device, dtype if t.is_floating_point() else None, non_blocking)
424
--> 425         return self._apply(convert)
426
427     def register_backward_hook(self, hook):

~/.local/lib/python3.6/site-packages/torch/nn/modules/module.py in _apply(self, fn)
199     def _apply(self, fn):
200         for module in self.children():
--> 201             module._apply(fn)
202
203         def compute_should_use_set_data(tensor, tensor_applied):

~/.local/lib/python3.6/site-packages/torch/nn/modules/module.py in _apply(self, fn)
199     def _apply(self, fn):
200         for module in self.children():
--> 201             module._apply(fn)
202
203         def compute_should_use_set_data(tensor, tensor_applied):

~/.local/lib/python3.6/site-packages/torch/nn/modules/rnn.py in _apply(self, fn)
135         # Note: be v. careful before removing this, as 3rd party device types
136         # likely rely on this behavior to properly .to() modules like LSTM.
--> 137         self._flat_weights = [getattr(self, weight) for weight in self._flat_weights_names]
138
139         # Flattens params (on CUDA)

~/.local/lib/python3.6/site-packages/torch/nn/modules/module.py in __getattr__(self, name)
574                 return modules[name]
575         raise AttributeError("'{}' object has no attribute '{}'".format(
--> 576             type(self).__name__, name))
577
578     def __setattr__(self, name, value):

AttributeError: 'GRU' object has no attribute '_flat_weights_names'

# Fixed code
def _add_embeddings_internal(self, sentences: Union[List[Sentence], Sentence]):
    """Add embeddings to all sentences in the given list of sentences. If embeddings are already added, update
    only if embeddings are non-static."""

    # TODO: remove in future versions
    if not hasattr(self, "locked_dropout"):
        self.locked_dropout = None
    if not hasattr(self, "word_dropout"):
        self.word_dropout = None

    if type(sentences) is Sentence:
        sentences = [sentences]

    self.rnn.zero_grad()

    # embed words in the sentence
    self.embeddings.embed(sentences)

    lengths: List[int] = [len(sentence.tokens) for sentence in sentences]
    longest_token_sequence_in_batch: int = max(lengths)

    pre_allocated_zero_tensor = torch.zeros(
        self.embeddings.embedding_length * longest_token_sequence_in_batch,
        dtype=torch.float,
        device=flair.device,
    )

    all_embs: List[torch.Tensor] = list()
    for sentence in sentences:
        all_embs += [emb for token in sentence for emb in token.get_each_embedding()]
        nb_padding_tokens = longest_token_sequence_in_batch - len(sentence)

        if nb_padding_tokens > 0:
            t = pre_allocated_zero_tensor[
                : self.embeddings.embedding_length * nb_padding_tokens
            ]
            all_embs.append(t)

    sentence_tensor = torch.cat(all_embs).view(
        [
            len(sentences),
            longest_token_sequence_in_batch,
            self.embeddings.embedding_length,
        ]
    )

    # before-RNN dropout
    if self.dropout:
        sentence_tensor = self.dropout(sentence_tensor)
    if self.locked_dropout:
        sentence_tensor = self.locked_dropout(sentence_tensor)
    if self.word_dropout:
        sentence_tensor = self.word_dropout(sentence_tensor)

    # reproject if set
    if self.reproject_words:
        sentence_tensor = self.word_reprojection_map(sentence_tensor)

    # push through RNN
    packed = pack_padded_sequence(
        sentence_tensor, lengths, enforce_sorted=False, batch_first=True
    )
    rnn_out, hidden = self.rnn(packed)
    outputs, output_lengths = pad_packed_sequence(rnn_out, batch_first=True)

    # after-RNN dropout
    if self.dropout:
        outputs = self.dropout(outputs)
    if self.locked_dropout:
        outputs = self.locked_dropout(outputs)

    # extract embeddings from RNN
    for sentence_no, length in enumerate(lengths):
        last_rep = outputs[sentence_no, length - 1]

        embedding = last_rep
        if self.bidirectional:
            first_rep = outputs[sentence_no, 0]
            embedding = torch.cat([first_rep, last_rep], 0)

        if self.static_embeddings:
            embedding = embedding.detach()

        sentence = sentences[sentence_no]
        sentence.set_embedding(self.name, embedding)