internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: pytorch/ignite

Issue:
[Docs] Provide TOC for core metrics
Currently, as there is a lot of different core metrics provided : https://pytorch.org/ignite/master/metrics.html a Table of Content is missing for better navigation.


Discussion:

Resolving patch:
diff --git a/ignite/contrib/handlers/polyaxon_logger.py b/ignite/contrib/handlers/polyaxon_logger.py
--- a/ignite/contrib/handlers/polyaxon_logger.py
+++ b/ignite/contrib/handlers/polyaxon_logger.py
@@ -31,7 +31,7 @@ class OutputHandler(BaseOutputHandler):
 
         Example with CustomPeriodicEvent, where model is evaluated every 500 iterations:
 
-        ..code-block:: python
+        .. code-block:: python
 
             from ignite.contrib.handlers import CustomPeriodicEvent
 
diff --git a/ignite/contrib/handlers/tensorboard_logger.py b/ignite/contrib/handlers/tensorboard_logger.py
--- a/ignite/contrib/handlers/tensorboard_logger.py
+++ b/ignite/contrib/handlers/tensorboard_logger.py
@@ -33,7 +33,7 @@ class OutputHandler(BaseOutputHandler):
 
         Example with CustomPeriodicEvent, where model is evaluated every 500 iterations:
 
-        ..code-block:: python
+        .. code-block:: python
 
             from ignite.contrib.handlers import CustomPeriodicEvent
 
diff --git a/ignite/contrib/handlers/visdom_logger.py b/ignite/contrib/handlers/visdom_logger.py
--- a/ignite/contrib/handlers/visdom_logger.py
+++ b/ignite/contrib/handlers/visdom_logger.py
@@ -82,7 +82,7 @@ class OutputHandler(BaseOutputHandler, _BaseVisDrawer):
 
         Example with CustomPeriodicEvent, where model is evaluated every 500 iterations:
 
-        ..code-block:: python
+        .. code-block:: python
 
             from ignite.contrib.handlers import CustomPeriodicEvent
 


Test patch:
Repository: pytorch/ignite

Issue:
BaseWeightsScalarHandler has side effects on random number generation
### Problem
BaseWeightsScalarHandler uses `torch.rand` to test the reduction function that is passed as an argument. 
This is very confusing, because experiments are not reproducible when tensorboard logging is switched on or off, e.g. in debug sessions. 

### Solution
Replace the random tensor with a non random tensor. 




Discussion:
@Bibonaut no problem, please send a PR for that :)

Resolving patch:
diff --git a/ignite/contrib/handlers/base_logger.py b/ignite/contrib/handlers/base_logger.py
--- a/ignite/contrib/handlers/base_logger.py
+++ b/ignite/contrib/handlers/base_logger.py
@@ -142,8 +142,8 @@ def __init__(self, model, reduction=torch.norm, tag=None):
         def _is_0D_tensor(t):
             return isinstance(t, torch.Tensor) and t.ndimension() == 0
 
-        # Test reduction function on a random tensor
-        o = reduction(torch.rand(4, 2))
+        # Test reduction function on a tensor
+        o = reduction(torch.ones(4, 2))
         if not (isinstance(o, numbers.Number) or _is_0D_tensor(o)):
             raise ValueError("Output of the reduction function should be a scalar, but got {}".format(type(o)))
 


Test patch:
Repository: pytorch/ignite

Issue:
Switch website theme to PyTorch?
I am updating the docs theme to leverage [pytorch_sphinx_theme](https://github.com/pytorch/pytorch_sphinx_theme) so that Ignite docs look like PyTorch's. The diffs are minimal.

Pros:
- closer to PyTorch
- darkifiable with existing Userstyles (see screenshots)

Caveats:
- pytorch_sphinx_theme comes with footers that are not really relevant to Ignite, and I could not yet find a way to alter them.
- the links to various Ignite versions are eaten by some monster somewhere

Here are some screenshots (built with `make html` or with `sphinx-versioning ...`). What is your opinion? Should I open a PR?

## some text and code (that look nice IMO)

<img width="1348" alt="Screenshot 2019-09-14 at 20 00 54" src="https://user-images.githubusercontent.com/1936828/64912083-697e6480-d72a-11e9-8712-1bbbe64aab4b.png">

<img width="1348" alt="Screenshot 2019-09-14 at 19 44 04" src="https://user-images.githubusercontent.com/1936828/64912055-1f957e80-d72a-11e9-9478-2ae7e4891a50.png">

## the main caveat: PyTorch footer (irrelevant to Ignite)

<img width="1348" alt="Screenshot 2019-09-14 at 20 02 23" src="https://user-images.githubusercontent.com/1936828/64912094-9763a900-d72a-11e9-9eae-30cc55e67c59.png">




Discussion:

Resolving patch:
diff --git a/docs/source/conf.py b/docs/source/conf.py
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -16,12 +16,12 @@
 import sys
 sys.path.insert(0, os.path.abspath('../..'))
 import ignite
-import sphinx_rtd_theme
+import pytorch_sphinx_theme
 
 # -- Project information -----------------------------------------------------
 
 project = 'ignite'
-copyright = '2018, Torch Contributors'
+copyright = '2019, Torch Contributors'
 author = 'Torch Contributors'
 
 # The short X.Y version
@@ -91,10 +91,11 @@
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
 #
-html_theme = 'sphinx_rtd_theme'
-html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+html_theme = 'pytorch_sphinx_theme'
+html_theme_path = [pytorch_sphinx_theme.get_html_theme_path()]
 
 html_theme_options = {
+    'canonical_url': 'https://pytorch.org/ignite/index.html',
     'collapse_navigation': False,
     'display_version': True,
     'logo_only': True,
@@ -111,12 +112,13 @@
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ['_static', '_templates/_static']
 
 html_context = {
     'css_files': [
-        'https://fonts.googleapis.com/css?family=Lato',
-        '_static/css/pytorch_theme.css'
+        # 'https://fonts.googleapis.com/css?family=Lato',
+        # '_static/css/pytorch_theme.css'
+        '_static/css/ignite_theme.css'
     ],
 }
 


Test patch:
Repository: pytorch/ignite

Issue:
Dynamic Typing
Sometimes there are types assumed and hardcoded, where it is not necessary.

For example there is [this part](https://github.com/pytorch/ignite/blob/master/ignite/engine/engine.py#L971) where we should infer the previous type of the data loader and re-use this. 
Other examples include type specific operations. E.g. we often check for mappings in general but then we only create dicts after doing some operations without restoring the original type. 

I will go through the core package and change this.


Discussion:

Resolving patch:
diff --git a/ignite/engine/engine.py b/ignite/engine/engine.py
--- a/ignite/engine/engine.py
+++ b/ignite/engine/engine.py
@@ -974,7 +974,7 @@ def _update_dataloader(dataloader, new_batch_sampler):
             params_keys.remove(k)
     params = {k: getattr(dataloader, k) for k in params_keys}
     params['batch_sampler'] = new_batch_sampler
-    return torch.utils.data.DataLoader(**params)
+    return type(dataloader)(**params)
 
 
 class ReproducibleBatchSampler(torch.utils.data.sampler.BatchSampler):
diff --git a/ignite/utils.py b/ignite/utils.py
--- a/ignite/utils.py
+++ b/ignite/utils.py
@@ -34,9 +34,9 @@ def apply_to_type(input_, input_type, func):
     elif isinstance(input_, (str, bytes)):
         return input_
     elif isinstance(input_, collections.Mapping):
-        return {k: apply_to_type(sample, input_type, func) for k, sample in input_.items()}
+        return type(input_)({k: apply_to_type(sample, input_type, func) for k, sample in input_.items()})
     elif isinstance(input_, collections.Sequence):
-        return [apply_to_type(sample, input_type, func) for sample in input_]
+        return type(input_)([apply_to_type(sample, input_type, func) for sample in input_])
     else:
         raise TypeError(("input must contain {}, dicts or lists; found {}"
                          .format(input_type, type(input_))))


Test patch:
diff --git a/tests/ignite/test_utils.py b/tests/ignite/test_utils.py
--- a/tests/ignite/test_utils.py
+++ b/tests/ignite/test_utils.py
@@ -19,12 +19,18 @@ def test_convert_tensor():
     tensor = convert_tensor(x, device='cpu', non_blocking=False)
     assert torch.is_tensor(tensor)
 
-    x = (torch.tensor([0.0]), torch.tensor([0.0]))
+    x = [torch.tensor([0.0]), torch.tensor([0.0])]
     list_ = convert_tensor(x)
     assert isinstance(list_, list)
     assert torch.is_tensor(list_[0])
     assert torch.is_tensor(list_[1])
 
+    x = (torch.tensor([0.0]), torch.tensor([0.0]))
+    tuple_ = convert_tensor(x)
+    assert isinstance(tuple_, tuple)
+    assert torch.is_tensor(tuple_[0])
+    assert torch.is_tensor(tuple_[1])
+
     x = {'a': torch.tensor([0.0]), 'b': torch.tensor([0.0])}
     dict_ = convert_tensor(x)
     assert isinstance(dict_, dict)
Repository: pytorch/ignite

Issue:
RuntimeWarning: Only one class present in y_true. ROC AUC score is not defined in that case..
Hi, I am using ROC_AUC metric to track the training performance. However, this warning frequently appears:

> RuntimeWarning: Probably, there can be a problem with `compute_fn`: Only one class present in y_true. ROC AUC score is not defined in that case.

It seems the ROC_AUC compute_fn will be called every time we update the (y, y_pred) accumulator. In my scenario, it's possible that one batch only contains negative samples (unbalanced classes). So this warning may be annoying. 

Is there any way to disable this warning? Or whether it's better to change the behavior of this sanity check for the AUC calculation? (e.g. check the label/pred type after collecting all the data) 

Appreciate your help!


Discussion:
@wangyirui I see your problem and agree that such warnings can be annoying. 
Normally, such warning you should see once at the first update only. Idea of this sanity check is to avoid some exceptions raised (some typos, bugs) after iterating over complete epoch which can take time.

What can we do from your side is to replace that `RuntimeWarning` warning by a specific warning `EpochMetricWarning` and which can be then filtered with 
```
import warnings
warnings.filterwarnings('ignore', category=EpochMetricWarning)
```
@vfdev-5 Thanks for your suggestion! I will do so from my end.

Is it possible to change the behavior officially in the next version? Thanks!
Yes, I can do this rather quickly. And it can be available in next nightly releases.
@vfdev-5 Appreciate it!

Resolving patch:
diff --git a/ignite/metrics/epoch_metric.py b/ignite/metrics/epoch_metric.py
--- a/ignite/metrics/epoch_metric.py
+++ b/ignite/metrics/epoch_metric.py
@@ -80,7 +80,11 @@ def update(self, output):
                 self.compute_fn(self._predictions, self._targets)
             except Exception as e:
                 warnings.warn("Probably, there can be a problem with `compute_fn`:\n {}.".format(e),
-                              RuntimeWarning)
+                              EpochMetricWarning)
 
     def compute(self):
         return self.compute_fn(self._predictions, self._targets)
+
+
+class EpochMetricWarning(UserWarning):
+    pass


Test patch:
diff --git a/tests/ignite/metrics/test_epoch_metric.py b/tests/ignite/metrics/test_epoch_metric.py
--- a/tests/ignite/metrics/test_epoch_metric.py
+++ b/tests/ignite/metrics/test_epoch_metric.py
@@ -2,6 +2,7 @@
 import torch
 
 from ignite.metrics import EpochMetric
+from ignite.metrics.epoch_metric import EpochMetricWarning
 
 import pytest
 
@@ -113,7 +114,7 @@ def compute_fn(y_preds, y_targets):
 
     em.reset()
     output1 = (torch.rand(4, 3), torch.randint(0, 2, size=(4, 4), dtype=torch.long))
-    with pytest.warns(RuntimeWarning):
+    with pytest.warns(EpochMetricWarning, match=r"Probably, there can be a problem with `compute_fn`"):
         em.update(output1)
Repository: pytorch/ignite

Issue:
correct the type hints of this function
https://github.com/pytorch/ignite/blob/ca738d8f3f106093aa04b6bce9506129a1059df8/ignite/engine/events.py#L81

this really should read

`    def wrapper(engine, event: int) -> bool:`


Discussion:
@CDitzel Thanks for the feedback! 
@justusschock could you please take a look on that.
Yep, that's right. I'll fix that

Resolving patch:
diff --git a/ignite/engine/events.py b/ignite/engine/events.py
--- a/ignite/engine/events.py
+++ b/ignite/engine/events.py
@@ -77,7 +77,7 @@ def __call__(self, event_filter: Optional[Callable] = None,
 
     @staticmethod
     def every_event_filter(every: int) -> Callable:
-        def wrapper(engine, event: bool):
+        def wrapper(engine, event: int) -> bool:
             if event % every == 0:
                 return True
             return False


Test patch:
Repository: pytorch/ignite

Issue:
log_message() method fails `desc` is passed to contrib tqdm
## 🐛 Bug description

If I pass a `desc` argument when instantiating a `ignite.contrib.handlers.ProgressBar` the calls to its `log_message()` method fail with this exception:

```
TypeError: write() got an unexpected keyword argument 'desc'
```

## Environment

 - PyTorch Version: 1.3.1
 - Ignite Version: 0.3.0
 - OS: Linux
 - How you installed Ignite (`conda`, `pip`, source): Conda
 - Python version: 3.7
 - Any other relevant information:




Discussion:
@mi-lad could you please provide installed tqdm version ?
@maxfrei750 could you please take a look at this issue as it is most probably related to your pull request https://github.com/pytorch/ignite/pull/695 ? thanks
tqdm version: 4.36.1
The reason for the error is, that not all optional arguments of tqdm are valid for the write method as well. I'm going to write a fix and make a PR.

Resolving patch:
diff --git a/ignite/contrib/handlers/tqdm_logger.py b/ignite/contrib/handlers/tqdm_logger.py
--- a/ignite/contrib/handlers/tqdm_logger.py
+++ b/ignite/contrib/handlers/tqdm_logger.py
@@ -146,7 +146,8 @@ def log_message(self, message):
             message (str): string you wish to log.
         """
         from tqdm import tqdm
-        tqdm.write(message, **self.tqdm_kwargs)
+
+        tqdm.write(message, file=self.tqdm_kwargs.get("file", None))
 
     def attach(self, engine, metric_names=None, output_transform=None,
                event_name=Events.ITERATION_COMPLETED,


Test patch:
diff --git a/tests/ignite/contrib/handlers/test_tqdm_logger.py b/tests/ignite/contrib/handlers/test_tqdm_logger.py
--- a/tests/ignite/contrib/handlers/test_tqdm_logger.py
+++ b/tests/ignite/contrib/handlers/test_tqdm_logger.py
@@ -36,6 +36,27 @@ def test_pbar(capsys):
     assert err[-1] == expected
 
 
+def test_pbar_file(tmp_path):
+    n_epochs = 2
+    loader = [1, 2]
+    engine = Engine(update_fn)
+
+    file_path = tmp_path / "temp.txt"
+    file = open(str(file_path), "w+")
+
+    pbar = ProgressBar(file=file)
+    pbar.attach(engine, ['a'])
+    engine.run(loader, max_epochs=n_epochs)
+
+    file.close()  # Force a flush of the buffer. file.flush() does not work.
+
+    file = open(str(file_path), "r")
+    lines = file.readlines()
+
+    expected = u"Epoch [2/2]: [1/2]  50%|█████     , a=1 [00:00<00:00]\n"
+    assert lines[-2] == expected
+
+
 def test_pbar_log_message(capsys):
     pbar = ProgressBar()
 
@@ -49,6 +70,22 @@ def test_pbar_log_message(capsys):
     assert out[-1] == expected
 
 
+def test_pbar_log_message_file(tmp_path):
+    file_path = tmp_path / "temp.txt"
+    file = open(str(file_path), "w+")
+
+    pbar = ProgressBar(file=file)
+    pbar.log_message("test")
+
+    file.close()  # Force a flush of the buffer. file.flush() does not work.
+
+    file = open(str(file_path), "r")
+    lines = file.readlines()
+
+    expected = u"test\n"
+    assert lines[0] == expected
+
+
 def test_attach_fail_with_string():
     engine = Engine(update_fn)
     pbar = ProgressBar()
Repository: pytorch/ignite

Issue:
Add example notebooks to Google Colab
Similar to Pytorch [examples](https://pytorch.org/tutorials/), we should try to port most of the ignite examples (at least all the notebooks) to be runnable in Google Colab. This way it becomes more accessible to new users.

We could add an [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/googlecolab/colabtools/blob/master/notebooks/colab-github-demo.ipynb) badge next to the links to notebooks in the Readme as described [here](https://colab.research.google.com/github/googlecolab/colabtools/blob/master/notebooks/colab-github-demo.ipynb).


Discussion:
Totally agree with this !

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,7 @@ def find_version(*file_paths):
     raise RuntimeError("Unable to find version string.")
 
 
-readme = read("README.rst")
+readme = read("README.md")
 
 VERSION = find_version("ignite", "__init__.py")
 
@@ -33,6 +33,7 @@ def find_version(*file_paths):
     author_email="soumith@pytorch.org",
     url="https://github.com/pytorch/ignite",
     description="A lightweight library to help with training neural networks in PyTorch.",
+    long_description_content_type="text/markdown",
     long_description=readme,
     license="BSD",
     # Package info


Test patch:
Repository: pytorch/ignite

Issue:
Typehint of ignite._utils._to_hours_mins_secs  not satisfied with float
## 🐛 Bug description

That is a so tiny bug. The `typehint` of the following function of `ignite._utils` is not satisfied with a `float` argument
``` python
def _to_hours_mins_secs(time_taken: Union[float, int]) -> Tuple[int, int, int]:
    """Convert seconds to hours, mins, and seconds."""
    mins, secs = divmod(time_taken, 60)
    hours, mins = divmod(mins, 60)
    return hours, mins, secs
```
We have
```python
>>> divmod(10.0,2)
(5.0, 0.0)
```

## Environment

 - PyTorch Version (e.g., 1.4): 1.4
 - Ignite Version (e.g., 0.3.0): 0.3.0
 - OS (e.g., Linux): Linux
 - How you installed Ignite (`conda`, `pip`, source): conda
 - Python version: 3.7
 - Any other relevant information:




Discussion:
@sdesrozis please send a PR to fix it :) I think there could be others like that. I think typing issue is not completely done.

Resolving patch:
diff --git a/ignite/_utils.py b/ignite/_utils.py
--- a/ignite/_utils.py
+++ b/ignite/_utils.py
@@ -8,4 +8,4 @@ def _to_hours_mins_secs(time_taken: Union[float, int]) -> Tuple[int, int, int]:
     """Convert seconds to hours, mins, and seconds."""
     mins, secs = divmod(time_taken, 60)
     hours, mins = divmod(mins, 60)
-    return hours, mins, secs
+    return round(hours), round(mins), round(secs)


Test patch:
Repository: pytorch/ignite

Issue:
Bug with average="recall" in Confusion matrix
## 🐛 Bug description

```python
from ignite.metrics import ConfusionMatrix


cm = ConfusionMatrix(num_classes=3, average="recall")

cm.confusion_matrix[0, 0] = 50
cm.confusion_matrix[0, 1] = 50
cm.confusion_matrix[0, 2] = 50

cm.confusion_matrix[1, 0] = 24
cm.confusion_matrix[1, 1] = 56
cm.confusion_matrix[1, 2] = 78

cm.confusion_matrix[2, 0] = 54
cm.confusion_matrix[2, 1] = 32
cm.confusion_matrix[2, 2] = 21

print(cm.confusion_matrix)

cm._num_examples = 1
res = cm.compute()
print("Wrong result:", res)
print(res.sum(dim=1))

res2 = cm.confusion_matrix / (cm.confusion_matrix.sum(dim=1).unsqueeze(1) + 1e-15)
print("True result:", res2)
print(res2.sum(dim=1))
```
gives
```
tensor([[50, 50, 50],
        [24, 56, 78],
        [54, 32, 21]])
Wrong: tensor([[0.3333, 0.3165, 0.4673],
        [0.1600, 0.3544, 0.7290],
        [0.3600, 0.2025, 0.1963]])
tensor([1.1171, 1.2434, 0.7588])
True: tensor([[0.3333, 0.3333, 0.3333],
        [0.1519, 0.3544, 0.4937],
        [0.5047, 0.2991, 0.1963]])
tensor([1., 1., 1.])
```

## Environment

 - PyTorch Version (e.g., 1.4): 1.4
 - Ignite Version (e.g., 0.3.0): 0.4.0.dev20200302
 - OS (e.g., Linux): Linux
 - How you installed Ignite (`conda`, `pip`, source): pip
 - Python version: 3.7
 - Any other relevant information:




Discussion:

Resolving patch:
diff --git a/ignite/metrics/confusion_matrix.py b/ignite/metrics/confusion_matrix.py
--- a/ignite/metrics/confusion_matrix.py
+++ b/ignite/metrics/confusion_matrix.py
@@ -120,7 +120,7 @@ def compute(self) -> torch.Tensor:
             if self.average == "samples":
                 return self.confusion_matrix / self._num_examples
             elif self.average == "recall":
-                return self.confusion_matrix / (self.confusion_matrix.sum(dim=1) + 1e-15)
+                return self.confusion_matrix / (self.confusion_matrix.sum(dim=1).unsqueeze(1) + 1e-15)
             elif self.average == "precision":
                 return self.confusion_matrix / (self.confusion_matrix.sum(dim=0) + 1e-15)
         return self.confusion_matrix


Test patch:
diff --git a/tests/ignite/metrics/test_confusion_matrix.py b/tests/ignite/metrics/test_confusion_matrix.py
--- a/tests/ignite/metrics/test_confusion_matrix.py
+++ b/tests/ignite/metrics/test_confusion_matrix.py
@@ -465,12 +465,20 @@ def test_cm_with_average():
     res = cm.compute().numpy().diagonal()
     np.testing.assert_almost_equal(true_re, res)
 
+    res = cm.compute().numpy()
+    true_res = confusion_matrix(np_y, np_y_pred, normalize="true")
+    np.testing.assert_almost_equal(true_res, res)
+
     cm = ConfusionMatrix(num_classes=num_classes, average="precision")
     cm.update((y_pred, y))
     true_pr = precision_score(np_y, np_y_pred, average=None, labels=list(range(num_classes)))
     res = cm.compute().numpy().diagonal()
     np.testing.assert_almost_equal(true_pr, res)
 
+    res = cm.compute().numpy()
+    true_res = confusion_matrix(np_y, np_y_pred, normalize="pred")
+    np.testing.assert_almost_equal(true_res, res)
+
 
 def test_dice_coefficient_wrong_input():
Repository: pytorch/ignite

Issue:
Update mnist example
## 🚀 Feature

Please update the mnist [example](https://github.com/pytorch/ignite/tree/master/examples/mnist) `mnist_with_tensorboardx.py`. Rather than depend on an external library (tensorboardX), it would be nice to have an example that utilizes the [built-in](https://pytorch.org/docs/stable/tensorboard.html) version of PyTorch.


Discussion:
Yes, that's true, but unfortunately this would limit the users to a certain PyTorch version. But we can use a conditional import there and first check, whether the PyTorch version will be recent enough.
@justusschock you mean something in the idea of what is done in `tensorboard_logger.py` ?
https://github.com/pytorch/ignite/blob/587644fa7ff506323b58a62e4399d798c76b9ce5/ignite/contrib/handlers/tensorboard_logger.py#L446-L456

Resolving patch:
diff --git a/examples/mnist/mnist_with_tensorboardx.py b/examples/mnist/mnist_with_tensorboard.py
similarity index 91%
rename from examples/mnist/mnist_with_tensorboardx.py
rename to examples/mnist/mnist_with_tensorboard.py
--- a/examples/mnist/mnist_with_tensorboardx.py
+++ b/examples/mnist/mnist_with_tensorboard.py
@@ -1,7 +1,8 @@
 """
- MNIST example with training and validation monitoring using TensorboardX and Tensorboard.
+ MNIST example with training and validation monitoring using Tensorboard.
  Requirements:
     TensorboardX (https://github.com/lanpa/tensorboard-pytorch): `pip install tensorboardX`
+    or PyTorch >= 1.2 which supports Tensorboard
     Tensorboard: `pip install tensorflow` (or just install tensorboard without the rest of tensorflow)
  Usage:
     Start tensorboard:
@@ -10,7 +11,7 @@
     ```
     Run the example:
     ```bash
-    python mnist_with_tensorboardx.py --log_dir=/tmp/tensorboard_logs
+    python mnist_with_tensorboard.py --log_dir=/tmp/tensorboard_logs
     ```
 """
 
@@ -26,7 +27,14 @@
 try:
     from tensorboardX import SummaryWriter
 except ImportError:
-    raise RuntimeError("No tensorboardX package is found. Please install with the command: \npip install tensorboardX")
+    try:
+        from torch.utils.tensorboard import SummaryWriter
+    except ImportError:
+        raise RuntimeError(
+            "This module requires either tensorboardX or torch >= 1.2.0. "
+            "You may install tensorboardX with command: \n pip install tensorboardX \n"
+            "or upgrade PyTorch using your package manager of choice (pip or conda)."
+        )
 
 from ignite.engine import Events, create_supervised_trainer, create_supervised_evaluator
 from ignite.metrics import Accuracy, Loss


Test patch: