We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Provide basic update + inference functions
See #37 for discussion on this. We should provide something for simple supervised training

cc @jasonkriss

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ignite/trainer/trainer.py`
Content:
```
1 from __future__ import division
2 
3 import logging
4 import time
5 from collections import Iterable
6 
7 from enum import Enum
8 from ignite.trainer.history import History
9 
10 __all__ = ["TrainingEvents", "Trainer"]
11 
12 
13 class TrainingEvents(Enum):
14     EPOCH_STARTED = "epoch_started"
15     EPOCH_COMPLETED = "epoch_completed"
16     TRAINING_EPOCH_STARTED = "training_epoch_started"
17     TRAINING_EPOCH_COMPLETED = "training_epoch_completed"
18     VALIDATION_STARTING = "validation_starting"
19     VALIDATION_COMPLETED = "validation_completed"
20     TRAINING_STARTED = "training_started"
21     TRAINING_COMPLETED = "training_completed"
22     TRAINING_ITERATION_STARTED = "training_iteration_started"
23     TRAINING_ITERATION_COMPLETED = "training_iteration_completed"
24     VALIDATION_ITERATION_STARTED = "validation_iteration_started"
25     VALIDATION_ITERATION_COMPLETED = "validation_iteration_completed"
26     EXCEPTION_RAISED = "exception_raised"
27 
28 
29 def _to_hours_mins_secs(time_taken):
30     mins, secs = divmod(time_taken, 60)
31     hours, mins = divmod(mins, 60)
32     return hours, mins, secs
33 
34 
35 class Trainer(object):
36     """
37     Generic trainer class.
38 
39     Training update and validation functions receive batches of data and return values which will
40     be stored in the `training_history` and `validation_history`. The trainer defines multiple
41     events in `TrainingEvents` for which the user can attach event handlers to. The events get
42     passed the trainer, so they can access the training/validation history
43 
44 
45     Parameters
46     ----------
47     training_update_function : callable
48         Update function receiving the current training batch in each iteration
49 
50     validation_inference_function : callable
51         Function receiving data and performing a feed forward without update
52     """
53 
54     def __init__(self, training_update_function, validation_inference_function=None):
55 
56         self._logger = self._get_logger()
57         self._training_update_function = training_update_function
58         self._validation_inference_function = validation_inference_function
59         self._event_handlers = {}
60 
61         self.training_history = History()
62         self.validation_history = History()
63         self.current_iteration = 0
64         self.current_validation_iteration = 0
65         self.current_epoch = 0
66         self.max_epochs = 0
67         self.should_terminate = False
68 
69     def _get_logger(self):
70         logger = logging.getLogger(__name__ + "." + self.__class__.__name__)
71         logger.addHandler(logging.NullHandler())
72         return logger
73 
74     def add_event_handler(self, event_name, handler, *args, **kwargs):
75         """
76         Add an event handler to be executed when the specified event is fired
77 
78         Parameters
79         ----------
80         event_name: enum
81             event from ignite.trainer.TrainingEvents to attach the
82             handler to
83         handler: Callable
84             the callable event handler that should be invoked
85         args:
86             optional args to be passed to `handler`
87         kwargs:
88             optional keyword args to be passed to `handler`
89 
90         Returns
91         -------
92         None
93         """
94         if event_name not in TrainingEvents.__members__.values():
95             self._logger.error("attempt to add event handler to non-existent event %s ",
96                                event_name)
97             raise ValueError("Event {} not a valid training event".format(event_name))
98 
99         if event_name not in self._event_handlers.keys():
100             self._event_handlers[event_name] = []
101 
102         self._event_handlers[event_name].append((handler, args, kwargs))
103         self._logger.debug("added handler for event % ", event_name)
104 
105     def _fire_event(self, event_name):
106         if event_name in self._event_handlers.keys():
107             self._logger.debug("firing handlers for event %s ", event_name)
108             for func, args, kwargs in self._event_handlers[event_name]:
109                 func(self, *args, **kwargs)
110 
111     def _train_one_epoch(self, training_data):
112         self._fire_event(TrainingEvents.TRAINING_EPOCH_STARTED)
113         start_time = time.time()
114 
115         self.epoch_losses = []
116         for _, batch in enumerate(training_data, 1):
117             self._fire_event(TrainingEvents.TRAINING_ITERATION_STARTED)
118 
119             training_step_result = self._training_update_function(batch)
120             if training_step_result is not None:
121                 self.training_history.append(training_step_result)
122 
123             self.current_iteration += 1
124 
125             self._fire_event(TrainingEvents.TRAINING_ITERATION_COMPLETED)
126             if self.should_terminate:
127                 return
128 
129         time_taken = time.time() - start_time
130         hours, mins, secs = _to_hours_mins_secs(time_taken)
131         self._logger.info("Epoch[%s] Complete. Time taken: %02d:%02d:%02d", self.current_epoch, hours,
132                           mins, secs)
133 
134         self._fire_event(TrainingEvents.TRAINING_EPOCH_COMPLETED)
135 
136     def validate(self, validation_data):
137         """ Evaluates the validation set"""
138         if self._validation_inference_function is None:
139             raise ValueError("Trainer must have a validation_inference_function in order to validate")
140 
141         self.current_validation_iteration = 0
142         self._fire_event(TrainingEvents.VALIDATION_STARTING)
143         start_time = time.time()
144 
145         for _, batch in enumerate(validation_data, 1):
146             self._fire_event(TrainingEvents.VALIDATION_ITERATION_STARTED)
147             validation_step_result = self._validation_inference_function(batch)
148             if validation_step_result is not None:
149                 self.validation_history.append(validation_step_result)
150 
151             self.current_validation_iteration += 1
152             self._fire_event(TrainingEvents.VALIDATION_ITERATION_COMPLETED)
153             if self.should_terminate:
154                 break
155 
156         time_taken = time.time() - start_time
157         hours, mins, secs = _to_hours_mins_secs(time_taken)
158         self._logger.info("Validation Complete. Time taken: %02d:%02d:%02d", hours, mins, secs)
159 
160         self._fire_event(TrainingEvents.VALIDATION_COMPLETED)
161 
162     def terminate(self):
163         """
164         Sends terminate signal to trainer, so that training terminates after the current iteration
165         """
166         self._logger.info("Terminate signaled to trainer. " +
167                           "Training will stop after current iteration is finished")
168         self.should_terminate = True
169 
170     def run(self, training_data, max_epochs=1):
171         """
172         Train the model, evaluate the validation set and update best parameters if the validation loss
173         improves.
174         In the event that the validation set is not run (or doesn't exist), the training loss is used
175         to update the best parameters.
176 
177         Parameters
178         ----------
179         training_data : Iterable
180             Collection of training batches allowing repeated iteration (e.g., list or DataLoader)
181         max_epochs: int, optional
182             max epochs to train for [default=1]
183 
184         Returns
185         -------
186         None
187         """
188 
189         try:
190             self._logger.info("Training starting with max_epochs={}".format(max_epochs))
191 
192             self.max_epochs = max_epochs
193 
194             start_time = time.time()
195 
196             self._fire_event(TrainingEvents.TRAINING_STARTED)
197             while self.current_epoch < max_epochs and not self.should_terminate:
198                 self._fire_event(TrainingEvents.EPOCH_STARTED)
199                 self._train_one_epoch(training_data)
200                 if self.should_terminate:
201                     break
202 
203                 self._fire_event(TrainingEvents.EPOCH_COMPLETED)
204                 self.current_epoch += 1
205 
206             self._fire_event(TrainingEvents.TRAINING_COMPLETED)
207             time_taken = time.time() - start_time
208             mins, secs = divmod(time_taken, 60)
209             hours, mins = divmod(mins, 60)
210             self._logger.info("Training complete. Time taken %02d:%02d:%02d" % (hours, mins, secs))
211         except BaseException as e:
212             self._logger.error("Training is terminating due to exception: %s", str(e))
213             self._fire_event(TrainingEvents.EXCEPTION_RAISED)
214             raise e
215
```
--- 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/ignite/trainer/trainer.py b/ignite/trainer/trainer.py
--- a/ignite/trainer/trainer.py
+++ b/ignite/trainer/trainer.py
@@ -5,9 +5,10 @@
 from collections import Iterable
 
 from enum import Enum
+from torch.autograd import Variable
 from ignite.trainer.history import History
 
-__all__ = ["TrainingEvents", "Trainer"]
+__all__ = ["TrainingEvents", "Trainer", "create_supervised"]
 
 
 class TrainingEvents(Enum):
@@ -212,3 +213,41 @@
             self._logger.error("Training is terminating due to exception: %s", str(e))
             self._fire_event(TrainingEvents.EXCEPTION_RAISED)
             raise e
+
+
+def create_supervised(model, optimizer, loss_fn, cuda=False):
+    """
+    Factory function for creating a trainer for supervised models
+
+    Args:
+        model (torch.nn.Module): the model to train
+        optimizer (torch.optim.Optimizer): the optimizer to use
+        loss_fn (torch.nn loss function): the loss function to use
+        cuda (bool, optional): whether or not to transfer batch to GPU (default: False)
+
+    Returns:
+        Trainer: a trainer instance with supervised update and inference functions
+    """
+    def _prepare_batch(batch, volatile=False):
+        x, y = batch
+        if cuda:
+            x, y = x.cuda(), y.cuda()
+        return Variable(x, volatile=volatile), Variable(y, volatile=volatile)
+
+    def _update(batch):
+        model.train()
+        optimizer.zero_grad()
+        x, y = _prepare_batch(batch)
+        y_pred = model(x)
+        loss = loss_fn(y_pred, y)
+        loss.backward()
+        optimizer.step()
+        return loss.data.cpu()[0]
+
+    def _inference(batch):
+        model.eval()
+        x, y = _prepare_batch(batch, volatile=True)
+        y_pred = model(x)
+        return y_pred.data.cpu(), y.data.cpu()
+
+    return Trainer(_update, _inference)

{"golden_diff": "diff --git a/ignite/trainer/trainer.py b/ignite/trainer/trainer.py\n--- a/ignite/trainer/trainer.py\n+++ b/ignite/trainer/trainer.py\n@@ -5,9 +5,10 @@\n from collections import Iterable\n \n from enum import Enum\n+from torch.autograd import Variable\n from ignite.trainer.history import History\n \n-__all__ = [\"TrainingEvents\", \"Trainer\"]\n+__all__ = [\"TrainingEvents\", \"Trainer\", \"create_supervised\"]\n \n \n class TrainingEvents(Enum):\n@@ -212,3 +213,41 @@\n             self._logger.error(\"Training is terminating due to exception: %s\", str(e))\n             self._fire_event(TrainingEvents.EXCEPTION_RAISED)\n             raise e\n+\n+\n+def create_supervised(model, optimizer, loss_fn, cuda=False):\n+    \"\"\"\n+    Factory function for creating a trainer for supervised models\n+\n+    Args:\n+        model (torch.nn.Module): the model to train\n+        optimizer (torch.optim.Optimizer): the optimizer to use\n+        loss_fn (torch.nn loss function): the loss function to use\n+        cuda (bool, optional): whether or not to transfer batch to GPU (default: False)\n+\n+    Returns:\n+        Trainer: a trainer instance with supervised update and inference functions\n+    \"\"\"\n+    def _prepare_batch(batch, volatile=False):\n+        x, y = batch\n+        if cuda:\n+            x, y = x.cuda(), y.cuda()\n+        return Variable(x, volatile=volatile), Variable(y, volatile=volatile)\n+\n+    def _update(batch):\n+        model.train()\n+        optimizer.zero_grad()\n+        x, y = _prepare_batch(batch)\n+        y_pred = model(x)\n+        loss = loss_fn(y_pred, y)\n+        loss.backward()\n+        optimizer.step()\n+        return loss.data.cpu()[0]\n+\n+    def _inference(batch):\n+        model.eval()\n+        x, y = _prepare_batch(batch, volatile=True)\n+        y_pred = model(x)\n+        return y_pred.data.cpu(), y.data.cpu()\n+\n+    return Trainer(_update, _inference)\n", "issue": "Provide basic update + inference functions\nSee #37 for discussion on this. We should provide something for simple supervised training\r\n\r\ncc @jasonkriss\n", "before_files": [{"content": "from __future__ import division\n\nimport logging\nimport time\nfrom collections import Iterable\n\nfrom enum import Enum\nfrom ignite.trainer.history import History\n\n__all__ = [\"TrainingEvents\", \"Trainer\"]\n\n\nclass TrainingEvents(Enum):\n    EPOCH_STARTED = \"epoch_started\"\n    EPOCH_COMPLETED = \"epoch_completed\"\n    TRAINING_EPOCH_STARTED = \"training_epoch_started\"\n    TRAINING_EPOCH_COMPLETED = \"training_epoch_completed\"\n    VALIDATION_STARTING = \"validation_starting\"\n    VALIDATION_COMPLETED = \"validation_completed\"\n    TRAINING_STARTED = \"training_started\"\n    TRAINING_COMPLETED = \"training_completed\"\n    TRAINING_ITERATION_STARTED = \"training_iteration_started\"\n    TRAINING_ITERATION_COMPLETED = \"training_iteration_completed\"\n    VALIDATION_ITERATION_STARTED = \"validation_iteration_started\"\n    VALIDATION_ITERATION_COMPLETED = \"validation_iteration_completed\"\n    EXCEPTION_RAISED = \"exception_raised\"\n\n\ndef _to_hours_mins_secs(time_taken):\n    mins, secs = divmod(time_taken, 60)\n    hours, mins = divmod(mins, 60)\n    return hours, mins, secs\n\n\nclass Trainer(object):\n    \"\"\"\n    Generic trainer class.\n\n    Training update and validation functions receive batches of data and return values which will\n    be stored in the `training_history` and `validation_history`. The trainer defines multiple\n    events in `TrainingEvents` for which the user can attach event handlers to. The events get\n    passed the trainer, so they can access the training/validation history\n\n\n    Parameters\n    ----------\n    training_update_function : callable\n        Update function receiving the current training batch in each iteration\n\n    validation_inference_function : callable\n        Function receiving data and performing a feed forward without update\n    \"\"\"\n\n    def __init__(self, training_update_function, validation_inference_function=None):\n\n        self._logger = self._get_logger()\n        self._training_update_function = training_update_function\n        self._validation_inference_function = validation_inference_function\n        self._event_handlers = {}\n\n        self.training_history = History()\n        self.validation_history = History()\n        self.current_iteration = 0\n        self.current_validation_iteration = 0\n        self.current_epoch = 0\n        self.max_epochs = 0\n        self.should_terminate = False\n\n    def _get_logger(self):\n        logger = logging.getLogger(__name__ + \".\" + self.__class__.__name__)\n        logger.addHandler(logging.NullHandler())\n        return logger\n\n    def add_event_handler(self, event_name, handler, *args, **kwargs):\n        \"\"\"\n        Add an event handler to be executed when the specified event is fired\n\n        Parameters\n        ----------\n        event_name: enum\n            event from ignite.trainer.TrainingEvents to attach the\n            handler to\n        handler: Callable\n            the callable event handler that should be invoked\n        args:\n            optional args to be passed to `handler`\n        kwargs:\n            optional keyword args to be passed to `handler`\n\n        Returns\n        -------\n        None\n        \"\"\"\n        if event_name not in TrainingEvents.__members__.values():\n            self._logger.error(\"attempt to add event handler to non-existent event %s \",\n                               event_name)\n            raise ValueError(\"Event {} not a valid training event\".format(event_name))\n\n        if event_name not in self._event_handlers.keys():\n            self._event_handlers[event_name] = []\n\n        self._event_handlers[event_name].append((handler, args, kwargs))\n        self._logger.debug(\"added handler for event % \", event_name)\n\n    def _fire_event(self, event_name):\n        if event_name in self._event_handlers.keys():\n            self._logger.debug(\"firing handlers for event %s \", event_name)\n            for func, args, kwargs in self._event_handlers[event_name]:\n                func(self, *args, **kwargs)\n\n    def _train_one_epoch(self, training_data):\n        self._fire_event(TrainingEvents.TRAINING_EPOCH_STARTED)\n        start_time = time.time()\n\n        self.epoch_losses = []\n        for _, batch in enumerate(training_data, 1):\n            self._fire_event(TrainingEvents.TRAINING_ITERATION_STARTED)\n\n            training_step_result = self._training_update_function(batch)\n            if training_step_result is not None:\n                self.training_history.append(training_step_result)\n\n            self.current_iteration += 1\n\n            self._fire_event(TrainingEvents.TRAINING_ITERATION_COMPLETED)\n            if self.should_terminate:\n                return\n\n        time_taken = time.time() - start_time\n        hours, mins, secs = _to_hours_mins_secs(time_taken)\n        self._logger.info(\"Epoch[%s] Complete. Time taken: %02d:%02d:%02d\", self.current_epoch, hours,\n                          mins, secs)\n\n        self._fire_event(TrainingEvents.TRAINING_EPOCH_COMPLETED)\n\n    def validate(self, validation_data):\n        \"\"\" Evaluates the validation set\"\"\"\n        if self._validation_inference_function is None:\n            raise ValueError(\"Trainer must have a validation_inference_function in order to validate\")\n\n        self.current_validation_iteration = 0\n        self._fire_event(TrainingEvents.VALIDATION_STARTING)\n        start_time = time.time()\n\n        for _, batch in enumerate(validation_data, 1):\n            self._fire_event(TrainingEvents.VALIDATION_ITERATION_STARTED)\n            validation_step_result = self._validation_inference_function(batch)\n            if validation_step_result is not None:\n                self.validation_history.append(validation_step_result)\n\n            self.current_validation_iteration += 1\n            self._fire_event(TrainingEvents.VALIDATION_ITERATION_COMPLETED)\n            if self.should_terminate:\n                break\n\n        time_taken = time.time() - start_time\n        hours, mins, secs = _to_hours_mins_secs(time_taken)\n        self._logger.info(\"Validation Complete. Time taken: %02d:%02d:%02d\", hours, mins, secs)\n\n        self._fire_event(TrainingEvents.VALIDATION_COMPLETED)\n\n    def terminate(self):\n        \"\"\"\n        Sends terminate signal to trainer, so that training terminates after the current iteration\n        \"\"\"\n        self._logger.info(\"Terminate signaled to trainer. \" +\n                          \"Training will stop after current iteration is finished\")\n        self.should_terminate = True\n\n    def run(self, training_data, max_epochs=1):\n        \"\"\"\n        Train the model, evaluate the validation set and update best parameters if the validation loss\n        improves.\n        In the event that the validation set is not run (or doesn't exist), the training loss is used\n        to update the best parameters.\n\n        Parameters\n        ----------\n        training_data : Iterable\n            Collection of training batches allowing repeated iteration (e.g., list or DataLoader)\n        max_epochs: int, optional\n            max epochs to train for [default=1]\n\n        Returns\n        -------\n        None\n        \"\"\"\n\n        try:\n            self._logger.info(\"Training starting with max_epochs={}\".format(max_epochs))\n\n            self.max_epochs = max_epochs\n\n            start_time = time.time()\n\n            self._fire_event(TrainingEvents.TRAINING_STARTED)\n            while self.current_epoch < max_epochs and not self.should_terminate:\n                self._fire_event(TrainingEvents.EPOCH_STARTED)\n                self._train_one_epoch(training_data)\n                if self.should_terminate:\n                    break\n\n                self._fire_event(TrainingEvents.EPOCH_COMPLETED)\n                self.current_epoch += 1\n\n            self._fire_event(TrainingEvents.TRAINING_COMPLETED)\n            time_taken = time.time() - start_time\n            mins, secs = divmod(time_taken, 60)\n            hours, mins = divmod(mins, 60)\n            self._logger.info(\"Training complete. Time taken %02d:%02d:%02d\" % (hours, mins, secs))\n        except BaseException as e:\n            self._logger.error(\"Training is terminating due to exception: %s\", str(e))\n            self._fire_event(TrainingEvents.EXCEPTION_RAISED)\n            raise e\n", "path": "ignite/trainer/trainer.py"}], "after_files": [{"content": "from __future__ import division\n\nimport logging\nimport time\nfrom collections import Iterable\n\nfrom enum import Enum\nfrom torch.autograd import Variable\nfrom ignite.trainer.history import History\n\n__all__ = [\"TrainingEvents\", \"Trainer\", \"create_supervised\"]\n\n\nclass TrainingEvents(Enum):\n    EPOCH_STARTED = \"epoch_started\"\n    EPOCH_COMPLETED = \"epoch_completed\"\n    TRAINING_EPOCH_STARTED = \"training_epoch_started\"\n    TRAINING_EPOCH_COMPLETED = \"training_epoch_completed\"\n    VALIDATION_STARTING = \"validation_starting\"\n    VALIDATION_COMPLETED = \"validation_completed\"\n    TRAINING_STARTED = \"training_started\"\n    TRAINING_COMPLETED = \"training_completed\"\n    TRAINING_ITERATION_STARTED = \"training_iteration_started\"\n    TRAINING_ITERATION_COMPLETED = \"training_iteration_completed\"\n    VALIDATION_ITERATION_STARTED = \"validation_iteration_started\"\n    VALIDATION_ITERATION_COMPLETED = \"validation_iteration_completed\"\n    EXCEPTION_RAISED = \"exception_raised\"\n\n\ndef _to_hours_mins_secs(time_taken):\n    mins, secs = divmod(time_taken, 60)\n    hours, mins = divmod(mins, 60)\n    return hours, mins, secs\n\n\nclass Trainer(object):\n    \"\"\"\n    Generic trainer class.\n\n    Training update and validation functions receive batches of data and return values which will\n    be stored in the `training_history` and `validation_history`. The trainer defines multiple\n    events in `TrainingEvents` for which the user can attach event handlers to. The events get\n    passed the trainer, so they can access the training/validation history\n\n\n    Parameters\n    ----------\n    training_update_function : callable\n        Update function receiving the current training batch in each iteration\n\n    validation_inference_function : callable\n        Function receiving data and performing a feed forward without update\n    \"\"\"\n\n    def __init__(self, training_update_function, validation_inference_function=None):\n\n        self._logger = self._get_logger()\n        self._training_update_function = training_update_function\n        self._validation_inference_function = validation_inference_function\n        self._event_handlers = {}\n\n        self.training_history = History()\n        self.validation_history = History()\n        self.current_iteration = 0\n        self.current_validation_iteration = 0\n        self.current_epoch = 0\n        self.max_epochs = 0\n        self.should_terminate = False\n\n    def _get_logger(self):\n        logger = logging.getLogger(__name__ + \".\" + self.__class__.__name__)\n        logger.addHandler(logging.NullHandler())\n        return logger\n\n    def add_event_handler(self, event_name, handler, *args, **kwargs):\n        \"\"\"\n        Add an event handler to be executed when the specified event is fired\n\n        Parameters\n        ----------\n        event_name: enum\n            event from ignite.trainer.TrainingEvents to attach the\n            handler to\n        handler: Callable\n            the callable event handler that should be invoked\n        args:\n            optional args to be passed to `handler`\n        kwargs:\n            optional keyword args to be passed to `handler`\n\n        Returns\n        -------\n        None\n        \"\"\"\n        if event_name not in TrainingEvents.__members__.values():\n            self._logger.error(\"attempt to add event handler to non-existent event %s \",\n                               event_name)\n            raise ValueError(\"Event {} not a valid training event\".format(event_name))\n\n        if event_name not in self._event_handlers.keys():\n            self._event_handlers[event_name] = []\n\n        self._event_handlers[event_name].append((handler, args, kwargs))\n        self._logger.debug(\"added handler for event % \", event_name)\n\n    def _fire_event(self, event_name):\n        if event_name in self._event_handlers.keys():\n            self._logger.debug(\"firing handlers for event %s \", event_name)\n            for func, args, kwargs in self._event_handlers[event_name]:\n                func(self, *args, **kwargs)\n\n    def _train_one_epoch(self, training_data):\n        self._fire_event(TrainingEvents.TRAINING_EPOCH_STARTED)\n        start_time = time.time()\n\n        self.epoch_losses = []\n        for _, batch in enumerate(training_data, 1):\n            self._fire_event(TrainingEvents.TRAINING_ITERATION_STARTED)\n\n            training_step_result = self._training_update_function(batch)\n            if training_step_result is not None:\n                self.training_history.append(training_step_result)\n\n            self.current_iteration += 1\n\n            self._fire_event(TrainingEvents.TRAINING_ITERATION_COMPLETED)\n            if self.should_terminate:\n                return\n\n        time_taken = time.time() - start_time\n        hours, mins, secs = _to_hours_mins_secs(time_taken)\n        self._logger.info(\"Epoch[%s] Complete. Time taken: %02d:%02d:%02d\", self.current_epoch, hours,\n                          mins, secs)\n\n        self._fire_event(TrainingEvents.TRAINING_EPOCH_COMPLETED)\n\n    def validate(self, validation_data):\n        \"\"\" Evaluates the validation set\"\"\"\n        if self._validation_inference_function is None:\n            raise ValueError(\"Trainer must have a validation_inference_function in order to validate\")\n\n        self.current_validation_iteration = 0\n        self._fire_event(TrainingEvents.VALIDATION_STARTING)\n        start_time = time.time()\n\n        for _, batch in enumerate(validation_data, 1):\n            self._fire_event(TrainingEvents.VALIDATION_ITERATION_STARTED)\n            validation_step_result = self._validation_inference_function(batch)\n            if validation_step_result is not None:\n                self.validation_history.append(validation_step_result)\n\n            self.current_validation_iteration += 1\n            self._fire_event(TrainingEvents.VALIDATION_ITERATION_COMPLETED)\n            if self.should_terminate:\n                break\n\n        time_taken = time.time() - start_time\n        hours, mins, secs = _to_hours_mins_secs(time_taken)\n        self._logger.info(\"Validation Complete. Time taken: %02d:%02d:%02d\", hours, mins, secs)\n\n        self._fire_event(TrainingEvents.VALIDATION_COMPLETED)\n\n    def terminate(self):\n        \"\"\"\n        Sends terminate signal to trainer, so that training terminates after the current iteration\n        \"\"\"\n        self._logger.info(\"Terminate signaled to trainer. \" +\n                          \"Training will stop after current iteration is finished\")\n        self.should_terminate = True\n\n    def run(self, training_data, max_epochs=1):\n        \"\"\"\n        Train the model, evaluate the validation set and update best parameters if the validation loss\n        improves.\n        In the event that the validation set is not run (or doesn't exist), the training loss is used\n        to update the best parameters.\n\n        Parameters\n        ----------\n        training_data : Iterable\n            Collection of training batches allowing repeated iteration (e.g., list or DataLoader)\n        max_epochs: int, optional\n            max epochs to train for [default=1]\n\n        Returns\n        -------\n        None\n        \"\"\"\n\n        try:\n            self._logger.info(\"Training starting with max_epochs={}\".format(max_epochs))\n\n            self.max_epochs = max_epochs\n\n            start_time = time.time()\n\n            self._fire_event(TrainingEvents.TRAINING_STARTED)\n            while self.current_epoch < max_epochs and not self.should_terminate:\n                self._fire_event(TrainingEvents.EPOCH_STARTED)\n                self._train_one_epoch(training_data)\n                if self.should_terminate:\n                    break\n\n                self._fire_event(TrainingEvents.EPOCH_COMPLETED)\n                self.current_epoch += 1\n\n            self._fire_event(TrainingEvents.TRAINING_COMPLETED)\n            time_taken = time.time() - start_time\n            mins, secs = divmod(time_taken, 60)\n            hours, mins = divmod(mins, 60)\n            self._logger.info(\"Training complete. Time taken %02d:%02d:%02d\" % (hours, mins, secs))\n        except BaseException as e:\n            self._logger.error(\"Training is terminating due to exception: %s\", str(e))\n            self._fire_event(TrainingEvents.EXCEPTION_RAISED)\n            raise e\n\n\ndef create_supervised(model, optimizer, loss_fn, cuda=False):\n    \"\"\"\n    Factory function for creating a trainer for supervised models\n\n    Args:\n        model (torch.nn.Module): the model to train\n        optimizer (torch.optim.Optimizer): the optimizer to use\n        loss_fn (torch.nn loss function): the loss function to use\n        cuda (bool, optional): whether or not to transfer batch to GPU (default: False)\n\n    Returns:\n        Trainer: a trainer instance with supervised update and inference functions\n    \"\"\"\n    def _prepare_batch(batch, volatile=False):\n        x, y = batch\n        if cuda:\n            x, y = x.cuda(), y.cuda()\n        return Variable(x, volatile=volatile), Variable(y, volatile=volatile)\n\n    def _update(batch):\n        model.train()\n        optimizer.zero_grad()\n        x, y = _prepare_batch(batch)\n        y_pred = model(x)\n        loss = loss_fn(y_pred, y)\n        loss.backward()\n        optimizer.step()\n        return loss.data.cpu()[0]\n\n    def _inference(batch):\n        model.eval()\n        x, y = _prepare_batch(batch, volatile=True)\n        y_pred = model(x)\n        return y_pred.data.cpu(), y.data.cpu()\n\n    return Trainer(_update, _inference)\n", "path": "ignite/trainer/trainer.py"}]}