We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
one redundant code line
in TextClassifier class
`
34 self.document_embeddings = document_embeddings
`
`
38 self.document_embeddings: flair.embeddings.DocumentLSTMEmbeddings = document_embeddings
`

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `flair/models/text_classification_model.py`
Content:
```
1 import warnings
2 import logging
3 from pathlib import Path
4 from typing import List, Union
5 
6 import torch
7 import torch.nn as nn
8 
9 import flair.nn
10 import flair.embeddings
11 from flair.data import Dictionary, Sentence, Label
12 from flair.file_utils import cached_path
13 from flair.training_utils import convert_labels_to_one_hot, clear_embeddings
14 
15 
16 log = logging.getLogger('flair')
17 
18 
19 class TextClassifier(flair.nn.Model):
20     """
21     Text Classification Model
22     The model takes word embeddings, puts them into an LSTM to obtain a text representation, and puts the
23     text representation in the end into a linear layer to get the actual class label.
24     The model can handle single and multi class data sets.
25     """
26 
27     def __init__(self,
28                  document_embeddings: flair.embeddings.DocumentEmbeddings,
29                  label_dictionary: Dictionary,
30                  multi_label: bool):
31 
32         super(TextClassifier, self).__init__()
33 
34         self.document_embeddings = document_embeddings
35         self.label_dictionary: Dictionary = label_dictionary
36         self.multi_label = multi_label
37 
38         self.document_embeddings: flair.embeddings.DocumentLSTMEmbeddings = document_embeddings
39 
40         self.decoder = nn.Linear(self.document_embeddings.embedding_length, len(self.label_dictionary))
41 
42         self._init_weights()
43 
44         if multi_label:
45             self.loss_function = nn.BCELoss()
46         else:
47             self.loss_function = nn.CrossEntropyLoss()
48 
49         # auto-spawn on GPU if available
50         self.to(flair.device)
51 
52     def _init_weights(self):
53         nn.init.xavier_uniform_(self.decoder.weight)
54 
55     def forward(self, sentences) -> List[List[float]]:
56         self.document_embeddings.embed(sentences)
57 
58         text_embedding_list = [sentence.get_embedding().unsqueeze(0) for sentence in sentences]
59         text_embedding_tensor = torch.cat(text_embedding_list, 0).to(flair.device)
60 
61         label_scores = self.decoder(text_embedding_tensor)
62 
63         return label_scores
64 
65     def save(self, model_file: Union[str, Path]):
66         """
67         Saves the current model to the provided file.
68         :param model_file: the model file
69         """
70         model_state = {
71             'state_dict': self.state_dict(),
72             'document_embeddings': self.document_embeddings,
73             'label_dictionary': self.label_dictionary,
74             'multi_label': self.multi_label,
75         }
76         torch.save(model_state, str(model_file), pickle_protocol=4)
77 
78     def save_checkpoint(self, model_file: Union[str, Path], optimizer_state: dict, scheduler_state: dict, epoch: int, loss: float):
79         """
80         Saves the current model to the provided file.
81         :param model_file: the model file
82         """
83         model_state = {
84             'state_dict': self.state_dict(),
85             'document_embeddings': self.document_embeddings,
86             'label_dictionary': self.label_dictionary,
87             'multi_label': self.multi_label,
88             'optimizer_state_dict': optimizer_state,
89             'scheduler_state_dict': scheduler_state,
90             'epoch': epoch,
91             'loss': loss
92         }
93         torch.save(model_state, str(model_file), pickle_protocol=4)
94 
95     @classmethod
96     def load_from_file(cls, model_file: Union[str, Path]):
97         """
98         Loads the model from the given file.
99         :param model_file: the model file
100         :return: the loaded text classifier model
101         """
102         state = TextClassifier._load_state(model_file)
103 
104         model = TextClassifier(
105             document_embeddings=state['document_embeddings'],
106             label_dictionary=state['label_dictionary'],
107             multi_label=state['multi_label']
108         )
109         model.load_state_dict(state['state_dict'])
110         model.eval()
111         model.to(flair.device)
112 
113         return model
114 
115     @classmethod
116     def load_checkpoint(cls, model_file: Union[str, Path]):
117         state = TextClassifier._load_state(model_file)
118         model = TextClassifier.load_from_file(model_file)
119 
120         epoch = state['epoch'] if 'epoch' in state else None
121         loss = state['loss'] if 'loss' in state else None
122         optimizer_state_dict = state['optimizer_state_dict'] if 'optimizer_state_dict' in state else None
123         scheduler_state_dict = state['scheduler_state_dict'] if 'scheduler_state_dict' in state else None
124 
125         return {
126             'model': model, 'epoch': epoch, 'loss': loss,
127             'optimizer_state_dict': optimizer_state_dict, 'scheduler_state_dict': scheduler_state_dict
128         }
129 
130     @classmethod
131     def _load_state(cls, model_file: Union[str, Path]):
132         # ATTENTION: suppressing torch serialization warnings. This needs to be taken out once we sort out recursive
133         # serialization of torch objects
134         # https://docs.python.org/3/library/warnings.html#temporarily-suppressing-warnings
135         with warnings.catch_warnings():
136             warnings.filterwarnings("ignore")
137             # load_big_file is a workaround by https://github.com/highway11git to load models on some Mac/Windows setups
138             # see https://github.com/zalandoresearch/flair/issues/351
139             f = flair.file_utils.load_big_file(str(model_file))
140             state = torch.load(f, map_location=flair.device)
141             return state
142 
143     def forward_loss(self, sentences: Union[List[Sentence], Sentence]) -> torch.tensor:
144         scores = self.forward(sentences)
145         return self._calculate_loss(scores, sentences)
146 
147     def forward_labels_and_loss(self, sentences: Union[Sentence, List[Sentence]]) -> (List[List[Label]], torch.tensor):
148         scores = self.forward(sentences)
149         labels = self._obtain_labels(scores)
150         loss = self._calculate_loss(scores, sentences)
151         return labels, loss
152 
153     def predict(self, sentences: Union[Sentence, List[Sentence]], mini_batch_size: int = 32) -> List[Sentence]:
154         """
155         Predicts the class labels for the given sentences. The labels are directly added to the sentences.
156         :param sentences: list of sentences
157         :param mini_batch_size: mini batch size to use
158         :return: the list of sentences containing the labels
159         """
160         with torch.no_grad():
161             if type(sentences) is Sentence:
162                 sentences = [sentences]
163 
164             filtered_sentences = self._filter_empty_sentences(sentences)
165 
166             batches = [filtered_sentences[x:x + mini_batch_size] for x in range(0, len(filtered_sentences), mini_batch_size)]
167 
168             for batch in batches:
169                 scores = self.forward(batch)
170                 predicted_labels = self._obtain_labels(scores)
171 
172                 for (sentence, labels) in zip(batch, predicted_labels):
173                     sentence.labels = labels
174 
175                 clear_embeddings(batch)
176 
177             return sentences
178 
179     @staticmethod
180     def _filter_empty_sentences(sentences: List[Sentence]) -> List[Sentence]:
181         filtered_sentences = [sentence for sentence in sentences if sentence.tokens]
182         if len(sentences) != len(filtered_sentences):
183             log.warning('Ignore {} sentence(s) with no tokens.'.format(len(sentences) - len(filtered_sentences)))
184         return filtered_sentences
185 
186     def _calculate_loss(self, scores: List[List[float]], sentences: List[Sentence]) -> float:
187         """
188         Calculates the loss.
189         :param scores: the prediction scores from the model
190         :param sentences: list of sentences
191         :return: loss value
192         """
193         if self.multi_label:
194             return self._calculate_multi_label_loss(scores, sentences)
195 
196         return self._calculate_single_label_loss(scores, sentences)
197 
198     def _obtain_labels(self, scores: List[List[float]]) -> List[List[Label]]:
199         """
200         Predicts the labels of sentences.
201         :param scores: the prediction scores from the model
202         :return: list of predicted labels
203         """
204 
205         if self.multi_label:
206             return [self._get_multi_label(s) for s in scores]
207 
208         return [self._get_single_label(s) for s in scores]
209 
210     def _get_multi_label(self, label_scores) -> List[Label]:
211         labels = []
212 
213         sigmoid = torch.nn.Sigmoid()
214 
215         results = list(map(lambda x: sigmoid(x), label_scores))
216         for idx, conf in enumerate(results):
217             if conf > 0.5:
218                 label = self.label_dictionary.get_item_for_index(idx)
219                 labels.append(Label(label, conf.item()))
220 
221         return labels
222 
223     def _get_single_label(self, label_scores) -> List[Label]:
224         conf, idx = torch.max(label_scores, 0)
225         label = self.label_dictionary.get_item_for_index(idx.item())
226 
227         return [Label(label, conf.item())]
228 
229     def _calculate_multi_label_loss(self, label_scores, sentences: List[Sentence]) -> float:
230         sigmoid = nn.Sigmoid()
231         return self.loss_function(sigmoid(label_scores), self._labels_to_one_hot(sentences))
232 
233     def _calculate_single_label_loss(self, label_scores, sentences: List[Sentence]) -> float:
234         return self.loss_function(label_scores, self._labels_to_indices(sentences))
235 
236     def _labels_to_one_hot(self, sentences: List[Sentence]):
237         label_list = [sentence.get_label_names() for sentence in sentences]
238         one_hot = convert_labels_to_one_hot(label_list, self.label_dictionary)
239         one_hot = [torch.FloatTensor(l).unsqueeze(0) for l in one_hot]
240         one_hot = torch.cat(one_hot, 0).to(flair.device)
241         return one_hot
242 
243     def _labels_to_indices(self, sentences: List[Sentence]):
244         indices = [
245             torch.LongTensor([self.label_dictionary.get_idx_for_item(label.value) for label in sentence.labels])
246             for sentence in sentences
247         ]
248 
249         vec = torch.cat(indices, 0).to(flair.device)
250 
251         return vec
252 
253     @staticmethod
254     def load(model: str):
255         model_file = None
256         aws_resource_path = 'https://s3.eu-central-1.amazonaws.com/alan-nlp/resources/models-v0.4'
257         cache_dir = Path('models')
258 
259         if model.lower() == 'de-offensive-language':
260             base_path = '/'.join([aws_resource_path, 'TEXT-CLASSIFICATION_germ-eval-2018_task-1',
261                                   'germ-eval-2018-task-1.pt'])
262             model_file = cached_path(base_path, cache_dir=cache_dir)
263 
264         elif model.lower() == 'en-sentiment':
265             base_path = '/'.join([aws_resource_path, 'TEXT-CLASSIFICATION_imdb', 'imdb.pt'])
266             model_file = cached_path(base_path, cache_dir=cache_dir)
267 
268         if model_file is not None:
269             return TextClassifier.load_from_file(model_file)
270
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/flair/models/text_classification_model.py b/flair/models/text_classification_model.py
--- a/flair/models/text_classification_model.py
+++ b/flair/models/text_classification_model.py
@@ -31,12 +31,10 @@
 
         super(TextClassifier, self).__init__()
 
-        self.document_embeddings = document_embeddings
+        self.document_embeddings: flair.embeddings.DocumentLSTMEmbeddings = document_embeddings
         self.label_dictionary: Dictionary = label_dictionary
         self.multi_label = multi_label
 
-        self.document_embeddings: flair.embeddings.DocumentLSTMEmbeddings = document_embeddings
-
         self.decoder = nn.Linear(self.document_embeddings.embedding_length, len(self.label_dictionary))
 
         self._init_weights()

{"golden_diff": "diff --git a/flair/models/text_classification_model.py b/flair/models/text_classification_model.py\n--- a/flair/models/text_classification_model.py\n+++ b/flair/models/text_classification_model.py\n@@ -31,12 +31,10 @@\n \n         super(TextClassifier, self).__init__()\n \n-        self.document_embeddings = document_embeddings\n+        self.document_embeddings: flair.embeddings.DocumentLSTMEmbeddings = document_embeddings\n         self.label_dictionary: Dictionary = label_dictionary\n         self.multi_label = multi_label\n \n-        self.document_embeddings: flair.embeddings.DocumentLSTMEmbeddings = document_embeddings\n-\n         self.decoder = nn.Linear(self.document_embeddings.embedding_length, len(self.label_dictionary))\n \n         self._init_weights()\n", "issue": "one redundant code line\nin TextClassifier class\r\n`\r\n34 self.document_embeddings = document_embeddings\r\n`\r\n`\r\n38 self.document_embeddings: flair.embeddings.DocumentLSTMEmbeddings = document_embeddings\r\n`\n", "before_files": [{"content": "import warnings\nimport logging\nfrom pathlib import Path\nfrom typing import List, Union\n\nimport torch\nimport torch.nn as nn\n\nimport flair.nn\nimport flair.embeddings\nfrom flair.data import Dictionary, Sentence, Label\nfrom flair.file_utils import cached_path\nfrom flair.training_utils import convert_labels_to_one_hot, clear_embeddings\n\n\nlog = logging.getLogger('flair')\n\n\nclass TextClassifier(flair.nn.Model):\n    \"\"\"\n    Text Classification Model\n    The model takes word embeddings, puts them into an LSTM to obtain a text representation, and puts the\n    text representation in the end into a linear layer to get the actual class label.\n    The model can handle single and multi class data sets.\n    \"\"\"\n\n    def __init__(self,\n                 document_embeddings: flair.embeddings.DocumentEmbeddings,\n                 label_dictionary: Dictionary,\n                 multi_label: bool):\n\n        super(TextClassifier, self).__init__()\n\n        self.document_embeddings = document_embeddings\n        self.label_dictionary: Dictionary = label_dictionary\n        self.multi_label = multi_label\n\n        self.document_embeddings: flair.embeddings.DocumentLSTMEmbeddings = document_embeddings\n\n        self.decoder = nn.Linear(self.document_embeddings.embedding_length, len(self.label_dictionary))\n\n        self._init_weights()\n\n        if multi_label:\n            self.loss_function = nn.BCELoss()\n        else:\n            self.loss_function = nn.CrossEntropyLoss()\n\n        # auto-spawn on GPU if available\n        self.to(flair.device)\n\n    def _init_weights(self):\n        nn.init.xavier_uniform_(self.decoder.weight)\n\n    def forward(self, sentences) -> List[List[float]]:\n        self.document_embeddings.embed(sentences)\n\n        text_embedding_list = [sentence.get_embedding().unsqueeze(0) for sentence in sentences]\n        text_embedding_tensor = torch.cat(text_embedding_list, 0).to(flair.device)\n\n        label_scores = self.decoder(text_embedding_tensor)\n\n        return label_scores\n\n    def save(self, model_file: Union[str, Path]):\n        \"\"\"\n        Saves the current model to the provided file.\n        :param model_file: the model file\n        \"\"\"\n        model_state = {\n            'state_dict': self.state_dict(),\n            'document_embeddings': self.document_embeddings,\n            'label_dictionary': self.label_dictionary,\n            'multi_label': self.multi_label,\n        }\n        torch.save(model_state, str(model_file), pickle_protocol=4)\n\n    def save_checkpoint(self, model_file: Union[str, Path], optimizer_state: dict, scheduler_state: dict, epoch: int, loss: float):\n        \"\"\"\n        Saves the current model to the provided file.\n        :param model_file: the model file\n        \"\"\"\n        model_state = {\n            'state_dict': self.state_dict(),\n            'document_embeddings': self.document_embeddings,\n            'label_dictionary': self.label_dictionary,\n            'multi_label': self.multi_label,\n            'optimizer_state_dict': optimizer_state,\n            'scheduler_state_dict': scheduler_state,\n            'epoch': epoch,\n            'loss': loss\n        }\n        torch.save(model_state, str(model_file), pickle_protocol=4)\n\n    @classmethod\n    def load_from_file(cls, model_file: Union[str, Path]):\n        \"\"\"\n        Loads the model from the given file.\n        :param model_file: the model file\n        :return: the loaded text classifier model\n        \"\"\"\n        state = TextClassifier._load_state(model_file)\n\n        model = TextClassifier(\n            document_embeddings=state['document_embeddings'],\n            label_dictionary=state['label_dictionary'],\n            multi_label=state['multi_label']\n        )\n        model.load_state_dict(state['state_dict'])\n        model.eval()\n        model.to(flair.device)\n\n        return model\n\n    @classmethod\n    def load_checkpoint(cls, model_file: Union[str, Path]):\n        state = TextClassifier._load_state(model_file)\n        model = TextClassifier.load_from_file(model_file)\n\n        epoch = state['epoch'] if 'epoch' in state else None\n        loss = state['loss'] if 'loss' in state else None\n        optimizer_state_dict = state['optimizer_state_dict'] if 'optimizer_state_dict' in state else None\n        scheduler_state_dict = state['scheduler_state_dict'] if 'scheduler_state_dict' in state else None\n\n        return {\n            'model': model, 'epoch': epoch, 'loss': loss,\n            'optimizer_state_dict': optimizer_state_dict, 'scheduler_state_dict': scheduler_state_dict\n        }\n\n    @classmethod\n    def _load_state(cls, model_file: Union[str, Path]):\n        # ATTENTION: suppressing torch serialization warnings. This needs to be taken out once we sort out recursive\n        # serialization of torch objects\n        # https://docs.python.org/3/library/warnings.html#temporarily-suppressing-warnings\n        with warnings.catch_warnings():\n            warnings.filterwarnings(\"ignore\")\n            # load_big_file is a workaround by https://github.com/highway11git to load models on some Mac/Windows setups\n            # see https://github.com/zalandoresearch/flair/issues/351\n            f = flair.file_utils.load_big_file(str(model_file))\n            state = torch.load(f, map_location=flair.device)\n            return state\n\n    def forward_loss(self, sentences: Union[List[Sentence], Sentence]) -> torch.tensor:\n        scores = self.forward(sentences)\n        return self._calculate_loss(scores, sentences)\n\n    def forward_labels_and_loss(self, sentences: Union[Sentence, List[Sentence]]) -> (List[List[Label]], torch.tensor):\n        scores = self.forward(sentences)\n        labels = self._obtain_labels(scores)\n        loss = self._calculate_loss(scores, sentences)\n        return labels, loss\n\n    def predict(self, sentences: Union[Sentence, List[Sentence]], mini_batch_size: int = 32) -> List[Sentence]:\n        \"\"\"\n        Predicts the class labels for the given sentences. The labels are directly added to the sentences.\n        :param sentences: list of sentences\n        :param mini_batch_size: mini batch size to use\n        :return: the list of sentences containing the labels\n        \"\"\"\n        with torch.no_grad():\n            if type(sentences) is Sentence:\n                sentences = [sentences]\n\n            filtered_sentences = self._filter_empty_sentences(sentences)\n\n            batches = [filtered_sentences[x:x + mini_batch_size] for x in range(0, len(filtered_sentences), mini_batch_size)]\n\n            for batch in batches:\n                scores = self.forward(batch)\n                predicted_labels = self._obtain_labels(scores)\n\n                for (sentence, labels) in zip(batch, predicted_labels):\n                    sentence.labels = labels\n\n                clear_embeddings(batch)\n\n            return sentences\n\n    @staticmethod\n    def _filter_empty_sentences(sentences: List[Sentence]) -> List[Sentence]:\n        filtered_sentences = [sentence for sentence in sentences if sentence.tokens]\n        if len(sentences) != len(filtered_sentences):\n            log.warning('Ignore {} sentence(s) with no tokens.'.format(len(sentences) - len(filtered_sentences)))\n        return filtered_sentences\n\n    def _calculate_loss(self, scores: List[List[float]], sentences: List[Sentence]) -> float:\n        \"\"\"\n        Calculates the loss.\n        :param scores: the prediction scores from the model\n        :param sentences: list of sentences\n        :return: loss value\n        \"\"\"\n        if self.multi_label:\n            return self._calculate_multi_label_loss(scores, sentences)\n\n        return self._calculate_single_label_loss(scores, sentences)\n\n    def _obtain_labels(self, scores: List[List[float]]) -> List[List[Label]]:\n        \"\"\"\n        Predicts the labels of sentences.\n        :param scores: the prediction scores from the model\n        :return: list of predicted labels\n        \"\"\"\n\n        if self.multi_label:\n            return [self._get_multi_label(s) for s in scores]\n\n        return [self._get_single_label(s) for s in scores]\n\n    def _get_multi_label(self, label_scores) -> List[Label]:\n        labels = []\n\n        sigmoid = torch.nn.Sigmoid()\n\n        results = list(map(lambda x: sigmoid(x), label_scores))\n        for idx, conf in enumerate(results):\n            if conf > 0.5:\n                label = self.label_dictionary.get_item_for_index(idx)\n                labels.append(Label(label, conf.item()))\n\n        return labels\n\n    def _get_single_label(self, label_scores) -> List[Label]:\n        conf, idx = torch.max(label_scores, 0)\n        label = self.label_dictionary.get_item_for_index(idx.item())\n\n        return [Label(label, conf.item())]\n\n    def _calculate_multi_label_loss(self, label_scores, sentences: List[Sentence]) -> float:\n        sigmoid = nn.Sigmoid()\n        return self.loss_function(sigmoid(label_scores), self._labels_to_one_hot(sentences))\n\n    def _calculate_single_label_loss(self, label_scores, sentences: List[Sentence]) -> float:\n        return self.loss_function(label_scores, self._labels_to_indices(sentences))\n\n    def _labels_to_one_hot(self, sentences: List[Sentence]):\n        label_list = [sentence.get_label_names() for sentence in sentences]\n        one_hot = convert_labels_to_one_hot(label_list, self.label_dictionary)\n        one_hot = [torch.FloatTensor(l).unsqueeze(0) for l in one_hot]\n        one_hot = torch.cat(one_hot, 0).to(flair.device)\n        return one_hot\n\n    def _labels_to_indices(self, sentences: List[Sentence]):\n        indices = [\n            torch.LongTensor([self.label_dictionary.get_idx_for_item(label.value) for label in sentence.labels])\n            for sentence in sentences\n        ]\n\n        vec = torch.cat(indices, 0).to(flair.device)\n\n        return vec\n\n    @staticmethod\n    def load(model: str):\n        model_file = None\n        aws_resource_path = 'https://s3.eu-central-1.amazonaws.com/alan-nlp/resources/models-v0.4'\n        cache_dir = Path('models')\n\n        if model.lower() == 'de-offensive-language':\n            base_path = '/'.join([aws_resource_path, 'TEXT-CLASSIFICATION_germ-eval-2018_task-1',\n                                  'germ-eval-2018-task-1.pt'])\n            model_file = cached_path(base_path, cache_dir=cache_dir)\n\n        elif model.lower() == 'en-sentiment':\n            base_path = '/'.join([aws_resource_path, 'TEXT-CLASSIFICATION_imdb', 'imdb.pt'])\n            model_file = cached_path(base_path, cache_dir=cache_dir)\n\n        if model_file is not None:\n            return TextClassifier.load_from_file(model_file)\n", "path": "flair/models/text_classification_model.py"}], "after_files": [{"content": "import warnings\nimport logging\nfrom pathlib import Path\nfrom typing import List, Union\n\nimport torch\nimport torch.nn as nn\n\nimport flair.nn\nimport flair.embeddings\nfrom flair.data import Dictionary, Sentence, Label\nfrom flair.file_utils import cached_path\nfrom flair.training_utils import convert_labels_to_one_hot, clear_embeddings\n\n\nlog = logging.getLogger('flair')\n\n\nclass TextClassifier(flair.nn.Model):\n    \"\"\"\n    Text Classification Model\n    The model takes word embeddings, puts them into an LSTM to obtain a text representation, and puts the\n    text representation in the end into a linear layer to get the actual class label.\n    The model can handle single and multi class data sets.\n    \"\"\"\n\n    def __init__(self,\n                 document_embeddings: flair.embeddings.DocumentEmbeddings,\n                 label_dictionary: Dictionary,\n                 multi_label: bool):\n\n        super(TextClassifier, self).__init__()\n\n        self.document_embeddings: flair.embeddings.DocumentLSTMEmbeddings = document_embeddings\n        self.label_dictionary: Dictionary = label_dictionary\n        self.multi_label = multi_label\n\n        self.decoder = nn.Linear(self.document_embeddings.embedding_length, len(self.label_dictionary))\n\n        self._init_weights()\n\n        if multi_label:\n            self.loss_function = nn.BCELoss()\n        else:\n            self.loss_function = nn.CrossEntropyLoss()\n\n        # auto-spawn on GPU if available\n        self.to(flair.device)\n\n    def _init_weights(self):\n        nn.init.xavier_uniform_(self.decoder.weight)\n\n    def forward(self, sentences) -> List[List[float]]:\n        self.document_embeddings.embed(sentences)\n\n        text_embedding_list = [sentence.get_embedding().unsqueeze(0) for sentence in sentences]\n        text_embedding_tensor = torch.cat(text_embedding_list, 0).to(flair.device)\n\n        label_scores = self.decoder(text_embedding_tensor)\n\n        return label_scores\n\n    def save(self, model_file: Union[str, Path]):\n        \"\"\"\n        Saves the current model to the provided file.\n        :param model_file: the model file\n        \"\"\"\n        model_state = {\n            'state_dict': self.state_dict(),\n            'document_embeddings': self.document_embeddings,\n            'label_dictionary': self.label_dictionary,\n            'multi_label': self.multi_label,\n        }\n        torch.save(model_state, str(model_file), pickle_protocol=4)\n\n    def save_checkpoint(self, model_file: Union[str, Path], optimizer_state: dict, scheduler_state: dict, epoch: int, loss: float):\n        \"\"\"\n        Saves the current model to the provided file.\n        :param model_file: the model file\n        \"\"\"\n        model_state = {\n            'state_dict': self.state_dict(),\n            'document_embeddings': self.document_embeddings,\n            'label_dictionary': self.label_dictionary,\n            'multi_label': self.multi_label,\n            'optimizer_state_dict': optimizer_state,\n            'scheduler_state_dict': scheduler_state,\n            'epoch': epoch,\n            'loss': loss\n        }\n        torch.save(model_state, str(model_file), pickle_protocol=4)\n\n    @classmethod\n    def load_from_file(cls, model_file: Union[str, Path]):\n        \"\"\"\n        Loads the model from the given file.\n        :param model_file: the model file\n        :return: the loaded text classifier model\n        \"\"\"\n        state = TextClassifier._load_state(model_file)\n\n        model = TextClassifier(\n            document_embeddings=state['document_embeddings'],\n            label_dictionary=state['label_dictionary'],\n            multi_label=state['multi_label']\n        )\n        model.load_state_dict(state['state_dict'])\n        model.eval()\n        model.to(flair.device)\n\n        return model\n\n    @classmethod\n    def load_checkpoint(cls, model_file: Union[str, Path]):\n        state = TextClassifier._load_state(model_file)\n        model = TextClassifier.load_from_file(model_file)\n\n        epoch = state['epoch'] if 'epoch' in state else None\n        loss = state['loss'] if 'loss' in state else None\n        optimizer_state_dict = state['optimizer_state_dict'] if 'optimizer_state_dict' in state else None\n        scheduler_state_dict = state['scheduler_state_dict'] if 'scheduler_state_dict' in state else None\n\n        return {\n            'model': model, 'epoch': epoch, 'loss': loss,\n            'optimizer_state_dict': optimizer_state_dict, 'scheduler_state_dict': scheduler_state_dict\n        }\n\n    @classmethod\n    def _load_state(cls, model_file: Union[str, Path]):\n        # ATTENTION: suppressing torch serialization warnings. This needs to be taken out once we sort out recursive\n        # serialization of torch objects\n        # https://docs.python.org/3/library/warnings.html#temporarily-suppressing-warnings\n        with warnings.catch_warnings():\n            warnings.filterwarnings(\"ignore\")\n            # load_big_file is a workaround by https://github.com/highway11git to load models on some Mac/Windows setups\n            # see https://github.com/zalandoresearch/flair/issues/351\n            f = flair.file_utils.load_big_file(str(model_file))\n            state = torch.load(f, map_location=flair.device)\n            return state\n\n    def forward_loss(self, sentences: Union[List[Sentence], Sentence]) -> torch.tensor:\n        scores = self.forward(sentences)\n        return self._calculate_loss(scores, sentences)\n\n    def forward_labels_and_loss(self, sentences: Union[Sentence, List[Sentence]]) -> (List[List[Label]], torch.tensor):\n        scores = self.forward(sentences)\n        labels = self._obtain_labels(scores)\n        loss = self._calculate_loss(scores, sentences)\n        return labels, loss\n\n    def predict(self, sentences: Union[Sentence, List[Sentence]], mini_batch_size: int = 32) -> List[Sentence]:\n        \"\"\"\n        Predicts the class labels for the given sentences. The labels are directly added to the sentences.\n        :param sentences: list of sentences\n        :param mini_batch_size: mini batch size to use\n        :return: the list of sentences containing the labels\n        \"\"\"\n        with torch.no_grad():\n            if type(sentences) is Sentence:\n                sentences = [sentences]\n\n            filtered_sentences = self._filter_empty_sentences(sentences)\n\n            batches = [filtered_sentences[x:x + mini_batch_size] for x in range(0, len(filtered_sentences), mini_batch_size)]\n\n            for batch in batches:\n                scores = self.forward(batch)\n                predicted_labels = self._obtain_labels(scores)\n\n                for (sentence, labels) in zip(batch, predicted_labels):\n                    sentence.labels = labels\n\n                clear_embeddings(batch)\n\n            return sentences\n\n    @staticmethod\n    def _filter_empty_sentences(sentences: List[Sentence]) -> List[Sentence]:\n        filtered_sentences = [sentence for sentence in sentences if sentence.tokens]\n        if len(sentences) != len(filtered_sentences):\n            log.warning('Ignore {} sentence(s) with no tokens.'.format(len(sentences) - len(filtered_sentences)))\n        return filtered_sentences\n\n    def _calculate_loss(self, scores: List[List[float]], sentences: List[Sentence]) -> float:\n        \"\"\"\n        Calculates the loss.\n        :param scores: the prediction scores from the model\n        :param sentences: list of sentences\n        :return: loss value\n        \"\"\"\n        if self.multi_label:\n            return self._calculate_multi_label_loss(scores, sentences)\n\n        return self._calculate_single_label_loss(scores, sentences)\n\n    def _obtain_labels(self, scores: List[List[float]]) -> List[List[Label]]:\n        \"\"\"\n        Predicts the labels of sentences.\n        :param scores: the prediction scores from the model\n        :return: list of predicted labels\n        \"\"\"\n\n        if self.multi_label:\n            return [self._get_multi_label(s) for s in scores]\n\n        return [self._get_single_label(s) for s in scores]\n\n    def _get_multi_label(self, label_scores) -> List[Label]:\n        labels = []\n\n        sigmoid = torch.nn.Sigmoid()\n\n        results = list(map(lambda x: sigmoid(x), label_scores))\n        for idx, conf in enumerate(results):\n            if conf > 0.5:\n                label = self.label_dictionary.get_item_for_index(idx)\n                labels.append(Label(label, conf.item()))\n\n        return labels\n\n    def _get_single_label(self, label_scores) -> List[Label]:\n        conf, idx = torch.max(label_scores, 0)\n        label = self.label_dictionary.get_item_for_index(idx.item())\n\n        return [Label(label, conf.item())]\n\n    def _calculate_multi_label_loss(self, label_scores, sentences: List[Sentence]) -> float:\n        sigmoid = nn.Sigmoid()\n        return self.loss_function(sigmoid(label_scores), self._labels_to_one_hot(sentences))\n\n    def _calculate_single_label_loss(self, label_scores, sentences: List[Sentence]) -> float:\n        return self.loss_function(label_scores, self._labels_to_indices(sentences))\n\n    def _labels_to_one_hot(self, sentences: List[Sentence]):\n        label_list = [sentence.get_label_names() for sentence in sentences]\n        one_hot = convert_labels_to_one_hot(label_list, self.label_dictionary)\n        one_hot = [torch.FloatTensor(l).unsqueeze(0) for l in one_hot]\n        one_hot = torch.cat(one_hot, 0).to(flair.device)\n        return one_hot\n\n    def _labels_to_indices(self, sentences: List[Sentence]):\n        indices = [\n            torch.LongTensor([self.label_dictionary.get_idx_for_item(label.value) for label in sentence.labels])\n            for sentence in sentences\n        ]\n\n        vec = torch.cat(indices, 0).to(flair.device)\n\n        return vec\n\n    @staticmethod\n    def load(model: str):\n        model_file = None\n        aws_resource_path = 'https://s3.eu-central-1.amazonaws.com/alan-nlp/resources/models-v0.4'\n        cache_dir = Path('models')\n\n        if model.lower() == 'de-offensive-language':\n            base_path = '/'.join([aws_resource_path, 'TEXT-CLASSIFICATION_germ-eval-2018_task-1',\n                                  'germ-eval-2018-task-1.pt'])\n            model_file = cached_path(base_path, cache_dir=cache_dir)\n\n        elif model.lower() == 'en-sentiment':\n            base_path = '/'.join([aws_resource_path, 'TEXT-CLASSIFICATION_imdb', 'imdb.pt'])\n            model_file = cached_path(base_path, cache_dir=cache_dir)\n\n        if model_file is not None:\n            return TextClassifier.load_from_file(model_file)\n", "path": "flair/models/text_classification_model.py"}]}