We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Match core API in contrib TBPTT trainer
I propose the following change so that tbptt trainer behaves like the supervised trainer:

- [ ] Replace `convert_tensor` by `prepare_batch` ([line](https://github.com/pytorch/ignite/blob/d3d7b146d56efb5b497f3cf4b22caab976774e7e/ignite/contrib/engines/tbptt.py#L29))
- [ ] Call `prepare_batch` on time chunks (the quantity used to compute gradients) rather that whole time series mini bactch
- [ ] Add `prepare_batch` function in the arguments
- [ ] Add `non_blocking` in the arguments
Match core API in contrib TBPTT trainer
I propose the following change so that tbptt trainer behaves like the supervised trainer:

- [ ] Replace `convert_tensor` by `prepare_batch` ([line](https://github.com/pytorch/ignite/blob/d3d7b146d56efb5b497f3cf4b22caab976774e7e/ignite/contrib/engines/tbptt.py#L29))
- [ ] Call `prepare_batch` on time chunks (the quantity used to compute gradients) rather that whole time series mini bactch
- [ ] Add `prepare_batch` function in the arguments
- [ ] Add `non_blocking` in the arguments

--- 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/engine/__init__.py`
Content:
```
1 import torch
2 
3 from ignite.engine.engine import Engine, State, Events
4 from ignite._utils import convert_tensor
5 
6 
7 def _prepare_batch(batch, device=None, non_blocking=False):
8     x, y = batch
9     return (convert_tensor(x, device=device, non_blocking=non_blocking),
10             convert_tensor(y, device=device, non_blocking=non_blocking))
11 
12 
13 def create_supervised_trainer(model, optimizer, loss_fn,
14                               device=None, non_blocking=False,
15                               prepare_batch=_prepare_batch):
16     """
17     Factory function for creating a trainer for supervised models
18 
19     Args:
20         model (`torch.nn.Module`): the model to train
21         optimizer (`torch.optim.Optimizer`): the optimizer to use
22         loss_fn (torch.nn loss function): the loss function to use
23         device (str, optional): device type specification (default: None).
24             Applies to both model and batches.
25         non_blocking (bool, optional): if True and this copy is between CPU and GPU, the copy may occur asynchronously
26             with respect to the host. For other cases, this argument has no effect.
27         prepare_batch (Callable, optional): function that receives `batch`, `device`, `non_blocking` and outputs
28             tuple of tensors `(batch_x, batch_y)`.
29 
30     Returns:
31         Engine: a trainer engine with supervised update function
32     """
33     if device:
34         model.to(device)
35 
36     def _update(engine, batch):
37         model.train()
38         optimizer.zero_grad()
39         x, y = prepare_batch(batch, device=device, non_blocking=non_blocking)
40         y_pred = model(x)
41         loss = loss_fn(y_pred, y)
42         loss.backward()
43         optimizer.step()
44         return loss.item()
45 
46     return Engine(_update)
47 
48 
49 def create_supervised_evaluator(model, metrics={},
50                                 device=None, non_blocking=False,
51                                 prepare_batch=_prepare_batch):
52     """
53     Factory function for creating an evaluator for supervised models
54 
55     Args:
56         model (`torch.nn.Module`): the model to train
57         metrics (dict of str - :class:`ignite.metrics.Metric`): a map of metric names to Metrics
58         device (str, optional): device type specification (default: None).
59             Applies to both model and batches.
60         non_blocking (bool, optional): if True and this copy is between CPU and GPU, the copy may occur asynchronously
61             with respect to the host. For other cases, this argument has no effect.
62         prepare_batch (Callable, optional): function that receives `batch`, `device`, `non_blocking` and outputs
63             tuple of tensors `(batch_x, batch_y)`.
64 
65     Returns:
66         Engine: an evaluator engine with supervised inference function
67     """
68     if device:
69         model.to(device)
70 
71     def _inference(engine, batch):
72         model.eval()
73         with torch.no_grad():
74             x, y = prepare_batch(batch, device=device, non_blocking=non_blocking)
75             y_pred = model(x)
76             return y_pred, y
77 
78     engine = Engine(_inference)
79 
80     for name, metric in metrics.items():
81         metric.attach(engine, name)
82 
83     return engine
84
```

Path: `ignite/contrib/engines/tbptt.py`
Content:
```
1 # coding: utf-8
2 
3 from enum import Enum
4 
5 import torch
6 
7 from ignite._utils import convert_tensor, apply_to_tensor
8 from ignite.engine import Engine
9 
10 
11 class Tbptt_Events(Enum):
12     """Aditional tbptt events.
13 
14     Additional events for truncated backpropagation throught time dedicated
15     trainer.
16     """
17 
18     TIME_ITERATION_STARTED = "time_iteration_started"
19     TIME_ITERATION_COMPLETED = "time_iteration_completed"
20 
21 
22 def _prepare_tbptt_batch(batch, tbptt_step, dim=0, device=None):
23     """Prepare batch for tbptt trainer.
24 
25     Batch come from the dataloader. It is split in chunks along the time
26     dimension and fed to the truncated backpropagation throught time trainer.
27     """
28     x, y = batch
29     x = convert_tensor(x, device=device)
30     y = convert_tensor(y, device=device)
31     return zip(x.split(tbptt_step, dim=dim), y.split(tbptt_step, dim=dim))
32 
33 
34 def _detach_hidden(hidden):
35     """Cut backpropagation graph.
36 
37     Auxillary function to cut the backpropagation graph by detaching the hidden
38     vector.
39     """
40     return apply_to_tensor(hidden, torch.Tensor.detach)
41 
42 
43 def create_supervised_tbptt_trainer(
44     model,
45     optimizer,
46     loss_fn,
47     tbtt_step,
48     dim=0,
49     device=None
50 ):
51     """Create a trainer for truncated backprop through time supervised models.
52 
53     Training recurrent model on long sequences is computationally intensive as
54     it requires to process the whole sequence before getting a gradient.
55     However, when the training loss is computed over many outputs
56     (`X to many <https://karpathy.github.io/2015/05/21/rnn-effectiveness/>`_),
57     there is an opportunity to compute a gradient over a subsequence. This is
58     known as
59     `truncated backpropagation through time <https://machinelearningmastery.com/
60     gentle-introduction-backpropagation-time/>`_.
61     This supervised trainer apply gradient optimization step every `tbtt_step`
62     time steps of the sequence, while backpropagating through the same
63     `tbtt_step` time steps.
64 
65     Args:
66         model (`torch.nn.Module`): the model to train
67         optimizer (`torch.optim.Optimizer`): the optimizer to use
68         loss_fn (torch.nn loss function): the loss function to use
69         tbtt_step (int): the length of time chunks (last one may be smaller)
70         dim (int): axis representing the time dimension
71         device (str, optional): device type specification (default: None).
72             Applies to both model and batches.
73 
74     Returns:
75         Engine: a trainer engine with supervised update function
76 
77     """
78     if device:
79         model.to(device)
80 
81     def _update(engine, batch):
82         loss_list = []
83         hidden = None
84 
85         # Batches split in time chunks
86         batch_splits = _prepare_tbptt_batch(
87             batch, tbtt_step, dim=dim, device=device
88         )
89         for x_t, y_t in batch_splits:
90             # Fire event for start of iteration
91             engine.fire_event(Tbptt_Events.TIME_ITERATION_STARTED)
92             # Forward, backward and
93             model.train()
94             optimizer.zero_grad()
95             if hidden is None:
96                 y_pred_t, hidden = model(x_t)
97             else:
98                 hidden = _detach_hidden(hidden)
99                 y_pred_t, hidden = model(x_t, hidden)
100             loss_t = loss_fn(y_pred_t, y_t)
101             loss_t.backward()
102             optimizer.step()
103 
104             # Setting state of engine for consistent behaviour
105             engine.state.output = loss_t.item()
106             loss_list.append(loss_t.item())
107 
108             # Fire event for end of iteration
109             engine.fire_event(Tbptt_Events.TIME_ITERATION_COMPLETED)
110 
111         # return average loss over the time splits
112         return sum(loss_list) / len(loss_list)
113 
114     engine = Engine(_update)
115     engine.register_events(*Tbptt_Events)
116     return engine
117
```
--- 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/contrib/engines/tbptt.py b/ignite/contrib/engines/tbptt.py
--- a/ignite/contrib/engines/tbptt.py
+++ b/ignite/contrib/engines/tbptt.py
@@ -4,8 +4,8 @@
 
 import torch
 
-from ignite._utils import convert_tensor, apply_to_tensor
-from ignite.engine import Engine
+from ignite._utils import apply_to_tensor
+from ignite.engine import Engine, _prepare_batch
 
 
 class Tbptt_Events(Enum):
@@ -19,18 +19,6 @@
     TIME_ITERATION_COMPLETED = "time_iteration_completed"
 
 
-def _prepare_tbptt_batch(batch, tbptt_step, dim=0, device=None):
-    """Prepare batch for tbptt trainer.
-
-    Batch come from the dataloader. It is split in chunks along the time
-    dimension and fed to the truncated backpropagation throught time trainer.
-    """
-    x, y = batch
-    x = convert_tensor(x, device=device)
-    y = convert_tensor(y, device=device)
-    return zip(x.split(tbptt_step, dim=dim), y.split(tbptt_step, dim=dim))
-
-
 def _detach_hidden(hidden):
     """Cut backpropagation graph.
 
@@ -46,7 +34,9 @@
     loss_fn,
     tbtt_step,
     dim=0,
-    device=None
+    device=None,
+    non_blocking=False,
+    prepare_batch=_prepare_batch
 ):
     """Create a trainer for truncated backprop through time supervised models.
 
@@ -70,6 +60,11 @@
         dim (int): axis representing the time dimension
         device (str, optional): device type specification (default: None).
             Applies to both model and batches.
+        non_blocking (bool, optional): if True and this copy is between CPU and GPU,
+            the copy may occur asynchronously with respect to the host. For other cases,
+            this argument has no effect.
+        prepare_batch (Callable, optional): function that receives `batch`, `device`,
+            `non_blocking` and outputs tuple of tensors `(batch_x, batch_y)`.
 
     Returns:
         Engine: a trainer engine with supervised update function
@@ -82,11 +77,9 @@
         loss_list = []
         hidden = None
 
-        # Batches split in time chunks
-        batch_splits = _prepare_tbptt_batch(
-            batch, tbtt_step, dim=dim, device=device
-        )
-        for x_t, y_t in batch_splits:
+        x, y = batch
+        for batch_t in zip(x.split(tbtt_step, dim=dim), y.split(tbtt_step, dim=dim)):
+            x_t, y_t = prepare_batch(batch_t, device=device, non_blocking=non_blocking)
             # Fire event for start of iteration
             engine.fire_event(Tbptt_Events.TIME_ITERATION_STARTED)
             # Forward, backward and
diff --git a/ignite/engine/__init__.py b/ignite/engine/__init__.py
--- a/ignite/engine/__init__.py
+++ b/ignite/engine/__init__.py
@@ -5,6 +5,9 @@
 
 
 def _prepare_batch(batch, device=None, non_blocking=False):
+    """Prepare batch for training: pass to a device with options
+
+    """
     x, y = batch
     return (convert_tensor(x, device=device, non_blocking=non_blocking),
             convert_tensor(y, device=device, non_blocking=non_blocking))

{"golden_diff": "diff --git a/ignite/contrib/engines/tbptt.py b/ignite/contrib/engines/tbptt.py\n--- a/ignite/contrib/engines/tbptt.py\n+++ b/ignite/contrib/engines/tbptt.py\n@@ -4,8 +4,8 @@\n \n import torch\n \n-from ignite._utils import convert_tensor, apply_to_tensor\n-from ignite.engine import Engine\n+from ignite._utils import apply_to_tensor\n+from ignite.engine import Engine, _prepare_batch\n \n \n class Tbptt_Events(Enum):\n@@ -19,18 +19,6 @@\n     TIME_ITERATION_COMPLETED = \"time_iteration_completed\"\n \n \n-def _prepare_tbptt_batch(batch, tbptt_step, dim=0, device=None):\n-    \"\"\"Prepare batch for tbptt trainer.\n-\n-    Batch come from the dataloader. It is split in chunks along the time\n-    dimension and fed to the truncated backpropagation throught time trainer.\n-    \"\"\"\n-    x, y = batch\n-    x = convert_tensor(x, device=device)\n-    y = convert_tensor(y, device=device)\n-    return zip(x.split(tbptt_step, dim=dim), y.split(tbptt_step, dim=dim))\n-\n-\n def _detach_hidden(hidden):\n     \"\"\"Cut backpropagation graph.\n \n@@ -46,7 +34,9 @@\n     loss_fn,\n     tbtt_step,\n     dim=0,\n-    device=None\n+    device=None,\n+    non_blocking=False,\n+    prepare_batch=_prepare_batch\n ):\n     \"\"\"Create a trainer for truncated backprop through time supervised models.\n \n@@ -70,6 +60,11 @@\n         dim (int): axis representing the time dimension\n         device (str, optional): device type specification (default: None).\n             Applies to both model and batches.\n+        non_blocking (bool, optional): if True and this copy is between CPU and GPU,\n+            the copy may occur asynchronously with respect to the host. For other cases,\n+            this argument has no effect.\n+        prepare_batch (Callable, optional): function that receives `batch`, `device`,\n+            `non_blocking` and outputs tuple of tensors `(batch_x, batch_y)`.\n \n     Returns:\n         Engine: a trainer engine with supervised update function\n@@ -82,11 +77,9 @@\n         loss_list = []\n         hidden = None\n \n-        # Batches split in time chunks\n-        batch_splits = _prepare_tbptt_batch(\n-            batch, tbtt_step, dim=dim, device=device\n-        )\n-        for x_t, y_t in batch_splits:\n+        x, y = batch\n+        for batch_t in zip(x.split(tbtt_step, dim=dim), y.split(tbtt_step, dim=dim)):\n+            x_t, y_t = prepare_batch(batch_t, device=device, non_blocking=non_blocking)\n             # Fire event for start of iteration\n             engine.fire_event(Tbptt_Events.TIME_ITERATION_STARTED)\n             # Forward, backward and\ndiff --git a/ignite/engine/__init__.py b/ignite/engine/__init__.py\n--- a/ignite/engine/__init__.py\n+++ b/ignite/engine/__init__.py\n@@ -5,6 +5,9 @@\n \n \n def _prepare_batch(batch, device=None, non_blocking=False):\n+    \"\"\"Prepare batch for training: pass to a device with options\n+\n+    \"\"\"\n     x, y = batch\n     return (convert_tensor(x, device=device, non_blocking=non_blocking),\n             convert_tensor(y, device=device, non_blocking=non_blocking))\n", "issue": "Match core API in contrib TBPTT trainer\nI propose the following change so that tbptt trainer behaves like the supervised trainer:\r\n\r\n- [ ] Replace `convert_tensor` by `prepare_batch` ([line](https://github.com/pytorch/ignite/blob/d3d7b146d56efb5b497f3cf4b22caab976774e7e/ignite/contrib/engines/tbptt.py#L29))\r\n- [ ] Call `prepare_batch` on time chunks (the quantity used to compute gradients) rather that whole time series mini bactch\r\n- [ ] Add `prepare_batch` function in the arguments\r\n- [ ] Add `non_blocking` in the arguments\nMatch core API in contrib TBPTT trainer\nI propose the following change so that tbptt trainer behaves like the supervised trainer:\r\n\r\n- [ ] Replace `convert_tensor` by `prepare_batch` ([line](https://github.com/pytorch/ignite/blob/d3d7b146d56efb5b497f3cf4b22caab976774e7e/ignite/contrib/engines/tbptt.py#L29))\r\n- [ ] Call `prepare_batch` on time chunks (the quantity used to compute gradients) rather that whole time series mini bactch\r\n- [ ] Add `prepare_batch` function in the arguments\r\n- [ ] Add `non_blocking` in the arguments\n", "before_files": [{"content": "import torch\n\nfrom ignite.engine.engine import Engine, State, Events\nfrom ignite._utils import convert_tensor\n\n\ndef _prepare_batch(batch, device=None, non_blocking=False):\n    x, y = batch\n    return (convert_tensor(x, device=device, non_blocking=non_blocking),\n            convert_tensor(y, device=device, non_blocking=non_blocking))\n\n\ndef create_supervised_trainer(model, optimizer, loss_fn,\n                              device=None, non_blocking=False,\n                              prepare_batch=_prepare_batch):\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        device (str, optional): device type specification (default: None).\n            Applies to both model and batches.\n        non_blocking (bool, optional): if True and this copy is between CPU and GPU, the copy may occur asynchronously\n            with respect to the host. For other cases, this argument has no effect.\n        prepare_batch (Callable, optional): function that receives `batch`, `device`, `non_blocking` and outputs\n            tuple of tensors `(batch_x, batch_y)`.\n\n    Returns:\n        Engine: a trainer engine with supervised update function\n    \"\"\"\n    if device:\n        model.to(device)\n\n    def _update(engine, batch):\n        model.train()\n        optimizer.zero_grad()\n        x, y = prepare_batch(batch, device=device, non_blocking=non_blocking)\n        y_pred = model(x)\n        loss = loss_fn(y_pred, y)\n        loss.backward()\n        optimizer.step()\n        return loss.item()\n\n    return Engine(_update)\n\n\ndef create_supervised_evaluator(model, metrics={},\n                                device=None, non_blocking=False,\n                                prepare_batch=_prepare_batch):\n    \"\"\"\n    Factory function for creating an evaluator for supervised models\n\n    Args:\n        model (`torch.nn.Module`): the model to train\n        metrics (dict of str - :class:`ignite.metrics.Metric`): a map of metric names to Metrics\n        device (str, optional): device type specification (default: None).\n            Applies to both model and batches.\n        non_blocking (bool, optional): if True and this copy is between CPU and GPU, the copy may occur asynchronously\n            with respect to the host. For other cases, this argument has no effect.\n        prepare_batch (Callable, optional): function that receives `batch`, `device`, `non_blocking` and outputs\n            tuple of tensors `(batch_x, batch_y)`.\n\n    Returns:\n        Engine: an evaluator engine with supervised inference function\n    \"\"\"\n    if device:\n        model.to(device)\n\n    def _inference(engine, batch):\n        model.eval()\n        with torch.no_grad():\n            x, y = prepare_batch(batch, device=device, non_blocking=non_blocking)\n            y_pred = model(x)\n            return y_pred, y\n\n    engine = Engine(_inference)\n\n    for name, metric in metrics.items():\n        metric.attach(engine, name)\n\n    return engine\n", "path": "ignite/engine/__init__.py"}, {"content": "# coding: utf-8\n\nfrom enum import Enum\n\nimport torch\n\nfrom ignite._utils import convert_tensor, apply_to_tensor\nfrom ignite.engine import Engine\n\n\nclass Tbptt_Events(Enum):\n    \"\"\"Aditional tbptt events.\n\n    Additional events for truncated backpropagation throught time dedicated\n    trainer.\n    \"\"\"\n\n    TIME_ITERATION_STARTED = \"time_iteration_started\"\n    TIME_ITERATION_COMPLETED = \"time_iteration_completed\"\n\n\ndef _prepare_tbptt_batch(batch, tbptt_step, dim=0, device=None):\n    \"\"\"Prepare batch for tbptt trainer.\n\n    Batch come from the dataloader. It is split in chunks along the time\n    dimension and fed to the truncated backpropagation throught time trainer.\n    \"\"\"\n    x, y = batch\n    x = convert_tensor(x, device=device)\n    y = convert_tensor(y, device=device)\n    return zip(x.split(tbptt_step, dim=dim), y.split(tbptt_step, dim=dim))\n\n\ndef _detach_hidden(hidden):\n    \"\"\"Cut backpropagation graph.\n\n    Auxillary function to cut the backpropagation graph by detaching the hidden\n    vector.\n    \"\"\"\n    return apply_to_tensor(hidden, torch.Tensor.detach)\n\n\ndef create_supervised_tbptt_trainer(\n    model,\n    optimizer,\n    loss_fn,\n    tbtt_step,\n    dim=0,\n    device=None\n):\n    \"\"\"Create a trainer for truncated backprop through time supervised models.\n\n    Training recurrent model on long sequences is computationally intensive as\n    it requires to process the whole sequence before getting a gradient.\n    However, when the training loss is computed over many outputs\n    (`X to many <https://karpathy.github.io/2015/05/21/rnn-effectiveness/>`_),\n    there is an opportunity to compute a gradient over a subsequence. This is\n    known as\n    `truncated backpropagation through time <https://machinelearningmastery.com/\n    gentle-introduction-backpropagation-time/>`_.\n    This supervised trainer apply gradient optimization step every `tbtt_step`\n    time steps of the sequence, while backpropagating through the same\n    `tbtt_step` time steps.\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        tbtt_step (int): the length of time chunks (last one may be smaller)\n        dim (int): axis representing the time dimension\n        device (str, optional): device type specification (default: None).\n            Applies to both model and batches.\n\n    Returns:\n        Engine: a trainer engine with supervised update function\n\n    \"\"\"\n    if device:\n        model.to(device)\n\n    def _update(engine, batch):\n        loss_list = []\n        hidden = None\n\n        # Batches split in time chunks\n        batch_splits = _prepare_tbptt_batch(\n            batch, tbtt_step, dim=dim, device=device\n        )\n        for x_t, y_t in batch_splits:\n            # Fire event for start of iteration\n            engine.fire_event(Tbptt_Events.TIME_ITERATION_STARTED)\n            # Forward, backward and\n            model.train()\n            optimizer.zero_grad()\n            if hidden is None:\n                y_pred_t, hidden = model(x_t)\n            else:\n                hidden = _detach_hidden(hidden)\n                y_pred_t, hidden = model(x_t, hidden)\n            loss_t = loss_fn(y_pred_t, y_t)\n            loss_t.backward()\n            optimizer.step()\n\n            # Setting state of engine for consistent behaviour\n            engine.state.output = loss_t.item()\n            loss_list.append(loss_t.item())\n\n            # Fire event for end of iteration\n            engine.fire_event(Tbptt_Events.TIME_ITERATION_COMPLETED)\n\n        # return average loss over the time splits\n        return sum(loss_list) / len(loss_list)\n\n    engine = Engine(_update)\n    engine.register_events(*Tbptt_Events)\n    return engine\n", "path": "ignite/contrib/engines/tbptt.py"}], "after_files": [{"content": "import torch\n\nfrom ignite.engine.engine import Engine, State, Events\nfrom ignite._utils import convert_tensor\n\n\ndef _prepare_batch(batch, device=None, non_blocking=False):\n    \"\"\"Prepare batch for training: pass to a device with options\n\n    \"\"\"\n    x, y = batch\n    return (convert_tensor(x, device=device, non_blocking=non_blocking),\n            convert_tensor(y, device=device, non_blocking=non_blocking))\n\n\ndef create_supervised_trainer(model, optimizer, loss_fn,\n                              device=None, non_blocking=False,\n                              prepare_batch=_prepare_batch):\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        device (str, optional): device type specification (default: None).\n            Applies to both model and batches.\n        non_blocking (bool, optional): if True and this copy is between CPU and GPU, the copy may occur asynchronously\n            with respect to the host. For other cases, this argument has no effect.\n        prepare_batch (Callable, optional): function that receives `batch`, `device`, `non_blocking` and outputs\n            tuple of tensors `(batch_x, batch_y)`.\n\n    Returns:\n        Engine: a trainer engine with supervised update function\n    \"\"\"\n    if device:\n        model.to(device)\n\n    def _update(engine, batch):\n        model.train()\n        optimizer.zero_grad()\n        x, y = prepare_batch(batch, device=device, non_blocking=non_blocking)\n        y_pred = model(x)\n        loss = loss_fn(y_pred, y)\n        loss.backward()\n        optimizer.step()\n        return loss.item()\n\n    return Engine(_update)\n\n\ndef create_supervised_evaluator(model, metrics={},\n                                device=None, non_blocking=False,\n                                prepare_batch=_prepare_batch):\n    \"\"\"\n    Factory function for creating an evaluator for supervised models\n\n    Args:\n        model (`torch.nn.Module`): the model to train\n        metrics (dict of str - :class:`ignite.metrics.Metric`): a map of metric names to Metrics\n        device (str, optional): device type specification (default: None).\n            Applies to both model and batches.\n        non_blocking (bool, optional): if True and this copy is between CPU and GPU, the copy may occur asynchronously\n            with respect to the host. For other cases, this argument has no effect.\n        prepare_batch (Callable, optional): function that receives `batch`, `device`, `non_blocking` and outputs\n            tuple of tensors `(batch_x, batch_y)`.\n\n    Returns:\n        Engine: an evaluator engine with supervised inference function\n    \"\"\"\n    if device:\n        model.to(device)\n\n    def _inference(engine, batch):\n        model.eval()\n        with torch.no_grad():\n            x, y = prepare_batch(batch, device=device, non_blocking=non_blocking)\n            y_pred = model(x)\n            return y_pred, y\n\n    engine = Engine(_inference)\n\n    for name, metric in metrics.items():\n        metric.attach(engine, name)\n\n    return engine\n", "path": "ignite/engine/__init__.py"}, {"content": "# coding: utf-8\n\nfrom enum import Enum\n\nimport torch\n\nfrom ignite._utils import apply_to_tensor\nfrom ignite.engine import Engine, _prepare_batch\n\n\nclass Tbptt_Events(Enum):\n    \"\"\"Aditional tbptt events.\n\n    Additional events for truncated backpropagation throught time dedicated\n    trainer.\n    \"\"\"\n\n    TIME_ITERATION_STARTED = \"time_iteration_started\"\n    TIME_ITERATION_COMPLETED = \"time_iteration_completed\"\n\n\ndef _detach_hidden(hidden):\n    \"\"\"Cut backpropagation graph.\n\n    Auxillary function to cut the backpropagation graph by detaching the hidden\n    vector.\n    \"\"\"\n    return apply_to_tensor(hidden, torch.Tensor.detach)\n\n\ndef create_supervised_tbptt_trainer(\n    model,\n    optimizer,\n    loss_fn,\n    tbtt_step,\n    dim=0,\n    device=None,\n    non_blocking=False,\n    prepare_batch=_prepare_batch\n):\n    \"\"\"Create a trainer for truncated backprop through time supervised models.\n\n    Training recurrent model on long sequences is computationally intensive as\n    it requires to process the whole sequence before getting a gradient.\n    However, when the training loss is computed over many outputs\n    (`X to many <https://karpathy.github.io/2015/05/21/rnn-effectiveness/>`_),\n    there is an opportunity to compute a gradient over a subsequence. This is\n    known as\n    `truncated backpropagation through time <https://machinelearningmastery.com/\n    gentle-introduction-backpropagation-time/>`_.\n    This supervised trainer apply gradient optimization step every `tbtt_step`\n    time steps of the sequence, while backpropagating through the same\n    `tbtt_step` time steps.\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        tbtt_step (int): the length of time chunks (last one may be smaller)\n        dim (int): axis representing the time dimension\n        device (str, optional): device type specification (default: None).\n            Applies to both model and batches.\n        non_blocking (bool, optional): if True and this copy is between CPU and GPU,\n            the copy may occur asynchronously with respect to the host. For other cases,\n            this argument has no effect.\n        prepare_batch (Callable, optional): function that receives `batch`, `device`,\n            `non_blocking` and outputs tuple of tensors `(batch_x, batch_y)`.\n\n    Returns:\n        Engine: a trainer engine with supervised update function\n\n    \"\"\"\n    if device:\n        model.to(device)\n\n    def _update(engine, batch):\n        loss_list = []\n        hidden = None\n\n        x, y = batch\n        for batch_t in zip(x.split(tbtt_step, dim=dim), y.split(tbtt_step, dim=dim)):\n            x_t, y_t = prepare_batch(batch_t, device=device, non_blocking=non_blocking)\n            # Fire event for start of iteration\n            engine.fire_event(Tbptt_Events.TIME_ITERATION_STARTED)\n            # Forward, backward and\n            model.train()\n            optimizer.zero_grad()\n            if hidden is None:\n                y_pred_t, hidden = model(x_t)\n            else:\n                hidden = _detach_hidden(hidden)\n                y_pred_t, hidden = model(x_t, hidden)\n            loss_t = loss_fn(y_pred_t, y_t)\n            loss_t.backward()\n            optimizer.step()\n\n            # Setting state of engine for consistent behaviour\n            engine.state.output = loss_t.item()\n            loss_list.append(loss_t.item())\n\n            # Fire event for end of iteration\n            engine.fire_event(Tbptt_Events.TIME_ITERATION_COMPLETED)\n\n        # return average loss over the time splits\n        return sum(loss_list) / len(loss_list)\n\n    engine = Engine(_update)\n    engine.register_events(*Tbptt_Events)\n    return engine\n", "path": "ignite/contrib/engines/tbptt.py"}]}