Repository: Lightning-AI/pytorch-lightning

Issue:
Disabling validation with val_percent_check=0.0 not working
<!-- 
### Common bugs:
1. Tensorboard not showing in Jupyter-notebook see [issue 79](https://github.com/PyTorchLightning/pytorch-lightning/issues/79).    
2. PyTorch 1.1.0 vs 1.2.0 support [see FAQ](https://github.com/PyTorchLightning/pytorch-lightning#faq)    
-->

## 🐛 Bug

I am trying to train on a small subset of data by settting `train_percent_check` and `val_percent_check` flags. I am not able to disable validation by setting `ver_percent_check=0.0`. Despite it being set to 0, `validation_epoch_end` is executed. 

<!-- A clear and concise description of what the bug is. -->

### To Reproduce

Steps to reproduce the behavior: Running the MNIST model on the Google Colab link

<!-- If you have a code sample, error messages, stack traces, please provide it here as well -->

<img width="1068" alt="Screen Shot 2020-03-26 at 11 06 16 AM" src="https://user-images.githubusercontent.com/4838833/77662280-0c256480-6f52-11ea-873c-7a9d41bf347c.png">


#### Code sample
<!-- Ideally attach a minimal code sample to reproduce the decried issue. 
Minimal means having the shortest code but still preserving the bug. -->
```
mnist_model = MNISTModel()

# most basic trainer, uses good defaults (1 gpu)
trainer = pl.Trainer(gpus=1, val_percent_check=0.0, train_percent_check=0.1)    
trainer.fit(mnist_model)
```

### Expected behavior

<!-- A clear and concise description of what you expected to happen. -->

I expected the `validation_epoch_end` to not be invoked but it is.

### Environment

Running on Google Colab with the sample MNIST tutorial



Discussion:
Hi! thanks for your contribution!, great first issue!
I can confirm there is an issue. I tested it with the pl_example gpu template on master. I get a different error: 
```
...
  File "C:\Users\aeduw\Documents\Repositories\pytorch-lightning\pytorch_lightning\trainer\training_loop.py", line 437, in run_training_epoch
    self.run_evaluation(test_mode=self.testing)
  File "C:\Users\aeduw\Documents\Repositories\pytorch-lightning\pytorch_lightning\trainer\evaluation_loop.py", line 368, in run_evaluation
    eval_results = self.evaluate(self.model, dataloaders, max_batches, test_mode)
  File "C:\Users\aeduw\Documents\Repositories\pytorch-lightning\pytorch_lightning\trainer\evaluation_loop.py", line 312, in evaluate
    eval_results = model.validation_epoch_end(outputs)
  File "C:\Users\aeduw\Documents\Repositories\pytorch-lightning\pl_examples\basic_examples\lightning_module_template.py", line 190, in validation_epoch_end
    val_loss_mean /= len(outputs)
ZeroDivisionError: division by zero
```
I think I know how to fix it and will submit a PR soon + unit test.

Resolving patch:
diff --git a/pytorch_lightning/trainer/trainer.py b/pytorch_lightning/trainer/trainer.py
--- a/pytorch_lightning/trainer/trainer.py
+++ b/pytorch_lightning/trainer/trainer.py
@@ -876,7 +876,8 @@ def run_pretrain_routine(self, model: LightningModule):
             return
 
         # check if we should run validation during training
-        self.disable_validation = not self.is_overriden('validation_step') and not self.fast_dev_run
+        self.disable_validation = not (self.is_overriden('validation_step') and self.val_percent_check > 0) \
+            and not self.fast_dev_run
 
         # run tiny validation (if validation defined)
         # to make sure program won't crash during val


Test patch:
diff --git a/tests/models/test_cpu.py b/tests/models/test_cpu.py
--- a/tests/models/test_cpu.py
+++ b/tests/models/test_cpu.py
@@ -14,6 +14,7 @@
     LightTrainDataloader,
     LightningTestModel,
     LightTestMixin,
+    LightValidationMixin
 )
 
 
@@ -156,6 +157,55 @@ class CurrentTestModel(LightTrainDataloader, LightTestMixin, TestModelBase):
     tutils.assert_ok_model_acc(trainer)
 
 
+def test_disabled_validation():
+    """Verify that `val_percent_check=0` disables the validation loop unless `fast_dev_run=True`."""
+    tutils.reset_seed()
+
+    class CurrentModel(LightTrainDataloader, LightValidationMixin, TestModelBase):
+
+        validation_step_invoked = False
+        validation_end_invoked = False
+
+        def validation_step(self, *args, **kwargs):
+            self.validation_step_invoked = True
+            return super().validation_step(*args, **kwargs)
+
+        def validation_end(self, *args, **kwargs):
+            self.validation_end_invoked = True
+            return super().validation_end(*args, **kwargs)
+
+    hparams = tutils.get_default_hparams()
+    model = CurrentModel(hparams)
+
+    trainer_options = dict(
+        show_progress_bar=False,
+        max_epochs=2,
+        train_percent_check=0.4,
+        val_percent_check=0.0,
+        fast_dev_run=False,
+    )
+
+    trainer = Trainer(**trainer_options)
+    result = trainer.fit(model)
+
+    # check that val_percent_check=0 turns off validation
+    assert result == 1, 'training failed to complete'
+    assert trainer.current_epoch == 1
+    assert not model.validation_step_invoked, '`validation_step` should not run when `val_percent_check=0`'
+    assert not model.validation_end_invoked, '`validation_end` should not run when `val_percent_check=0`'
+
+    # check that val_percent_check has no influence when fast_dev_run is turned on
+    model = CurrentModel(hparams)
+    trainer_options.update(fast_dev_run=True)
+    trainer = Trainer(**trainer_options)
+    result = trainer.fit(model)
+
+    assert result == 1, 'training failed to complete'
+    assert trainer.current_epoch == 0
+    assert model.validation_step_invoked, 'did not run `validation_step` with `fast_dev_run=True`'
+    assert model.validation_end_invoked, 'did not run `validation_end` with `fast_dev_run=True`'
+
+
 def test_single_gpu_batch_parse():
     tutils.reset_seed()