We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ZeroDivisionError with default_epoch_optim_loop
I get an `ZeroDivisionError: integer division or modulo by zero` when using the `default_transformer_epoch_optim_loop`. This is probably because the `num_batches` of the `batch_sampler` is much smaller than in the `default_transformer_optim_loop` which results in `log_freq=0` in `default_transformer_optim_log_fn.` 

Below is a minimal example to reproduce the error: 
```python
from pystiche.optim.log import default_transformer_optim_log_fn, OptimLogger

logger = OptimLogger()
num_batches = 300
log_fn = default_transformer_optim_log_fn(logger, num_batches)
image_loading_velocity = 1
image_processing_velocity = 1
batch = 1
loss = 1
log_fn(batch, loss, image_loading_velocity, image_processing_velocity)
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pystiche/optim/log.py`
Content:
```
1 from typing import Union, Optional, Tuple, Callable
2 import contextlib
3 import sys
4 import logging
5 import torch
6 from torch.optim.optimizer import Optimizer
7 from torch.optim.lr_scheduler import _LRScheduler as LRScheduler
8 import pystiche
9 from pystiche.pyramid.level import PyramidLevel
10 from .meter import FloatMeter, LossMeter, ProgressMeter
11 
12 __all__ = [
13     "default_logger",
14     "OptimLogger",
15     "default_image_optim_log_fn",
16     "default_pyramid_level_header",
17     "default_transformer_optim_log_fn",
18 ]
19 
20 
21 def default_logger(name: Optional[str] = None, log_file: Optional[str] = None):
22     logger = logging.getLogger(name)
23     logger.setLevel(logging.INFO)
24 
25     fmt = logging.Formatter(
26         fmt="|%(asctime)s| %(message)s", datefmt="%d.%m.%Y %H:%M:%S"
27     )
28 
29     sh = logging.StreamHandler(sys.stdout)
30     sh.setLevel(logging.INFO)
31     sh.addFilter(lambda record: record.levelno <= logging.INFO)
32     sh.setFormatter(fmt)
33     logger.addHandler(sh)
34 
35     sh = logging.StreamHandler(sys.stderr)
36     sh.setLevel(logging.WARNING)
37     sh.setFormatter(fmt)
38     logger.addHandler(sh)
39 
40     if log_file is not None:
41         fh = logging.FileHandler(log_file)
42         fh.setLevel(logging.INFO)
43         fh.setFormatter(fmt)
44         logger.addHandler(fh)
45 
46     return logger
47 
48 
49 class OptimLogger:
50     INDENT = 2
51     SEP_LINE_LENGTH = 80
52     SEP_CHARS = ("#", "=", "-", ".")
53 
54     def __init__(self, logger: Optional[logging.Logger] = None):
55         if logger is None:
56             logger = default_logger()
57         self.logger = logger
58 
59         self._environ_indent_offset = 0
60         self._environ_level_offset = 0
61 
62     def _calc_abs_indent(self, indent: int, rel: bool):
63         abs_indent = indent
64         if rel:
65             abs_indent += self._environ_indent_offset
66         return abs_indent
67 
68     def _calc_abs_level(self, level: int, rel: bool):
69         abs_level = level
70         if rel:
71             abs_level += self._environ_level_offset
72         return abs_level
73 
74     def message(self, msg: str, indent: int = 0, rel=True) -> None:
75         abs_indent = self._calc_abs_indent(indent, rel)
76         for line in msg.splitlines():
77             self.logger.info(" " * abs_indent + line)
78 
79     def sepline(self, level: int = 0, rel=True):
80         abs_level = self._calc_abs_level(level, rel)
81         self.message(self.SEP_CHARS[abs_level] * self.SEP_LINE_LENGTH)
82 
83     def sep_message(
84         self, msg: str, level: int = 0, rel=True, top_sep=True, bottom_sep=True
85     ):
86         if top_sep:
87             self.sepline(level=level, rel=rel)
88         self.message(msg, rel=rel)
89         if bottom_sep:
90             self.sepline(level=level, rel=rel)
91 
92     @contextlib.contextmanager
93     def environment(self, header: str):
94         self.sep_message(header)
95         self._environ_indent_offset += self.INDENT
96         self._environ_level_offset += 1
97         try:
98             yield
99         finally:
100             self._environ_level_offset -= 1
101             self._environ_indent_offset -= self.INDENT
102 
103 
104 def default_image_optim_log_fn(
105     optim_logger: OptimLogger, log_freq: int = 50, max_depth: int = 1
106 ) -> Callable[[int, Union[torch.Tensor, pystiche.LossDict]], None]:
107     def log_fn(step: int, loss: Union[torch.Tensor, pystiche.LossDict]) -> None:
108         if step % log_freq == 0:
109             with optim_logger.environment(f"Step {step}"):
110                 if isinstance(loss, torch.Tensor):
111                     optim_logger.message(f"loss: {loss.item():.3e}")
112                 else:  # isinstance(loss, pystiche.LossDict)
113                     optim_logger.message(loss.aggregate(max_depth).format())
114 
115     return log_fn
116 
117 
118 def default_pyramid_level_header(
119     num: int, level: PyramidLevel, input_image_size: Tuple[int, int]
120 ):
121     height, width = input_image_size
122     return f"Pyramid level {num} with {level.num_steps} steps " f"({width} x {height})"
123 
124 
125 def default_transformer_optim_log_fn(
126     optim_logger: OptimLogger,
127     num_batches: int,
128     log_freq: Optional[int] = None,
129     show_loading_velocity: bool = True,
130     show_processing_velocity: bool = True,
131     show_running_means: bool = True,
132 ):
133     if log_freq is None:
134         log_freq = min(round(1e-3 * num_batches) * 10, 50)
135 
136     window_size = min(10 * log_freq, 1000)
137 
138     meters = [LossMeter(show_avg=show_running_means, window_size=window_size)]
139     if show_loading_velocity:
140         meters.append(
141             FloatMeter(
142                 name="loading_velocity",
143                 fmt="{:3.1f} img/s",
144                 show_avg=show_running_means,
145                 window_size=window_size,
146             )
147         )
148     if show_processing_velocity:
149         meters.append(
150             FloatMeter(
151                 name="processing_velocity",
152                 fmt="{:3.1f} img/s",
153                 show_avg=show_running_means,
154                 window_size=window_size,
155             )
156         )
157 
158     progress_meter = ProgressMeter(num_batches, *meters)
159 
160     def log_fn(batch, loss, loading_velocity, processing_velocity):
161         progress_meter.update(
162             batch,
163             loss=loss,
164             loading_velocity=loading_velocity,
165             processing_velocity=processing_velocity,
166         )
167 
168         if batch % log_freq == 0:
169             optim_logger.message(str(progress_meter))
170 
171     return log_fn
172 
173 
174 def default_epoch_header_fn(
175     epoch: int, optimizer: Optimizer, lr_scheduler: Optional[LRScheduler]
176 ):
177     return f"Epoch {epoch}"
178
```
--- 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/pystiche/optim/log.py b/pystiche/optim/log.py
--- a/pystiche/optim/log.py
+++ b/pystiche/optim/log.py
@@ -131,7 +131,7 @@
     show_running_means: bool = True,
 ):
     if log_freq is None:
-        log_freq = min(round(1e-3 * num_batches) * 10, 50)
+        log_freq = max(min(round(1e-3 * num_batches) * 10, 50), 1)
 
     window_size = min(10 * log_freq, 1000)

{"golden_diff": "diff --git a/pystiche/optim/log.py b/pystiche/optim/log.py\n--- a/pystiche/optim/log.py\n+++ b/pystiche/optim/log.py\n@@ -131,7 +131,7 @@\n     show_running_means: bool = True,\n ):\n     if log_freq is None:\n-        log_freq = min(round(1e-3 * num_batches) * 10, 50)\n+        log_freq = max(min(round(1e-3 * num_batches) * 10, 50), 1)\n \n     window_size = min(10 * log_freq, 1000)\n", "issue": "ZeroDivisionError with default_epoch_optim_loop\nI get an `ZeroDivisionError: integer division or modulo by zero` when using the `default_transformer_epoch_optim_loop`. This is probably because the `num_batches` of the `batch_sampler` is much smaller than in the `default_transformer_optim_loop` which results in `log_freq=0` in `default_transformer_optim_log_fn.` \r\n\r\nBelow is a minimal example to reproduce the error: \r\n```python\r\nfrom pystiche.optim.log import default_transformer_optim_log_fn, OptimLogger\r\n\r\nlogger = OptimLogger()\r\nnum_batches = 300\r\nlog_fn = default_transformer_optim_log_fn(logger, num_batches)\r\nimage_loading_velocity = 1\r\nimage_processing_velocity = 1\r\nbatch = 1\r\nloss = 1\r\nlog_fn(batch, loss, image_loading_velocity, image_processing_velocity)\r\n```\n", "before_files": [{"content": "from typing import Union, Optional, Tuple, Callable\nimport contextlib\nimport sys\nimport logging\nimport torch\nfrom torch.optim.optimizer import Optimizer\nfrom torch.optim.lr_scheduler import _LRScheduler as LRScheduler\nimport pystiche\nfrom pystiche.pyramid.level import PyramidLevel\nfrom .meter import FloatMeter, LossMeter, ProgressMeter\n\n__all__ = [\n    \"default_logger\",\n    \"OptimLogger\",\n    \"default_image_optim_log_fn\",\n    \"default_pyramid_level_header\",\n    \"default_transformer_optim_log_fn\",\n]\n\n\ndef default_logger(name: Optional[str] = None, log_file: Optional[str] = None):\n    logger = logging.getLogger(name)\n    logger.setLevel(logging.INFO)\n\n    fmt = logging.Formatter(\n        fmt=\"|%(asctime)s| %(message)s\", datefmt=\"%d.%m.%Y %H:%M:%S\"\n    )\n\n    sh = logging.StreamHandler(sys.stdout)\n    sh.setLevel(logging.INFO)\n    sh.addFilter(lambda record: record.levelno <= logging.INFO)\n    sh.setFormatter(fmt)\n    logger.addHandler(sh)\n\n    sh = logging.StreamHandler(sys.stderr)\n    sh.setLevel(logging.WARNING)\n    sh.setFormatter(fmt)\n    logger.addHandler(sh)\n\n    if log_file is not None:\n        fh = logging.FileHandler(log_file)\n        fh.setLevel(logging.INFO)\n        fh.setFormatter(fmt)\n        logger.addHandler(fh)\n\n    return logger\n\n\nclass OptimLogger:\n    INDENT = 2\n    SEP_LINE_LENGTH = 80\n    SEP_CHARS = (\"#\", \"=\", \"-\", \".\")\n\n    def __init__(self, logger: Optional[logging.Logger] = None):\n        if logger is None:\n            logger = default_logger()\n        self.logger = logger\n\n        self._environ_indent_offset = 0\n        self._environ_level_offset = 0\n\n    def _calc_abs_indent(self, indent: int, rel: bool):\n        abs_indent = indent\n        if rel:\n            abs_indent += self._environ_indent_offset\n        return abs_indent\n\n    def _calc_abs_level(self, level: int, rel: bool):\n        abs_level = level\n        if rel:\n            abs_level += self._environ_level_offset\n        return abs_level\n\n    def message(self, msg: str, indent: int = 0, rel=True) -> None:\n        abs_indent = self._calc_abs_indent(indent, rel)\n        for line in msg.splitlines():\n            self.logger.info(\" \" * abs_indent + line)\n\n    def sepline(self, level: int = 0, rel=True):\n        abs_level = self._calc_abs_level(level, rel)\n        self.message(self.SEP_CHARS[abs_level] * self.SEP_LINE_LENGTH)\n\n    def sep_message(\n        self, msg: str, level: int = 0, rel=True, top_sep=True, bottom_sep=True\n    ):\n        if top_sep:\n            self.sepline(level=level, rel=rel)\n        self.message(msg, rel=rel)\n        if bottom_sep:\n            self.sepline(level=level, rel=rel)\n\n    @contextlib.contextmanager\n    def environment(self, header: str):\n        self.sep_message(header)\n        self._environ_indent_offset += self.INDENT\n        self._environ_level_offset += 1\n        try:\n            yield\n        finally:\n            self._environ_level_offset -= 1\n            self._environ_indent_offset -= self.INDENT\n\n\ndef default_image_optim_log_fn(\n    optim_logger: OptimLogger, log_freq: int = 50, max_depth: int = 1\n) -> Callable[[int, Union[torch.Tensor, pystiche.LossDict]], None]:\n    def log_fn(step: int, loss: Union[torch.Tensor, pystiche.LossDict]) -> None:\n        if step % log_freq == 0:\n            with optim_logger.environment(f\"Step {step}\"):\n                if isinstance(loss, torch.Tensor):\n                    optim_logger.message(f\"loss: {loss.item():.3e}\")\n                else:  # isinstance(loss, pystiche.LossDict)\n                    optim_logger.message(loss.aggregate(max_depth).format())\n\n    return log_fn\n\n\ndef default_pyramid_level_header(\n    num: int, level: PyramidLevel, input_image_size: Tuple[int, int]\n):\n    height, width = input_image_size\n    return f\"Pyramid level {num} with {level.num_steps} steps \" f\"({width} x {height})\"\n\n\ndef default_transformer_optim_log_fn(\n    optim_logger: OptimLogger,\n    num_batches: int,\n    log_freq: Optional[int] = None,\n    show_loading_velocity: bool = True,\n    show_processing_velocity: bool = True,\n    show_running_means: bool = True,\n):\n    if log_freq is None:\n        log_freq = min(round(1e-3 * num_batches) * 10, 50)\n\n    window_size = min(10 * log_freq, 1000)\n\n    meters = [LossMeter(show_avg=show_running_means, window_size=window_size)]\n    if show_loading_velocity:\n        meters.append(\n            FloatMeter(\n                name=\"loading_velocity\",\n                fmt=\"{:3.1f} img/s\",\n                show_avg=show_running_means,\n                window_size=window_size,\n            )\n        )\n    if show_processing_velocity:\n        meters.append(\n            FloatMeter(\n                name=\"processing_velocity\",\n                fmt=\"{:3.1f} img/s\",\n                show_avg=show_running_means,\n                window_size=window_size,\n            )\n        )\n\n    progress_meter = ProgressMeter(num_batches, *meters)\n\n    def log_fn(batch, loss, loading_velocity, processing_velocity):\n        progress_meter.update(\n            batch,\n            loss=loss,\n            loading_velocity=loading_velocity,\n            processing_velocity=processing_velocity,\n        )\n\n        if batch % log_freq == 0:\n            optim_logger.message(str(progress_meter))\n\n    return log_fn\n\n\ndef default_epoch_header_fn(\n    epoch: int, optimizer: Optimizer, lr_scheduler: Optional[LRScheduler]\n):\n    return f\"Epoch {epoch}\"\n", "path": "pystiche/optim/log.py"}], "after_files": [{"content": "from typing import Union, Optional, Tuple, Callable\nimport contextlib\nimport sys\nimport logging\nimport torch\nfrom torch.optim.optimizer import Optimizer\nfrom torch.optim.lr_scheduler import _LRScheduler as LRScheduler\nimport pystiche\nfrom pystiche.pyramid.level import PyramidLevel\nfrom .meter import FloatMeter, LossMeter, ProgressMeter\n\n__all__ = [\n    \"default_logger\",\n    \"OptimLogger\",\n    \"default_image_optim_log_fn\",\n    \"default_pyramid_level_header\",\n    \"default_transformer_optim_log_fn\",\n]\n\n\ndef default_logger(name: Optional[str] = None, log_file: Optional[str] = None):\n    logger = logging.getLogger(name)\n    logger.setLevel(logging.INFO)\n\n    fmt = logging.Formatter(\n        fmt=\"|%(asctime)s| %(message)s\", datefmt=\"%d.%m.%Y %H:%M:%S\"\n    )\n\n    sh = logging.StreamHandler(sys.stdout)\n    sh.setLevel(logging.INFO)\n    sh.addFilter(lambda record: record.levelno <= logging.INFO)\n    sh.setFormatter(fmt)\n    logger.addHandler(sh)\n\n    sh = logging.StreamHandler(sys.stderr)\n    sh.setLevel(logging.WARNING)\n    sh.setFormatter(fmt)\n    logger.addHandler(sh)\n\n    if log_file is not None:\n        fh = logging.FileHandler(log_file)\n        fh.setLevel(logging.INFO)\n        fh.setFormatter(fmt)\n        logger.addHandler(fh)\n\n    return logger\n\n\nclass OptimLogger:\n    INDENT = 2\n    SEP_LINE_LENGTH = 80\n    SEP_CHARS = (\"#\", \"=\", \"-\", \".\")\n\n    def __init__(self, logger: Optional[logging.Logger] = None):\n        if logger is None:\n            logger = default_logger()\n        self.logger = logger\n\n        self._environ_indent_offset = 0\n        self._environ_level_offset = 0\n\n    def _calc_abs_indent(self, indent: int, rel: bool):\n        abs_indent = indent\n        if rel:\n            abs_indent += self._environ_indent_offset\n        return abs_indent\n\n    def _calc_abs_level(self, level: int, rel: bool):\n        abs_level = level\n        if rel:\n            abs_level += self._environ_level_offset\n        return abs_level\n\n    def message(self, msg: str, indent: int = 0, rel=True) -> None:\n        abs_indent = self._calc_abs_indent(indent, rel)\n        for line in msg.splitlines():\n            self.logger.info(\" \" * abs_indent + line)\n\n    def sepline(self, level: int = 0, rel=True):\n        abs_level = self._calc_abs_level(level, rel)\n        self.message(self.SEP_CHARS[abs_level] * self.SEP_LINE_LENGTH)\n\n    def sep_message(\n        self, msg: str, level: int = 0, rel=True, top_sep=True, bottom_sep=True\n    ):\n        if top_sep:\n            self.sepline(level=level, rel=rel)\n        self.message(msg, rel=rel)\n        if bottom_sep:\n            self.sepline(level=level, rel=rel)\n\n    @contextlib.contextmanager\n    def environment(self, header: str):\n        self.sep_message(header)\n        self._environ_indent_offset += self.INDENT\n        self._environ_level_offset += 1\n        try:\n            yield\n        finally:\n            self._environ_level_offset -= 1\n            self._environ_indent_offset -= self.INDENT\n\n\ndef default_image_optim_log_fn(\n    optim_logger: OptimLogger, log_freq: int = 50, max_depth: int = 1\n) -> Callable[[int, Union[torch.Tensor, pystiche.LossDict]], None]:\n    def log_fn(step: int, loss: Union[torch.Tensor, pystiche.LossDict]) -> None:\n        if step % log_freq == 0:\n            with optim_logger.environment(f\"Step {step}\"):\n                if isinstance(loss, torch.Tensor):\n                    optim_logger.message(f\"loss: {loss.item():.3e}\")\n                else:  # isinstance(loss, pystiche.LossDict)\n                    optim_logger.message(loss.aggregate(max_depth).format())\n\n    return log_fn\n\n\ndef default_pyramid_level_header(\n    num: int, level: PyramidLevel, input_image_size: Tuple[int, int]\n):\n    height, width = input_image_size\n    return f\"Pyramid level {num} with {level.num_steps} steps \" f\"({width} x {height})\"\n\n\ndef default_transformer_optim_log_fn(\n    optim_logger: OptimLogger,\n    num_batches: int,\n    log_freq: Optional[int] = None,\n    show_loading_velocity: bool = True,\n    show_processing_velocity: bool = True,\n    show_running_means: bool = True,\n):\n    if log_freq is None:\n        log_freq = max(min(round(1e-3 * num_batches) * 10, 50), 1)\n\n    window_size = min(10 * log_freq, 1000)\n\n    meters = [LossMeter(show_avg=show_running_means, window_size=window_size)]\n    if show_loading_velocity:\n        meters.append(\n            FloatMeter(\n                name=\"loading_velocity\",\n                fmt=\"{:3.1f} img/s\",\n                show_avg=show_running_means,\n                window_size=window_size,\n            )\n        )\n    if show_processing_velocity:\n        meters.append(\n            FloatMeter(\n                name=\"processing_velocity\",\n                fmt=\"{:3.1f} img/s\",\n                show_avg=show_running_means,\n                window_size=window_size,\n            )\n        )\n\n    progress_meter = ProgressMeter(num_batches, *meters)\n\n    def log_fn(batch, loss, loading_velocity, processing_velocity):\n        progress_meter.update(\n            batch,\n            loss=loss,\n            loading_velocity=loading_velocity,\n            processing_velocity=processing_velocity,\n        )\n\n        if batch % log_freq == 0:\n            optim_logger.message(str(progress_meter))\n\n    return log_fn\n\n\ndef default_epoch_header_fn(\n    epoch: int, optimizer: Optimizer, lr_scheduler: Optional[LRScheduler]\n):\n    return f\"Epoch {epoch}\"\n", "path": "pystiche/optim/log.py"}]}