Repository: Lightning-AI/pytorch-lightning

Issue:
Mismatch of displayed 'epoch'
## 🐛 Bug

The display of epoch's number mismatches between the progress bar and the checkpoint indicator. I wonder this mismatch could confuse users.

- progress bar: The number of epochs starts from 1.
- checkpoint indicator: The number of epochs starts from 0.
- metrics.csv also starts from 0.

I think that to change checkpoint and metrics.csv causes a serious problem.
So progress bar should be changed in my opinion.

What do you think about it?

```
Epoch 32: 100%|██████████| 331/331 [00:05<00:00, 88.73batch/s, batch_idx=17, loss=1.148, train_batch_loss=1.02, v_num=0, val_loss=1.05]
AINFO:root:
Epoch 00031: val_loss reached 1.04545 (best 1.04545), saving model to /dummy/version_0/checkpoints/_ckpt_epoch_31.ckpt as top 1
{'loss': 1.022357702255249, 'train_batch_loss': 1.022357702255249, 'val_loss': 1.0454469919204712}
Epoch 33:   5%|▌         | 18/331 [00:00<00:05, 61.06batch/s, batch_idx=17, loss=1.073, train_batch_loss=1.31, v_num=0, val_loss=1.05]
```

### Environment

 - PyTorch Version : 1.3.1
 - OS : macOS 10.14.6
 - How you installed PyTorch : `pip install git+https://github.com/williamFalcon/pytorch-lightning.git@master --upgrade`
 - Python version : 3.7.3
 - use CPU



Discussion:
Indeed, the inconsistency of zero-based/one-based epoch is very confusing.

I think we should use zero-based only.
@matthew-z i  agree it should be zero based.  want to submit a PR?
@onkyo14taro @matthew-z 
@williamFalcon I'll try this weekend.
@matthew-z @neggert  @williamFalcon @Borda

I found a 'one epoch'-based API in `GradientAccumulationScheduler` while I was fixing the code.
If we force the API and display to be zero-based, it will break backward compatibility.
However, I think that mixing 0 and 1 will confuse users than changing the API, it should be zero based.
I think it would be better we warn with FutureWarning in version 0.6.x, and then change the API and display to be zero-based in version 0.7.x.
What do you think about it?
I can't quite wrap my head around this. If you make it zero based, then when the progress bar shows 
Epoch 1: 50/100% 
it will no longer mean that the first epoch is in progress, but actually it is the second epoch 50% completed? Is this really what you want? Why should it be this way? 
@awaelchli 

I agree with you, but I think zero-based would be better than one-based.

Zero-based implementations are:
- Progress bar (_console display_)
- `GradientAccumulationScheduler` (_console display, API_)
- `EarlyStopping` (_console display_)

One-based implementations are:
- metrics.csv (_in the **file**_)
- \_ckpt_epoch_{0-based epoch number}.ckpt (_**file**name_)
- `ModelCheckpoint` (_console display_)

I think what of most influensive in these items are "metrics.csv" and "\_ckpt_epoch_{0-based epoch number}.ckpt."
That's because we usually use the result **file** rather than console display.
So I think that zero-based implementations have less confusion than one-based when breaking backward compatibility in order to unify representation of epoch numbers.
agreed. let’s do zero-based
@williamFalcon Is it ok that `FutureWarning` is thrown when Progress bar, `GradientAccumulationScheduler` or `EarlyStopping` are used in version 0.6.x , and then the API and display renew in version 0.7.0?
we are using `DeprecatedWarning` :]

Resolving patch:
diff --git a/pytorch_lightning/callbacks/pt_callbacks.py b/pytorch_lightning/callbacks/pt_callbacks.py
--- a/pytorch_lightning/callbacks/pt_callbacks.py
+++ b/pytorch_lightning/callbacks/pt_callbacks.py
@@ -174,6 +174,8 @@ def on_epoch_end(self, epoch, logs=None):
 
     def on_train_end(self, logs=None):
         if self.stopped_epoch > 0 and self.verbose > 0:
+            warnings.warn('Displayed epoch numbers by `EarlyStopping` start from "1" until v0.6.x,'
+                          ' but will start from "0" in v0.8.0.', DeprecationWarning)
             log.info(f'Epoch {self.stopped_epoch + 1:05d}: early stopping')
 
 
@@ -374,6 +376,7 @@ class GradientAccumulationScheduler(Callback):
 
     Args:
         scheduling (dict): scheduling in format {epoch: accumulation_factor}
+        warning:: Epochs indexing starts from "1" until v0.6.x, but will start from "0" in v0.8.0.
 
     Example::
 
@@ -394,6 +397,8 @@ def __init__(self, scheduling: dict):
                 raise TypeError("All epoches and accumulation factor must be integers")
 
         minimal_epoch = min(scheduling.keys())
+        warnings.warn('Epochs indexing of `scheduling` starts from "1" until v0.6.x,'
+                      ' but will start from "0" in v0.8.0.', DeprecationWarning)
         if minimal_epoch < 1:
             msg = f"Epochs indexing from 1, epoch {minimal_epoch} cannot be interpreted correct"
             raise IndexError(msg)
@@ -404,7 +409,9 @@ def __init__(self, scheduling: dict):
         self.epochs = sorted(scheduling.keys())
 
     def on_epoch_begin(self, epoch, trainer):
-        epoch += 1  # indexing epochs from 1
+        # indexing epochs from 1 (until v0.6.x)
+        # In v0.8.0, `epoch += 1` should be removed.
+        epoch += 1
         for i in reversed(range(len(self.epochs))):
             if epoch >= self.epochs[i]:
                 trainer.accumulate_grad_batches = self.scheduling.get(self.epochs[i])
diff --git a/pytorch_lightning/trainer/training_loop.py b/pytorch_lightning/trainer/training_loop.py
--- a/pytorch_lightning/trainer/training_loop.py
+++ b/pytorch_lightning/trainer/training_loop.py
@@ -281,6 +281,8 @@ def process_output(self, output, train):
         pass
 
     def train(self):
+        warnings.warn('Displayed epoch numbers in the progress bar start from "1" until v0.6.x,'
+                      ' but will start from "0" in v0.8.0.', DeprecationWarning)
         model = self.get_model()
         # run all epochs
         for epoch in range(self.current_epoch, self.max_epochs):


Test patch: