We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
"Trainer" doesn't take into account the case that "loss_fn" doesn't need to be passed in.
"Trainer" does not take into account the case where "loss" is already defined in the model, and there is no need to pass "loss_fn" to "Trainer".

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mindnlp/engine/trainer.py`
Content:
```
1 # Copyright 2022 Huawei Technologies Co., Ltd
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 # ============================================================================
15 # pylint: disable=W0212
16 # pylint: disable=no-name-in-module, ungrouped-imports
17 """
18 Trainer for training.
19 """
20 from inspect import signature
21 from tqdm import tqdm
22 from mindspore import ops
23 from mindspore import log, mutable
24 from mindspore.ops import value_and_grad
25 from mindnlp import ms_jit
26 from mindnlp.abc.callback import Callback
27 from mindnlp.engine.callbacks.callback_manager import CallbackManager, RunContext
28 from mindnlp.engine.callbacks.earlystop_callback import EarlyStopCallback
29 from mindnlp.engine.callbacks.best_model_callback import BestModelCallback
30 from mindnlp.engine.evaluator import Evaluator
31 
32 class Trainer:
33     r"""
34     Trainer to train the model.
35 
36 
37     Args:
38         network (Cell): A training network.
39         train_dataset (Dataset): A training dataset iterator. If `loss_fn` is defined, the data and label will be
40             passed to the `network` and the `loss_fn` respectively, so a tuple (data, label)
41             should be returned from dataset. If there is multiple data or labels, set `loss_fn`
42             to None and implement calculation of loss in `network`,
43             then a tuple (data1, data2, data3, ...) with all data returned from dataset will be
44             passed to the `network`.
45         eval_dataset (Dataset): A evaluating dataset iterator. If `loss_fn` is defined, the data and label will be
46             passed to the `network` and the `loss_fn` respectively, so a tuple (data, label)
47             should be returned from dataset. If there is multiple data or labels, set `loss_fn`
48             to None and implement calculation of loss in `network`,
49             then a tuple (data1, data2, data3, ...) with all data returned from dataset will be
50             passed to the `network`.
51         metrcis (Optional[list[Metrics], Metrics]): List of metrics objects which should be used
52             while evaluating. Default:None.
53         epochs (int): Total number of iterations on the data. Default: 10.
54         optimizer (Cell): Optimizer for updating the weights. If `optimizer` is None, the `network` needs to
55             do backpropagation and update weights. Default value: None.
56         loss_fn (Cell): Objective function. If `loss_fn` is None, the `network` should contain the calculation of loss
57             and parallel if needed. Default: None.
58         callbacks (Optional[list[Callback], Callback]): List of callback objects which should be executed
59             while training. Default: None.
60 
61     """
62 
63     def __init__(self, network=None, train_dataset=None, eval_dataset=None, metrics=None, epochs=10,
64                  loss_fn=None, optimizer=None, callbacks=None):
65         self.network = network
66         self.train_dataset = train_dataset
67         self.eval_dataset = eval_dataset
68         self.metrics = metrics
69         self.epochs = epochs
70         self.loss_fn = loss_fn
71         self.optimizer = optimizer
72         self.callbacks = callbacks
73         self.cur_epoch_nums = 0
74         self.cur_step_nums = 0
75         self.earlystop = False
76         self.grad_fn = None
77         if callbacks:
78             self._prepare_callbacks(callbacks)
79         self._prepare_eval()
80         self.callback_manager = CallbackManager(callbacks=self.callbacks)
81 
82     def _prepare_callbacks(self, callbacks):
83         self.callbacks = []
84         if isinstance(callbacks, Callback):
85             self.callbacks.append(callbacks)
86         elif isinstance(callbacks, list):
87             if all(isinstance(cb, Callback) for cb in callbacks) is True:
88                 self.callbacks = callbacks
89             else:
90                 obj = [not isinstance(cb, Callback) for cb in callbacks][0]
91                 raise TypeError(f"Expect sub-classes of Callback. Got {type(obj)}")
92         else:
93             raise TypeError(f"Expect callbacks to be list or Callback. Got {type(callbacks)}.")
94 
95     def _check_callbacks_type(self):
96         for callback in self.callbacks:
97             if isinstance(callback, EarlyStopCallback):
98                 raise ValueError("EarlyStopCallback is not effective when eval_dataset is None.")
99             if isinstance(callback, BestModelCallback):
100                 raise ValueError("BestModelCallback is not effective when eval_dataset is None.")
101 
102     def _prepare_eval(self):
103         if self.eval_dataset is not None and self.metrics is not None:
104             self.evaluator = Evaluator(network=self.network, eval_dataset=self.eval_dataset, metrics=self.metrics,
105                                         callbacks=self.callbacks)
106         elif self.eval_dataset is None and self.metrics is None:
107             if self.callbacks:
108                 self._check_callbacks_type()
109             self.evaluator = None
110         else:
111             raise ValueError("For evaluation in training process, both eval dataset and metrics should be not None.")
112 
113     def _check_amp_level_arg(self, optimizer, amp_level):
114         """Check mixed-precision argument rules."""
115         raise NotImplementedError
116 
117     def _check_for_graph_cell(self, kwargs):
118         """Check network rules of GraphCell."""
119         raise NotImplementedError
120 
121     def _build_boost_network(self, *kwargs):
122         """Build boost network."""
123         raise NotImplementedError
124 
125     def _check_reuse_dataset(self, dataset):
126         """Check if dataset is being used by other models under the data sink mode."""
127         if not hasattr(dataset, '__model_hash__'):
128             dataset.__model_hash__ = hash(self)
129         if hasattr(dataset, '__model_hash__') and dataset.__model_hash__ != hash(self):
130             raise RuntimeError("The dataset object had been used in other model by model.train(...), "
131                                "please create a new dataset.")
132 
133     def run(self, tgt_columns=None, jit=False):
134         """
135         Training process entry.
136 
137         Args:
138             tgt_columns (Optional[list[str], str]): Target label column names for loss function.
139             jit (bool): Whether use Just-In-Time compile.
140 
141         """
142 
143         args_dict = vars(self)
144         run_context = RunContext(args_dict)
145         self.callback_manager.train_begin(run_context)
146         self._run(run_context, tgt_columns, jit)
147         self.callback_manager.train_end(run_context)
148 
149     def _run(self, run_context, tgt_columns=None, jit=False):
150         """
151         Training process for non-data sinking mode. The data would be passed to network directly.
152         """
153         # forward function
154         net = self.network
155 
156         loss_fn = self.loss_fn
157         optimizer = self.optimizer
158         def forward_fn(inputs, labels):
159             logits_list = ()
160             logits = net(*inputs)
161             if isinstance(logits, tuple):
162                 logits_list += logits
163             else:
164                 logits_list += (logits,)
165 
166             loss = loss_fn(*logits_list, *labels)
167             return_list = (loss,) + logits_list
168             return return_list
169 
170         grad_fn = value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)
171 
172         def _run_step(inputs, labels):
173             """Core process of each step, including the forward propagation process and back propagation of data."""
174             (loss, *_), grads = grad_fn(inputs, labels)
175             optimizer(grads)
176             return loss
177 
178         @ms_jit
179         def _run_step_graph(inputs, labels):
180             """Core process of each step, including the forward propagation process and back propagation of data."""
181             (loss, _), grads = grad_fn(inputs, labels)
182             loss = ops.depend(loss, optimizer(grads))
183             return loss
184 
185         total = self.train_dataset.get_dataset_size()
186         # train epoch begin
187         for epoch in range(0, self.epochs):
188             net.set_train()
189             self.cur_epoch_nums = epoch + 1
190             self.cur_step_nums = 0
191             run_context.cur_epoch_nums = self.cur_epoch_nums
192             run_context.cur_step_nums = 0
193             if self.earlystop is True:
194                 break
195             self.callback_manager.train_epoch_begin(run_context)
196             with tqdm(total=total) as progress:
197                 progress.set_description(f'Epoch {epoch}')
198                 loss_total = 0
199                 # step begin
200                 for data in self.train_dataset.create_dict_iterator():
201                     inputs, tgts = self._data_process(data, tgt_columns)
202                     run_context.cur_step_nums += 1
203                     self.cur_step_nums += 1
204                     self.callback_manager.train_step_begin(run_context)
205                     if jit:
206                         loss = _run_step_graph(inputs, tgts)
207                     else:
208                         loss = _run_step(inputs, tgts)
209                     loss_total += loss
210                     progress.set_postfix(loss=loss_total/self.cur_step_nums)
211                     progress.update(1)
212                     # step end
213                     self.callback_manager.train_step_end(run_context)
214             # train epoch end
215             progress.close()
216             self.callback_manager.train_epoch_end(run_context)
217             # do epoch evaluation
218             if self.evaluator is not None:
219                 self._do_eval_epoch(run_context, tgt_columns, jit)
220 
221     def _run_ds_sink(self, train_dataset, eval_dataset, list_callback,
222                      cb_params, print_steps, eval_steps):
223         """Training process for data sinking mode."""
224         raise NotImplementedError
225 
226     def _load_checkpoint(self, path):
227         """Load checkpoint."""
228         raise NotImplementedError
229 
230     def _save_checkpoint(self, path):
231         """Save checkpoint."""
232         raise NotImplementedError
233 
234     def _do_eval_steps(self, steps, eval_dataset):
235         """Evaluate the model after n steps."""
236         raise NotImplementedError
237 
238     def _do_eval_epoch(self, run_context, tgt_columns=None, jit=False):
239         """Evaluate the model after an epoch."""
240         self.callback_manager.evaluate_begin(run_context)
241         self.evaluator.clear_metrics()
242         metrics_result, metrics_names, metrics_values = self.evaluator._run(tgt_columns, jit)
243         setattr(run_context, "metrics_values", metrics_values)
244         setattr(run_context, "metrics_result", metrics_result)
245         setattr(run_context, "metrics_names", metrics_names)
246         self.callback_manager.evaluate_end(run_context)
247         self.earlystop = run_context.earlystop
248 
249     def _data_process(self, data, tgt_columns):
250         """Process data match the network construct"""
251         # prepare input dataset.
252         sig = signature(self.network.construct)
253         net_args = sig.parameters
254         inputs = ()
255         for arg in net_args:
256             if arg == 'self':
257                 continue
258             if arg not in data.keys():
259                 if str(net_args[arg])[-4:] == 'None':
260                     continue
261             inputs = inputs + (data[arg],)
262         # process target dataset.
263         tgt_columns = self._prepare_tgt_columns(tgt_columns)
264         tgts = ()
265         for tgt_column in tgt_columns:
266             tgts = tgts + (data[tgt_column],)
267         return mutable(inputs), mutable(tgts)
268 
269     def _prepare_tgt_columns(self, tgt_columns):
270         """Check and prepare target columns for training."""
271         out_columns = []
272         if tgt_columns is None:
273             log.warning("In the process of training model, tgt_column can not be None.")
274             return []
275         if isinstance(tgt_columns, str):
276             out_columns.append(tgt_columns)
277         elif isinstance(tgt_columns, list):
278             if all(isinstance(tgt_column, str) for tgt_column in tgt_columns) is True:
279                 out_columns = tgt_columns
280             else:
281                 obj = [not isinstance(tgt_column, str) for tgt_column in tgt_columns][0]
282                 raise TypeError(f"Expect str of tgt_column. Got {type(obj)}")
283         else:
284             raise TypeError(f"Expect tgt_columns to be list or str. Got {type(tgt_columns)}.")
285         return out_columns
286
```
--- 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/mindnlp/engine/trainer.py b/mindnlp/engine/trainer.py
--- a/mindnlp/engine/trainer.py
+++ b/mindnlp/engine/trainer.py
@@ -167,7 +167,14 @@
             return_list = (loss,) + logits_list
             return return_list
 
-        grad_fn = value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)
+        def forward_without_loss_fn(inputs, labels):
+            loss_and_logits = net(*inputs, *labels)
+            return loss_and_logits
+
+        if self.loss_fn is None:
+            grad_fn = value_and_grad(forward_without_loss_fn, None, optimizer.parameters, has_aux=True)
+        else:
+            grad_fn = value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)
 
         def _run_step(inputs, labels):
             """Core process of each step, including the forward propagation process and back propagation of data."""

{"golden_diff": "diff --git a/mindnlp/engine/trainer.py b/mindnlp/engine/trainer.py\n--- a/mindnlp/engine/trainer.py\n+++ b/mindnlp/engine/trainer.py\n@@ -167,7 +167,14 @@\n             return_list = (loss,) + logits_list\n             return return_list\n \n-        grad_fn = value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)\n+        def forward_without_loss_fn(inputs, labels):\n+            loss_and_logits = net(*inputs, *labels)\n+            return loss_and_logits\n+\n+        if self.loss_fn is None:\n+            grad_fn = value_and_grad(forward_without_loss_fn, None, optimizer.parameters, has_aux=True)\n+        else:\n+            grad_fn = value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)\n \n         def _run_step(inputs, labels):\n             \"\"\"Core process of each step, including the forward propagation process and back propagation of data.\"\"\"\n", "issue": "\"Trainer\" doesn't take into account the case that \"loss_fn\" doesn't need to be passed in.\n\"Trainer\" does not take into account the case where \"loss\" is already defined in the model, and there is no need to pass \"loss_fn\" to \"Trainer\".\n", "before_files": [{"content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n# pylint: disable=W0212\n# pylint: disable=no-name-in-module, ungrouped-imports\n\"\"\"\nTrainer for training.\n\"\"\"\nfrom inspect import signature\nfrom tqdm import tqdm\nfrom mindspore import ops\nfrom mindspore import log, mutable\nfrom mindspore.ops import value_and_grad\nfrom mindnlp import ms_jit\nfrom mindnlp.abc.callback import Callback\nfrom mindnlp.engine.callbacks.callback_manager import CallbackManager, RunContext\nfrom mindnlp.engine.callbacks.earlystop_callback import EarlyStopCallback\nfrom mindnlp.engine.callbacks.best_model_callback import BestModelCallback\nfrom mindnlp.engine.evaluator import Evaluator\n\nclass Trainer:\n    r\"\"\"\n    Trainer to train the model.\n\n\n    Args:\n        network (Cell): A training network.\n        train_dataset (Dataset): A training dataset iterator. If `loss_fn` is defined, the data and label will be\n            passed to the `network` and the `loss_fn` respectively, so a tuple (data, label)\n            should be returned from dataset. If there is multiple data or labels, set `loss_fn`\n            to None and implement calculation of loss in `network`,\n            then a tuple (data1, data2, data3, ...) with all data returned from dataset will be\n            passed to the `network`.\n        eval_dataset (Dataset): A evaluating dataset iterator. If `loss_fn` is defined, the data and label will be\n            passed to the `network` and the `loss_fn` respectively, so a tuple (data, label)\n            should be returned from dataset. If there is multiple data or labels, set `loss_fn`\n            to None and implement calculation of loss in `network`,\n            then a tuple (data1, data2, data3, ...) with all data returned from dataset will be\n            passed to the `network`.\n        metrcis (Optional[list[Metrics], Metrics]): List of metrics objects which should be used\n            while evaluating. Default:None.\n        epochs (int): Total number of iterations on the data. Default: 10.\n        optimizer (Cell): Optimizer for updating the weights. If `optimizer` is None, the `network` needs to\n            do backpropagation and update weights. Default value: None.\n        loss_fn (Cell): Objective function. If `loss_fn` is None, the `network` should contain the calculation of loss\n            and parallel if needed. Default: None.\n        callbacks (Optional[list[Callback], Callback]): List of callback objects which should be executed\n            while training. Default: None.\n\n    \"\"\"\n\n    def __init__(self, network=None, train_dataset=None, eval_dataset=None, metrics=None, epochs=10,\n                 loss_fn=None, optimizer=None, callbacks=None):\n        self.network = network\n        self.train_dataset = train_dataset\n        self.eval_dataset = eval_dataset\n        self.metrics = metrics\n        self.epochs = epochs\n        self.loss_fn = loss_fn\n        self.optimizer = optimizer\n        self.callbacks = callbacks\n        self.cur_epoch_nums = 0\n        self.cur_step_nums = 0\n        self.earlystop = False\n        self.grad_fn = None\n        if callbacks:\n            self._prepare_callbacks(callbacks)\n        self._prepare_eval()\n        self.callback_manager = CallbackManager(callbacks=self.callbacks)\n\n    def _prepare_callbacks(self, callbacks):\n        self.callbacks = []\n        if isinstance(callbacks, Callback):\n            self.callbacks.append(callbacks)\n        elif isinstance(callbacks, list):\n            if all(isinstance(cb, Callback) for cb in callbacks) is True:\n                self.callbacks = callbacks\n            else:\n                obj = [not isinstance(cb, Callback) for cb in callbacks][0]\n                raise TypeError(f\"Expect sub-classes of Callback. Got {type(obj)}\")\n        else:\n            raise TypeError(f\"Expect callbacks to be list or Callback. Got {type(callbacks)}.\")\n\n    def _check_callbacks_type(self):\n        for callback in self.callbacks:\n            if isinstance(callback, EarlyStopCallback):\n                raise ValueError(\"EarlyStopCallback is not effective when eval_dataset is None.\")\n            if isinstance(callback, BestModelCallback):\n                raise ValueError(\"BestModelCallback is not effective when eval_dataset is None.\")\n\n    def _prepare_eval(self):\n        if self.eval_dataset is not None and self.metrics is not None:\n            self.evaluator = Evaluator(network=self.network, eval_dataset=self.eval_dataset, metrics=self.metrics,\n                                        callbacks=self.callbacks)\n        elif self.eval_dataset is None and self.metrics is None:\n            if self.callbacks:\n                self._check_callbacks_type()\n            self.evaluator = None\n        else:\n            raise ValueError(\"For evaluation in training process, both eval dataset and metrics should be not None.\")\n\n    def _check_amp_level_arg(self, optimizer, amp_level):\n        \"\"\"Check mixed-precision argument rules.\"\"\"\n        raise NotImplementedError\n\n    def _check_for_graph_cell(self, kwargs):\n        \"\"\"Check network rules of GraphCell.\"\"\"\n        raise NotImplementedError\n\n    def _build_boost_network(self, *kwargs):\n        \"\"\"Build boost network.\"\"\"\n        raise NotImplementedError\n\n    def _check_reuse_dataset(self, dataset):\n        \"\"\"Check if dataset is being used by other models under the data sink mode.\"\"\"\n        if not hasattr(dataset, '__model_hash__'):\n            dataset.__model_hash__ = hash(self)\n        if hasattr(dataset, '__model_hash__') and dataset.__model_hash__ != hash(self):\n            raise RuntimeError(\"The dataset object had been used in other model by model.train(...), \"\n                               \"please create a new dataset.\")\n\n    def run(self, tgt_columns=None, jit=False):\n        \"\"\"\n        Training process entry.\n\n        Args:\n            tgt_columns (Optional[list[str], str]): Target label column names for loss function.\n            jit (bool): Whether use Just-In-Time compile.\n\n        \"\"\"\n\n        args_dict = vars(self)\n        run_context = RunContext(args_dict)\n        self.callback_manager.train_begin(run_context)\n        self._run(run_context, tgt_columns, jit)\n        self.callback_manager.train_end(run_context)\n\n    def _run(self, run_context, tgt_columns=None, jit=False):\n        \"\"\"\n        Training process for non-data sinking mode. The data would be passed to network directly.\n        \"\"\"\n        # forward function\n        net = self.network\n\n        loss_fn = self.loss_fn\n        optimizer = self.optimizer\n        def forward_fn(inputs, labels):\n            logits_list = ()\n            logits = net(*inputs)\n            if isinstance(logits, tuple):\n                logits_list += logits\n            else:\n                logits_list += (logits,)\n\n            loss = loss_fn(*logits_list, *labels)\n            return_list = (loss,) + logits_list\n            return return_list\n\n        grad_fn = value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)\n\n        def _run_step(inputs, labels):\n            \"\"\"Core process of each step, including the forward propagation process and back propagation of data.\"\"\"\n            (loss, *_), grads = grad_fn(inputs, labels)\n            optimizer(grads)\n            return loss\n\n        @ms_jit\n        def _run_step_graph(inputs, labels):\n            \"\"\"Core process of each step, including the forward propagation process and back propagation of data.\"\"\"\n            (loss, _), grads = grad_fn(inputs, labels)\n            loss = ops.depend(loss, optimizer(grads))\n            return loss\n\n        total = self.train_dataset.get_dataset_size()\n        # train epoch begin\n        for epoch in range(0, self.epochs):\n            net.set_train()\n            self.cur_epoch_nums = epoch + 1\n            self.cur_step_nums = 0\n            run_context.cur_epoch_nums = self.cur_epoch_nums\n            run_context.cur_step_nums = 0\n            if self.earlystop is True:\n                break\n            self.callback_manager.train_epoch_begin(run_context)\n            with tqdm(total=total) as progress:\n                progress.set_description(f'Epoch {epoch}')\n                loss_total = 0\n                # step begin\n                for data in self.train_dataset.create_dict_iterator():\n                    inputs, tgts = self._data_process(data, tgt_columns)\n                    run_context.cur_step_nums += 1\n                    self.cur_step_nums += 1\n                    self.callback_manager.train_step_begin(run_context)\n                    if jit:\n                        loss = _run_step_graph(inputs, tgts)\n                    else:\n                        loss = _run_step(inputs, tgts)\n                    loss_total += loss\n                    progress.set_postfix(loss=loss_total/self.cur_step_nums)\n                    progress.update(1)\n                    # step end\n                    self.callback_manager.train_step_end(run_context)\n            # train epoch end\n            progress.close()\n            self.callback_manager.train_epoch_end(run_context)\n            # do epoch evaluation\n            if self.evaluator is not None:\n                self._do_eval_epoch(run_context, tgt_columns, jit)\n\n    def _run_ds_sink(self, train_dataset, eval_dataset, list_callback,\n                     cb_params, print_steps, eval_steps):\n        \"\"\"Training process for data sinking mode.\"\"\"\n        raise NotImplementedError\n\n    def _load_checkpoint(self, path):\n        \"\"\"Load checkpoint.\"\"\"\n        raise NotImplementedError\n\n    def _save_checkpoint(self, path):\n        \"\"\"Save checkpoint.\"\"\"\n        raise NotImplementedError\n\n    def _do_eval_steps(self, steps, eval_dataset):\n        \"\"\"Evaluate the model after n steps.\"\"\"\n        raise NotImplementedError\n\n    def _do_eval_epoch(self, run_context, tgt_columns=None, jit=False):\n        \"\"\"Evaluate the model after an epoch.\"\"\"\n        self.callback_manager.evaluate_begin(run_context)\n        self.evaluator.clear_metrics()\n        metrics_result, metrics_names, metrics_values = self.evaluator._run(tgt_columns, jit)\n        setattr(run_context, \"metrics_values\", metrics_values)\n        setattr(run_context, \"metrics_result\", metrics_result)\n        setattr(run_context, \"metrics_names\", metrics_names)\n        self.callback_manager.evaluate_end(run_context)\n        self.earlystop = run_context.earlystop\n\n    def _data_process(self, data, tgt_columns):\n        \"\"\"Process data match the network construct\"\"\"\n        # prepare input dataset.\n        sig = signature(self.network.construct)\n        net_args = sig.parameters\n        inputs = ()\n        for arg in net_args:\n            if arg == 'self':\n                continue\n            if arg not in data.keys():\n                if str(net_args[arg])[-4:] == 'None':\n                    continue\n            inputs = inputs + (data[arg],)\n        # process target dataset.\n        tgt_columns = self._prepare_tgt_columns(tgt_columns)\n        tgts = ()\n        for tgt_column in tgt_columns:\n            tgts = tgts + (data[tgt_column],)\n        return mutable(inputs), mutable(tgts)\n\n    def _prepare_tgt_columns(self, tgt_columns):\n        \"\"\"Check and prepare target columns for training.\"\"\"\n        out_columns = []\n        if tgt_columns is None:\n            log.warning(\"In the process of training model, tgt_column can not be None.\")\n            return []\n        if isinstance(tgt_columns, str):\n            out_columns.append(tgt_columns)\n        elif isinstance(tgt_columns, list):\n            if all(isinstance(tgt_column, str) for tgt_column in tgt_columns) is True:\n                out_columns = tgt_columns\n            else:\n                obj = [not isinstance(tgt_column, str) for tgt_column in tgt_columns][0]\n                raise TypeError(f\"Expect str of tgt_column. Got {type(obj)}\")\n        else:\n            raise TypeError(f\"Expect tgt_columns to be list or str. Got {type(tgt_columns)}.\")\n        return out_columns\n", "path": "mindnlp/engine/trainer.py"}], "after_files": [{"content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n# pylint: disable=W0212\n# pylint: disable=no-name-in-module, ungrouped-imports\n\"\"\"\nTrainer for training.\n\"\"\"\nfrom inspect import signature\nfrom tqdm import tqdm\nfrom mindspore import ops\nfrom mindspore import log, mutable\nfrom mindspore.ops import value_and_grad\nfrom mindnlp import ms_jit\nfrom mindnlp.abc.callback import Callback\nfrom mindnlp.engine.callbacks.callback_manager import CallbackManager, RunContext\nfrom mindnlp.engine.callbacks.earlystop_callback import EarlyStopCallback\nfrom mindnlp.engine.callbacks.best_model_callback import BestModelCallback\nfrom mindnlp.engine.evaluator import Evaluator\n\nclass Trainer:\n    r\"\"\"\n    Trainer to train the model.\n\n\n    Args:\n        network (Cell): A training network.\n        train_dataset (Dataset): A training dataset iterator. If `loss_fn` is defined, the data and label will be\n            passed to the `network` and the `loss_fn` respectively, so a tuple (data, label)\n            should be returned from dataset. If there is multiple data or labels, set `loss_fn`\n            to None and implement calculation of loss in `network`,\n            then a tuple (data1, data2, data3, ...) with all data returned from dataset will be\n            passed to the `network`.\n        eval_dataset (Dataset): A evaluating dataset iterator. If `loss_fn` is defined, the data and label will be\n            passed to the `network` and the `loss_fn` respectively, so a tuple (data, label)\n            should be returned from dataset. If there is multiple data or labels, set `loss_fn`\n            to None and implement calculation of loss in `network`,\n            then a tuple (data1, data2, data3, ...) with all data returned from dataset will be\n            passed to the `network`.\n        metrcis (Optional[list[Metrics], Metrics]): List of metrics objects which should be used\n            while evaluating. Default:None.\n        epochs (int): Total number of iterations on the data. Default: 10.\n        optimizer (Cell): Optimizer for updating the weights. If `optimizer` is None, the `network` needs to\n            do backpropagation and update weights. Default value: None.\n        loss_fn (Cell): Objective function. If `loss_fn` is None, the `network` should contain the calculation of loss\n            and parallel if needed. Default: None.\n        callbacks (Optional[list[Callback], Callback]): List of callback objects which should be executed\n            while training. Default: None.\n\n    \"\"\"\n\n    def __init__(self, network=None, train_dataset=None, eval_dataset=None, metrics=None, epochs=10,\n                 loss_fn=None, optimizer=None, callbacks=None):\n        self.network = network\n        self.train_dataset = train_dataset\n        self.eval_dataset = eval_dataset\n        self.metrics = metrics\n        self.epochs = epochs\n        self.loss_fn = loss_fn\n        self.optimizer = optimizer\n        self.callbacks = callbacks\n        self.cur_epoch_nums = 0\n        self.cur_step_nums = 0\n        self.earlystop = False\n        self.grad_fn = None\n        if callbacks:\n            self._prepare_callbacks(callbacks)\n        self._prepare_eval()\n        self.callback_manager = CallbackManager(callbacks=self.callbacks)\n\n    def _prepare_callbacks(self, callbacks):\n        self.callbacks = []\n        if isinstance(callbacks, Callback):\n            self.callbacks.append(callbacks)\n        elif isinstance(callbacks, list):\n            if all(isinstance(cb, Callback) for cb in callbacks) is True:\n                self.callbacks = callbacks\n            else:\n                obj = [not isinstance(cb, Callback) for cb in callbacks][0]\n                raise TypeError(f\"Expect sub-classes of Callback. Got {type(obj)}\")\n        else:\n            raise TypeError(f\"Expect callbacks to be list or Callback. Got {type(callbacks)}.\")\n\n    def _check_callbacks_type(self):\n        for callback in self.callbacks:\n            if isinstance(callback, EarlyStopCallback):\n                raise ValueError(\"EarlyStopCallback is not effective when eval_dataset is None.\")\n            if isinstance(callback, BestModelCallback):\n                raise ValueError(\"BestModelCallback is not effective when eval_dataset is None.\")\n\n    def _prepare_eval(self):\n        if self.eval_dataset is not None and self.metrics is not None:\n            self.evaluator = Evaluator(network=self.network, eval_dataset=self.eval_dataset, metrics=self.metrics,\n                                        callbacks=self.callbacks)\n        elif self.eval_dataset is None and self.metrics is None:\n            if self.callbacks:\n                self._check_callbacks_type()\n            self.evaluator = None\n        else:\n            raise ValueError(\"For evaluation in training process, both eval dataset and metrics should be not None.\")\n\n    def _check_amp_level_arg(self, optimizer, amp_level):\n        \"\"\"Check mixed-precision argument rules.\"\"\"\n        raise NotImplementedError\n\n    def _check_for_graph_cell(self, kwargs):\n        \"\"\"Check network rules of GraphCell.\"\"\"\n        raise NotImplementedError\n\n    def _build_boost_network(self, *kwargs):\n        \"\"\"Build boost network.\"\"\"\n        raise NotImplementedError\n\n    def _check_reuse_dataset(self, dataset):\n        \"\"\"Check if dataset is being used by other models under the data sink mode.\"\"\"\n        if not hasattr(dataset, '__model_hash__'):\n            dataset.__model_hash__ = hash(self)\n        if hasattr(dataset, '__model_hash__') and dataset.__model_hash__ != hash(self):\n            raise RuntimeError(\"The dataset object had been used in other model by model.train(...), \"\n                               \"please create a new dataset.\")\n\n    def run(self, tgt_columns=None, jit=False):\n        \"\"\"\n        Training process entry.\n\n        Args:\n            tgt_columns (Optional[list[str], str]): Target label column names for loss function.\n            jit (bool): Whether use Just-In-Time compile.\n\n        \"\"\"\n\n        args_dict = vars(self)\n        run_context = RunContext(args_dict)\n        self.callback_manager.train_begin(run_context)\n        self._run(run_context, tgt_columns, jit)\n        self.callback_manager.train_end(run_context)\n\n    def _run(self, run_context, tgt_columns=None, jit=False):\n        \"\"\"\n        Training process for non-data sinking mode. The data would be passed to network directly.\n        \"\"\"\n        # forward function\n        net = self.network\n\n        loss_fn = self.loss_fn\n        optimizer = self.optimizer\n        def forward_fn(inputs, labels):\n            logits_list = ()\n            logits = net(*inputs)\n            if isinstance(logits, tuple):\n                logits_list += logits\n            else:\n                logits_list += (logits,)\n\n            loss = loss_fn(*logits_list, *labels)\n            return_list = (loss,) + logits_list\n            return return_list\n\n        def forward_without_loss_fn(inputs, labels):\n            loss_and_logits = net(*inputs, *labels)\n            return loss_and_logits\n\n        if self.loss_fn is None:\n            grad_fn = value_and_grad(forward_without_loss_fn, None, optimizer.parameters, has_aux=True)\n        else:\n            grad_fn = value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)\n\n        def _run_step(inputs, labels):\n            \"\"\"Core process of each step, including the forward propagation process and back propagation of data.\"\"\"\n            (loss, *_), grads = grad_fn(inputs, labels)\n            optimizer(grads)\n            return loss\n\n        @ms_jit\n        def _run_step_graph(inputs, labels):\n            \"\"\"Core process of each step, including the forward propagation process and back propagation of data.\"\"\"\n            (loss, _), grads = grad_fn(inputs, labels)\n            loss = ops.depend(loss, optimizer(grads))\n            return loss\n\n        total = self.train_dataset.get_dataset_size()\n        # train epoch begin\n        for epoch in range(0, self.epochs):\n            net.set_train()\n            self.cur_epoch_nums = epoch + 1\n            self.cur_step_nums = 0\n            run_context.cur_epoch_nums = self.cur_epoch_nums\n            run_context.cur_step_nums = 0\n            if self.earlystop is True:\n                break\n            self.callback_manager.train_epoch_begin(run_context)\n            with tqdm(total=total) as progress:\n                progress.set_description(f'Epoch {epoch}')\n                loss_total = 0\n                # step begin\n                for data in self.train_dataset.create_dict_iterator():\n                    inputs, tgts = self._data_process(data, tgt_columns)\n                    run_context.cur_step_nums += 1\n                    self.cur_step_nums += 1\n                    self.callback_manager.train_step_begin(run_context)\n                    if jit:\n                        loss = _run_step_graph(inputs, tgts)\n                    else:\n                        loss = _run_step(inputs, tgts)\n                    loss_total += loss\n                    progress.set_postfix(loss=loss_total/self.cur_step_nums)\n                    progress.update(1)\n                    # step end\n                    self.callback_manager.train_step_end(run_context)\n            # train epoch end\n            progress.close()\n            self.callback_manager.train_epoch_end(run_context)\n            # do epoch evaluation\n            if self.evaluator is not None:\n                self._do_eval_epoch(run_context, tgt_columns, jit)\n\n    def _run_ds_sink(self, train_dataset, eval_dataset, list_callback,\n                     cb_params, print_steps, eval_steps):\n        \"\"\"Training process for data sinking mode.\"\"\"\n        raise NotImplementedError\n\n    def _load_checkpoint(self, path):\n        \"\"\"Load checkpoint.\"\"\"\n        raise NotImplementedError\n\n    def _save_checkpoint(self, path):\n        \"\"\"Save checkpoint.\"\"\"\n        raise NotImplementedError\n\n    def _do_eval_steps(self, steps, eval_dataset):\n        \"\"\"Evaluate the model after n steps.\"\"\"\n        raise NotImplementedError\n\n    def _do_eval_epoch(self, run_context, tgt_columns=None, jit=False):\n        \"\"\"Evaluate the model after an epoch.\"\"\"\n        self.callback_manager.evaluate_begin(run_context)\n        self.evaluator.clear_metrics()\n        metrics_result, metrics_names, metrics_values = self.evaluator._run(tgt_columns, jit)\n        setattr(run_context, \"metrics_values\", metrics_values)\n        setattr(run_context, \"metrics_result\", metrics_result)\n        setattr(run_context, \"metrics_names\", metrics_names)\n        self.callback_manager.evaluate_end(run_context)\n        self.earlystop = run_context.earlystop\n\n    def _data_process(self, data, tgt_columns):\n        \"\"\"Process data match the network construct\"\"\"\n        # prepare input dataset.\n        sig = signature(self.network.construct)\n        net_args = sig.parameters\n        inputs = ()\n        for arg in net_args:\n            if arg == 'self':\n                continue\n            if arg not in data.keys():\n                if str(net_args[arg])[-4:] == 'None':\n                    continue\n            inputs = inputs + (data[arg],)\n        # process target dataset.\n        tgt_columns = self._prepare_tgt_columns(tgt_columns)\n        tgts = ()\n        for tgt_column in tgt_columns:\n            tgts = tgts + (data[tgt_column],)\n        return mutable(inputs), mutable(tgts)\n\n    def _prepare_tgt_columns(self, tgt_columns):\n        \"\"\"Check and prepare target columns for training.\"\"\"\n        out_columns = []\n        if tgt_columns is None:\n            log.warning(\"In the process of training model, tgt_column can not be None.\")\n            return []\n        if isinstance(tgt_columns, str):\n            out_columns.append(tgt_columns)\n        elif isinstance(tgt_columns, list):\n            if all(isinstance(tgt_column, str) for tgt_column in tgt_columns) is True:\n                out_columns = tgt_columns\n            else:\n                obj = [not isinstance(tgt_column, str) for tgt_column in tgt_columns][0]\n                raise TypeError(f\"Expect str of tgt_column. Got {type(obj)}\")\n        else:\n            raise TypeError(f\"Expect tgt_columns to be list or str. Got {type(tgt_columns)}.\")\n        return out_columns\n", "path": "mindnlp/engine/trainer.py"}]}