From 5875fadc67f698f9ab4d707ccda5ede0c203b9ca Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 07:26:18 -0400 Subject: [PATCH 001/222] added cpu model test --- .../new_project_templates/lightning_module_template.py | 2 +- pytorch_lightning/models/trainer.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index 7f5459e1..df7dbe32 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -108,7 +108,7 @@ class LightningTemplateModel(LightningModule): output = OrderedDict({ 'val_loss': loss_val, - 'val_acc': torch.tensor(val_acc).cuda(loss_val.device.index), + 'val_acc': torch.tensor(val_acc).type(loss_val.dtype), }) # can also return just a scalar instead of a dict (return loss_val) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index fea7213e..b7f8fbe7 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -436,6 +436,10 @@ class Trainer(TrainerIO): self.__run_pretrain_routine(model) + # return 1 when finished + # used for testing or when we need to know that training succeeded + return 1 + def dp_train(self, model): # CHOOSE OPTIMIZER From b59866f8557292586fd592fbf1611b7c44405506 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 08:31:57 -0400 Subject: [PATCH 002/222] added cpu, gpu tests --- __init__.py | 0 pytorch_lightning/examples/__init__.py | 1 + tests/test_models.py | 92 ++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 __init__.py create mode 100644 pytorch_lightning/examples/__init__.py create mode 100644 tests/test_models.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pytorch_lightning/examples/__init__.py b/pytorch_lightning/examples/__init__.py new file mode 100644 index 00000000..6743d7f9 --- /dev/null +++ b/pytorch_lightning/examples/__init__.py @@ -0,0 +1 @@ +from .new_project_templates.lightning_module_template import LightningTemplateModel \ No newline at end of file diff --git a/tests/test_models.py b/tests/test_models.py new file mode 100644 index 00000000..5dec59a5 --- /dev/null +++ b/tests/test_models.py @@ -0,0 +1,92 @@ +import pytest +from pytorch_lightning import Trainer +from pytorch_lightning.examples.new_project_templates.lightning_module_template import LightningTemplateModel +from argparse import Namespace +from test_tube import Experiment +import os + + +def get_model(): + root_dir = os.path.dirname(os.path.realpath(__file__)) + hparams = Namespace(**{'drop_prob': 0.2, + 'batch_size': 32, + 'in_features': 28*28, + 'learning_rate': 0.001*8, + 'optimizer_name': 'adam', + 'data_root': os.path.join(root_dir, 'mnist'), + 'out_features': 10, + 'hidden_dim': 1000}) + model = LightningTemplateModel(hparams) + + return model + +def get_exp(): + exp = Experiment(debug=True) + return exp + +def test_cpu_model(): + model = get_model() + + trainer = Trainer( + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + result = trainer.fit(model) + + assert result == 1 + + +def test_single_gpu_model(): + model = get_model() + + trainer = Trainer( + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4, + gpus=[0] + ) + + result = trainer.fit(model) + + assert result == 1 + + +def test_multi_gpu_model_dp(): + model = get_model() + + trainer = Trainer( + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4, + gpus=[0, 1] + ) + + result = trainer.fit(model) + + assert result == 1 + + +def test_multi_gpu_model_ddp(): + model = get_model() + + trainer = Trainer( + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4, + gpus=[0, 1], + distributed_backend='ddp' + ) + + result = trainer.fit(model) + + assert result == 1 + + +if __name__ == '__main__': + pytest.main([__file__]) From 6ad542e2b6831ad2cc548e4aed361a98402cf1f7 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 08:44:00 -0400 Subject: [PATCH 003/222] added gpu check for each gpu test --- tests/test_models.py | 93 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index 5dec59a5..36bc87bf 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -3,6 +3,8 @@ from pytorch_lightning import Trainer from pytorch_lightning.examples.new_project_templates.lightning_module_template import LightningTemplateModel from argparse import Namespace from test_tube import Experiment +import warnings +import torch import os @@ -36,10 +38,21 @@ def test_cpu_model(): result = trainer.fit(model) + metrics = result.__tng_tqdm_dic + print(metrics) + assert result == 1 def test_single_gpu_model(): + """ + Make sure single GPU works (DP mode) + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') + return + model = get_model() trainer = Trainer( @@ -56,6 +69,17 @@ def test_single_gpu_model(): def test_multi_gpu_model_dp(): + """ + Make sure DP works + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model = get_model() trainer = Trainer( @@ -72,6 +96,17 @@ def test_multi_gpu_model_dp(): def test_multi_gpu_model_ddp(): + """ + Make sure DDP works + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model = get_model() trainer = Trainer( @@ -88,5 +123,63 @@ def test_multi_gpu_model_ddp(): assert result == 1 +def test_amp_gpu_ddp(): + """ + Make sure DDP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + model = get_model() + + trainer = Trainer( + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + result = trainer.fit(model) + + assert result == 1 + + +def test_amp_gpu_dp(): + """ + Make sure DP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + model = get_model() + + trainer = Trainer( + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4, + gpus=[0, 1], + distributed_backend='dp', + use_amp=True + ) + + result = trainer.fit(model) + + assert result == 1 + + if __name__ == '__main__': pytest.main([__file__]) From 5f810275c9584a185a9e96383f8d4abf7907064f Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 08:53:00 -0400 Subject: [PATCH 004/222] added min accuracy to models test --- pytorch_lightning/models/trainer.py | 8 ++++++++ tests/test_models.py | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index b7f8fbe7..a5c90711 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -264,6 +264,14 @@ class Trainer(TrainerIO): return tqdm_dic + @property + def tng_tqdm_dic(self): + """ + Read-only for tqdm metrics + :return: + """ + return self.__tng_tqdm_dic + def __layout_bookeeping(self): # training bookeeping self.total_batch_nb = 0 diff --git a/tests/test_models.py b/tests/test_models.py index 36bc87bf..87e9bd31 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -3,10 +3,15 @@ from pytorch_lightning import Trainer from pytorch_lightning.examples.new_project_templates.lightning_module_template import LightningTemplateModel from argparse import Namespace from test_tube import Experiment +import numpy as np import warnings import torch import os +SEED = 2334 +torch.manual_seed(SEED) +np.random.seed(SEED) + def get_model(): root_dir = os.path.dirname(os.path.realpath(__file__)) @@ -26,6 +31,10 @@ def get_exp(): exp = Experiment(debug=True) return exp +def assert_ok_acc(trainer): + # this model should get 0.80+ acc + assert trainer.tng_tqdm_dic['val_acc'] > 0.80 + def test_cpu_model(): model = get_model() @@ -38,10 +47,11 @@ def test_cpu_model(): result = trainer.fit(model) - metrics = result.__tng_tqdm_dic + metrics = trainer.tng_tqdm_dic print(metrics) assert result == 1 + assert_ok_acc(trainer) def test_single_gpu_model(): @@ -66,6 +76,7 @@ def test_single_gpu_model(): result = trainer.fit(model) assert result == 1 + assert_ok_acc(trainer) def test_multi_gpu_model_dp(): @@ -93,6 +104,7 @@ def test_multi_gpu_model_dp(): result = trainer.fit(model) assert result == 1 + assert_ok_acc(trainer) def test_multi_gpu_model_ddp(): @@ -121,6 +133,7 @@ def test_multi_gpu_model_ddp(): result = trainer.fit(model) assert result == 1 + assert_ok_acc(trainer) def test_amp_gpu_ddp(): @@ -150,6 +163,7 @@ def test_amp_gpu_ddp(): result = trainer.fit(model) assert result == 1 + assert_ok_acc(trainer) def test_amp_gpu_dp(): @@ -179,6 +193,7 @@ def test_amp_gpu_dp(): result = trainer.fit(model) assert result == 1 + assert_ok_acc(trainer) if __name__ == '__main__': From e62973dfd30e28715fea6faaaf8701221ee84968 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 08:53:59 -0400 Subject: [PATCH 005/222] added min accuracy to models test --- tests/test_models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index 87e9bd31..d34f3b4b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -27,14 +27,17 @@ def get_model(): return model + def get_exp(): exp = Experiment(debug=True) return exp + def assert_ok_acc(trainer): # this model should get 0.80+ acc assert trainer.tng_tqdm_dic['val_acc'] > 0.80 + def test_cpu_model(): model = get_model() From b776fce2e7f43ff09d1cbcb6c70b20a6b0fa9e3f Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 08:56:22 -0400 Subject: [PATCH 006/222] added test docs --- tests/test_models.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index d34f3b4b..212c3e8f 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -14,6 +14,7 @@ np.random.seed(SEED) def get_model(): + # set up model with these hyperparams root_dir = os.path.dirname(os.path.realpath(__file__)) hparams = Namespace(**{'drop_prob': 0.2, 'batch_size': 32, @@ -29,6 +30,7 @@ def get_model(): def get_exp(): + # set up exp object without actually saving logs exp = Experiment(debug=True) return exp @@ -39,6 +41,10 @@ def assert_ok_acc(trainer): def test_cpu_model(): + """ + Make sure model trains on CPU + :return: + """ model = get_model() trainer = Trainer( From 8bbd65c95da2c17a2e1d1dd41ecd17ab3a43aecb Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:04:36 -0400 Subject: [PATCH 007/222] added test docs --- tests/test_models.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 212c3e8f..b5b6445a 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -37,7 +37,7 @@ def get_exp(): def assert_ok_acc(trainer): # this model should get 0.80+ acc - assert trainer.tng_tqdm_dic['val_acc'] > 0.80 + assert trainer.tng_tqdm_dic['val_acc'] > 0.80, "model failed to get expected 0.80 validation accuracy" def test_cpu_model(): @@ -55,11 +55,8 @@ def test_cpu_model(): ) result = trainer.fit(model) + assert result == 1, 'cpu model failed to complete' - metrics = trainer.tng_tqdm_dic - print(metrics) - - assert result == 1 assert_ok_acc(trainer) @@ -84,7 +81,7 @@ def test_single_gpu_model(): result = trainer.fit(model) - assert result == 1 + assert result == 1, 'single gpu model failed to complete' assert_ok_acc(trainer) @@ -112,7 +109,7 @@ def test_multi_gpu_model_dp(): result = trainer.fit(model) - assert result == 1 + assert result == 1, 'multi-gpu dp model failed to complete' assert_ok_acc(trainer) @@ -141,7 +138,7 @@ def test_multi_gpu_model_ddp(): result = trainer.fit(model) - assert result == 1 + assert result == 1, 'multi-gpu ddp model failed to complete' assert_ok_acc(trainer) @@ -171,7 +168,7 @@ def test_amp_gpu_ddp(): result = trainer.fit(model) - assert result == 1 + assert result == 1, 'amp + ddp model failed to complete' assert_ok_acc(trainer) @@ -201,7 +198,7 @@ def test_amp_gpu_dp(): result = trainer.fit(model) - assert result == 1 + assert result == 1, 'amp + gpu model failed to complete' assert_ok_acc(trainer) From 81cd8037db341f2313448f7d4844eff4ad93dbb3 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:06:26 -0400 Subject: [PATCH 008/222] updated reqs --- requirements.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 730be99c..ab69c839 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,11 @@ - atomicwrites==1.2.1 attrs==18.2.0 certifi==2018.11.29 cffi==1.11.5 +coverage==4.5.3 imageio==2.4.1 mkl-fft==1.0.6 +mkdocs==1.0.4 mkl-random==1.0.2 more-itertools==5.0.0 numpy==1.15.4 @@ -14,7 +15,7 @@ Pillow==5.3.0 pluggy==0.8.0 py==1.7.0 pycparser==2.19 -pytest==4.0.2 +pytest==5.0.1 python-dateutil==2.7.5 pytz==2018.7 scikit-learn==0.20.2 @@ -25,7 +26,7 @@ tensorboard==1.14.0 tensorboardX==1.7 tensorflow==1.14.0 test-tube==0.643 -torch==1.0.0 +torch==1.1.0 torchvision==0.2.1 tqdm==4.32.1 twine==1.13.0 From c689034650f078d4f218242e3d1f068e1d6949e6 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:12:37 -0400 Subject: [PATCH 009/222] updated reqs --- tests/test_models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index b5b6445a..e0842eb6 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -31,7 +31,8 @@ def get_model(): def get_exp(): # set up exp object without actually saving logs - exp = Experiment(debug=True) + root_dir = os.path.dirname(os.path.realpath(__file__)) + exp = Experiment(debug=True, save_dir=root_dir) return exp From e5c92e75ec9b20c7413f2de3939b53634fb0b449 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:13:02 -0400 Subject: [PATCH 010/222] updated reqs --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index e0842eb6..86e14578 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -32,7 +32,7 @@ def get_model(): def get_exp(): # set up exp object without actually saving logs root_dir = os.path.dirname(os.path.realpath(__file__)) - exp = Experiment(debug=True, save_dir=root_dir) + exp = Experiment(debug=True, save_dir=root_dir, name='tests_tt_dir') return exp From 8d44ebbb384f976377f69c1a4558e866b8b04316 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:15:26 -0400 Subject: [PATCH 011/222] updated reqs --- tests/test_models.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 86e14578..c1c0ceab 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -36,6 +36,13 @@ def get_exp(): return exp +def clear_tt_dir(): + root_dir = os.path.dirname(os.path.realpath(__file__)) + tt_dir = os.path.join(root_dir, 'tests_tt_dir') + if os.path.exists(tt_dir): + os.remove(tt_dir) + + def assert_ok_acc(trainer): # this model should get 0.80+ acc assert trainer.tng_tqdm_dic['val_acc'] > 0.80, "model failed to get expected 0.80 validation accuracy" @@ -54,12 +61,14 @@ def test_cpu_model(): train_percent_check=0.4, val_percent_check=0.4 ) - result = trainer.fit(model) - assert result == 1, 'cpu model failed to complete' + # correct result and ok accuracy + assert result == 1, 'cpu model failed to complete' assert_ok_acc(trainer) + clear_tt_dir() + def test_single_gpu_model(): """ @@ -82,9 +91,12 @@ def test_single_gpu_model(): result = trainer.fit(model) + # correct result and ok accuracy assert result == 1, 'single gpu model failed to complete' assert_ok_acc(trainer) + clear_tt_dir() + def test_multi_gpu_model_dp(): """ @@ -110,9 +122,12 @@ def test_multi_gpu_model_dp(): result = trainer.fit(model) + # correct result and ok accuracy assert result == 1, 'multi-gpu dp model failed to complete' assert_ok_acc(trainer) + clear_tt_dir() + def test_multi_gpu_model_ddp(): """ @@ -139,9 +154,12 @@ def test_multi_gpu_model_ddp(): result = trainer.fit(model) + # correct result and ok accuracy assert result == 1, 'multi-gpu ddp model failed to complete' assert_ok_acc(trainer) + clear_tt_dir() + def test_amp_gpu_ddp(): """ @@ -169,9 +187,12 @@ def test_amp_gpu_ddp(): result = trainer.fit(model) + # correct result and ok accuracy assert result == 1, 'amp + ddp model failed to complete' assert_ok_acc(trainer) + clear_tt_dir() + def test_amp_gpu_dp(): """ @@ -199,9 +220,11 @@ def test_amp_gpu_dp(): result = trainer.fit(model) + # correct result and ok accuracy assert result == 1, 'amp + gpu model failed to complete' assert_ok_acc(trainer) + clear_tt_dir() if __name__ == '__main__': pytest.main([__file__]) From 76aeab7c93561f643b19081b739ec7ba3276076a Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:17:10 -0400 Subject: [PATCH 012/222] updated reqs --- tests/test_models.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index c1c0ceab..2da111f4 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -40,7 +40,7 @@ def clear_tt_dir(): root_dir = os.path.dirname(os.path.realpath(__file__)) tt_dir = os.path.join(root_dir, 'tests_tt_dir') if os.path.exists(tt_dir): - os.remove(tt_dir) + os.rmdir(tt_dir) def assert_ok_acc(trainer): @@ -53,6 +53,8 @@ def test_cpu_model(): Make sure model trains on CPU :return: """ + clear_tt_dir() + model = get_model() trainer = Trainer( @@ -79,6 +81,7 @@ def test_single_gpu_model(): warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') return + clear_tt_dir() model = get_model() trainer = Trainer( @@ -110,6 +113,7 @@ def test_multi_gpu_model_dp(): warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') return + clear_tt_dir() model = get_model() trainer = Trainer( @@ -141,6 +145,7 @@ def test_multi_gpu_model_ddp(): warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') return + clear_tt_dir() model = get_model() trainer = Trainer( @@ -173,6 +178,7 @@ def test_amp_gpu_ddp(): warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') return + clear_tt_dir() model = get_model() trainer = Trainer( @@ -206,6 +212,7 @@ def test_amp_gpu_dp(): warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') return + clear_tt_dir() model = get_model() trainer = Trainer( @@ -226,5 +233,6 @@ def test_amp_gpu_dp(): clear_tt_dir() + if __name__ == '__main__': pytest.main([__file__]) From 297174eb6324e9cb511cc24d57650985fbb88e9d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:18:37 -0400 Subject: [PATCH 013/222] updated reqs --- tests/test_models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 2da111f4..44fead1b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -7,6 +7,7 @@ import numpy as np import warnings import torch import os +import shutil SEED = 2334 torch.manual_seed(SEED) @@ -40,7 +41,7 @@ def clear_tt_dir(): root_dir = os.path.dirname(os.path.realpath(__file__)) tt_dir = os.path.join(root_dir, 'tests_tt_dir') if os.path.exists(tt_dir): - os.rmdir(tt_dir) + shutil.rmtree(tt_dir) def assert_ok_acc(trainer): From 8e9737c194eadafd32de9348c838f9e3ff8515eb Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:23:30 -0400 Subject: [PATCH 014/222] updated reqs --- tests/test_models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 44fead1b..836bc65b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -41,7 +41,8 @@ def clear_tt_dir(): root_dir = os.path.dirname(os.path.realpath(__file__)) tt_dir = os.path.join(root_dir, 'tests_tt_dir') if os.path.exists(tt_dir): - shutil.rmtree(tt_dir) + shutil.move(tt_dir, '/efs/trash') + # shutil.rmtree(tt_dir) def assert_ok_acc(trainer): From 0cf9fa1a60e2ade462d94e87554554fc6eb7b26e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:24:41 -0400 Subject: [PATCH 015/222] updated reqs --- tests/test_models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 836bc65b..44fead1b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -41,8 +41,7 @@ def clear_tt_dir(): root_dir = os.path.dirname(os.path.realpath(__file__)) tt_dir = os.path.join(root_dir, 'tests_tt_dir') if os.path.exists(tt_dir): - shutil.move(tt_dir, '/efs/trash') - # shutil.rmtree(tt_dir) + shutil.rmtree(tt_dir) def assert_ok_acc(trainer): From d77914e466ea8bbd077e467ff9eed75d90447338 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:29:46 -0400 Subject: [PATCH 016/222] updated reqs --- .../new_project_templates/lightning_module_template.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index df7dbe32..490ccebe 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -105,10 +105,14 @@ class LightningTemplateModel(LightningModule): # acc labels_hat = torch.argmax(y_hat, dim=1) val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) + val_acc = torch.tensor(val_acc) + + if self.on_gpu: + val_acc = val_acc.cuda(loss_val.device.index) output = OrderedDict({ 'val_loss': loss_val, - 'val_acc': torch.tensor(val_acc).type(loss_val.dtype), + 'val_acc': val_acc, }) # can also return just a scalar instead of a dict (return loss_val) From a8a8ccb499b09436c9acc2e1b304b1b69420510b Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:32:51 -0400 Subject: [PATCH 017/222] updated reqs --- tests/test_models.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index 44fead1b..3cbe386b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -59,6 +59,7 @@ def test_cpu_model(): model = get_model() trainer = Trainer( + progress_bar=False, experiment=get_exp(), max_nb_epochs=1, train_percent_check=0.4, @@ -86,6 +87,7 @@ def test_single_gpu_model(): model = get_model() trainer = Trainer( + progress_bar=False, experiment=get_exp(), max_nb_epochs=1, train_percent_check=0.4, @@ -118,6 +120,7 @@ def test_multi_gpu_model_dp(): model = get_model() trainer = Trainer( + progress_bar=False, experiment=get_exp(), max_nb_epochs=1, train_percent_check=0.4, @@ -150,6 +153,7 @@ def test_multi_gpu_model_ddp(): model = get_model() trainer = Trainer( + progress_bar=False, experiment=get_exp(), max_nb_epochs=1, train_percent_check=0.4, @@ -183,6 +187,7 @@ def test_amp_gpu_ddp(): model = get_model() trainer = Trainer( + progress_bar=False, experiment=get_exp(), max_nb_epochs=1, train_percent_check=0.4, @@ -217,6 +222,7 @@ def test_amp_gpu_dp(): model = get_model() trainer = Trainer( + progress_bar=False, experiment=get_exp(), max_nb_epochs=1, train_percent_check=0.4, From 1793d40b95370e828a373a972c2b6a956a52ad01 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:33:41 -0400 Subject: [PATCH 018/222] updated reqs --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 3cbe386b..79dfaf34 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -46,7 +46,7 @@ def clear_tt_dir(): def assert_ok_acc(trainer): # this model should get 0.80+ acc - assert trainer.tng_tqdm_dic['val_acc'] > 0.80, "model failed to get expected 0.80 validation accuracy" + assert trainer.tng_tqdm_dic['val_acc'] > 0.70, "model failed to get expected 0.80 validation accuracy" def test_cpu_model(): From 6479f493ed308fa35e92fd6acbe0606680bd546e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:39:43 -0400 Subject: [PATCH 019/222] updated reqs --- tests/test_models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 79dfaf34..e0b0a36e 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -46,7 +46,8 @@ def clear_tt_dir(): def assert_ok_acc(trainer): # this model should get 0.80+ acc - assert trainer.tng_tqdm_dic['val_acc'] > 0.70, "model failed to get expected 0.80 validation accuracy" + acc = trainer.tng_tqdm_dic['val_acc'] + assert acc > 0.70, f'model failed to get expected 0.80 validation accuracy. Got: {acc}' def test_cpu_model(): From db95187b6b122994f73bedd6263b62fb0c886eb2 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 09:44:36 -0400 Subject: [PATCH 020/222] updated reqs --- pytorch_lightning/models/trainer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index a5c90711..7c45f35a 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -223,7 +223,7 @@ class Trainer(TrainerIO): this run will NOT use 16 bit precision ''' - warnings.warn(msg) + raise ModuleNotFoundError(msg) @property def data_parallel(self): From cfbf305c9c344bc9b5933a527eb288d05d0b2616 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:09:47 -0400 Subject: [PATCH 021/222] updated test docs --- tests/README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/README.md diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..d7eb4f92 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,35 @@ +# Pytorch-Lightning Tests + +## Running tests + +To run all tests do the following: +```bash +git clone https://github.com/williamFalcon/pytorch-lightning +cd pytorch-lightning + +# install module locally +pip install -e . + +# install dev deps +pip install -r requirements.txt + +# run tests +py.test +``` + +To test models that require GPU make sure to run the above command on a GPU machine. +The GPU machine must have: +1. At least 2 GPUs. +2. [NVIDIA-apex](https://github.com/NVIDIA/apex#linux) installed. + + +### test_models.py +This file fits a tiny model on MNIST using these different set-ups. +1. CPU only. +2. Single GPU with DP. +3. Multiple (2) GPUs using DP. +3. Multiple (2) GPUs using DDP. +3. Multiple (2) GPUs using DP + apex (for 16-bit precision). +3. Multiple (2) GPUs using DDP + apex (for 16-bit precision). + + From 73c104c80aa46d1568ece534a8d1e1bcf48a71c3 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:17:08 -0400 Subject: [PATCH 022/222] updated test docs --- pytorch_lightning/models/trainer.py | 3 +++ tests/test_models.py | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 7c45f35a..3b129d78 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -150,6 +150,9 @@ class Trainer(TrainerIO): self.use_ddp = False self.use_dp = False + # bookkeeping + self.avg_loss = 0 + # gpus come in as a string. # if gpus = -1 then use all available devices diff --git a/tests/test_models.py b/tests/test_models.py index e0b0a36e..6bac63cf 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -227,7 +227,6 @@ def test_amp_gpu_dp(): experiment=get_exp(), max_nb_epochs=1, train_percent_check=0.4, - val_percent_check=0.4, gpus=[0, 1], distributed_backend='dp', use_amp=True From f478fd942593dc45110797e2c549fb164a56000d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:19:42 -0400 Subject: [PATCH 023/222] updated test docs --- pytorch_lightning/models/trainer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 3b129d78..ae5eb55c 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -152,7 +152,7 @@ class Trainer(TrainerIO): # bookkeeping self.avg_loss = 0 - + self.batch_nb = 0 # gpus come in as a string. # if gpus = -1 then use all available devices From da19e0f7bcd9f257ea3a6f62d6f603ed4d261df3 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:24:15 -0400 Subject: [PATCH 024/222] updated test docs --- tests/test_models.py | 66 +++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 6bac63cf..580ba1af 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -138,6 +138,40 @@ def test_multi_gpu_model_dp(): clear_tt_dir() +def test_amp_gpu_dp(): + """ + Make sure DP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + clear_tt_dir() + model = get_model() + + trainer = Trainer( + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + gpus=[0, 1], + distributed_backend='dp', + use_amp=True + ) + + result = trainer.fit(model) + + # correct result and ok accuracy + assert result == 1, 'amp + gpu model failed to complete' + assert_ok_acc(trainer) + + clear_tt_dir() + + def test_multi_gpu_model_ddp(): """ Make sure DDP works @@ -207,38 +241,6 @@ def test_amp_gpu_ddp(): clear_tt_dir() -def test_amp_gpu_dp(): - """ - Make sure DP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - - clear_tt_dir() - model = get_model() - - trainer = Trainer( - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - gpus=[0, 1], - distributed_backend='dp', - use_amp=True - ) - - result = trainer.fit(model) - - # correct result and ok accuracy - assert result == 1, 'amp + gpu model failed to complete' - assert_ok_acc(trainer) - - clear_tt_dir() if __name__ == '__main__': From 490da9f7d3bc05666271c604f9d85b7dfdd89e0d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:28:44 -0400 Subject: [PATCH 025/222] updated test docs --- tests/debug.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 tests/debug.py diff --git a/tests/debug.py b/tests/debug.py new file mode 100644 index 00000000..facb7b62 --- /dev/null +++ b/tests/debug.py @@ -0,0 +1,66 @@ +import pytest +from pytorch_lightning import Trainer +from pytorch_lightning.examples.new_project_templates.lightning_module_template import LightningTemplateModel +from argparse import Namespace +from test_tube import Experiment +import numpy as np +import warnings +import torch +import os +import shutil + +def get_model(): + # set up model with these hyperparams + root_dir = os.path.dirname(os.path.realpath(__file__)) + hparams = Namespace(**{'drop_prob': 0.2, + 'batch_size': 32, + 'in_features': 28*28, + 'learning_rate': 0.001*8, + 'optimizer_name': 'adam', + 'data_root': os.path.join(root_dir, 'mnist'), + 'out_features': 10, + 'hidden_dim': 1000}) + model = LightningTemplateModel(hparams) + + return model + + +def get_exp(): + # set up exp object without actually saving logs + root_dir = os.path.dirname(os.path.realpath(__file__)) + exp = Experiment(debug=True, save_dir=root_dir, name='tests_tt_dir') + return exp + + +def clear_tt_dir(): + root_dir = os.path.dirname(os.path.realpath(__file__)) + tt_dir = os.path.join(root_dir, 'tests_tt_dir') + if os.path.exists(tt_dir): + shutil.rmtree(tt_dir) + + +def main(): + + clear_tt_dir() + model = get_model() + + trainer = Trainer( + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + result = trainer.fit(model) + + # correct result and ok accuracy + assert result == 1, 'amp + ddp model failed to complete' + + clear_tt_dir() + +if __name__ == '__main__': + main() \ No newline at end of file From 57a99e2aa5ad6d4b192dae24a3c352d970b6df37 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:30:41 -0400 Subject: [PATCH 026/222] updated test docs --- pytorch_lightning/models/trainer.py | 2 ++ tests/debug.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index ae5eb55c..62df9ef4 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -254,6 +254,8 @@ class Trainer(TrainerIO): @property def __tng_tqdm_dic(self): + import pdb + pdb.set_trace() tqdm_dic = { 'tng_loss': '{0:.3f}'.format(self.avg_loss), 'v_nb': '{}'.format(self.experiment.version), diff --git a/tests/debug.py b/tests/debug.py index facb7b62..42b5ef75 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -60,6 +60,8 @@ def main(): # correct result and ok accuracy assert result == 1, 'amp + ddp model failed to complete' + trainer.tng_tqdm_dic + clear_tt_dir() if __name__ == '__main__': From 1fd6158cea4ea9a03d591ef65e3d7c5808b01580 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:32:21 -0400 Subject: [PATCH 027/222] added debugging util --- tests/debug.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/debug.py b/tests/debug.py index 42b5ef75..3f0c58f0 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -8,6 +8,8 @@ import warnings import torch import os import shutil +import pdb + def get_model(): # set up model with these hyperparams From 96ca1c1b3926d36e24613358a7f86054db5b541e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:33:03 -0400 Subject: [PATCH 028/222] added debugging util --- pytorch_lightning/models/trainer.py | 5 ++--- tests/test_models.py | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 62df9ef4..74b147e3 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -19,7 +19,7 @@ import tqdm from pytorch_lightning.root_module.memory import get_gpu_memory_map from pytorch_lightning.root_module.model_saving import TrainerIO from pytorch_lightning.pt_overrides.override_data_parallel import LightningDistributedDataParallel, LightningDataParallel - +from pytorch_lightning.utils.debugging import ForkedPdb try: from apex import amp @@ -254,8 +254,7 @@ class Trainer(TrainerIO): @property def __tng_tqdm_dic(self): - import pdb - pdb.set_trace() + ForkedPdb().set_trace() tqdm_dic = { 'tng_loss': '{0:.3f}'.format(self.avg_loss), 'v_nb': '{}'.format(self.experiment.version), diff --git a/tests/test_models.py b/tests/test_models.py index 580ba1af..a02bde91 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -242,6 +242,5 @@ def test_amp_gpu_ddp(): - if __name__ == '__main__': pytest.main([__file__]) From b41f49dbef6daf826a81ba2f95fee0e6890f252e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:34:21 -0400 Subject: [PATCH 029/222] added debugging util --- pytorch_lightning/utils/debugging.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 pytorch_lightning/utils/debugging.py diff --git a/pytorch_lightning/utils/debugging.py b/pytorch_lightning/utils/debugging.py new file mode 100644 index 00000000..7a4d1445 --- /dev/null +++ b/pytorch_lightning/utils/debugging.py @@ -0,0 +1,15 @@ +import pdb +import sys + +class ForkedPdb(pdb.Pdb): + """A Pdb subclass that may be used + from a forked multiprocessing child + + """ + def interaction(self, *args, **kwargs): + _stdin = sys.stdin + try: + sys.stdin = open('/dev/stdin') + pdb.Pdb.interaction(self, *args, **kwargs) + finally: + sys.stdin = _stdin \ No newline at end of file From 5b9a59d486eb315b842efc9a85673f83951704f3 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:38:22 -0400 Subject: [PATCH 030/222] added debugging util --- pytorch_lightning/models/trainer.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 74b147e3..6d3a72fc 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -150,10 +150,6 @@ class Trainer(TrainerIO): self.use_ddp = False self.use_dp = False - # bookkeeping - self.avg_loss = 0 - self.batch_nb = 0 - # gpus come in as a string. # if gpus = -1 then use all available devices # otherwise, split the string using commas @@ -430,7 +426,7 @@ class Trainer(TrainerIO): # 1 gpu or dp option triggers training using DP module # easier to avoid NCCL issues elif self.use_dp: - self.dp_train(model) + self.__dp_train(model) # ON CPU else: @@ -452,7 +448,7 @@ class Trainer(TrainerIO): # used for testing or when we need to know that training succeeded return 1 - def dp_train(self, model): + def __dp_train(self, model): # CHOOSE OPTIMIZER # filter out the weights that were done on gpu so we can load on good old cpus From b3ed4abe0f771b72b926c1da3503f7b81934c432 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:38:45 -0400 Subject: [PATCH 031/222] added debugging util --- pytorch_lightning/models/trainer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 6d3a72fc..9cdbd7c2 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -250,7 +250,7 @@ class Trainer(TrainerIO): @property def __tng_tqdm_dic(self): - ForkedPdb().set_trace() + # ForkedPdb().set_trace() tqdm_dic = { 'tng_loss': '{0:.3f}'.format(self.avg_loss), 'v_nb': '{}'.format(self.experiment.version), From d7edaa867f58f7decd57ab91fad82584f5047eb5 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:39:59 -0400 Subject: [PATCH 032/222] added debugging util --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 3f0c58f0..34da26ed 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -50,7 +50,7 @@ def main(): progress_bar=False, experiment=get_exp(), max_nb_epochs=1, - train_percent_check=0.4, + train_percent_check=1.0, val_percent_check=0.4, gpus=[0, 1], distributed_backend='ddp', From 60dae4d50108d9f83ffb9e0cf8c8b723266bbb2a Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:42:01 -0400 Subject: [PATCH 033/222] added debugging util --- pytorch_lightning/models/trainer.py | 16 ++++++++++------ tests/debug.py | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 9cdbd7c2..6aa2ab54 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -150,6 +150,16 @@ class Trainer(TrainerIO): self.use_ddp = False self.use_dp = False + # training bookeeping + self.total_batch_nb = 0 + self.running_loss = [] + self.avg_loss = 0 + self.batch_nb = 0 + self.tqdm_metrics = {} + self.nb_val_batches = None + self.nb_tng_batches = None + self.nb_test_batches = None + # gpus come in as a string. # if gpus = -1 then use all available devices # otherwise, split the string using commas @@ -273,12 +283,6 @@ class Trainer(TrainerIO): return self.__tng_tqdm_dic def __layout_bookeeping(self): - # training bookeeping - self.total_batch_nb = 0 - self.running_loss = [] - self.avg_loss = 0 - self.batch_nb = 0 - self.tqdm_metrics = {} # determine number of training batches self.nb_tng_batches = len(self.tng_dataloader) diff --git a/tests/debug.py b/tests/debug.py index 34da26ed..3f0c58f0 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -50,7 +50,7 @@ def main(): progress_bar=False, experiment=get_exp(), max_nb_epochs=1, - train_percent_check=1.0, + train_percent_check=0.4, val_percent_check=0.4, gpus=[0, 1], distributed_backend='ddp', From 938fd58009dc3c075ccb5afb51dd39881a225a9d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:42:57 -0400 Subject: [PATCH 034/222] added debugging util --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 3f0c58f0..9db58fb2 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -62,7 +62,7 @@ def main(): # correct result and ok accuracy assert result == 1, 'amp + ddp model failed to complete' - trainer.tng_tqdm_dic + print(trainer.tng_tqdm_dic) clear_tt_dir() From 0009aa2bcd7d209bdd30e14452031cac94a8c2d7 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:44:35 -0400 Subject: [PATCH 035/222] added debugging util --- tests/debug.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 9db58fb2..dfa83a0c 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -47,7 +47,7 @@ def main(): model = get_model() trainer = Trainer( - progress_bar=False, + progress_bar=True, experiment=get_exp(), max_nb_epochs=1, train_percent_check=0.4, @@ -66,5 +66,6 @@ def main(): clear_tt_dir() + if __name__ == '__main__': main() \ No newline at end of file From f41fdc1ad8408d67d99daf554cc4fff242707ad1 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:47:49 -0400 Subject: [PATCH 036/222] added debugging util --- pytorch_lightning/models/trainer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 6aa2ab54..93eaf1b7 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -425,7 +425,9 @@ class Trainer(TrainerIO): If you're not using SLURM, ignore this message! """ warnings.warn(msg) - mp.spawn(self.ddp_train, nprocs=len(self.data_parallel_device_ids), args=(model, )) + d = {} + mp.spawn(self.ddp_train, nprocs=len(self.data_parallel_device_ids), args=(model, d)) + print(d) # 1 gpu or dp option triggers training using DP module # easier to avoid NCCL issues @@ -472,7 +474,7 @@ class Trainer(TrainerIO): self.__run_pretrain_routine(model) - def ddp_train(self, gpu_nb, model): + def ddp_train(self, gpu_nb, model, d): """ Entry point into a DP thread :param gpu_nb: @@ -482,6 +484,8 @@ class Trainer(TrainerIO): """ # node rank using relative slurm id # otherwise default to node rank 0 + d['helloooo'] = 12.0 + try: node_id = os.environ['SLURM_NODEID'] self.node_rank = int(node_id) From caa5cf2cee6def57aed836bb50cea80499b4bee1 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:50:29 -0400 Subject: [PATCH 037/222] removed dummy d --- pytorch_lightning/models/trainer.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 93eaf1b7..04b18a14 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -425,9 +425,7 @@ class Trainer(TrainerIO): If you're not using SLURM, ignore this message! """ warnings.warn(msg) - d = {} - mp.spawn(self.ddp_train, nprocs=len(self.data_parallel_device_ids), args=(model, d)) - print(d) + mp.spawn(self.ddp_train, nprocs=len(self.data_parallel_device_ids), args=(model, )) # 1 gpu or dp option triggers training using DP module # easier to avoid NCCL issues From b8cc9b2dba374d73ca28817b0def566026fb5a54 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:51:07 -0400 Subject: [PATCH 038/222] removed dummy d --- tests/debug.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index dfa83a0c..1375930d 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -50,8 +50,8 @@ def main(): progress_bar=True, experiment=get_exp(), max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4, + train_percent_check=0.1, + val_percent_check=0.1, gpus=[0, 1], distributed_backend='ddp', use_amp=True @@ -62,8 +62,6 @@ def main(): # correct result and ok accuracy assert result == 1, 'amp + ddp model failed to complete' - print(trainer.tng_tqdm_dic) - clear_tt_dir() From 853232b6946080ccac93a34908b19da0b87c7dd0 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:51:35 -0400 Subject: [PATCH 039/222] removed dummy d --- pytorch_lightning/models/trainer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 04b18a14..909d38df 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -472,7 +472,7 @@ class Trainer(TrainerIO): self.__run_pretrain_routine(model) - def ddp_train(self, gpu_nb, model, d): + def ddp_train(self, gpu_nb, model): """ Entry point into a DP thread :param gpu_nb: From e4313b0b3df722f8fb089e04ac6f8671f7e920f3 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:52:24 -0400 Subject: [PATCH 040/222] removed dummy d --- pytorch_lightning/models/trainer.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 909d38df..6aa2ab54 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -482,8 +482,6 @@ class Trainer(TrainerIO): """ # node rank using relative slurm id # otherwise default to node rank 0 - d['helloooo'] = 12.0 - try: node_id = os.environ['SLURM_NODEID'] self.node_rank = int(node_id) From b684fdf502212f91a033f14da03a484d588bc2ac Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:55:17 -0400 Subject: [PATCH 041/222] removed dummy d --- tests/debug.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/debug.py b/tests/debug.py index 1375930d..49483e0b 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -62,6 +62,14 @@ def main(): # correct result and ok accuracy assert result == 1, 'amp + ddp model failed to complete' + # test prediction + data = model.test_dataloader + for batch in data: + break + out = model(data[0]) + print(out) + + clear_tt_dir() From eb4b3a5752b57b5dfeac67034e8a55b04dd22550 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:55:56 -0400 Subject: [PATCH 042/222] removed dummy d --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 49483e0b..14d1e56b 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -66,7 +66,7 @@ def main(): data = model.test_dataloader for batch in data: break - out = model(data[0]) + out = model(batch[0]) print(out) From 88f064d276868b70961bc7f80265b5ef33666f70 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:57:46 -0400 Subject: [PATCH 043/222] removed dummy d --- tests/debug.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 14d1e56b..a7dd56aa 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -66,7 +66,10 @@ def main(): data = model.test_dataloader for batch in data: break - out = model(batch[0]) + + x, y = batch + x = x.view(x.size(0), -1) + out = model(x) print(out) From 8e131f9d79a86908d7338a5d8dbbba6779a23f16 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 10:59:15 -0400 Subject: [PATCH 044/222] removed dummy d --- tests/debug.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index a7dd56aa..6b27fd33 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -70,7 +70,11 @@ def main(): x, y = batch x = x.view(x.size(0), -1) out = model(x) - print(out) + + labels_hat = torch.argmax(out, dim=1) + val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) + val_acc = torch.tensor(val_acc) + print(val_acc) clear_tt_dir() From 5606fd86dfab04885f0dec50468e70e2bf791fb6 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:00:36 -0400 Subject: [PATCH 045/222] removed dummy d --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 6b27fd33..ed8d26cf 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -63,7 +63,7 @@ def main(): assert result == 1, 'amp + ddp model failed to complete' # test prediction - data = model.test_dataloader + data = model.val_dataloader for batch in data: break From 480dcb02134db993f76a1e315ff44bd149424968 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:09:50 -0400 Subject: [PATCH 046/222] removed dummy d --- tests/debug.py | 57 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index ed8d26cf..ca701d71 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -3,6 +3,7 @@ from pytorch_lightning import Trainer from pytorch_lightning.examples.new_project_templates.lightning_module_template import LightningTemplateModel from argparse import Namespace from test_tube import Experiment +from pytorch_lightning.callbacks import ModelCheckpoint import numpy as np import warnings import torch @@ -27,28 +28,48 @@ def get_model(): return model -def get_exp(): +def get_exp(debug=True): # set up exp object without actually saving logs root_dir = os.path.dirname(os.path.realpath(__file__)) - exp = Experiment(debug=True, save_dir=root_dir, name='tests_tt_dir') + exp = Experiment(debug=debug, save_dir=root_dir, name='tests_tt_dir') return exp -def clear_tt_dir(): +def init_save_dir(): root_dir = os.path.dirname(os.path.realpath(__file__)) - tt_dir = os.path.join(root_dir, 'tests_tt_dir') - if os.path.exists(tt_dir): - shutil.rmtree(tt_dir) + save_dir = os.path.join(root_dir, 'save_dir') + + if os.path.exists(save_dir): + shutil.rmtree(save_dir) + + os.makedirs(save_dir, exist_ok=True) + + return save_dir + + +def clear_save_dir(): + root_dir = os.path.dirname(os.path.realpath(__file__)) + save_dir = os.path.join(root_dir, 'save_dir') + if os.path.exists(save_dir): + shutil.rmtree(save_dir) def main(): - clear_tt_dir() + save_dir = init_save_dir() model = get_model() + # exp file to get meta + exp = get_exp(False) + exp.save() + + # exp file to get weights + checkpoint = ModelCheckpoint(save_dir) + trainer = Trainer( + checkpoint_callback=checkpoint, progress_bar=True, - experiment=get_exp(), + experiment=exp, max_nb_epochs=1, train_percent_check=0.1, val_percent_check=0.1, @@ -62,22 +83,12 @@ def main(): # correct result and ok accuracy assert result == 1, 'amp + ddp model failed to complete' - # test prediction - data = model.val_dataloader - for batch in data: - break + # load trained model + pdb.set_trace() + tags_path = exp.get_data_path(exp.name, exp.version) + LightningTemplateModel.load_from_metrics(weights_path=save_dir, tags_csv=) - x, y = batch - x = x.view(x.size(0), -1) - out = model(x) - - labels_hat = torch.argmax(out, dim=1) - val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) - val_acc = torch.tensor(val_acc) - print(val_acc) - - - clear_tt_dir() + clear_save_dir() if __name__ == '__main__': From a4b8aa0a416ab4dad22879f3b01a63717746d80e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:10:22 -0400 Subject: [PATCH 047/222] removed dummy d --- tests/debug.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index ca701d71..6caebd6d 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -86,7 +86,8 @@ def main(): # load trained model pdb.set_trace() tags_path = exp.get_data_path(exp.name, exp.version) - LightningTemplateModel.load_from_metrics(weights_path=save_dir, tags_csv=) + tags_path = os.path.join(tags_path, 'meta_tags.csv') + LightningTemplateModel.load_from_metrics(weights_path=save_dir, tags_csv=tags_path) clear_save_dir() From 8fd7a6001bdbe06159b1755ad8df77c450e6a789 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:14:19 -0400 Subject: [PATCH 048/222] added safeguards for callbacks in loading saving --- pytorch_lightning/root_module/model_saving.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/pytorch_lightning/root_module/model_saving.py b/pytorch_lightning/root_module/model_saving.py index a8bf366c..ab2ceb07 100644 --- a/pytorch_lightning/root_module/model_saving.py +++ b/pytorch_lightning/root_module/model_saving.py @@ -51,14 +51,19 @@ class TrainerIO(object): torch.save(checkpoint, filepath) def dump_checkpoint(self): + checkpoint = { 'epoch': self.current_epoch, - 'checkpoint_callback_best': self.checkpoint_callback.best, - 'early_stop_callback_wait': self.early_stop_callback.wait, - 'early_stop_callback_patience': self.early_stop_callback.patience, 'global_step': self.global_step } + if self.checkpoint_callback is not None: + checkpoint['checkpoint_callback_best'] = self.checkpoint_callback_best.best + + if self.early_stop_callback is not None: + checkpoint['early_stop_callback_wait'] = self.early_stop_callback.wait + checkpoint['early_stop_callback_patience'] = self.early_stop_callback.patience + optimizer_states = [] for i, optimizer in enumerate(self.optimizers): optimizer_states.append(optimizer.state_dict()) @@ -104,9 +109,13 @@ class TrainerIO(object): :param checkpoint: :return: """ - self.checkpoint_callback.best = checkpoint['checkpoint_callback_best'] - self.early_stop_callback.wait = checkpoint['early_stop_callback_wait'] - self.early_stop_callback.patience = checkpoint['early_stop_callback_patience'] + if self.checkpoint_callback is not None: + self.checkpoint_callback.best = checkpoint['checkpoint_callback_best'] + + if self.early_stop_callback is not None: + self.early_stop_callback.wait = checkpoint['early_stop_callback_wait'] + self.early_stop_callback.patience = checkpoint['early_stop_callback_patience'] + self.global_step = checkpoint['global_step'] self.current_epoch = checkpoint['epoch'] From 8a3abec83a8ee78ee4e667c7d295ab339cf37d71 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:30:14 -0400 Subject: [PATCH 049/222] added safeguards for callbacks in loading saving --- pytorch_lightning/root_module/model_saving.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytorch_lightning/root_module/model_saving.py b/pytorch_lightning/root_module/model_saving.py index ab2ceb07..b06225db 100644 --- a/pytorch_lightning/root_module/model_saving.py +++ b/pytorch_lightning/root_module/model_saving.py @@ -57,6 +57,8 @@ class TrainerIO(object): 'global_step': self.global_step } + from pytorch_lightning.utils.debugging import ForkedPdb + ForkedPdb().set_trace() if self.checkpoint_callback is not None: checkpoint['checkpoint_callback_best'] = self.checkpoint_callback_best.best From 98c112598e077596e80b121cc1f1d2569300a888 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:31:13 -0400 Subject: [PATCH 050/222] added safeguards for callbacks in loading saving --- pytorch_lightning/root_module/model_saving.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pytorch_lightning/root_module/model_saving.py b/pytorch_lightning/root_module/model_saving.py index b06225db..818c1947 100644 --- a/pytorch_lightning/root_module/model_saving.py +++ b/pytorch_lightning/root_module/model_saving.py @@ -57,10 +57,8 @@ class TrainerIO(object): 'global_step': self.global_step } - from pytorch_lightning.utils.debugging import ForkedPdb - ForkedPdb().set_trace() if self.checkpoint_callback is not None: - checkpoint['checkpoint_callback_best'] = self.checkpoint_callback_best.best + checkpoint['checkpoint_callback_best'] = self.checkpoint_callback.best if self.early_stop_callback is not None: checkpoint['early_stop_callback_wait'] = self.early_stop_callback.wait From 55a33edd0ac45ffef922a83c1b4e820d33a86717 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:34:56 -0400 Subject: [PATCH 051/222] added safeguards for callbacks in loading saving --- tests/debug.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 6caebd6d..a9700356 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -87,7 +87,23 @@ def main(): pdb.set_trace() tags_path = exp.get_data_path(exp.name, exp.version) tags_path = os.path.join(tags_path, 'meta_tags.csv') - LightningTemplateModel.load_from_metrics(weights_path=save_dir, tags_csv=tags_path) + trained_model = LightningTemplateModel.load_from_metrics(weights_path=save_dir, tags_csv=tags_path) + + # run prediction + for batch in model.test_dataloader: + break + + x, y = batch + x = x.view(x.size(0), -1) + + y_hat = model(x) + + # acc + labels_hat = torch.argmax(y_hat, dim=1) + val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) + val_acc = torch.tensor(val_acc) + + print(val_acc) clear_save_dir() From 2e30dd94bc9fc1464240deebfde0a085b334c8d6 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:35:46 -0400 Subject: [PATCH 052/222] added safeguards for callbacks in loading saving --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index a9700356..7f97d86d 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -87,7 +87,7 @@ def main(): pdb.set_trace() tags_path = exp.get_data_path(exp.name, exp.version) tags_path = os.path.join(tags_path, 'meta_tags.csv') - trained_model = LightningTemplateModel.load_from_metrics(weights_path=save_dir, tags_csv=tags_path) + trained_model = LightningTemplateModel.load_from_metrics(weights_path=save_dir, tags_csv=tags_path, on_gpu=True) # run prediction for batch in model.test_dataloader: From 3fc8166f51badbe36dde17817df1474020223b4b Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:35:55 -0400 Subject: [PATCH 053/222] added safeguards for callbacks in loading saving --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 7f97d86d..c0d845c5 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -96,7 +96,7 @@ def main(): x, y = batch x = x.view(x.size(0), -1) - y_hat = model(x) + y_hat = trained_model(x) # acc labels_hat = torch.argmax(y_hat, dim=1) From 245ef862f8ba5b79cecea9b5365306347f87b467 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:38:16 -0400 Subject: [PATCH 054/222] added safeguards for callbacks in loading saving --- tests/debug.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index c0d845c5..d3e478a4 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -87,7 +87,12 @@ def main(): pdb.set_trace() tags_path = exp.get_data_path(exp.name, exp.version) tags_path = os.path.join(tags_path, 'meta_tags.csv') - trained_model = LightningTemplateModel.load_from_metrics(weights_path=save_dir, tags_csv=tags_path, on_gpu=True) + + pdb.set_trace() + checkpoints = [x for x in os.listdir(save_dir) if '.ckpt' in x] + weights_dir = os.path.join(save_dir, checkpoints[0]) + + trained_model = LightningTemplateModel.load_from_metrics(weights_path=weights_dir, tags_csv=tags_path, on_gpu=True) # run prediction for batch in model.test_dataloader: From cd931c8220804fe399f69997455b14dea6a2ca44 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:40:45 -0400 Subject: [PATCH 055/222] added safeguards for callbacks in loading saving --- tests/debug.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index d3e478a4..a7135568 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -25,7 +25,7 @@ def get_model(): 'hidden_dim': 1000}) model = LightningTemplateModel(hparams) - return model + return model, hparams def get_exp(debug=True): @@ -57,10 +57,11 @@ def clear_save_dir(): def main(): save_dir = init_save_dir() - model = get_model() + model, hparams = get_model() # exp file to get meta exp = get_exp(False) + exp.add_meta_from_hyperopt(hparams) exp.save() # exp file to get weights From 0705e3e8583e8c10f02f95bc7f7fe81df57c3c2c Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:42:38 -0400 Subject: [PATCH 056/222] added safeguards for callbacks in loading saving --- tests/debug.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index a7135568..6910f3da 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -1,7 +1,7 @@ import pytest from pytorch_lightning import Trainer from pytorch_lightning.examples.new_project_templates.lightning_module_template import LightningTemplateModel -from argparse import Namespace +from test_tube.argparse_hopt import TTNamespace from test_tube import Experiment from pytorch_lightning.callbacks import ModelCheckpoint import numpy as np @@ -15,7 +15,7 @@ import pdb def get_model(): # set up model with these hyperparams root_dir = os.path.dirname(os.path.realpath(__file__)) - hparams = Namespace(**{'drop_prob': 0.2, + hparams = TTNamespace(**{'drop_prob': 0.2, 'batch_size': 32, 'in_features': 28*28, 'learning_rate': 0.001*8, From aac5ba00ef57e66fd7431a01c1c98bcae3d5f73b Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:42:47 -0400 Subject: [PATCH 057/222] added safeguards for callbacks in loading saving --- tests/debug.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index 6910f3da..9f2959af 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -16,13 +16,13 @@ def get_model(): # set up model with these hyperparams root_dir = os.path.dirname(os.path.realpath(__file__)) hparams = TTNamespace(**{'drop_prob': 0.2, - 'batch_size': 32, - 'in_features': 28*28, - 'learning_rate': 0.001*8, - 'optimizer_name': 'adam', - 'data_root': os.path.join(root_dir, 'mnist'), - 'out_features': 10, - 'hidden_dim': 1000}) + 'batch_size': 32, + 'in_features': 28*28, + 'learning_rate': 0.001*8, + 'optimizer_name': 'adam', + 'data_root': os.path.join(root_dir, 'mnist'), + 'out_features': 10, + 'hidden_dim': 1000}) model = LightningTemplateModel(hparams) return model, hparams From 926fa206ff85d90d81723deace47e58196af7495 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:45:59 -0400 Subject: [PATCH 058/222] added safeguards for callbacks in loading saving --- tests/debug.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index 9f2959af..21761baa 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -1,7 +1,7 @@ import pytest from pytorch_lightning import Trainer from pytorch_lightning.examples.new_project_templates.lightning_module_template import LightningTemplateModel -from test_tube.argparse_hopt import TTNamespace +from argparse import Namespace from test_tube import Experiment from pytorch_lightning.callbacks import ModelCheckpoint import numpy as np @@ -15,14 +15,14 @@ import pdb def get_model(): # set up model with these hyperparams root_dir = os.path.dirname(os.path.realpath(__file__)) - hparams = TTNamespace(**{'drop_prob': 0.2, - 'batch_size': 32, - 'in_features': 28*28, - 'learning_rate': 0.001*8, - 'optimizer_name': 'adam', - 'data_root': os.path.join(root_dir, 'mnist'), - 'out_features': 10, - 'hidden_dim': 1000}) + hparams = Namespace(**{'drop_prob': 0.2, + 'batch_size': 32, + 'in_features': 28*28, + 'learning_rate': 0.001*8, + 'optimizer_name': 'adam', + 'data_root': os.path.join(root_dir, 'mnist'), + 'out_features': 10, + 'hidden_dim': 1000}) model = LightningTemplateModel(hparams) return model, hparams @@ -61,7 +61,7 @@ def main(): # exp file to get meta exp = get_exp(False) - exp.add_meta_from_hyperopt(hparams) + exp.argparse(hparams) exp.save() # exp file to get weights From 85eaa28872ba0d445d5a231070be173d8d3dd07d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:51:38 -0400 Subject: [PATCH 059/222] added test for model loading and predicting --- tests/debug.py | 66 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index 21761baa..8fbd4e3c 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -54,6 +54,41 @@ def clear_save_dir(): shutil.rmtree(save_dir) +def load_model(exp, save_dir): + + # load trained model + tags_path = exp.get_data_path(exp.name, exp.version) + tags_path = os.path.join(tags_path, 'meta_tags.csv') + + checkpoints = [x for x in os.listdir(save_dir) if '.ckpt' in x] + weights_dir = os.path.join(save_dir, checkpoints[0]) + + trained_model = LightningTemplateModel.load_from_metrics(weights_path=weights_dir, tags_csv=tags_path, on_gpu=True) + + assert trained_model is not None, 'loading model failed' + + return trained_model + + +def run_prediction(dataloader, trained_model): + # run prediction on 1 batch + for batch in dataloader: + break + + x, y = batch + x = x.view(x.size(0), -1) + + y_hat = trained_model(x) + + # acc + labels_hat = torch.argmax(y_hat, dim=1) + val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) + val_acc = torch.tensor(val_acc) + val_acc = val_acc.item() + + assert val_acc > 0.70, 'this model is expected to get > 0.7 in test set' + + def main(): save_dir = init_save_dir() @@ -72,7 +107,7 @@ def main(): progress_bar=True, experiment=exp, max_nb_epochs=1, - train_percent_check=0.1, + train_percent_check=0.2, val_percent_check=0.1, gpus=[0, 1], distributed_backend='ddp', @@ -84,32 +119,11 @@ def main(): # correct result and ok accuracy assert result == 1, 'amp + ddp model failed to complete' - # load trained model - pdb.set_trace() - tags_path = exp.get_data_path(exp.name, exp.version) - tags_path = os.path.join(tags_path, 'meta_tags.csv') + # test model loading + pretrained_model = load_model(exp, save_dir) - pdb.set_trace() - checkpoints = [x for x in os.listdir(save_dir) if '.ckpt' in x] - weights_dir = os.path.join(save_dir, checkpoints[0]) - - trained_model = LightningTemplateModel.load_from_metrics(weights_path=weights_dir, tags_csv=tags_path, on_gpu=True) - - # run prediction - for batch in model.test_dataloader: - break - - x, y = batch - x = x.view(x.size(0), -1) - - y_hat = trained_model(x) - - # acc - labels_hat = torch.argmax(y_hat, dim=1) - val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) - val_acc = torch.tensor(val_acc) - - print(val_acc) + # test model preds + run_prediction(model.test_dataloader, pretrained_model) clear_save_dir() From aa900403870d157596e2fd119373e7ecc741b62e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:54:08 -0400 Subject: [PATCH 060/222] added test for model loading and predicting --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 8fbd4e3c..d8020f29 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -86,7 +86,7 @@ def run_prediction(dataloader, trained_model): val_acc = torch.tensor(val_acc) val_acc = val_acc.item() - assert val_acc > 0.70, 'this model is expected to get > 0.7 in test set' + assert val_acc > 0.60, 'this model is expected to get > 0.7 in test set' def main(): From d3651ba15ce3afaf83c0c43b68f1555b7546ace7 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:55:22 -0400 Subject: [PATCH 061/222] added test for model loading and predicting --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index d8020f29..81611acc 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -86,7 +86,7 @@ def run_prediction(dataloader, trained_model): val_acc = torch.tensor(val_acc) val_acc = val_acc.item() - assert val_acc > 0.60, 'this model is expected to get > 0.7 in test set' + assert val_acc > 0.60, f'this model is expected to get > 0.7 in test set (it got {val_acc})' def main(): From 8781d8aeabbf53c97ef445b6cd4dad7591ec7fcb Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:56:16 -0400 Subject: [PATCH 062/222] added test for model loading and predicting --- tests/debug.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/debug.py b/tests/debug.py index 81611acc..978322db 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -86,6 +86,8 @@ def run_prediction(dataloader, trained_model): val_acc = torch.tensor(val_acc) val_acc = val_acc.item() + print(val_acc) + assert val_acc > 0.60, f'this model is expected to get > 0.7 in test set (it got {val_acc})' From 98f6afd99ac11213a680a8479387d0753293f12d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 11:56:25 -0400 Subject: [PATCH 063/222] added test for model loading and predicting --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 978322db..b3011049 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -109,7 +109,7 @@ def main(): progress_bar=True, experiment=exp, max_nb_epochs=1, - train_percent_check=0.2, + train_percent_check=0.5, val_percent_check=0.1, gpus=[0, 1], distributed_backend='ddp', From 078cad768b419b435a2c6bfd5a1fbd78b691a837 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 12:00:40 -0400 Subject: [PATCH 064/222] fixed multi-gpu tests --- tests/debug.py | 4 +- tests/test_models.py | 124 ++++++++++++++++++++++++++++++++----------- 2 files changed, 96 insertions(+), 32 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index b3011049..b3c30deb 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -88,7 +88,7 @@ def run_prediction(dataloader, trained_model): print(val_acc) - assert val_acc > 0.60, f'this model is expected to get > 0.7 in test set (it got {val_acc})' + assert val_acc > 0.70, f'this model is expected to get > 0.7 in test set (it got {val_acc})' def main(): @@ -109,7 +109,7 @@ def main(): progress_bar=True, experiment=exp, max_nb_epochs=1, - train_percent_check=0.5, + train_percent_check=0.7, val_percent_check=0.1, gpus=[0, 1], distributed_backend='ddp', diff --git a/tests/test_models.py b/tests/test_models.py index a02bde91..0715ebf3 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -3,6 +3,7 @@ from pytorch_lightning import Trainer from pytorch_lightning.examples.new_project_templates.lightning_module_template import LightningTemplateModel from argparse import Namespace from test_tube import Experiment +from pytorch_lightning.callbacks import ModelCheckpoint import numpy as np import warnings import torch @@ -27,21 +28,70 @@ def get_model(): 'hidden_dim': 1000}) model = LightningTemplateModel(hparams) - return model + return model, hparams -def get_exp(): +def get_exp(debug=True): # set up exp object without actually saving logs root_dir = os.path.dirname(os.path.realpath(__file__)) - exp = Experiment(debug=True, save_dir=root_dir, name='tests_tt_dir') + exp = Experiment(debug=debug, save_dir=root_dir, name='tests_tt_dir') return exp -def clear_tt_dir(): +def init_save_dir(): root_dir = os.path.dirname(os.path.realpath(__file__)) - tt_dir = os.path.join(root_dir, 'tests_tt_dir') - if os.path.exists(tt_dir): - shutil.rmtree(tt_dir) + save_dir = os.path.join(root_dir, 'save_dir') + + if os.path.exists(save_dir): + shutil.rmtree(save_dir) + + os.makedirs(save_dir, exist_ok=True) + + return save_dir + + +def clear_save_dir(): + root_dir = os.path.dirname(os.path.realpath(__file__)) + save_dir = os.path.join(root_dir, 'save_dir') + if os.path.exists(save_dir): + shutil.rmtree(save_dir) + + +def load_model(exp, save_dir): + + # load trained model + tags_path = exp.get_data_path(exp.name, exp.version) + tags_path = os.path.join(tags_path, 'meta_tags.csv') + + checkpoints = [x for x in os.listdir(save_dir) if '.ckpt' in x] + weights_dir = os.path.join(save_dir, checkpoints[0]) + + trained_model = LightningTemplateModel.load_from_metrics(weights_path=weights_dir, tags_csv=tags_path, on_gpu=True) + + assert trained_model is not None, 'loading model failed' + + return trained_model + + +def run_prediction(dataloader, trained_model): + # run prediction on 1 batch + for batch in dataloader: + break + + x, y = batch + x = x.view(x.size(0), -1) + + y_hat = trained_model(x) + + # acc + labels_hat = torch.argmax(y_hat, dim=1) + val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) + val_acc = torch.tensor(val_acc) + val_acc = val_acc.item() + + print(val_acc) + + assert val_acc > 0.70, f'this model is expected to get > 0.7 in test set (it got {val_acc})' def assert_ok_acc(trainer): @@ -55,9 +105,9 @@ def test_cpu_model(): Make sure model trains on CPU :return: """ - clear_tt_dir() + save_dir = init_save_dir() - model = get_model() + model, hparams = get_model() trainer = Trainer( progress_bar=False, @@ -72,7 +122,7 @@ def test_cpu_model(): assert result == 1, 'cpu model failed to complete' assert_ok_acc(trainer) - clear_tt_dir() + clear_save_dir() def test_single_gpu_model(): @@ -84,8 +134,8 @@ def test_single_gpu_model(): warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') return - clear_tt_dir() - model = get_model() + save_dir = init_save_dir() + model, hparams = get_model() trainer = Trainer( progress_bar=False, @@ -102,7 +152,7 @@ def test_single_gpu_model(): assert result == 1, 'single gpu model failed to complete' assert_ok_acc(trainer) - clear_tt_dir() + clear_save_dir() def test_multi_gpu_model_dp(): @@ -117,8 +167,8 @@ def test_multi_gpu_model_dp(): warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') return - clear_tt_dir() - model = get_model() + save_dir = init_save_dir() + model, hparams = get_model() trainer = Trainer( progress_bar=False, @@ -135,7 +185,7 @@ def test_multi_gpu_model_dp(): assert result == 1, 'multi-gpu dp model failed to complete' assert_ok_acc(trainer) - clear_tt_dir() + clear_save_dir() def test_amp_gpu_dp(): @@ -150,8 +200,8 @@ def test_amp_gpu_dp(): warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') return - clear_tt_dir() - model = get_model() + save_dir = init_save_dir() + model, hparams = get_model() trainer = Trainer( progress_bar=False, @@ -169,7 +219,7 @@ def test_amp_gpu_dp(): assert result == 1, 'amp + gpu model failed to complete' assert_ok_acc(trainer) - clear_tt_dir() + clear_save_dir() def test_multi_gpu_model_ddp(): @@ -184,8 +234,8 @@ def test_multi_gpu_model_ddp(): warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') return - clear_tt_dir() - model = get_model() + save_dir = init_save_dir() + model, hparams = get_model() trainer = Trainer( progress_bar=False, @@ -203,7 +253,7 @@ def test_multi_gpu_model_ddp(): assert result == 1, 'multi-gpu ddp model failed to complete' assert_ok_acc(trainer) - clear_tt_dir() + clear_save_dir() def test_amp_gpu_ddp(): @@ -218,15 +268,25 @@ def test_amp_gpu_ddp(): warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') return - clear_tt_dir() - model = get_model() + + save_dir = init_save_dir() + model, hparams = get_model() + + # exp file to get meta + exp = get_exp(False) + exp.argparse(hparams) + exp.save() + + # exp file to get weights + checkpoint = ModelCheckpoint(save_dir) trainer = Trainer( - progress_bar=False, - experiment=get_exp(), + checkpoint_callback=checkpoint, + progress_bar=True, + experiment=exp, max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4, + train_percent_check=0.7, + val_percent_check=0.1, gpus=[0, 1], distributed_backend='ddp', use_amp=True @@ -236,10 +296,14 @@ def test_amp_gpu_ddp(): # correct result and ok accuracy assert result == 1, 'amp + ddp model failed to complete' - assert_ok_acc(trainer) - clear_tt_dir() + # test model loading + pretrained_model = load_model(exp, save_dir) + # test model preds + run_prediction(model.test_dataloader, pretrained_model) + + clear_save_dir() if __name__ == '__main__': From f50026c21f2937e051ae2c6f92b2fb1e0bf13eba Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 12:03:39 -0400 Subject: [PATCH 065/222] refactored model tests --- tests/test_models.py | 176 ++++++++++++++++++++++--------------------- 1 file changed, 91 insertions(+), 85 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 0715ebf3..3297ac09 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -15,91 +15,9 @@ torch.manual_seed(SEED) np.random.seed(SEED) -def get_model(): - # set up model with these hyperparams - root_dir = os.path.dirname(os.path.realpath(__file__)) - hparams = Namespace(**{'drop_prob': 0.2, - 'batch_size': 32, - 'in_features': 28*28, - 'learning_rate': 0.001*8, - 'optimizer_name': 'adam', - 'data_root': os.path.join(root_dir, 'mnist'), - 'out_features': 10, - 'hidden_dim': 1000}) - model = LightningTemplateModel(hparams) - - return model, hparams - - -def get_exp(debug=True): - # set up exp object without actually saving logs - root_dir = os.path.dirname(os.path.realpath(__file__)) - exp = Experiment(debug=debug, save_dir=root_dir, name='tests_tt_dir') - return exp - - -def init_save_dir(): - root_dir = os.path.dirname(os.path.realpath(__file__)) - save_dir = os.path.join(root_dir, 'save_dir') - - if os.path.exists(save_dir): - shutil.rmtree(save_dir) - - os.makedirs(save_dir, exist_ok=True) - - return save_dir - - -def clear_save_dir(): - root_dir = os.path.dirname(os.path.realpath(__file__)) - save_dir = os.path.join(root_dir, 'save_dir') - if os.path.exists(save_dir): - shutil.rmtree(save_dir) - - -def load_model(exp, save_dir): - - # load trained model - tags_path = exp.get_data_path(exp.name, exp.version) - tags_path = os.path.join(tags_path, 'meta_tags.csv') - - checkpoints = [x for x in os.listdir(save_dir) if '.ckpt' in x] - weights_dir = os.path.join(save_dir, checkpoints[0]) - - trained_model = LightningTemplateModel.load_from_metrics(weights_path=weights_dir, tags_csv=tags_path, on_gpu=True) - - assert trained_model is not None, 'loading model failed' - - return trained_model - - -def run_prediction(dataloader, trained_model): - # run prediction on 1 batch - for batch in dataloader: - break - - x, y = batch - x = x.view(x.size(0), -1) - - y_hat = trained_model(x) - - # acc - labels_hat = torch.argmax(y_hat, dim=1) - val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) - val_acc = torch.tensor(val_acc) - val_acc = val_acc.item() - - print(val_acc) - - assert val_acc > 0.70, f'this model is expected to get > 0.7 in test set (it got {val_acc})' - - -def assert_ok_acc(trainer): - # this model should get 0.80+ acc - acc = trainer.tng_tqdm_dic['val_acc'] - assert acc > 0.70, f'model failed to get expected 0.80 validation accuracy. Got: {acc}' - - +# ----------------- +# TESTS +# ----------------- def test_cpu_model(): """ Make sure model trains on CPU @@ -306,5 +224,93 @@ def test_amp_gpu_ddp(): clear_save_dir() +# ----------------- +# UTILS +# ----------------- +def get_model(): + # set up model with these hyperparams + root_dir = os.path.dirname(os.path.realpath(__file__)) + hparams = Namespace(**{'drop_prob': 0.2, + 'batch_size': 32, + 'in_features': 28*28, + 'learning_rate': 0.001*8, + 'optimizer_name': 'adam', + 'data_root': os.path.join(root_dir, 'mnist'), + 'out_features': 10, + 'hidden_dim': 1000}) + model = LightningTemplateModel(hparams) + + return model, hparams + + +def get_exp(debug=True): + # set up exp object without actually saving logs + root_dir = os.path.dirname(os.path.realpath(__file__)) + exp = Experiment(debug=debug, save_dir=root_dir, name='tests_tt_dir') + return exp + + +def init_save_dir(): + root_dir = os.path.dirname(os.path.realpath(__file__)) + save_dir = os.path.join(root_dir, 'save_dir') + + if os.path.exists(save_dir): + shutil.rmtree(save_dir) + + os.makedirs(save_dir, exist_ok=True) + + return save_dir + + +def clear_save_dir(): + root_dir = os.path.dirname(os.path.realpath(__file__)) + save_dir = os.path.join(root_dir, 'save_dir') + if os.path.exists(save_dir): + shutil.rmtree(save_dir) + + +def load_model(exp, save_dir): + + # load trained model + tags_path = exp.get_data_path(exp.name, exp.version) + tags_path = os.path.join(tags_path, 'meta_tags.csv') + + checkpoints = [x for x in os.listdir(save_dir) if '.ckpt' in x] + weights_dir = os.path.join(save_dir, checkpoints[0]) + + trained_model = LightningTemplateModel.load_from_metrics(weights_path=weights_dir, tags_csv=tags_path, on_gpu=True) + + assert trained_model is not None, 'loading model failed' + + return trained_model + + +def run_prediction(dataloader, trained_model): + # run prediction on 1 batch + for batch in dataloader: + break + + x, y = batch + x = x.view(x.size(0), -1) + + y_hat = trained_model(x) + + # acc + labels_hat = torch.argmax(y_hat, dim=1) + val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) + val_acc = torch.tensor(val_acc) + val_acc = val_acc.item() + + print(val_acc) + + assert val_acc > 0.70, f'this model is expected to get > 0.7 in test set (it got {val_acc})' + + +def assert_ok_acc(trainer): + # this model should get 0.80+ acc + acc = trainer.tng_tqdm_dic['val_acc'] + assert acc > 0.70, f'model failed to get expected 0.70 validation accuracy. Got: {acc}' + + if __name__ == '__main__': pytest.main([__file__]) From de95179556044fcdde036bfdcd4ea08b899c82b5 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 12:04:11 -0400 Subject: [PATCH 066/222] refactored model tests --- tests/test_models.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 3297ac09..43ae5524 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -135,7 +135,6 @@ def test_amp_gpu_dp(): # correct result and ok accuracy assert result == 1, 'amp + gpu model failed to complete' - assert_ok_acc(trainer) clear_save_dir() @@ -169,7 +168,6 @@ def test_multi_gpu_model_ddp(): # correct result and ok accuracy assert result == 1, 'multi-gpu ddp model failed to complete' - assert_ok_acc(trainer) clear_save_dir() From e5f73304b3f211d4d36e7f52ceb0290fc31ba010 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 12:04:48 -0400 Subject: [PATCH 067/222] refactored model tests --- tests/test_models.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 43ae5524..30d09e38 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -15,9 +15,9 @@ torch.manual_seed(SEED) np.random.seed(SEED) -# ----------------- +# ------------------------------------------------------------------------ # TESTS -# ----------------- +# ------------------------------------------------------------------------ def test_cpu_model(): """ Make sure model trains on CPU @@ -222,9 +222,9 @@ def test_amp_gpu_ddp(): clear_save_dir() -# ----------------- +# ------------------------------------------------------------------------ # UTILS -# ----------------- +# ------------------------------------------------------------------------ def get_model(): # set up model with these hyperparams root_dir = os.path.dirname(os.path.realpath(__file__)) From c7ad04be571ee0db88f0bc49a9fc40ebcd5491c3 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 12:13:28 -0400 Subject: [PATCH 068/222] refactored model tests --- tests/test_models.py | 112 +++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 67 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 30d09e38..7bf4ee3f 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -52,25 +52,15 @@ def test_single_gpu_model(): warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') return - save_dir = init_save_dir() - model, hparams = get_model() - - trainer = Trainer( + trainer_options = dict( progress_bar=False, - experiment=get_exp(), max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4, + train_percent_check=0.1, + val_percent_check=0.1, gpus=[0] ) - result = trainer.fit(model) - - # correct result and ok accuracy - assert result == 1, 'single gpu model failed to complete' - assert_ok_acc(trainer) - - clear_save_dir() + run_gpu_model_test(trainer_options) def test_multi_gpu_model_dp(): @@ -85,25 +75,15 @@ def test_multi_gpu_model_dp(): warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') return - save_dir = init_save_dir() - model, hparams = get_model() - - trainer = Trainer( + trainer_options = dict( progress_bar=False, - experiment=get_exp(), max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4, + train_percent_check=0.1, + val_percent_check=0.1, gpus=[0, 1] ) - result = trainer.fit(model) - - # correct result and ok accuracy - assert result == 1, 'multi-gpu dp model failed to complete' - assert_ok_acc(trainer) - - clear_save_dir() + run_gpu_model_test(trainer_options) def test_amp_gpu_dp(): @@ -118,25 +98,15 @@ def test_amp_gpu_dp(): warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') return - save_dir = init_save_dir() - model, hparams = get_model() - - trainer = Trainer( + trainer_options = dict( progress_bar=False, - experiment=get_exp(), max_nb_epochs=1, - train_percent_check=0.4, gpus=[0, 1], distributed_backend='dp', use_amp=True ) - result = trainer.fit(model) - - # correct result and ok accuracy - assert result == 1, 'amp + gpu model failed to complete' - - clear_save_dir() + run_gpu_model_test(trainer_options) def test_multi_gpu_model_ddp(): @@ -151,25 +121,16 @@ def test_multi_gpu_model_ddp(): warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') return - save_dir = init_save_dir() - model, hparams = get_model() - - trainer = Trainer( + trainer_options = dict( progress_bar=False, - experiment=get_exp(), max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4, + train_percent_check=0.1, + val_percent_check=0.1, gpus=[0, 1], distributed_backend='ddp' ) - result = trainer.fit(model) - - # correct result and ok accuracy - assert result == 1, 'multi-gpu ddp model failed to complete' - - clear_save_dir() + run_gpu_model_test(trainer_options) def test_amp_gpu_ddp(): @@ -184,6 +145,32 @@ def test_amp_gpu_ddp(): warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') return + trainer_options = dict( + progress_bar=True, + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + run_gpu_model_test(trainer_options) + + +# ------------------------------------------------------------------------ +# UTILS +# ------------------------------------------------------------------------ + +def run_gpu_model_test(trainer_options): + """ + Make sure DDP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return save_dir = init_save_dir() model, hparams = get_model() @@ -196,18 +183,12 @@ def test_amp_gpu_ddp(): # exp file to get weights checkpoint = ModelCheckpoint(save_dir) - trainer = Trainer( - checkpoint_callback=checkpoint, - progress_bar=True, - experiment=exp, - max_nb_epochs=1, - train_percent_check=0.7, - val_percent_check=0.1, - gpus=[0, 1], - distributed_backend='ddp', - use_amp=True - ) + # add these to the trainer options + trainer_options.checkpoint_callback = checkpoint + trainer_options.experiment = exp + # fit model + trainer = Trainer(**trainer_options) result = trainer.fit(model) # correct result and ok accuracy @@ -222,9 +203,6 @@ def test_amp_gpu_ddp(): clear_save_dir() -# ------------------------------------------------------------------------ -# UTILS -# ------------------------------------------------------------------------ def get_model(): # set up model with these hyperparams root_dir = os.path.dirname(os.path.realpath(__file__)) From 24ceafa05cf9660b68d4e3e1d24dfccc0f5f934e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 12:14:26 -0400 Subject: [PATCH 069/222] refactored model tests --- tests/test_models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 7bf4ee3f..a39876b6 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -184,8 +184,8 @@ def run_gpu_model_test(trainer_options): checkpoint = ModelCheckpoint(save_dir) # add these to the trainer options - trainer_options.checkpoint_callback = checkpoint - trainer_options.experiment = exp + trainer_options['checkpoint_callback'] = checkpoint + trainer_options['experiment'] = exp # fit model trainer = Trainer(**trainer_options) From b90841dc3d243519d41b84a9fe42320c7e04232d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:41:28 -0400 Subject: [PATCH 070/222] refactored model tests --- .../new_project_templates/lightning_module_template.py | 2 ++ tests/debug.py | 8 ++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index 490ccebe..ca8b54cb 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -107,6 +107,8 @@ class LightningTemplateModel(LightningModule): val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) val_acc = torch.tensor(val_acc) + import pdb + pdb.set_trace() if self.on_gpu: val_acc = val_acc.cuda(loss_val.device.index) diff --git a/tests/debug.py b/tests/debug.py index b3c30deb..c3a356b3 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -105,14 +105,10 @@ def main(): checkpoint = ModelCheckpoint(save_dir) trainer = Trainer( - checkpoint_callback=checkpoint, - progress_bar=True, - experiment=exp, + progress_bar=False, max_nb_epochs=1, - train_percent_check=0.7, - val_percent_check=0.1, gpus=[0, 1], - distributed_backend='ddp', + distributed_backend='dp', use_amp=True ) From 8a43f4307ee3e0483445728f9887cd6c5c3d3126 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:42:42 -0400 Subject: [PATCH 071/222] refactored model tests --- tests/debug.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/debug.py b/tests/debug.py index c3a356b3..68aee841 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -105,6 +105,8 @@ def main(): checkpoint = ModelCheckpoint(save_dir) trainer = Trainer( + experiment=exp, + checkpoint_callback=checkpoint, progress_bar=False, max_nb_epochs=1, gpus=[0, 1], From 3d31219c85b08ced6b0bd0225a650a4ccaa81c29 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:45:22 -0400 Subject: [PATCH 072/222] refactored model tests --- .../new_project_templates/lightning_module_template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index ca8b54cb..6248ebcf 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -98,6 +98,8 @@ class LightningTemplateModel(LightningModule): """ x, y = data_batch x = x.view(x.size(0), -1) + print('x: ', x.device) + print('model: ', self.c_d1.weight.device) y_hat = self.forward(x) loss_val = self.loss(y, y_hat) @@ -107,8 +109,6 @@ class LightningTemplateModel(LightningModule): val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) val_acc = torch.tensor(val_acc) - import pdb - pdb.set_trace() if self.on_gpu: val_acc = val_acc.cuda(loss_val.device.index) From aba7006fc28170bdc0a9087bff8593fdf5c86f8e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:46:32 -0400 Subject: [PATCH 073/222] refactored model tests --- .../examples/new_project_templates/lightning_module_template.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index 6248ebcf..41f53518 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -98,8 +98,10 @@ class LightningTemplateModel(LightningModule): """ x, y = data_batch x = x.view(x.size(0), -1) + print('-'*100) print('x: ', x.device) print('model: ', self.c_d1.weight.device) + print('-'*100) y_hat = self.forward(x) loss_val = self.loss(y, y_hat) From 4e6c7f80e50116b88562f644065bd87bc5dc7857 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:47:37 -0400 Subject: [PATCH 074/222] refactored model tests --- .../new_project_templates/lightning_module_template.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index 41f53518..bf736227 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -78,6 +78,11 @@ class LightningTemplateModel(LightningModule): # forward pass x, y = data_batch x = x.view(x.size(0), -1) + print('-'*100) + print('TRAIN') + print('x: ', x.device) + print('model: ', self.c_d1.weight.device) + print('-'*100) y_hat = self.forward(x) # calculate loss @@ -99,6 +104,7 @@ class LightningTemplateModel(LightningModule): x, y = data_batch x = x.view(x.size(0), -1) print('-'*100) + print('VAL') print('x: ', x.device) print('model: ', self.c_d1.weight.device) print('-'*100) From 7d1e1eb7f98736eca3a7dc2aa2ad152809844b31 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:49:28 -0400 Subject: [PATCH 075/222] refactored model tests --- pytorch_lightning/models/trainer.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 6aa2ab54..9dfcc570 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -458,8 +458,6 @@ class Trainer(TrainerIO): # filter out the weights that were done on gpu so we can load on good old cpus self.optimizers = model.configure_optimizers() - model.cuda(self.data_parallel_device_ids[0]) - # run through amp wrapper if self.use_amp: # An example From 53f1f18442496962ee016552643955e6f8fbfdd4 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:50:02 -0400 Subject: [PATCH 076/222] refactored model tests --- pytorch_lightning/models/trainer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 9dfcc570..4b6c151f 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -460,6 +460,8 @@ class Trainer(TrainerIO): # run through amp wrapper if self.use_amp: + model.cuda(self.data_parallel_device_ids[0]) + # An example model, optimizers = amp.initialize( model, self.optimizers, opt_level=self.amp_level, From 3521051877a55e2a3128eb57e2b9a95f31b80790 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:51:12 -0400 Subject: [PATCH 077/222] refactored model tests --- .../examples/new_project_templates/lightning_module_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index bf736227..6c6ba68d 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -106,7 +106,7 @@ class LightningTemplateModel(LightningModule): print('-'*100) print('VAL') print('x: ', x.device) - print('model: ', self.c_d1.weight.device) + print('model: ', self.c_d1.weight.device, self.c_d1.bias.device) print('-'*100) y_hat = self.forward(x) From a729cfc9cc16392ed14059f253c2306387235563 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:51:54 -0400 Subject: [PATCH 078/222] refactored model tests --- .../examples/new_project_templates/lightning_module_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index 6c6ba68d..5507341b 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -105,7 +105,7 @@ class LightningTemplateModel(LightningModule): x = x.view(x.size(0), -1) print('-'*100) print('VAL') - print('x: ', x.device) + print('x: ', x.device, x.shape) print('model: ', self.c_d1.weight.device, self.c_d1.bias.device) print('-'*100) y_hat = self.forward(x) From 0e9e07835cfc457384a48a4aa5f26af44ffac202 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:53:34 -0400 Subject: [PATCH 079/222] refactored model tests --- .../examples/new_project_templates/lightning_module_template.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index 5507341b..16f588ae 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -55,6 +55,7 @@ class LightningTemplateModel(LightningModule): :return: """ + print(x.device) x = self.c_d1(x) x = torch.tanh(x) x = self.c_d1_bn(x) From cf7da86c7c15afdb503e78af045bd22463e2e9f7 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:55:20 -0400 Subject: [PATCH 080/222] refactored model tests --- .../lightning_module_template.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index 16f588ae..db065def 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -54,8 +54,11 @@ class LightningTemplateModel(LightningModule): :param x: :return: """ + print('-'*100) + print('x: ', x.device) + print('model: ', self.c_d1.weight.device) + print('-'*100) - print(x.device) x = self.c_d1(x) x = torch.tanh(x) x = self.c_d1_bn(x) @@ -79,11 +82,7 @@ class LightningTemplateModel(LightningModule): # forward pass x, y = data_batch x = x.view(x.size(0), -1) - print('-'*100) - print('TRAIN') - print('x: ', x.device) - print('model: ', self.c_d1.weight.device) - print('-'*100) + y_hat = self.forward(x) # calculate loss @@ -104,11 +103,6 @@ class LightningTemplateModel(LightningModule): """ x, y = data_batch x = x.view(x.size(0), -1) - print('-'*100) - print('VAL') - print('x: ', x.device, x.shape) - print('model: ', self.c_d1.weight.device, self.c_d1.bias.device) - print('-'*100) y_hat = self.forward(x) loss_val = self.loss(y, y_hat) From ef843d5f967e8220438969b1016e082c35fa3d31 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:56:21 -0400 Subject: [PATCH 081/222] refactored model tests --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 68aee841..095a060e 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -111,7 +111,7 @@ def main(): max_nb_epochs=1, gpus=[0, 1], distributed_backend='dp', - use_amp=True + use_amp=False ) result = trainer.fit(model) From ecb68b52f85bf92eaf424c4d3936b21e9ccc0cfc Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:56:49 -0400 Subject: [PATCH 082/222] refactored model tests --- pytorch_lightning/models/trainer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 4b6c151f..68ffe8c5 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -458,9 +458,10 @@ class Trainer(TrainerIO): # filter out the weights that were done on gpu so we can load on good old cpus self.optimizers = model.configure_optimizers() + model.cuda(self.data_parallel_device_ids[0]) + # run through amp wrapper if self.use_amp: - model.cuda(self.data_parallel_device_ids[0]) # An example model, optimizers = amp.initialize( From c26d200c417602b391d4acdb74bde4a9165905d1 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:57:34 -0400 Subject: [PATCH 083/222] refactored model tests --- .../new_project_templates/lightning_module_template.py | 4 ---- tests/debug.py | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index db065def..59d7210a 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -54,10 +54,6 @@ class LightningTemplateModel(LightningModule): :param x: :return: """ - print('-'*100) - print('x: ', x.device) - print('model: ', self.c_d1.weight.device) - print('-'*100) x = self.c_d1(x) x = torch.tanh(x) diff --git a/tests/debug.py b/tests/debug.py index 095a060e..876075c5 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -107,7 +107,7 @@ def main(): trainer = Trainer( experiment=exp, checkpoint_callback=checkpoint, - progress_bar=False, + progress_bar=True, max_nb_epochs=1, gpus=[0, 1], distributed_backend='dp', From 6169d22813fb50d594fd543a0bd18cfda5ca7008 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 13:59:51 -0400 Subject: [PATCH 084/222] refactored model tests --- .../new_project_templates/lightning_module_template.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index 59d7210a..c8622230 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -85,7 +85,7 @@ class LightningTemplateModel(LightningModule): loss_val = self.loss(y, y_hat) output = OrderedDict({ - 'loss': loss_val + 'loss': loss_val.unsqueeze(1) }) # can also return just a scalar instead of a dict (return loss_val) @@ -112,8 +112,8 @@ class LightningTemplateModel(LightningModule): val_acc = val_acc.cuda(loss_val.device.index) output = OrderedDict({ - 'val_loss': loss_val, - 'val_acc': val_acc, + 'val_loss': loss_val.unsqueeze(1), + 'val_acc': val_acc.unsqueeze(1), }) # can also return just a scalar instead of a dict (return loss_val) From d004fc57258e3aa8d67a305abb7c9ca53a25e271 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:00:29 -0400 Subject: [PATCH 085/222] refactored model tests --- .../new_project_templates/lightning_module_template.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index c8622230..10e6c028 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -85,7 +85,7 @@ class LightningTemplateModel(LightningModule): loss_val = self.loss(y, y_hat) output = OrderedDict({ - 'loss': loss_val.unsqueeze(1) + 'loss': loss_val.unsqueeze(0) }) # can also return just a scalar instead of a dict (return loss_val) @@ -112,8 +112,8 @@ class LightningTemplateModel(LightningModule): val_acc = val_acc.cuda(loss_val.device.index) output = OrderedDict({ - 'val_loss': loss_val.unsqueeze(1), - 'val_acc': val_acc.unsqueeze(1), + 'val_loss': loss_val.unsqueeze(0), + 'val_acc': val_acc.unsqueeze(0), }) # can also return just a scalar instead of a dict (return loss_val) From 42b86a160d0dd66d571e8e41de6122d982dfc3a0 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:04:17 -0400 Subject: [PATCH 086/222] refactored model tests --- .../lightning_module_template.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index 10e6c028..fc28c55d 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -84,8 +84,12 @@ class LightningTemplateModel(LightningModule): # calculate loss loss_val = self.loss(y, y_hat) + # in DP mode (default) make sure if result is scalar, there's another dim in the beginning + if self.trainer.use_dp: + loss_val = loss_val.unsqueeze(0) + output = OrderedDict({ - 'loss': loss_val.unsqueeze(0) + 'loss': loss_val }) # can also return just a scalar instead of a dict (return loss_val) @@ -111,9 +115,14 @@ class LightningTemplateModel(LightningModule): if self.on_gpu: val_acc = val_acc.cuda(loss_val.device.index) + # in DP mode (default) make sure if result is scalar, there's another dim in the beginning + if self.trainer.use_dp: + loss_val = loss_val.unsqueeze(0) + val_acc = val_acc.unsqueeze(0) + output = OrderedDict({ - 'val_loss': loss_val.unsqueeze(0), - 'val_acc': val_acc.unsqueeze(0), + 'val_loss': loss_val, + 'val_acc': val_acc, }) # can also return just a scalar instead of a dict (return loss_val) From dd4f8899c8d4459a09c7206e5bd77c99245430c5 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:06:35 -0400 Subject: [PATCH 087/222] refactored model tests --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index a39876b6..b9bb4c65 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -285,7 +285,7 @@ def run_prediction(dataloader, trained_model): def assert_ok_acc(trainer): # this model should get 0.80+ acc acc = trainer.tng_tqdm_dic['val_acc'] - assert acc > 0.70, f'model failed to get expected 0.70 validation accuracy. Got: {acc}' + assert acc > 0.60, f'model failed to get expected 0.60 validation accuracy. Got: {acc}' if __name__ == '__main__': From 1b273a32eea075295b0ea73b210cb43017d22194 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:11:05 -0400 Subject: [PATCH 088/222] fixed amp bug --- pytorch_lightning/models/trainer.py | 8 ++++++++ tests/debug.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 68ffe8c5..b2f9b66e 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -460,6 +460,14 @@ class Trainer(TrainerIO): model.cuda(self.data_parallel_device_ids[0]) + # check for this bug (amp + dp + !01 doesn't work) + # https://github.com/NVIDIA/apex/issues/227 + if self.use_dp and self.use_amp and self.amp_level != 'O1': + m = f'amp level {self.amp_level} with DataParallel is not supported. ' \ + f'See this note from NVIDIA for more info: https://github.com/NVIDIA/apex/issues/227. ' \ + f'We recommend you switch to ddp if you want to use amp' + raise Exception(m) + # run through amp wrapper if self.use_amp: diff --git a/tests/debug.py b/tests/debug.py index 876075c5..7c8543d3 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -111,7 +111,7 @@ def main(): max_nb_epochs=1, gpus=[0, 1], distributed_backend='dp', - use_amp=False + use_amp=True ) result = trainer.fit(model) From 4d559d9e3b5badc5a84f4cf1e83026b80c981e31 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:12:41 -0400 Subject: [PATCH 089/222] fixed amp bug --- tests/test_models.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index b9bb4c65..f9b7b91c 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -98,13 +98,15 @@ def test_amp_gpu_dp(): warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') return - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - gpus=[0, 1], - distributed_backend='dp', - use_amp=True - ) + try: + trainer_options = dict( + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='dp', + use_amp=True + ) + except Exception as e: + assert 'https://github.com/NVIDIA/apex/issues/227' in e run_gpu_model_test(trainer_options) From ca1835e063d2c6cc1a5065e0a830bbedc8493687 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:14:36 -0400 Subject: [PATCH 090/222] fixed amp bug --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index f9b7b91c..fa478b93 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -106,7 +106,7 @@ def test_amp_gpu_dp(): use_amp=True ) except Exception as e: - assert 'https://github.com/NVIDIA/apex/issues/227' in e + assert 'https://github.com/NVIDIA/apex/issues/227' in str(e) run_gpu_model_test(trainer_options) From 5fe833ae015c58fb585591eb598bf9114409176c Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:16:05 -0400 Subject: [PATCH 091/222] fixed amp bug --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index fa478b93..be9db386 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -281,7 +281,7 @@ def run_prediction(dataloader, trained_model): print(val_acc) - assert val_acc > 0.70, f'this model is expected to get > 0.7 in test set (it got {val_acc})' + assert val_acc > 0.60, f'this model is expected to get > 0.6 in test set (it got {val_acc})' def assert_ok_acc(trainer): From 9e187574dec463f43c62a5560164bddc2486103e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:17:36 -0400 Subject: [PATCH 092/222] fixed amp bug --- tests/test_models.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index be9db386..96e99156 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -23,24 +23,16 @@ def test_cpu_model(): Make sure model trains on CPU :return: """ - save_dir = init_save_dir() - model, hparams = get_model() - - trainer = Trainer( + trainer_options = dict( progress_bar=False, experiment=get_exp(), max_nb_epochs=1, train_percent_check=0.4, val_percent_check=0.4 ) - result = trainer.fit(model) - # correct result and ok accuracy - assert result == 1, 'cpu model failed to complete' - assert_ok_acc(trainer) - - clear_save_dir() + run_gpu_model_test(trainer_options, on_gpu=False) def test_single_gpu_model(): @@ -162,7 +154,7 @@ def test_amp_gpu_ddp(): # UTILS # ------------------------------------------------------------------------ -def run_gpu_model_test(trainer_options): +def run_gpu_model_test(trainer_options, on_gpu=True): """ Make sure DDP + AMP work :return: @@ -197,7 +189,7 @@ def run_gpu_model_test(trainer_options): assert result == 1, 'amp + ddp model failed to complete' # test model loading - pretrained_model = load_model(exp, save_dir) + pretrained_model = load_model(exp, save_dir, on_gpu) # test model preds run_prediction(model.test_dataloader, pretrained_model) @@ -247,7 +239,7 @@ def clear_save_dir(): shutil.rmtree(save_dir) -def load_model(exp, save_dir): +def load_model(exp, save_dir, on_gpu): # load trained model tags_path = exp.get_data_path(exp.name, exp.version) @@ -256,7 +248,7 @@ def load_model(exp, save_dir): checkpoints = [x for x in os.listdir(save_dir) if '.ckpt' in x] weights_dir = os.path.join(save_dir, checkpoints[0]) - trained_model = LightningTemplateModel.load_from_metrics(weights_path=weights_dir, tags_csv=tags_path, on_gpu=True) + trained_model = LightningTemplateModel.load_from_metrics(weights_path=weights_dir, tags_csv=tags_path, on_gpu=on_gpu) assert trained_model is not None, 'loading model failed' From b20a122e9ccbb8a3cebf61e331709449f329a114 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:23:52 -0400 Subject: [PATCH 093/222] fixed amp bug --- pytorch_lightning/models/trainer.py | 4 ++-- pytorch_lightning/utils/debugging.py | 6 +++++- tests/test_models.py | 20 +++++++++----------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index b2f9b66e..4fe8493a 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -19,7 +19,7 @@ import tqdm from pytorch_lightning.root_module.memory import get_gpu_memory_map from pytorch_lightning.root_module.model_saving import TrainerIO from pytorch_lightning.pt_overrides.override_data_parallel import LightningDistributedDataParallel, LightningDataParallel -from pytorch_lightning.utils.debugging import ForkedPdb +from pytorch_lightning.utils.debugging import IncompatibleArgumentsException try: from apex import amp @@ -466,7 +466,7 @@ class Trainer(TrainerIO): m = f'amp level {self.amp_level} with DataParallel is not supported. ' \ f'See this note from NVIDIA for more info: https://github.com/NVIDIA/apex/issues/227. ' \ f'We recommend you switch to ddp if you want to use amp' - raise Exception(m) + raise IncompatibleArgumentsException(m) # run through amp wrapper if self.use_amp: diff --git a/pytorch_lightning/utils/debugging.py b/pytorch_lightning/utils/debugging.py index 7a4d1445..629dda9d 100644 --- a/pytorch_lightning/utils/debugging.py +++ b/pytorch_lightning/utils/debugging.py @@ -12,4 +12,8 @@ class ForkedPdb(pdb.Pdb): sys.stdin = open('/dev/stdin') pdb.Pdb.interaction(self, *args, **kwargs) finally: - sys.stdin = _stdin \ No newline at end of file + sys.stdin = _stdin + + +class IncompatibleArgumentsException(Exception): + pass \ No newline at end of file diff --git a/tests/test_models.py b/tests/test_models.py index 96e99156..6716fef5 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -4,6 +4,7 @@ from pytorch_lightning.examples.new_project_templates.lightning_module_template from argparse import Namespace from test_tube import Experiment from pytorch_lightning.callbacks import ModelCheckpoint +from pytorch_lightning.utils.debugging import IncompatibleArgumentsException import numpy as np import warnings import torch @@ -90,17 +91,14 @@ def test_amp_gpu_dp(): warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') return - try: - trainer_options = dict( - max_nb_epochs=1, - gpus=[0, 1], - distributed_backend='dp', - use_amp=True - ) - except Exception as e: - assert 'https://github.com/NVIDIA/apex/issues/227' in str(e) - - run_gpu_model_test(trainer_options) + trainer_options = dict( + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='dp', + use_amp=True + ) + with pytest.raises(IncompatibleArgumentsException): + run_gpu_model_test(trainer_options) def test_multi_gpu_model_ddp(): From 1ae91aac3264b49784ee002b4b3d48d12ec4fd81 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:30:31 -0400 Subject: [PATCH 094/222] moved port name --- pytorch_lightning/models/trainer.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 4fe8493a..f04b1fda 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -114,6 +114,7 @@ class Trainer(TrainerIO): """ # Transfer params + self.nb_gpu_nodes = nb_gpu_nodes self.gradient_clip = gradient_clip self.check_val_every_n_epoch = check_val_every_n_epoch @@ -149,6 +150,7 @@ class Trainer(TrainerIO): self.node_rank = 0 self.use_ddp = False self.use_dp = False + self.default_ddp_port = 12910 # training bookeeping self.total_batch_nb = 0 @@ -396,10 +398,13 @@ class Trainer(TrainerIO): # ----------------------------- # MODEL TRAINING # ----------------------------- + def __kill_ddp_ports(self, port_nb): def fit(self, model): # when using multi-node or DDP within a node start each module in a separate process if self.use_ddp: + self.__kill_ddp_ports(self.default_ddp_port) + # must copy only the meta of the exp so it survives pickle/unpickle when going to new process self.experiment = self.experiment.get_meta_copy() @@ -548,12 +553,14 @@ class Trainer(TrainerIO): try: port = os.environ['MASTER_PORT'] except Exception as e: - port = 12910 + port = self.default_ddp_port os.environ['MASTER_PORT'] = f'{port}' root_node = self.__resolve_root_node_address() os.environ['MASTER_ADDR'] = root_node + self.default_ddp_port = port + dist.init_process_group("nccl", rank=self.proc_rank, world_size=self.world_size) From 8f06118154c1ba2803d3ff04b5af2251660109aa Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:36:29 -0400 Subject: [PATCH 095/222] auto port kill before starting ddp --- pytorch_lightning/models/trainer.py | 45 ++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index f04b1fda..01f10515 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -150,7 +150,7 @@ class Trainer(TrainerIO): self.node_rank = 0 self.use_ddp = False self.use_dp = False - self.default_ddp_port = 12910 + self._ddp_port = None # training bookeeping self.total_batch_nb = 0 @@ -399,11 +399,29 @@ class Trainer(TrainerIO): # MODEL TRAINING # ----------------------------- def __kill_ddp_ports(self, port_nb): + def get_pids(port): + command = "sudo lsof -i :%s | awk '{print $2}'" % port + pids = subprocess.check_output(command, shell=True) + pids = pids.strip() + if pids: + pids = re.sub(' +', ' ', pids) + for pid in pids.split('\n'): + try: + yield int(pid) + except: + pass + + # kill all processes on this port + pids = set(get_pids(port_nb)) + command = 'sudo kill -9 {}'.format(' '.join([str(pid) for pid in pids])) + os.system(command) + + def fit(self, model): # when using multi-node or DDP within a node start each module in a separate process if self.use_ddp: - self.__kill_ddp_ports(self.default_ddp_port) + self.__kill_ddp_ports(self.ddp_port) # must copy only the meta of the exp so it survives pickle/unpickle when going to new process self.experiment = self.experiment.get_meta_copy() @@ -542,6 +560,19 @@ class Trainer(TrainerIO): # continue training routine self.__run_pretrain_routine(model) + @property + def ddp_port(self): + if self._ddp_port is None: + try: + port = os.environ['MASTER_PORT'] + except Exception as e: + port = self.default_ddp_port + os.environ['MASTER_PORT'] = f'{port}' + + self._ddp_port = port + + return self._ddp_port + def __init_tcp_connection(self): """ Connect all procs in the world using the env:// init @@ -550,17 +581,11 @@ class Trainer(TrainerIO): :param tries: :return: """ - try: - port = os.environ['MASTER_PORT'] - except Exception as e: - port = self.default_ddp_port - os.environ['MASTER_PORT'] = f'{port}' + # sets the appropriate port + _ = self.ddp_port root_node = self.__resolve_root_node_address() os.environ['MASTER_ADDR'] = root_node - - self.default_ddp_port = port - dist.init_process_group("nccl", rank=self.proc_rank, world_size=self.world_size) From 446a44b085a2a7931d1c12d993ddaa0729a94882 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:36:47 -0400 Subject: [PATCH 096/222] auto port kill before starting ddp --- pytorch_lightning/models/trainer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 01f10515..acb2964b 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -421,6 +421,7 @@ class Trainer(TrainerIO): # when using multi-node or DDP within a node start each module in a separate process if self.use_ddp: + # clear any processes running on the ddp port self.__kill_ddp_ports(self.ddp_port) # must copy only the meta of the exp so it survives pickle/unpickle when going to new process From 5439dc0844d8d73ce741bf83d60c32ff6cc47e16 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:38:09 -0400 Subject: [PATCH 097/222] auto port kill before starting ddp --- pytorch_lightning/models/trainer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index acb2964b..16870931 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -567,7 +567,7 @@ class Trainer(TrainerIO): try: port = os.environ['MASTER_PORT'] except Exception as e: - port = self.default_ddp_port + port = 12910 os.environ['MASTER_PORT'] = f'{port}' self._ddp_port = port From 34ddb0ec98b847dee8438fce73c87175005e4011 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:45:47 -0400 Subject: [PATCH 098/222] added auto port find --- pytorch_lightning/models/trainer.py | 43 +++++++++++++---------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 16870931..55fd27dd 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -150,7 +150,6 @@ class Trainer(TrainerIO): self.node_rank = 0 self.use_ddp = False self.use_dp = False - self._ddp_port = None # training bookeeping self.total_batch_nb = 0 @@ -398,7 +397,15 @@ class Trainer(TrainerIO): # ----------------------------- # MODEL TRAINING # ----------------------------- - def __kill_ddp_ports(self, port_nb): + def __find_open_port(self, port=None): + + if port is None: + try: + port = os.environ['MASTER_PORT'] + except Exception as e: + port = 12910 + os.environ['MASTER_PORT'] = f'{port}' + def get_pids(port): command = "sudo lsof -i :%s | awk '{print $2}'" % port pids = subprocess.check_output(command, shell=True) @@ -411,19 +418,21 @@ class Trainer(TrainerIO): except: pass - # kill all processes on this port - pids = set(get_pids(port_nb)) - command = 'sudo kill -9 {}'.format(' '.join([str(pid) for pid in pids])) - os.system(command) + # get pids in this port + pids = set(get_pids(port)) + # if no processes on this port, then we're good + if len(pids) == 0: + return + + # port wasn't open. Pick a new port and keep trying + port = int(port) + 1 + self.__find_open_port(str(port)) def fit(self, model): # when using multi-node or DDP within a node start each module in a separate process if self.use_ddp: - # clear any processes running on the ddp port - self.__kill_ddp_ports(self.ddp_port) - # must copy only the meta of the exp so it survives pickle/unpickle when going to new process self.experiment = self.experiment.get_meta_copy() @@ -561,19 +570,6 @@ class Trainer(TrainerIO): # continue training routine self.__run_pretrain_routine(model) - @property - def ddp_port(self): - if self._ddp_port is None: - try: - port = os.environ['MASTER_PORT'] - except Exception as e: - port = 12910 - os.environ['MASTER_PORT'] = f'{port}' - - self._ddp_port = port - - return self._ddp_port - def __init_tcp_connection(self): """ Connect all procs in the world using the env:// init @@ -583,13 +579,12 @@ class Trainer(TrainerIO): :return: """ # sets the appropriate port - _ = self.ddp_port + self.__find_open_port() root_node = self.__resolve_root_node_address() os.environ['MASTER_ADDR'] = root_node dist.init_process_group("nccl", rank=self.proc_rank, world_size=self.world_size) - def __resolve_root_node_address(self): try: root_node = os.environ['SLURM_NODELIST'].split(' ')[0] From 01c0d9a2d45f2fa41dc099b7656d5c8198d96aef Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:48:56 -0400 Subject: [PATCH 099/222] added auto port find --- tests/debug.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 7c8543d3..32eaf7a0 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -127,6 +127,20 @@ def main(): clear_save_dir() +import subprocess +import re + +def get_pids(port): + command = "sudo lsof -i :%s | awk '{print $2}'" % port + pids = subprocess.check_output(command, shell=True) + pids = pids.strip() + if pids: + pids = re.sub(' +', ' ', pids) + for pid in pids.split('\n'): + try: + yield int(pid) + except: + pass if __name__ == '__main__': - main() \ No newline at end of file + get_pids(12910) \ No newline at end of file From 4b2096d2c697a7118490a5b5e5db7ac1a00124e1 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:52:19 -0400 Subject: [PATCH 100/222] added auto port find --- pytorch_lightning/utils/server.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 pytorch_lightning/utils/server.py diff --git a/pytorch_lightning/utils/server.py b/pytorch_lightning/utils/server.py new file mode 100644 index 00000000..455389d2 --- /dev/null +++ b/pytorch_lightning/utils/server.py @@ -0,0 +1,10 @@ +import socket + +s = socket.socket() +host = socket.gethostname() # Get local machine name +port = 12910 # Reserve a port for your service. +s.bind((host, port)) # Bind to the port + +s.listen(5) # Now wait for client connection. +while True: + c, addr = s.accept() # Establish connection with client. \ No newline at end of file From d0343604b31cc1019cebff64ce81a5f73283ba75 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:53:08 -0400 Subject: [PATCH 101/222] added auto port find --- pytorch_lightning/utils/{server.py => sherver.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pytorch_lightning/utils/{server.py => sherver.py} (100%) diff --git a/pytorch_lightning/utils/server.py b/pytorch_lightning/utils/sherver.py similarity index 100% rename from pytorch_lightning/utils/server.py rename to pytorch_lightning/utils/sherver.py From 0c239da17c9116cf8b3324bfec5a5737d4a93c93 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:54:20 -0400 Subject: [PATCH 102/222] added auto port find --- tests/debug.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/debug.py b/tests/debug.py index 32eaf7a0..770cb37a 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -134,6 +134,7 @@ def get_pids(port): command = "sudo lsof -i :%s | awk '{print $2}'" % port pids = subprocess.check_output(command, shell=True) pids = pids.strip() + print(pids) if pids: pids = re.sub(' +', ' ', pids) for pid in pids.split('\n'): From e52190e22bf8bbf97906333b9515d668c33bfb8a Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:55:00 -0400 Subject: [PATCH 103/222] added auto port find --- tests/debug.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index 770cb37a..11ca8c65 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -127,10 +127,11 @@ def main(): clear_save_dir() -import subprocess -import re def get_pids(port): + import subprocess + import re + command = "sudo lsof -i :%s | awk '{print $2}'" % port pids = subprocess.check_output(command, shell=True) pids = pids.strip() From 865117392092f5f6f26256eeb218070143eecabd Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:55:26 -0400 Subject: [PATCH 104/222] added auto port find --- tests/debug.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/debug.py b/tests/debug.py index 11ca8c65..52bd0ec5 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -132,6 +132,7 @@ def get_pids(port): import subprocess import re + print('getting pid') command = "sudo lsof -i :%s | awk '{print $2}'" % port pids = subprocess.check_output(command, shell=True) pids = pids.strip() From 9a3f373d16275e859c480e7512401d7b192668d3 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:56:35 -0400 Subject: [PATCH 105/222] added auto port find --- tests/debug.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 52bd0ec5..cb6306ed 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -91,7 +91,7 @@ def run_prediction(dataloader, trained_model): assert val_acc > 0.70, f'this model is expected to get > 0.7 in test set (it got {val_acc})' -def main(): +def mainasdf(): save_dir = init_save_dir() model, hparams = get_model() @@ -145,5 +145,6 @@ def get_pids(port): except: pass + if __name__ == '__main__': get_pids(12910) \ No newline at end of file From 46886f0c3cd8babe63573388a7b91191665c1662 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:57:09 -0400 Subject: [PATCH 106/222] added auto port find --- tests/debug.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index cb6306ed..473df9bf 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -128,12 +128,14 @@ def mainasdf(): clear_save_dir() -def get_pids(port): + + +if __name__ == '__main__': import subprocess import re print('getting pid') - command = "sudo lsof -i :%s | awk '{print $2}'" % port + command = "sudo lsof -i :%s | awk '{print $2}'" % 12910 pids = subprocess.check_output(command, shell=True) pids = pids.strip() print(pids) @@ -143,8 +145,4 @@ def get_pids(port): try: yield int(pid) except: - pass - - -if __name__ == '__main__': - get_pids(12910) \ No newline at end of file + pass \ No newline at end of file From afa25a26d9fe94189778517c18f8621406648217 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:57:17 -0400 Subject: [PATCH 107/222] added auto port find --- tests/debug.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/debug.py b/tests/debug.py index 473df9bf..bb71bc97 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -139,10 +139,3 @@ if __name__ == '__main__': pids = subprocess.check_output(command, shell=True) pids = pids.strip() print(pids) - if pids: - pids = re.sub(' +', ' ', pids) - for pid in pids.split('\n'): - try: - yield int(pid) - except: - pass \ No newline at end of file From e3f01388dfc42994da3a782336617f479c4a5b6b Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:57:54 -0400 Subject: [PATCH 108/222] added auto port find --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index bb71bc97..4e2675b5 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -135,7 +135,7 @@ if __name__ == '__main__': import re print('getting pid') - command = "sudo lsof -i :%s | awk '{print $2}'" % 12910 + command = "lsof -i :%s | awk '{print $2}'" % 12910 pids = subprocess.check_output(command, shell=True) pids = pids.strip() print(pids) From 98be54de8092c79996ed4d1ff1fabf846b0e4d85 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:59:40 -0400 Subject: [PATCH 109/222] added auto port find --- pytorch_lightning/models/trainer.py | 19 +++++-------------- tests/debug.py | 1 + 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 55fd27dd..23f426f6 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -406,20 +406,11 @@ class Trainer(TrainerIO): port = 12910 os.environ['MASTER_PORT'] = f'{port}' - def get_pids(port): - command = "sudo lsof -i :%s | awk '{print $2}'" % port - pids = subprocess.check_output(command, shell=True) - pids = pids.strip() - if pids: - pids = re.sub(' +', ' ', pids) - for pid in pids.split('\n'): - try: - yield int(pid) - except: - pass - - # get pids in this port - pids = set(get_pids(port)) + # check for pids + command = "lsof -i :%s | awk '{print $2}'" % port + pids = subprocess.check_output(command, shell=True) + pids = pids.strip() + pids = str(pids) # if no processes on this port, then we're good if len(pids) == 0: diff --git a/tests/debug.py b/tests/debug.py index 4e2675b5..9111c663 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -138,4 +138,5 @@ if __name__ == '__main__': command = "lsof -i :%s | awk '{print $2}'" % 12910 pids = subprocess.check_output(command, shell=True) pids = pids.strip() + print(pids) From 90ff41801791bf4417a3f1c9526d1ec4f1626158 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 14:59:51 -0400 Subject: [PATCH 110/222] added auto port find --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 9111c663..1699fe36 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -139,4 +139,4 @@ if __name__ == '__main__': pids = subprocess.check_output(command, shell=True) pids = pids.strip() - print(pids) + print(str(pids)) From b5c67d91e54c6a2eb91d96de05d85f68311f8a4f Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:00:14 -0400 Subject: [PATCH 111/222] added auto port find --- tests/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debug.py b/tests/debug.py index 1699fe36..d8204ed8 100644 --- a/tests/debug.py +++ b/tests/debug.py @@ -139,4 +139,4 @@ if __name__ == '__main__': pids = subprocess.check_output(command, shell=True) pids = pids.strip() - print(str(pids)) + print(len(pids)) From 9f0d963e37ed8d3f76afbda7f9d8a2a9fe3222de Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:08:59 -0400 Subject: [PATCH 112/222] added auto port find --- pytorch_lightning/models/trainer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 23f426f6..2f26e915 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -403,7 +403,7 @@ class Trainer(TrainerIO): try: port = os.environ['MASTER_PORT'] except Exception as e: - port = 12910 + port = 12801 os.environ['MASTER_PORT'] = f'{port}' # check for pids From b1e16c2e7bc7e7c98cd29df395488a6c43af0ce8 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:11:29 -0400 Subject: [PATCH 113/222] added auto port find --- pytorch_lightning/models/trainer.py | 6 +++++- tests/test_models.py | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 2f26e915..e098ba9a 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -570,7 +570,11 @@ class Trainer(TrainerIO): :return: """ # sets the appropriate port - self.__find_open_port() + try: + port = os.environ['MASTER_PORT'] + except Exception as e: + port = 12910 + os.environ['MASTER_PORT'] = f'{port}' root_node = self.__resolve_root_node_address() os.environ['MASTER_ADDR'] = root_node diff --git a/tests/test_models.py b/tests/test_models.py index 6716fef5..5159b33e 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -113,6 +113,8 @@ def test_multi_gpu_model_ddp(): warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') return + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + trainer_options = dict( progress_bar=False, max_nb_epochs=1, @@ -137,6 +139,8 @@ def test_amp_gpu_ddp(): warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') return + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + trainer_options = dict( progress_bar=True, max_nb_epochs=1, From 8b6217733a7f6364e8e551738fbb6a2958b6febc Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:11:50 -0400 Subject: [PATCH 114/222] added auto port find --- pytorch_lightning/models/trainer.py | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index e098ba9a..7875b5da 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -397,29 +397,6 @@ class Trainer(TrainerIO): # ----------------------------- # MODEL TRAINING # ----------------------------- - def __find_open_port(self, port=None): - - if port is None: - try: - port = os.environ['MASTER_PORT'] - except Exception as e: - port = 12801 - os.environ['MASTER_PORT'] = f'{port}' - - # check for pids - command = "lsof -i :%s | awk '{print $2}'" % port - pids = subprocess.check_output(command, shell=True) - pids = pids.strip() - pids = str(pids) - - # if no processes on this port, then we're good - if len(pids) == 0: - return - - # port wasn't open. Pick a new port and keep trying - port = int(port) + 1 - self.__find_open_port(str(port)) - def fit(self, model): # when using multi-node or DDP within a node start each module in a separate process From 1a6ee20dff887f404b1ef90ceed90dd292587ea5 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:15:14 -0400 Subject: [PATCH 115/222] removed old files --- pytorch_lightning/utils/embeddings.py | 104 -------------------------- pytorch_lightning/utils/plotting.py | 28 ------- pytorch_lightning/utils/sherver.py | 10 --- 3 files changed, 142 deletions(-) delete mode 100644 pytorch_lightning/utils/embeddings.py delete mode 100644 pytorch_lightning/utils/plotting.py delete mode 100644 pytorch_lightning/utils/sherver.py diff --git a/pytorch_lightning/utils/embeddings.py b/pytorch_lightning/utils/embeddings.py deleted file mode 100644 index 4e96c61b..00000000 --- a/pytorch_lightning/utils/embeddings.py +++ /dev/null @@ -1,104 +0,0 @@ -import torch -import numpy as np -from copy import deepcopy - - -class PretrainedEmbedding(torch.nn.Embedding): - - def __init__(self, embedding_path, embedding_dim, task_vocab, freeze=True, *args, **kwargs): - """ - Loads a prebuilt pytorch embedding from any embedding formated file. - Padding=0 by default. - - >>> emb = PretrainedEmbedding(embedding_path='glove.840B.300d.txt',embedding_dim=300, task_vocab={'hello': 1, 'world': 2}) - >>> data = torch.Tensor([[0, 1], [0, 2]]).long() - >>> embedded = emb(data) - - - - :param embedding_path: - :param emb_dim: - :param task_vocab: - :param freeze: - :return: - """ - # count the vocab - self.vocab_size = max(task_vocab.values()) + 1 - super(PretrainedEmbedding, self).__init__(self.vocab_size, embedding_dim, padding_idx=0, *args, **kwargs) - - # load pretrained embeddings - new_emb = self.__load_task_specific_embeddings(deepcopy(task_vocab), embedding_path, embedding_dim, freeze) - - # transfer weights - self.weight = new_emb.weight - - # apply freeze - should_freeze = not freeze - self.weight.requires_grad = should_freeze - - def __load_task_specific_embeddings(self, vocab_words, embedding_path, emb_dim, freeze): - """ - Iterates embedding file to only pull out task specific embeddings - :param vocab_words: - :param embedding_path: - :param emb_dim: - :param freeze: - :return: - """ - - # holds final embeddings for relevant words - embeddings = np.zeros(shape=(self.vocab_size, emb_dim)) - - # load embedding line by line and extract relevant embeddings - with open(embedding_path, encoding='utf-8') as f: - for line in f: - tokens = line.split(' ') - word = tokens[0] - embedding = tokens[1:] - embedding[-1] = embedding[-1][:-1] # remove last new line - - if word in vocab_words: - vocab_word_i = vocab_words[word] - - # skip words that try to overwrite pad idx - if vocab_word_i == 0: - del vocab_words[word] - continue - - emb_vals = np.asarray([float(x) for x in embedding]) - embeddings[vocab_word_i] = emb_vals - - # remove vocab word to early terminate - del vocab_words[word] - - # early break - if len(vocab_words) == 0: - break - - # add random vectors for the non-pretrained words - # these are vocab words NOT found in the pretrained embeddings - for w, i in vocab_words.items(): - # skip words that try to overwrite pad idx - if i == 0: - continue - - embedding = np.random.normal(size=emb_dim) - embeddings[i] = embedding - - # turn into pt embedding - embeddings = torch.FloatTensor(embeddings) - embeddings = torch.nn.Embedding.from_pretrained(embeddings, freeze=freeze) - - return embeddings - - -if __name__ == '__main__': - emb = PretrainedEmbedding( - embedding_path='/Users/waf/Developer', - embedding_dim=300, - task_vocab={'hello': 1, 'world': 2} - ) - - data = torch.Tensor([[0, 1], [0, 2]]).long() - embedded = emb(data) - print(embedded) diff --git a/pytorch_lightning/utils/plotting.py b/pytorch_lightning/utils/plotting.py deleted file mode 100644 index 3a8da113..00000000 --- a/pytorch_lightning/utils/plotting.py +++ /dev/null @@ -1,28 +0,0 @@ -import numpy as np -np.seterr(divide='ignore', invalid='ignore') - - -def plot_confusion_matrix(cm, - save_path, - normalize=False, - title='Confusion matrix', - ylabel='y', - xlabel='x'): - """ - This function prints and plots the confusion matrix. - Normalization can be applied by setting `normalize=True`. - """ - from matplotlib import pyplot as plt - if normalize: - cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis] - print("Normalized confusion matrix") - else: - print('Confusion matrix, without normalization') - - fig = plt.figure() - plt.matshow(cm) - plt.title(title) - plt.colorbar() - plt.ylabel(ylabel) - plt.xlabel(xlabel) - plt.savefig(save_path) diff --git a/pytorch_lightning/utils/sherver.py b/pytorch_lightning/utils/sherver.py deleted file mode 100644 index 455389d2..00000000 --- a/pytorch_lightning/utils/sherver.py +++ /dev/null @@ -1,10 +0,0 @@ -import socket - -s = socket.socket() -host = socket.gethostname() # Get local machine name -port = 12910 # Reserve a port for your service. -s.bind((host, port)) # Bind to the port - -s.listen(5) # Now wait for client connection. -while True: - c, addr = s.accept() # Establish connection with client. \ No newline at end of file From 1f67fbdb80a52292e15dfd8a1c6537d17e97d400 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:23:38 -0400 Subject: [PATCH 116/222] removed old files --- tests/test_models.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index 5159b33e..1717adc5 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -35,6 +35,26 @@ def test_cpu_model(): run_gpu_model_test(trainer_options, on_gpu=False) +def test_all_features_cpu_model(): + """ + Make sure model trains on CPU + :return: + """ + + trainer_options = dict( + gradient_clip=1.0, + overfit_pct=0.20, + track_grad_norm=2, + print_nan_grads=True, + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + run_gpu_model_test(trainer_options, on_gpu=False) + def test_single_gpu_model(): """ From bc40be3490d4e379d1c17a830a5a5564e54b3c76 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:23:52 -0400 Subject: [PATCH 117/222] removed old files --- tests/test_models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 1717adc5..4bcae380 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -35,9 +35,10 @@ def test_cpu_model(): run_gpu_model_test(trainer_options, on_gpu=False) + def test_all_features_cpu_model(): """ - Make sure model trains on CPU + Test each of the trainer options :return: """ From ebc120a3c3d9096476eda137ff276a5694a2eabf Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:27:59 -0400 Subject: [PATCH 118/222] removed forkedpdb --- pytorch_lightning/utils/debugging.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pytorch_lightning/utils/debugging.py b/pytorch_lightning/utils/debugging.py index 629dda9d..d313bfcd 100644 --- a/pytorch_lightning/utils/debugging.py +++ b/pytorch_lightning/utils/debugging.py @@ -1,19 +1,5 @@ import pdb import sys -class ForkedPdb(pdb.Pdb): - """A Pdb subclass that may be used - from a forked multiprocessing child - - """ - def interaction(self, *args, **kwargs): - _stdin = sys.stdin - try: - sys.stdin = open('/dev/stdin') - pdb.Pdb.interaction(self, *args, **kwargs) - finally: - sys.stdin = _stdin - - class IncompatibleArgumentsException(Exception): pass \ No newline at end of file From 79c0054c3839d6220b26f53908de2d6350db34fb Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:28:23 -0400 Subject: [PATCH 119/222] removed forkedpdb --- tests/test_models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 4bcae380..5ed769a0 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -296,13 +296,13 @@ def run_prediction(dataloader, trained_model): print(val_acc) - assert val_acc > 0.60, f'this model is expected to get > 0.6 in test set (it got {val_acc})' + assert val_acc > 0.55, f'this model is expected to get > 0.55 in test set (it got {val_acc})' def assert_ok_acc(trainer): # this model should get 0.80+ acc acc = trainer.tng_tqdm_dic['val_acc'] - assert acc > 0.60, f'model failed to get expected 0.60 validation accuracy. Got: {acc}' + assert acc > 0.55, f'model failed to get expected 0.55 validation accuracy. Got: {acc}' if __name__ == '__main__': From 74d714f1597240df6019990984ba6ef6f5a1f80a Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:33:08 -0400 Subject: [PATCH 120/222] removed opt check --- pytorch_lightning/root_module/optimization.py | 22 ------------------- pytorch_lightning/root_module/root_module.py | 3 +-- 2 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 pytorch_lightning/root_module/optimization.py diff --git a/pytorch_lightning/root_module/optimization.py b/pytorch_lightning/root_module/optimization.py deleted file mode 100644 index 3172e1a1..00000000 --- a/pytorch_lightning/root_module/optimization.py +++ /dev/null @@ -1,22 +0,0 @@ -from torch import nn -from torch import optim - - -class OptimizerConfig(nn.Module): - - def choose_optimizer(self, optimizer, params, optimizer_params, opt_name_key): - if optimizer == 'adam': - optimizer = optim.Adam(params, **optimizer_params) - if optimizer == 'sparse_adam': - optimizer = optim.SparseAdam(params, **optimizer_params) - if optimizer == 'sgd': - optimizer = optim.SGD(params, **optimizer_params) - if optimizer == 'adadelta': - optimizer = optim.Adadelta(params, **optimizer_params) - - # transfer opt state if loaded - if opt_name_key in self.loaded_optimizer_states_dict: - state = self.loaded_optimizer_states_dict[opt_name_key] - optimizer.load_state_dict(state) - - return optimizer diff --git a/pytorch_lightning/root_module/root_module.py b/pytorch_lightning/root_module/root_module.py index e2013d7a..2345997b 100644 --- a/pytorch_lightning/root_module/root_module.py +++ b/pytorch_lightning/root_module/root_module.py @@ -5,11 +5,10 @@ import math from pytorch_lightning.root_module.memory import ModelSummary from pytorch_lightning.root_module.grads import GradInformation from pytorch_lightning.root_module.model_saving import ModelIO, load_hparams_from_tags_csv -from pytorch_lightning.root_module.optimization import OptimizerConfig from pytorch_lightning.root_module.hooks import ModelHooks -class LightningModule(GradInformation, ModelIO, OptimizerConfig, ModelHooks): +class LightningModule(GradInformation, ModelIO, ModelHooks): def __init__(self, hparams): super(LightningModule, self).__init__() From 08c76c47bd092460d7840a362eaba58c68efa908 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:38:15 -0400 Subject: [PATCH 121/222] removed opt check --- setup.cfg | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/setup.cfg b/setup.cfg index c7616dab..268362a1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,3 +19,14 @@ max-line-length = 120 [flake8] ignore = E731,W504,F401,F841 max-line-length = 120 + +[report] +exclude_lines = + pragma: no cover + def __repr__ + if self.debug: + if settings.DEBUG + raise AssertionError + raise NotImplementedError + if 0: + if __name__ == .__main__.: From b836e6f3213a52c0ba62750fee01b3e014e131a8 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:43:10 -0400 Subject: [PATCH 122/222] removed dead code in model save --- pytorch_lightning/root_module/model_saving.py | 29 ------------------- setup.cfg | 2 ++ 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/pytorch_lightning/root_module/model_saving.py b/pytorch_lightning/root_module/model_saving.py index 818c1947..0569c890 100644 --- a/pytorch_lightning/root_module/model_saving.py +++ b/pytorch_lightning/root_module/model_saving.py @@ -184,32 +184,3 @@ class TrainerIO(object): return max(ckpt_vs) - -def load_hparams_from_tags_csv(tags_csv): - from argparse import Namespace - import pandas as pd - - tags_df = pd.read_csv(tags_csv) - dic = tags_df.to_dict(orient='records') - - ns_dict = {row['key']: convert(row['value']) for row in dic} - - ns = Namespace(**ns_dict) - return ns - - -def convert(val): - constructors = [int, float, str] - - if type(val) is str: - if val.lower() == 'true': - return True - if val.lower() == 'false': - return False - - for c in constructors: - try: - return c(val) - except ValueError: - pass - return val diff --git a/setup.cfg b/setup.cfg index 268362a1..8aea30d4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,3 +30,5 @@ exclude_lines = raise NotImplementedError if 0: if __name__ == .__main__.: + pt_callbacks.py + From b7ca8574347eeb56e83811f9be5d1fa55ed68ef1 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:44:04 -0400 Subject: [PATCH 123/222] removed dead code in model save --- pytorch_lightning/root_module/model_saving.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/pytorch_lightning/root_module/model_saving.py b/pytorch_lightning/root_module/model_saving.py index 0569c890..818c1947 100644 --- a/pytorch_lightning/root_module/model_saving.py +++ b/pytorch_lightning/root_module/model_saving.py @@ -184,3 +184,32 @@ class TrainerIO(object): return max(ckpt_vs) + +def load_hparams_from_tags_csv(tags_csv): + from argparse import Namespace + import pandas as pd + + tags_df = pd.read_csv(tags_csv) + dic = tags_df.to_dict(orient='records') + + ns_dict = {row['key']: convert(row['value']) for row in dic} + + ns = Namespace(**ns_dict) + return ns + + +def convert(val): + constructors = [int, float, str] + + if type(val) is str: + if val.lower() == 'true': + return True + if val.lower() == 'false': + return False + + for c in constructors: + try: + return c(val) + except ValueError: + pass + return val From d4d0f54a3775353a2e3109dc938b0515d148896e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:48:35 -0400 Subject: [PATCH 124/222] removed dead code in model save --- tests/test_models.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 5ed769a0..f7fd65e2 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -3,7 +3,7 @@ from pytorch_lightning import Trainer from pytorch_lightning.examples.new_project_templates.lightning_module_template import LightningTemplateModel from argparse import Namespace from test_tube import Experiment -from pytorch_lightning.callbacks import ModelCheckpoint +from pytorch_lightning.callbacks import ModelCheckpoint, EarlyStopping from pytorch_lightning.utils.debugging import IncompatibleArgumentsException import numpy as np import warnings @@ -57,6 +57,28 @@ def test_all_features_cpu_model(): run_gpu_model_test(trainer_options, on_gpu=False) +def test_early_stopping_cpu_model(): + """ + Test each of the trainer options + :return: + """ + + stopping = EarlyStopping() + trainer_options = dict( + early_stop_callback=stopping, + gradient_clip=1.0, + overfit_pct=0.20, + track_grad_norm=2, + print_nan_grads=True, + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + run_gpu_model_test(trainer_options, on_gpu=False) + def test_single_gpu_model(): """ Make sure single GPU works (DP mode) From 9b792bf4d4ef59903278f9b637afb92082e82a88 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:48:41 -0400 Subject: [PATCH 125/222] removed dead code in model save --- tests/test_models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_models.py b/tests/test_models.py index f7fd65e2..2596b303 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -79,6 +79,7 @@ def test_early_stopping_cpu_model(): run_gpu_model_test(trainer_options, on_gpu=False) + def test_single_gpu_model(): """ Make sure single GPU works (DP mode) From ea7be12bb12ea1f57a0b5bc17fd875566e1dacff Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:52:59 -0400 Subject: [PATCH 126/222] added coverage file --- .coveragerc | 11 +++++++++++ setup.cfg | 13 ------------- 2 files changed, 11 insertions(+), 13 deletions(-) create mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..79ef4df5 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,11 @@ +[report] +exclude_lines = + pragma: no cover + def __repr__ + if self.debug: + if settings.DEBUG + raise AssertionError + raise NotImplementedError + if 0: + if __name__ == .__main__.: + pt_callbacks.py \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 8aea30d4..c7616dab 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,16 +19,3 @@ max-line-length = 120 [flake8] ignore = E731,W504,F401,F841 max-line-length = 120 - -[report] -exclude_lines = - pragma: no cover - def __repr__ - if self.debug: - if settings.DEBUG - raise AssertionError - raise NotImplementedError - if 0: - if __name__ == .__main__.: - pt_callbacks.py - From 23e09861414242d61025114956f88023d451876c Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:54:14 -0400 Subject: [PATCH 127/222] removed coverage file --- .coveragerc | 11 ----------- setup.cfg | 13 +++++++++++++ 2 files changed, 13 insertions(+), 11 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 79ef4df5..00000000 --- a/.coveragerc +++ /dev/null @@ -1,11 +0,0 @@ -[report] -exclude_lines = - pragma: no cover - def __repr__ - if self.debug: - if settings.DEBUG - raise AssertionError - raise NotImplementedError - if 0: - if __name__ == .__main__.: - pt_callbacks.py \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index c7616dab..c77568ed 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,3 +19,16 @@ max-line-length = 120 [flake8] ignore = E731,W504,F401,F841 max-line-length = 120 + +[coverage:run] +exclude_lines = + pragma: no cover + def __repr__ + if self.debug: + if settings.DEBUG + raise AssertionError + raise NotImplementedError + if 0: + if __name__ == .__main__.: + pt_callbacks.py + From e3ed5bfbc77569da6ec25457fb4d6dd1c824c21f Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:56:27 -0400 Subject: [PATCH 128/222] added coverage file --- .coveragerc | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..dd7f9920 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,30 @@ +# .coveragerc to control coverage.py +[run] +branch = True + +[report] +# Regexes for lines to exclude from consideration +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain about missing debug-only code: + def __repr__ + if self\.debug + + # Don't complain if tests don't hit defensive assertion code: + raise AssertionError + raise NotImplementedError + + # Don't complain if non-runnable code isn't run: + if 0: + if __name__ == .__main__.: + + pragma: no cover + if settings.DEBUG + pt_callbacks.py + +ignore_errors = True + +[html] +directory = coverage_html_report \ No newline at end of file From cc875cd60372fe22546fcfc06543c05c4dbb8afc Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:56:33 -0400 Subject: [PATCH 129/222] added coverage file --- setup.cfg | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/setup.cfg b/setup.cfg index c77568ed..8a653754 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,15 +20,3 @@ max-line-length = 120 ignore = E731,W504,F401,F841 max-line-length = 120 -[coverage:run] -exclude_lines = - pragma: no cover - def __repr__ - if self.debug: - if settings.DEBUG - raise AssertionError - raise NotImplementedError - if 0: - if __name__ == .__main__.: - pt_callbacks.py - From eae4fa0495f06662430855afedbadc3d43f0e129 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 15:57:18 -0400 Subject: [PATCH 130/222] added coverage file --- .coveragerc | 30 ------------------------------ setup.cfg | 12 ++++++++++++ 2 files changed, 12 insertions(+), 30 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index dd7f9920..00000000 --- a/.coveragerc +++ /dev/null @@ -1,30 +0,0 @@ -# .coveragerc to control coverage.py -[run] -branch = True - -[report] -# Regexes for lines to exclude from consideration -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - - # Don't complain about missing debug-only code: - def __repr__ - if self\.debug - - # Don't complain if tests don't hit defensive assertion code: - raise AssertionError - raise NotImplementedError - - # Don't complain if non-runnable code isn't run: - if 0: - if __name__ == .__main__.: - - pragma: no cover - if settings.DEBUG - pt_callbacks.py - -ignore_errors = True - -[html] -directory = coverage_html_report \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 8a653754..c77568ed 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,3 +20,15 @@ max-line-length = 120 ignore = E731,W504,F401,F841 max-line-length = 120 +[coverage:run] +exclude_lines = + pragma: no cover + def __repr__ + if self.debug: + if settings.DEBUG + raise AssertionError + raise NotImplementedError + if 0: + if __name__ == .__main__.: + pt_callbacks.py + From 843675e9a1730a25651a91e031d258758d8a5a3e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:00:48 -0400 Subject: [PATCH 131/222] added coverage file --- setup.cfg | 2 -- 1 file changed, 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index c77568ed..2e98fb6c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,5 +30,3 @@ exclude_lines = raise NotImplementedError if 0: if __name__ == .__main__.: - pt_callbacks.py - From dfccc03da8214a4c9c0d5c373c85c24b5dfb409e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:04:18 -0400 Subject: [PATCH 132/222] added coverage file --- setup.cfg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.cfg b/setup.cfg index 2e98fb6c..7ce0077f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,10 +16,6 @@ markers = ignore = E731,W504 max-line-length = 120 -[flake8] -ignore = E731,W504,F401,F841 -max-line-length = 120 - [coverage:run] exclude_lines = pragma: no cover @@ -30,3 +26,7 @@ exclude_lines = raise NotImplementedError if 0: if __name__ == .__main__.: + +[flake8] +ignore = E731,W504,F401,F841 +max-line-length = 120 From cfd2792d76b2fb345b71344f4989bb517f629193 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:04:36 -0400 Subject: [PATCH 133/222] added coverage file --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 7ce0077f..e3b9fa06 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,7 +16,7 @@ markers = ignore = E731,W504 max-line-length = 120 -[coverage:run] +[coverage:report] exclude_lines = pragma: no cover def __repr__ From ad3d00bcaeab7a5b193b177c38c5be8eea3ae39d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:08:35 -0400 Subject: [PATCH 134/222] added coverage file --- setup.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup.cfg b/setup.cfg index e3b9fa06..b9c9a52b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,6 +27,10 @@ exclude_lines = if 0: if __name__ == .__main__.: +omit = + pt_callbacks.py + + [flake8] ignore = E731,W504,F401,F841 max-line-length = 120 From 2f4bd676e864af59e657ecc18ccf08876f9dd966 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:09:24 -0400 Subject: [PATCH 135/222] added coverage file --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index b9c9a52b..8ffa3240 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,7 +28,7 @@ exclude_lines = if __name__ == .__main__.: omit = - pt_callbacks.py + pytorch_lightning/callbacks/pt_callbacks.py [flake8] From 7a868c51ae29c7c85b22fac05a731a43ab51e44e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:10:32 -0400 Subject: [PATCH 136/222] removed dead code in grads --- pytorch_lightning/root_module/grads.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pytorch_lightning/root_module/grads.py b/pytorch_lightning/root_module/grads.py index e4d1701b..8ed17a3e 100644 --- a/pytorch_lightning/root_module/grads.py +++ b/pytorch_lightning/root_module/grads.py @@ -27,14 +27,3 @@ class GradInformation(nn.Module): results['grad_{}_norm_total'.format(norm_type)] = round(total_norm.data.cpu().numpy().flatten()[0], 3) return results - - def describe_grads(self): - for p in self.parameters(): - g = p.grad.data.numpy().flatten() - print(np.max(g), np.min(g), np.mean(g)) - - - def describe_params(self): - for p in self.parameters(): - g = p.data.numpy().flatten() - print(np.max(g), np.min(g), np.mean(g)) \ No newline at end of file From 97aa69c8f633245e09c8443fafaf447a215c3330 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:16:26 -0400 Subject: [PATCH 137/222] removed dead code in grads --- pytorch_lightning/root_module/memory.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index 17f20efe..0bafe562 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -115,11 +115,13 @@ class ModelSummary(object): ''' df = pd.DataFrame( np.zeros( (len(self.layer_names), 3) ) ) - df.columns = ['Name', 'Type', 'Params'] + df.columns = ['Name', 'Type', 'Params', 'In_sizes', 'Out_sizes'] df['Name'] = self.layer_names df['Type'] = self.layer_types df['Params'] = self.param_nums + df['In_sizes'] = self.in_sizes + df['Out_sizes'] = self.out_sizes self.summary = df return @@ -128,6 +130,7 @@ class ModelSummary(object): self.get_layer_names() self.get_parameter_sizes() self.get_parameter_nums() + self.get_variable_sizes() self.make_summary() From f3b0cbf998dd767b426ef8c8197f47c73f4727a3 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:19:19 -0400 Subject: [PATCH 138/222] removed dead code in grads --- pytorch_lightning/root_module/memory.py | 13 +++++++++---- pytorch_lightning/root_module/root_module.py | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index 0bafe562..4a166d63 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -115,13 +115,16 @@ class ModelSummary(object): ''' df = pd.DataFrame( np.zeros( (len(self.layer_names), 3) ) ) - df.columns = ['Name', 'Type', 'Params', 'In_sizes', 'Out_sizes'] + df.columns = ['Name', 'Type', 'Params'] df['Name'] = self.layer_names df['Type'] = self.layer_types df['Params'] = self.param_nums - df['In_sizes'] = self.in_sizes - df['Out_sizes'] = self.out_sizes + + if self.example_input_array: + df.columns.extend(['In_sizes', 'Out_sizes']) + df['In_sizes'] = self.in_sizes + df['Out_sizes'] = self.out_sizes self.summary = df return @@ -130,7 +133,9 @@ class ModelSummary(object): self.get_layer_names() self.get_parameter_sizes() self.get_parameter_nums() - self.get_variable_sizes() + + if self.example_input_array: + self.get_variable_sizes() self.make_summary() diff --git a/pytorch_lightning/root_module/root_module.py b/pytorch_lightning/root_module/root_module.py index 2345997b..7f99ef98 100644 --- a/pytorch_lightning/root_module/root_module.py +++ b/pytorch_lightning/root_module/root_module.py @@ -21,6 +21,7 @@ class LightningModule(GradInformation, ModelIO, ModelHooks): self.loaded_optimizer_states_dict = {} self.trainer = None self.experiment = None + self.example_input_array = None # track if gpu was requested for checkpointing self.on_gpu = False From 83ccd21beca24649f9d609761af0764a9f4adc3b Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:20:42 -0400 Subject: [PATCH 139/222] added sample input for summary --- .../examples/new_project_templates/lightning_module_template.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index fc28c55d..e4ca0c8f 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -28,6 +28,8 @@ class LightningTemplateModel(LightningModule): self.batch_size = hparams.batch_size + self.example_input_array = torch.rand(5, 3 * 28 * 28) + # build model self.__build_model() From 7c3786aa52010ba59c78a8422819d0812bcf55a9 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:22:09 -0400 Subject: [PATCH 140/222] added sample input for summary --- pytorch_lightning/root_module/memory.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index 4a166d63..909f97f1 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -33,7 +33,7 @@ class ModelSummary(object): mods = list(self.model.modules()) in_sizes = [] out_sizes = [] - input_ = self.example_input_array + input_ = self.model.example_input_array for i in range(1, len(mods)): m = mods[i] if type(input_) is list or type(input_) is tuple: @@ -121,7 +121,7 @@ class ModelSummary(object): df['Type'] = self.layer_types df['Params'] = self.param_nums - if self.example_input_array: + if self.model.example_input_array: df.columns.extend(['In_sizes', 'Out_sizes']) df['In_sizes'] = self.in_sizes df['Out_sizes'] = self.out_sizes @@ -134,7 +134,7 @@ class ModelSummary(object): self.get_parameter_sizes() self.get_parameter_nums() - if self.example_input_array: + if self.model.example_input_array: self.get_variable_sizes() self.make_summary() From 3a86e0fc6c7070b3d2694c2192bdc36d300aa6b0 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:23:30 -0400 Subject: [PATCH 141/222] added sample input for summary --- pytorch_lightning/root_module/memory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index 909f97f1..17fbe991 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -121,7 +121,7 @@ class ModelSummary(object): df['Type'] = self.layer_types df['Params'] = self.param_nums - if self.model.example_input_array: + if self.model.example_input_array is not None: df.columns.extend(['In_sizes', 'Out_sizes']) df['In_sizes'] = self.in_sizes df['Out_sizes'] = self.out_sizes @@ -134,7 +134,7 @@ class ModelSummary(object): self.get_parameter_sizes() self.get_parameter_nums() - if self.model.example_input_array: + if self.model.example_input_array is not None: self.get_variable_sizes() self.make_summary() From b8cc62ee5260f016472a6d719313baaf81876207 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:24:58 -0400 Subject: [PATCH 142/222] added sample input for summary --- pytorch_lightning/root_module/memory.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index 17fbe991..0482da6e 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -34,6 +34,11 @@ class ModelSummary(object): in_sizes = [] out_sizes = [] input_ = self.model.example_input_array + + if self.model.on_gpu: + input_ = input_.cuda(0) + + for i in range(1, len(mods)): m = mods[i] if type(input_) is list or type(input_) is tuple: From 77a7f3e33edf08aa2df7b17614c2a5275579b463 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:27:16 -0400 Subject: [PATCH 143/222] added sample input for summary --- .../lightning_module_template.py | 3 +- pytorch_lightning/root_module/memory.py | 48 ++++++++++--------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index e4ca0c8f..fd68ef2e 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -28,7 +28,8 @@ class LightningTemplateModel(LightningModule): self.batch_size = hparams.batch_size - self.example_input_array = torch.rand(5, 3 * 28 * 28) + # if you specify an example input, the summary will show input/output for each layer + self.example_input_array = torch.rand(5, 28 * 28) # build model self.__build_model() diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index 0482da6e..ed8854ba 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -38,33 +38,37 @@ class ModelSummary(object): if self.model.on_gpu: input_ = input_.cuda(0) + if self.model.trainer.use_amp: + input_ = input_.half() - for i in range(1, len(mods)): - m = mods[i] - if type(input_) is list or type(input_) is tuple: - out = m(*input_) - else: - out = m(input_) + with torch.no_grad: - if type(input_) is tuple or type(input_) is list: - in_size = [] - for x in input_: - if type(x) is list: - in_size.append(len(x)) - else: - in_size.append(x.size()) - else: - in_size = np.array(input_.size()) + for i in range(1, len(mods)): + m = mods[i] + if type(input_) is list or type(input_) is tuple: + out = m(*input_) + else: + out = m(input_) - in_sizes.append(in_size) + if type(input_) is tuple or type(input_) is list: + in_size = [] + for x in input_: + if type(x) is list: + in_size.append(len(x)) + else: + in_size.append(x.size()) + else: + in_size = np.array(input_.size()) - if type(out) is tuple or type(out) is list: - out_size = np.asarray([x.size() for x in out]) - else: - out_size = np.array(out.size()) + in_sizes.append(in_size) - out_sizes.append(out_size) - input_ = out + if type(out) is tuple or type(out) is list: + out_size = np.asarray([x.size() for x in out]) + else: + out_size = np.array(out.size()) + + out_sizes.append(out_size) + input_ = out self.in_sizes = in_sizes self.out_sizes = out_sizes From 8db8cd25394922c5fd8925a66881de71d72d389a Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:28:55 -0400 Subject: [PATCH 144/222] added sample input for summary --- pytorch_lightning/root_module/memory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index ed8854ba..a2feb689 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -41,7 +41,7 @@ class ModelSummary(object): if self.model.trainer.use_amp: input_ = input_.half() - with torch.no_grad: + with torch.no_grad(): for i in range(1, len(mods)): m = mods[i] From 5f814e48c4162a50bd90bda65191a372594a9526 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:30:27 -0400 Subject: [PATCH 145/222] added sample input for summary --- pytorch_lightning/root_module/memory.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index a2feb689..29d6e66d 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -124,14 +124,18 @@ class ModelSummary(object): ''' df = pd.DataFrame( np.zeros( (len(self.layer_names), 3) ) ) - df.columns = ['Name', 'Type', 'Params'] + cols = ['Name', 'Type', 'Params'] + if self.model.example_input_array is not None: + cols.extend(['In_sizes', 'Out_sizes']) + + df.columns = cols df['Name'] = self.layer_names df['Type'] = self.layer_types df['Params'] = self.param_nums if self.model.example_input_array is not None: - df.columns.extend(['In_sizes', 'Out_sizes']) + df['In_sizes'] = self.in_sizes df['Out_sizes'] = self.out_sizes From b824f184ff282cc316a7165a1a8b23f43c13869a Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:31:55 -0400 Subject: [PATCH 146/222] added sample input for summary --- pytorch_lightning/root_module/memory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index 29d6e66d..6f29b9ad 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -123,11 +123,11 @@ class ModelSummary(object): Layer Name, Layer Type, Input Size, Output Size, Number of Parameters ''' - df = pd.DataFrame( np.zeros( (len(self.layer_names), 3) ) ) cols = ['Name', 'Type', 'Params'] if self.model.example_input_array is not None: cols.extend(['In_sizes', 'Out_sizes']) + df = pd.DataFrame(np.zeros( (len(self.layer_names), len(cols)))) df.columns = cols df['Name'] = self.layer_names From 383b4cdac7d8b5ef2bb48dc395829942e244d052 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:35:32 -0400 Subject: [PATCH 147/222] added sample input for summary --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 2596b303..e31ae60e 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -137,7 +137,7 @@ def test_amp_gpu_dp(): trainer_options = dict( max_nb_epochs=1, - gpus=[0, 1], + gpus='0, 1', # test init with gpu string distributed_backend='dp', use_amp=True ) From f69ff593b582219e9ea35f54db199ccfdcb190da Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:37:05 -0400 Subject: [PATCH 148/222] ignoring multi-node flag --- pytorch_lightning/models/trainer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 7875b5da..fef5f927 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -188,7 +188,7 @@ class Trainer(TrainerIO): self.use_ddp = distributed_backend == 'ddp' # use ddp automatically if nb_gpu_nodes > 1 - if nb_gpu_nodes > 1 and self.use_dp: + if nb_gpu_nodes > 1 and self.use_dp: # pragma: no cover self.use_ddp = True self.use_dp = False w = 'DataParallel does not support nb_gpu_nodes > 1. ' \ From 5c2168356646fc8d6fc0a8c042839f9fd181f7a1 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:45:59 -0400 Subject: [PATCH 149/222] added model for tests --- tests/test_model.py | 269 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 tests/test_model.py diff --git a/tests/test_model.py b/tests/test_model.py new file mode 100644 index 00000000..3402f4ee --- /dev/null +++ b/tests/test_model.py @@ -0,0 +1,269 @@ +import os +from collections import OrderedDict +import torch.nn as nn +from torchvision.datasets import MNIST +import torchvision.transforms as transforms +import torch +import torch.nn.functional as F +from test_tube import HyperOptArgumentParser +from torch import optim +from torch.utils.data import DataLoader +from torch.utils.data.distributed import DistributedSampler + +from pytorch_lightning.root_module.root_module import LightningModule + + +class LightningTestModel(LightningModule): + """ + Sample model to show how to define a template + """ + + def __init__(self, hparams, force_remove_distributed_sampler): + """ + Pass in parsed HyperOptArgumentParser to the model + :param hparams: + """ + # init superclass + super(LightningTestModel, self).__init__(hparams) + + self.batch_size = hparams.batch_size + + # if you specify an example input, the summary will show input/output for each layer + self.example_input_array = torch.rand(5, 28 * 28) + + # remove to test warning for dist sampler + self.force_remove_distributed_sampler = force_remove_distributed_sampler + + # build model + self.__build_model() + + # --------------------- + # MODEL SETUP + # --------------------- + def __build_model(self): + """ + Layout model + :return: + """ + self.c_d1 = nn.Linear(in_features=self.hparams.in_features, out_features=self.hparams.hidden_dim) + self.c_d1_bn = nn.BatchNorm1d(self.hparams.hidden_dim) + self.c_d1_drop = nn.Dropout(self.hparams.drop_prob) + + self.c_d2 = nn.Linear(in_features=self.hparams.hidden_dim, out_features=self.hparams.out_features) + + # --------------------- + # TRAINING + # --------------------- + def forward(self, x): + """ + No special modification required for lightning, define as you normally would + :param x: + :return: + """ + + x = self.c_d1(x) + x = torch.tanh(x) + x = self.c_d1_bn(x) + x = self.c_d1_drop(x) + + x = self.c_d2(x) + logits = F.log_softmax(x, dim=1) + + return logits + + def loss(self, labels, logits): + nll = F.nll_loss(logits, labels) + return nll + + def training_step(self, data_batch, batch_i): + """ + Lightning calls this inside the training loop + :param data_batch: + :return: + """ + # forward pass + x, y = data_batch + x = x.view(x.size(0), -1) + + y_hat = self.forward(x) + + # calculate loss + loss_val = self.loss(y, y_hat) + + # in DP mode (default) make sure if result is scalar, there's another dim in the beginning + if self.trainer.use_dp: + loss_val = loss_val.unsqueeze(0) + + output = OrderedDict({ + 'loss': loss_val + }) + + # can also return just a scalar instead of a dict (return loss_val) + return output + + def validation_step(self, data_batch, batch_i): + """ + Lightning calls this inside the validation loop + :param data_batch: + :return: + """ + x, y = data_batch + x = x.view(x.size(0), -1) + y_hat = self.forward(x) + + loss_val = self.loss(y, y_hat) + + # acc + labels_hat = torch.argmax(y_hat, dim=1) + val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) + val_acc = torch.tensor(val_acc) + + if self.on_gpu: + val_acc = val_acc.cuda(loss_val.device.index) + + # in DP mode (default) make sure if result is scalar, there's another dim in the beginning + if self.trainer.use_dp: + loss_val = loss_val.unsqueeze(0) + val_acc = val_acc.unsqueeze(0) + + output = OrderedDict({ + 'val_loss': loss_val, + 'val_acc': val_acc, + }) + + # can also return just a scalar instead of a dict (return loss_val) + return output + + def validation_end(self, outputs): + """ + Called at the end of validation to aggregate outputs + :param outputs: list of individual outputs of each validation step + :return: + """ + # if returned a scalar from validation_step, outputs is a list of tensor scalars + # we return just the average in this case (if we want) + # return torch.stack(outputs).mean() + + val_loss_mean = 0 + val_acc_mean = 0 + for output in outputs: + val_loss_mean += output['val_loss'] + val_acc_mean += output['val_acc'] + + val_loss_mean /= len(outputs) + val_acc_mean /= len(outputs) + tqdm_dic = {'val_loss': val_loss_mean.item(), 'val_acc': val_acc_mean.item()} + return tqdm_dic + + def update_tng_log_metrics(self, logs): + return logs + + # --------------------- + # MODEL SAVING + # --------------------- + def get_save_dict(self): + checkpoint = {'state_dict': self.state_dict()} + return checkpoint + + def load_model_specific(self, checkpoint): + self.load_state_dict(checkpoint['state_dict']) + pass + + # --------------------- + # TRAINING SETUP + # --------------------- + def configure_optimizers(self): + """ + return whatever optimizers we want here + :return: list of optimizers + """ + optimizer = optim.Adam(self.parameters(), lr=self.hparams.learning_rate) + return [optimizer] + + def __dataloader(self, train): + # init data generators + transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (1.0,))]) + dataset = MNIST(root=self.hparams.data_root, train=train, transform=transform, download=True) + + # when using multi-node we need to add the datasampler + train_sampler = None + batch_size = self.hparams.batch_size + + try: + if self.on_gpu and not self.force_remove_distributed_sampler: + train_sampler = DistributedSampler(dataset, rank=self.trainer.proc_rank) + batch_size = batch_size // self.trainer.world_size # scale batch size + except Exception as e: + pass + + should_shuffle = train_sampler is None + loader = DataLoader( + dataset=dataset, + batch_size=batch_size, + shuffle=should_shuffle, + sampler=train_sampler + ) + + return loader + + @property + def tng_dataloader(self): + if self._tng_dataloader is None: + try: + self._tng_dataloader = self.__dataloader(train=True) + except Exception as e: + print(e) + raise e + return self._tng_dataloader + + @property + def val_dataloader(self): + if self._val_dataloader is None: + try: + self._val_dataloader = self.__dataloader(train=False) + except Exception as e: + print(e) + raise e + return self._val_dataloader + + @property + def test_dataloader(self): + if self._test_dataloader is None: + try: + self._test_dataloader = self.__dataloader(train=False) + except Exception as e: + print(e) + raise e + return self._test_dataloader + + @staticmethod + def add_model_specific_args(parent_parser, root_dir): + """ + Parameters you define here will be available to your model through self.hparams + :param parent_parser: + :param root_dir: + :return: + """ + parser = HyperOptArgumentParser(strategy=parent_parser.strategy, parents=[parent_parser]) + + # param overwrites + # parser.set_defaults(gradient_clip=5.0) + + # network params + parser.opt_list('--drop_prob', default=0.2, options=[0.2, 0.5], type=float, tunable=False) + parser.add_argument('--in_features', default=28*28, type=int) + parser.add_argument('--out_features', default=10, type=int) + parser.add_argument('--hidden_dim', default=50000, type=int) # use 500 for CPU, 50000 for GPU to see speed difference + + # data + parser.add_argument('--data_root', default=os.path.join(root_dir, 'mnist'), type=str) + + # training params (opt) + parser.opt_list('--learning_rate', default=0.001*8, type=float, options=[0.0001, 0.0005, 0.001, 0.005], + tunable=False) + parser.opt_list('--optimizer_name', default='adam', type=str, options=['adam'], tunable=False) + + # if using 2 nodes with 4 gpus each the batch size here (256) will be 256 / (2*8) = 16 per gpu + parser.opt_list('--batch_size', default=256*8, type=int, options=[32, 64, 128, 256], tunable=False, + help='batch size will be divided over all the gpus being used across all nodes') + return parser From 8064a77aa7f2c0afc4c39e4f013b4dc0e4a23c6e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 16:57:21 -0400 Subject: [PATCH 150/222] added test for no dist sampler --- pytorch_lightning/models/trainer.py | 6 +- pytorch_lightning/testing_models/__init__.py | 0 .../testing_models/lm_test_module.py | 0 pytorch_lightning/utils/debugging.py | 2 +- tests/test_models.py | 81 +++++++++++++------ 5 files changed, 61 insertions(+), 28 deletions(-) create mode 100644 pytorch_lightning/testing_models/__init__.py rename tests/test_model.py => pytorch_lightning/testing_models/lm_test_module.py (100%) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index fef5f927..a0c1c2aa 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -19,7 +19,7 @@ import tqdm from pytorch_lightning.root_module.memory import get_gpu_memory_map from pytorch_lightning.root_module.model_saving import TrainerIO from pytorch_lightning.pt_overrides.override_data_parallel import LightningDistributedDataParallel, LightningDataParallel -from pytorch_lightning.utils.debugging import IncompatibleArgumentsException +from pytorch_lightning.utils.debugging import MisconfigurationException try: from apex import amp @@ -392,7 +392,7 @@ class Trainer(TrainerIO): dist_sampler = torch.utils.data.distributed.DistributedSampler(dataset) dataloader = Dataloader(dataset, sampler=dist_sampler) ''' - raise Exception(msg) + raise MisconfigurationException(msg) # ----------------------------- # MODEL TRAINING @@ -467,7 +467,7 @@ class Trainer(TrainerIO): m = f'amp level {self.amp_level} with DataParallel is not supported. ' \ f'See this note from NVIDIA for more info: https://github.com/NVIDIA/apex/issues/227. ' \ f'We recommend you switch to ddp if you want to use amp' - raise IncompatibleArgumentsException(m) + raise MisconfigurationException(m) # run through amp wrapper if self.use_amp: diff --git a/pytorch_lightning/testing_models/__init__.py b/pytorch_lightning/testing_models/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_model.py b/pytorch_lightning/testing_models/lm_test_module.py similarity index 100% rename from tests/test_model.py rename to pytorch_lightning/testing_models/lm_test_module.py diff --git a/pytorch_lightning/utils/debugging.py b/pytorch_lightning/utils/debugging.py index d313bfcd..3091ff3b 100644 --- a/pytorch_lightning/utils/debugging.py +++ b/pytorch_lightning/utils/debugging.py @@ -1,5 +1,5 @@ import pdb import sys -class IncompatibleArgumentsException(Exception): +class MisconfigurationException(Exception): pass \ No newline at end of file diff --git a/tests/test_models.py b/tests/test_models.py index e31ae60e..6f3f933e 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,10 +1,11 @@ import pytest from pytorch_lightning import Trainer from pytorch_lightning.examples.new_project_templates.lightning_module_template import LightningTemplateModel +from pytorch_lightning.testing_models.lm_test_module import LightningTestModel from argparse import Namespace from test_tube import Experiment from pytorch_lightning.callbacks import ModelCheckpoint, EarlyStopping -from pytorch_lightning.utils.debugging import IncompatibleArgumentsException +from pytorch_lightning.utils.debugging import MisconfigurationException import numpy as np import warnings import torch @@ -33,7 +34,8 @@ def test_cpu_model(): val_percent_check=0.4 ) - run_gpu_model_test(trainer_options, on_gpu=False) + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) def test_all_features_cpu_model(): @@ -54,7 +56,8 @@ def test_all_features_cpu_model(): val_percent_check=0.4 ) - run_gpu_model_test(trainer_options, on_gpu=False) + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) def test_early_stopping_cpu_model(): @@ -77,7 +80,8 @@ def test_early_stopping_cpu_model(): val_percent_check=0.4 ) - run_gpu_model_test(trainer_options, on_gpu=False) + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) def test_single_gpu_model(): @@ -88,6 +92,7 @@ def test_single_gpu_model(): if not torch.cuda.is_available(): warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') return + model, hparams = get_model() trainer_options = dict( progress_bar=False, @@ -97,7 +102,7 @@ def test_single_gpu_model(): gpus=[0] ) - run_gpu_model_test(trainer_options) + run_gpu_model_test(trainer_options, model, hparams) def test_multi_gpu_model_dp(): @@ -111,7 +116,7 @@ def test_multi_gpu_model_dp(): if not torch.cuda.device_count() > 1: warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') return - + model, hparams = get_model() trainer_options = dict( progress_bar=False, max_nb_epochs=1, @@ -120,7 +125,7 @@ def test_multi_gpu_model_dp(): gpus=[0, 1] ) - run_gpu_model_test(trainer_options) + run_gpu_model_test(trainer_options, model, hparams) def test_amp_gpu_dp(): @@ -134,15 +139,15 @@ def test_amp_gpu_dp(): if not torch.cuda.device_count() > 1: warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') return - + model, hparams = get_model() trainer_options = dict( max_nb_epochs=1, gpus='0, 1', # test init with gpu string distributed_backend='dp', use_amp=True ) - with pytest.raises(IncompatibleArgumentsException): - run_gpu_model_test(trainer_options) + with pytest.raises(MisconfigurationException): + run_gpu_model_test(trainer_options, model, hparams) def test_multi_gpu_model_ddp(): @@ -158,7 +163,7 @@ def test_multi_gpu_model_ddp(): return os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - + model, hparams = get_model() trainer_options = dict( progress_bar=False, max_nb_epochs=1, @@ -168,7 +173,7 @@ def test_multi_gpu_model_ddp(): distributed_backend='ddp' ) - run_gpu_model_test(trainer_options) + run_gpu_model_test(trainer_options, model, hparams) def test_amp_gpu_ddp(): @@ -185,6 +190,7 @@ def test_amp_gpu_ddp(): os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + model, hparams = get_model() trainer_options = dict( progress_bar=True, max_nb_epochs=1, @@ -193,18 +199,14 @@ def test_amp_gpu_ddp(): use_amp=True ) - run_gpu_model_test(trainer_options) + run_gpu_model_test(trainer_options, model, hparams) -# ------------------------------------------------------------------------ -# UTILS -# ------------------------------------------------------------------------ - -def run_gpu_model_test(trainer_options, on_gpu=True): +def test_ddp_sampler_error(): + """ + Make sure DDP + AMP work + :return: """ - Make sure DDP + AMP work - :return: - """ if not torch.cuda.is_available(): warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') return @@ -212,8 +214,34 @@ def run_gpu_model_test(trainer_options, on_gpu=True): warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') return + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + + hparams = get_hparams() + model = LightningTestModel(hparams, force_remove_distributed_sampler=True) + + trainer_options = dict( + progress_bar=True, + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + with pytest.raises(MisconfigurationException): + run_gpu_model_test(trainer_options, model, hparams) + + +# ------------------------------------------------------------------------ +# UTILS +# ------------------------------------------------------------------------ + +def run_gpu_model_test(trainer_options, model, hparams, on_gpu=True): + """ + Make sure DDP + AMP work + :return: + """ + save_dir = init_save_dir() - model, hparams = get_model() # exp file to get meta exp = get_exp(False) @@ -243,8 +271,7 @@ def run_gpu_model_test(trainer_options, on_gpu=True): clear_save_dir() -def get_model(): - # set up model with these hyperparams +def get_hparams(): root_dir = os.path.dirname(os.path.realpath(__file__)) hparams = Namespace(**{'drop_prob': 0.2, 'batch_size': 32, @@ -254,6 +281,12 @@ def get_model(): 'data_root': os.path.join(root_dir, 'mnist'), 'out_features': 10, 'hidden_dim': 1000}) + return hparams + + +def get_model(): + # set up model with these hyperparams + hparams = get_hparams() model = LightningTemplateModel(hparams) return model, hparams From 1e0bae14da365a1c8d76c385c769ab4959e0f1a7 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:01:25 -0400 Subject: [PATCH 151/222] added test for no dist sampler --- tests/test_models.py | 55 +++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 6f3f933e..22e7711d 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -20,6 +20,35 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ +def test_ddp_sampler_error(): + """ + Make sure DDP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + + hparams = get_hparams() + model = LightningTestModel(hparams, force_remove_distributed_sampler=True) + + trainer_options = dict( + progress_bar=True, + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + with pytest.raises(MisconfigurationException): + run_gpu_model_test(trainer_options, model, hparams) + + def test_cpu_model(): """ Make sure model trains on CPU @@ -202,33 +231,7 @@ def test_amp_gpu_ddp(): run_gpu_model_test(trainer_options, model, hparams) -def test_ddp_sampler_error(): - """ - Make sure DDP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - - hparams = get_hparams() - model = LightningTestModel(hparams, force_remove_distributed_sampler=True) - - trainer_options = dict( - progress_bar=True, - max_nb_epochs=1, - gpus=[0, 1], - distributed_backend='ddp', - use_amp=True - ) - - with pytest.raises(MisconfigurationException): - run_gpu_model_test(trainer_options, model, hparams) # ------------------------------------------------------------------------ From 9e5dd7a7eae3ae123b4a6c925c31631ebc4e89f9 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:02:39 -0400 Subject: [PATCH 152/222] added test for no dist sampler --- tests/test_models.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 22e7711d..23e3e3cc 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -231,19 +231,10 @@ def test_amp_gpu_ddp(): run_gpu_model_test(trainer_options, model, hparams) - - - # ------------------------------------------------------------------------ # UTILS # ------------------------------------------------------------------------ - def run_gpu_model_test(trainer_options, model, hparams, on_gpu=True): - """ - Make sure DDP + AMP work - :return: - """ - save_dir = init_save_dir() # exp file to get meta From 096132b38981d5abdf57fd73911629de20838314 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:04:12 -0400 Subject: [PATCH 153/222] added test for no dist sampler --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 23e3e3cc..bd6606e4 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -38,7 +38,7 @@ def test_ddp_sampler_error(): model = LightningTestModel(hparams, force_remove_distributed_sampler=True) trainer_options = dict( - progress_bar=True, + progress_bar=False, max_nb_epochs=1, gpus=[0, 1], distributed_backend='ddp', From 164751c918da973817543295dce9a3261942a591 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:09:14 -0400 Subject: [PATCH 154/222] added test for no dist sampler --- pytorch_lightning/models/trainer.py | 4 ++-- tests/test_models.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index a0c1c2aa..4f4d012d 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -369,7 +369,7 @@ class Trainer(TrainerIO): return val_results - def __get_dataloaders(self, model): + def get_dataloaders(self, model): """ Dataloaders are provided by the model :param model: @@ -591,7 +591,7 @@ class Trainer(TrainerIO): ref_model.on_gpu = self.on_gpu # transfer data loaders from model - self.__get_dataloaders(ref_model) + self.get_dataloaders(ref_model) # init training constants self.__layout_bookeeping() diff --git a/tests/test_models.py b/tests/test_models.py index bd6606e4..21bee021 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -37,7 +37,7 @@ def test_ddp_sampler_error(): hparams = get_hparams() model = LightningTestModel(hparams, force_remove_distributed_sampler=True) - trainer_options = dict( + trainer = Trainer( progress_bar=False, max_nb_epochs=1, gpus=[0, 1], @@ -46,7 +46,7 @@ def test_ddp_sampler_error(): ) with pytest.raises(MisconfigurationException): - run_gpu_model_test(trainer_options, model, hparams) + trainer.get_dataloaders(model) def test_cpu_model(): From d1d33e8db60a7387249ba6f74ebd36dc2b852c07 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:10:14 -0400 Subject: [PATCH 155/222] added test for no dist sampler --- tests/test_models.py | 362 +++++++++++++++++++++---------------------- 1 file changed, 181 insertions(+), 181 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 21bee021..f80754f1 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -48,187 +48,187 @@ def test_ddp_sampler_error(): with pytest.raises(MisconfigurationException): trainer.get_dataloaders(model) - -def test_cpu_model(): - """ - Make sure model trains on CPU - :return: - """ - - trainer_options = dict( - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4 - ) - - model, hparams = get_model() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - -def test_all_features_cpu_model(): - """ - Test each of the trainer options - :return: - """ - - trainer_options = dict( - gradient_clip=1.0, - overfit_pct=0.20, - track_grad_norm=2, - print_nan_grads=True, - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4 - ) - - model, hparams = get_model() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - -def test_early_stopping_cpu_model(): - """ - Test each of the trainer options - :return: - """ - - stopping = EarlyStopping() - trainer_options = dict( - early_stop_callback=stopping, - gradient_clip=1.0, - overfit_pct=0.20, - track_grad_norm=2, - print_nan_grads=True, - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4 - ) - - model, hparams = get_model() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - -def test_single_gpu_model(): - """ - Make sure single GPU works (DP mode) - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') - return - model, hparams = get_model() - - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, - gpus=[0] - ) - - run_gpu_model_test(trainer_options, model, hparams) - - -def test_multi_gpu_model_dp(): - """ - Make sure DP works - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - model, hparams = get_model() - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, - gpus=[0, 1] - ) - - run_gpu_model_test(trainer_options, model, hparams) - - -def test_amp_gpu_dp(): - """ - Make sure DP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - model, hparams = get_model() - trainer_options = dict( - max_nb_epochs=1, - gpus='0, 1', # test init with gpu string - distributed_backend='dp', - use_amp=True - ) - with pytest.raises(MisconfigurationException): - run_gpu_model_test(trainer_options, model, hparams) - - -def test_multi_gpu_model_ddp(): - """ - Make sure DDP works - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - - os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - model, hparams = get_model() - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, - gpus=[0, 1], - distributed_backend='ddp' - ) - - run_gpu_model_test(trainer_options, model, hparams) - - -def test_amp_gpu_ddp(): - """ - Make sure DDP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - - os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - - model, hparams = get_model() - trainer_options = dict( - progress_bar=True, - max_nb_epochs=1, - gpus=[0, 1], - distributed_backend='ddp', - use_amp=True - ) - - run_gpu_model_test(trainer_options, model, hparams) +# +# def test_cpu_model(): +# """ +# Make sure model trains on CPU +# :return: +# """ +# +# trainer_options = dict( +# progress_bar=False, +# experiment=get_exp(), +# max_nb_epochs=1, +# train_percent_check=0.4, +# val_percent_check=0.4 +# ) +# +# model, hparams = get_model() +# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) +# +# +# def test_all_features_cpu_model(): +# """ +# Test each of the trainer options +# :return: +# """ +# +# trainer_options = dict( +# gradient_clip=1.0, +# overfit_pct=0.20, +# track_grad_norm=2, +# print_nan_grads=True, +# progress_bar=False, +# experiment=get_exp(), +# max_nb_epochs=1, +# train_percent_check=0.4, +# val_percent_check=0.4 +# ) +# +# model, hparams = get_model() +# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) +# +# +# def test_early_stopping_cpu_model(): +# """ +# Test each of the trainer options +# :return: +# """ +# +# stopping = EarlyStopping() +# trainer_options = dict( +# early_stop_callback=stopping, +# gradient_clip=1.0, +# overfit_pct=0.20, +# track_grad_norm=2, +# print_nan_grads=True, +# progress_bar=False, +# experiment=get_exp(), +# max_nb_epochs=1, +# train_percent_check=0.4, +# val_percent_check=0.4 +# ) +# +# model, hparams = get_model() +# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) +# +# +# def test_single_gpu_model(): +# """ +# Make sure single GPU works (DP mode) +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') +# return +# model, hparams = get_model() +# +# trainer_options = dict( +# progress_bar=False, +# max_nb_epochs=1, +# train_percent_check=0.1, +# val_percent_check=0.1, +# gpus=[0] +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_multi_gpu_model_dp(): +# """ +# Make sure DP works +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# model, hparams = get_model() +# trainer_options = dict( +# progress_bar=False, +# max_nb_epochs=1, +# train_percent_check=0.1, +# val_percent_check=0.1, +# gpus=[0, 1] +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_amp_gpu_dp(): +# """ +# Make sure DP + AMP work +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# model, hparams = get_model() +# trainer_options = dict( +# max_nb_epochs=1, +# gpus='0, 1', # test init with gpu string +# distributed_backend='dp', +# use_amp=True +# ) +# with pytest.raises(MisconfigurationException): +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_multi_gpu_model_ddp(): +# """ +# Make sure DDP works +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# +# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) +# model, hparams = get_model() +# trainer_options = dict( +# progress_bar=False, +# max_nb_epochs=1, +# train_percent_check=0.1, +# val_percent_check=0.1, +# gpus=[0, 1], +# distributed_backend='ddp' +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_amp_gpu_ddp(): +# """ +# Make sure DDP + AMP work +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# +# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) +# +# model, hparams = get_model() +# trainer_options = dict( +# progress_bar=True, +# max_nb_epochs=1, +# gpus=[0, 1], +# distributed_backend='ddp', +# use_amp=True +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) # ------------------------------------------------------------------------ From b30fbf80d0323a382db077eebe258bc00c28696a Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:11:25 -0400 Subject: [PATCH 156/222] added test for no dist sampler --- tests/test_models.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index f80754f1..e97b8a2a 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -37,7 +37,11 @@ def test_ddp_sampler_error(): hparams = get_hparams() model = LightningTestModel(hparams, force_remove_distributed_sampler=True) + exp = get_exp(True) + exp.save() + trainer = Trainer( + experiment=exp, progress_bar=False, max_nb_epochs=1, gpus=[0, 1], @@ -48,6 +52,8 @@ def test_ddp_sampler_error(): with pytest.raises(MisconfigurationException): trainer.get_dataloaders(model) + clear_save_dir() + # # def test_cpu_model(): # """ From 9101a70024b9df1ad420dd947ebf4b1185c098cd Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:12:12 -0400 Subject: [PATCH 157/222] refactor tests --- tests/test_models.py | 365 +++++++++++++++++++++---------------------- 1 file changed, 182 insertions(+), 183 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index e97b8a2a..553a5ccc 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -20,6 +20,188 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ +def test_cpu_model(): + """ + Make sure model trains on CPU + :return: + """ + + trainer_options = dict( + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + +def test_all_features_cpu_model(): + """ + Test each of the trainer options + :return: + """ + + trainer_options = dict( + gradient_clip=1.0, + overfit_pct=0.20, + track_grad_norm=2, + print_nan_grads=True, + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + +def test_early_stopping_cpu_model(): + """ + Test each of the trainer options + :return: + """ + + stopping = EarlyStopping() + trainer_options = dict( + early_stop_callback=stopping, + gradient_clip=1.0, + overfit_pct=0.20, + track_grad_norm=2, + print_nan_grads=True, + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + +def test_single_gpu_model(): + """ + Make sure single GPU works (DP mode) + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') + return + model, hparams = get_model() + + trainer_options = dict( + progress_bar=False, + max_nb_epochs=1, + train_percent_check=0.1, + val_percent_check=0.1, + gpus=[0] + ) + + run_gpu_model_test(trainer_options, model, hparams) + + +def test_multi_gpu_model_dp(): + """ + Make sure DP works + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model, hparams = get_model() + trainer_options = dict( + progress_bar=False, + max_nb_epochs=1, + train_percent_check=0.1, + val_percent_check=0.1, + gpus=[0, 1] + ) + + run_gpu_model_test(trainer_options, model, hparams) + + +def test_amp_gpu_dp(): + """ + Make sure DP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model, hparams = get_model() + trainer_options = dict( + max_nb_epochs=1, + gpus='0, 1', # test init with gpu string + distributed_backend='dp', + use_amp=True + ) + with pytest.raises(MisconfigurationException): + run_gpu_model_test(trainer_options, model, hparams) + + +def test_multi_gpu_model_ddp(): + """ + Make sure DDP works + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + model, hparams = get_model() + trainer_options = dict( + progress_bar=False, + max_nb_epochs=1, + train_percent_check=0.1, + val_percent_check=0.1, + gpus=[0, 1], + distributed_backend='ddp' + ) + + run_gpu_model_test(trainer_options, model, hparams) + + +def test_amp_gpu_ddp(): + """ + Make sure DDP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + + model, hparams = get_model() + trainer_options = dict( + progress_bar=True, + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + run_gpu_model_test(trainer_options, model, hparams) + + def test_ddp_sampler_error(): """ Make sure DDP + AMP work @@ -54,189 +236,6 @@ def test_ddp_sampler_error(): clear_save_dir() -# -# def test_cpu_model(): -# """ -# Make sure model trains on CPU -# :return: -# """ -# -# trainer_options = dict( -# progress_bar=False, -# experiment=get_exp(), -# max_nb_epochs=1, -# train_percent_check=0.4, -# val_percent_check=0.4 -# ) -# -# model, hparams = get_model() -# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -# -# -# def test_all_features_cpu_model(): -# """ -# Test each of the trainer options -# :return: -# """ -# -# trainer_options = dict( -# gradient_clip=1.0, -# overfit_pct=0.20, -# track_grad_norm=2, -# print_nan_grads=True, -# progress_bar=False, -# experiment=get_exp(), -# max_nb_epochs=1, -# train_percent_check=0.4, -# val_percent_check=0.4 -# ) -# -# model, hparams = get_model() -# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -# -# -# def test_early_stopping_cpu_model(): -# """ -# Test each of the trainer options -# :return: -# """ -# -# stopping = EarlyStopping() -# trainer_options = dict( -# early_stop_callback=stopping, -# gradient_clip=1.0, -# overfit_pct=0.20, -# track_grad_norm=2, -# print_nan_grads=True, -# progress_bar=False, -# experiment=get_exp(), -# max_nb_epochs=1, -# train_percent_check=0.4, -# val_percent_check=0.4 -# ) -# -# model, hparams = get_model() -# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -# -# -# def test_single_gpu_model(): -# """ -# Make sure single GPU works (DP mode) -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') -# return -# model, hparams = get_model() -# -# trainer_options = dict( -# progress_bar=False, -# max_nb_epochs=1, -# train_percent_check=0.1, -# val_percent_check=0.1, -# gpus=[0] -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_multi_gpu_model_dp(): -# """ -# Make sure DP works -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# model, hparams = get_model() -# trainer_options = dict( -# progress_bar=False, -# max_nb_epochs=1, -# train_percent_check=0.1, -# val_percent_check=0.1, -# gpus=[0, 1] -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_amp_gpu_dp(): -# """ -# Make sure DP + AMP work -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# model, hparams = get_model() -# trainer_options = dict( -# max_nb_epochs=1, -# gpus='0, 1', # test init with gpu string -# distributed_backend='dp', -# use_amp=True -# ) -# with pytest.raises(MisconfigurationException): -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_multi_gpu_model_ddp(): -# """ -# Make sure DDP works -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# -# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) -# model, hparams = get_model() -# trainer_options = dict( -# progress_bar=False, -# max_nb_epochs=1, -# train_percent_check=0.1, -# val_percent_check=0.1, -# gpus=[0, 1], -# distributed_backend='ddp' -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_amp_gpu_ddp(): -# """ -# Make sure DDP + AMP work -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# -# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) -# -# model, hparams = get_model() -# trainer_options = dict( -# progress_bar=True, -# max_nb_epochs=1, -# gpus=[0, 1], -# distributed_backend='ddp', -# use_amp=True -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) - - # ------------------------------------------------------------------------ # UTILS # ------------------------------------------------------------------------ From 3521e872868c2d2cdc381f15b7501523a932ea60 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:18:58 -0400 Subject: [PATCH 158/222] added multiple outputs to LightningTestModel --- pytorch_lightning/models/trainer.py | 2 +- .../testing_models/lm_test_module.py | 23 ++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 4f4d012d..0cd4d89a 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -225,7 +225,7 @@ class Trainer(TrainerIO): if self.use_amp: print('using 16bit precision') - if use_amp and not APEX_AVAILABLE: + if use_amp and not APEX_AVAILABLE: # pragma: no cover msg = ''' You set use_amp=True but do not have apex installed. Install apex first using this guide and rerun with use_amp=True: diff --git a/pytorch_lightning/testing_models/lm_test_module.py b/pytorch_lightning/testing_models/lm_test_module.py index 3402f4ee..c0843667 100644 --- a/pytorch_lightning/testing_models/lm_test_module.py +++ b/pytorch_lightning/testing_models/lm_test_module.py @@ -126,13 +126,23 @@ class LightningTestModel(LightningModule): loss_val = loss_val.unsqueeze(0) val_acc = val_acc.unsqueeze(0) - output = OrderedDict({ - 'val_loss': loss_val, - 'val_acc': val_acc, - }) + # alternate possible outputs to test + if self.trainer.batch_nb % 0 == 0: + output = OrderedDict({ + 'val_loss': loss_val, + 'val_acc': val_acc, + }) + return output + if self.trainer.batch_nb % 1 == 0: + return val_acc - # can also return just a scalar instead of a dict (return loss_val) - return output + if self.trainer.batch_nb % 2 == 0: + output = OrderedDict({ + 'val_loss': loss_val, + 'val_acc': val_acc, + 'test_dic': {'val_loss_a': loss_val} + }) + return output def validation_end(self, outputs): """ @@ -152,6 +162,7 @@ class LightningTestModel(LightningModule): val_loss_mean /= len(outputs) val_acc_mean /= len(outputs) + tqdm_dic = {'val_loss': val_loss_mean.item(), 'val_acc': val_acc_mean.item()} return tqdm_dic From 0aa91c7fdcbaab6e0dd7caac9b7fc2bef487ac7e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:19:31 -0400 Subject: [PATCH 159/222] added multiple outputs to LightningTestModel --- tests/test_models.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 553a5ccc..67c677a2 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -190,7 +190,9 @@ def test_amp_gpu_ddp(): os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - model, hparams = get_model() + hparams = get_hparams() + model = LightningTestModel(hparams) + trainer_options = dict( progress_bar=True, max_nb_epochs=1, From 516ee9c985495fc23bbf91c4d7d26affb4127e3f Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:21:18 -0400 Subject: [PATCH 160/222] added multiple outputs to LightningTestModel --- pytorch_lightning/testing_models/lm_test_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/testing_models/lm_test_module.py b/pytorch_lightning/testing_models/lm_test_module.py index c0843667..09c12c4d 100644 --- a/pytorch_lightning/testing_models/lm_test_module.py +++ b/pytorch_lightning/testing_models/lm_test_module.py @@ -18,7 +18,7 @@ class LightningTestModel(LightningModule): Sample model to show how to define a template """ - def __init__(self, hparams, force_remove_distributed_sampler): + def __init__(self, hparams, force_remove_distributed_sampler=False): """ Pass in parsed HyperOptArgumentParser to the model :param hparams: From 63ce8af27cb990ec41267247a2f945e42aa3b053 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:23:19 -0400 Subject: [PATCH 161/222] added multiple outputs to LightningTestModel --- pytorch_lightning/testing_models/lm_test_module.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytorch_lightning/testing_models/lm_test_module.py b/pytorch_lightning/testing_models/lm_test_module.py index 09c12c4d..685bb30b 100644 --- a/pytorch_lightning/testing_models/lm_test_module.py +++ b/pytorch_lightning/testing_models/lm_test_module.py @@ -127,16 +127,16 @@ class LightningTestModel(LightningModule): val_acc = val_acc.unsqueeze(0) # alternate possible outputs to test - if self.trainer.batch_nb % 0 == 0: + if self.trainer.batch_nb % 1 == 0: output = OrderedDict({ 'val_loss': loss_val, 'val_acc': val_acc, }) return output - if self.trainer.batch_nb % 1 == 0: + if self.trainer.batch_nb % 2 == 0: return val_acc - if self.trainer.batch_nb % 2 == 0: + if self.trainer.batch_nb % 3 == 0: output = OrderedDict({ 'val_loss': loss_val, 'val_acc': val_acc, From 56997a06222b1a2628954120efb5d9fd07e81213 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:26:40 -0400 Subject: [PATCH 162/222] ignore argparse from example for tests --- .../examples/new_project_templates/lightning_module_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index fd68ef2e..0f28e181 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -234,7 +234,7 @@ class LightningTemplateModel(LightningModule): return self._test_dataloader @staticmethod - def add_model_specific_args(parent_parser, root_dir): + def add_model_specific_args(parent_parser, root_dir): # pragma: no cover """ Parameters you define here will be available to your model through self.hparams :param parent_parser: From c277ab103672d151f47a5dc02d220ecfb7fdc195 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:27:33 -0400 Subject: [PATCH 163/222] ignore tests file --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 8ffa3240..1b1396ee 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,7 +29,7 @@ exclude_lines = omit = pytorch_lightning/callbacks/pt_callbacks.py - + tests/test_models.py [flake8] ignore = E731,W504,F401,F841 From d372b21b5eb255890c5b80851f2f991def80fbfc Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:28:23 -0400 Subject: [PATCH 164/222] ignore test module model --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 1b1396ee..99cb5715 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,6 +30,7 @@ exclude_lines = omit = pytorch_lightning/callbacks/pt_callbacks.py tests/test_models.py + pytorch_lightning/testing_models/lm_test_module.py [flake8] ignore = E731,W504,F401,F841 From 1d28b468bdb6e0325a7549e3152a20c966635372 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:30:16 -0400 Subject: [PATCH 165/222] remove exception line --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 99cb5715..3aa2e990 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,6 +26,7 @@ exclude_lines = raise NotImplementedError if 0: if __name__ == .__main__.: + except Exception as e omit = pytorch_lightning/callbacks/pt_callbacks.py From 66abd0d3825767148c003874dcbefb1f02d93b18 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:31:56 -0400 Subject: [PATCH 166/222] test memory printing --- tests/test_models.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index 67c677a2..c958b0d0 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -35,6 +35,10 @@ def test_cpu_model(): ) model, hparams = get_model() + + # test memory gathering + model.count_mem_items() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) From 5ebe4942120b400c5790e9c2d1137fb024ac1625 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:34:08 -0400 Subject: [PATCH 167/222] test memory printing --- setup.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.cfg b/setup.cfg index 3aa2e990..8d4afaee 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,6 +27,9 @@ exclude_lines = if 0: if __name__ == .__main__.: except Exception as e + print(e) + print(traceback.print_exc()) + return * omit = pytorch_lightning/callbacks/pt_callbacks.py From ffdf11b7edb1af86bb453b7566bab43e0c7306b9 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:35:39 -0400 Subject: [PATCH 168/222] test memory printing --- tests/test_models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index c958b0d0..4195f9a6 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -36,9 +36,6 @@ def test_cpu_model(): model, hparams = get_model() - # test memory gathering - model.count_mem_items() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) @@ -237,6 +234,9 @@ def test_ddp_sampler_error(): use_amp=True ) + # test memory gathering + trainer.count_mem_items() + with pytest.raises(MisconfigurationException): trainer.get_dataloaders(model) From 7f420c0cc2bd727a6b139dde2bb25b48ddfe13f3 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:41:08 -0400 Subject: [PATCH 169/222] test memory printing --- tests/test_models.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 4195f9a6..42c59738 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -6,6 +6,7 @@ from argparse import Namespace from test_tube import Experiment from pytorch_lightning.callbacks import ModelCheckpoint, EarlyStopping from pytorch_lightning.utils.debugging import MisconfigurationException +from pytorch_lightning.root_module import memory import numpy as np import warnings import torch @@ -128,6 +129,11 @@ def test_multi_gpu_model_dp(): run_gpu_model_test(trainer_options, model, hparams) + # test memory helper functions + memory.count_mem_items() + memory.print_mem_stack() + memory.get_gpu_memory_map() + def test_amp_gpu_dp(): """ @@ -234,14 +240,12 @@ def test_ddp_sampler_error(): use_amp=True ) - # test memory gathering - trainer.count_mem_items() - with pytest.raises(MisconfigurationException): trainer.get_dataloaders(model) clear_save_dir() + # ------------------------------------------------------------------------ # UTILS # ------------------------------------------------------------------------ From 436e929458464fba3b348e72fc63e4296c3a03df Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:47:51 -0400 Subject: [PATCH 170/222] test memory printing --- pytorch_lightning/root_module/memory.py | 4 ++-- tests/test_models.py | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index 6f29b9ad..ffcf8572 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -152,7 +152,7 @@ class ModelSummary(object): self.make_summary() -def print_mem_stack(): +def print_mem_stack(): # pragma: no cover for obj in gc.get_objects(): try: if torch.is_tensor(obj) or (hasattr(obj, 'data') and torch.is_tensor(obj.data)): @@ -161,7 +161,7 @@ def print_mem_stack(): pass -def count_mem_items(): +def count_mem_items(): # pragma: no cover nb_params = 0 nb_tensors = 0 for obj in gc.get_objects(): diff --git a/tests/test_models.py b/tests/test_models.py index 42c59738..f08ddf36 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -130,8 +130,6 @@ def test_multi_gpu_model_dp(): run_gpu_model_test(trainer_options, model, hparams) # test memory helper functions - memory.count_mem_items() - memory.print_mem_stack() memory.get_gpu_memory_map() From 8191f268ec088e87483d400feaaac2492bba253d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:56:47 -0400 Subject: [PATCH 171/222] test memory printing --- tests/test_models.py | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index f08ddf36..ae37ccb0 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -107,6 +107,54 @@ def test_single_gpu_model(): run_gpu_model_test(trainer_options, model, hparams) +def test_hpc_save_load_gpu_models(): + """ + Make sure DP works + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model, hparams = get_model() + trainer_options = dict( + progress_bar=False, + max_nb_epochs=1, + train_percent_check=0.1, + val_percent_check=0.1, + gpus=[0, 1] + ) + + save_dir = init_save_dir() + + # exp file to get meta + exp = get_exp(False) + exp.argparse(hparams) + exp.save() + + # exp file to get weights + checkpoint = ModelCheckpoint(save_dir) + + # add these to the trainer options + trainer_options['checkpoint_callback'] = checkpoint + trainer_options['experiment'] = exp + + # fit model + trainer = Trainer(**trainer_options) + result = trainer.fit(model) + + # correct result and ok accuracy + assert result == 1, 'amp + ddp model failed to complete' + + trainer.hpc_save(save_dir, exp) + trainer.hpc_load(save_dir, on_gpu=True) + + clear_save_dir() + + + def test_multi_gpu_model_dp(): """ Make sure DP works From 17f56c83b5e6d3be20fda2fee002318e3840faf7 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:57:15 -0400 Subject: [PATCH 172/222] testing hpc save load --- tests/test_models.py | 94 ++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index ae37ccb0..83288f07 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -21,6 +21,54 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ + +def test_hpc_save_load_gpu_models(): + """ + Make sure DP works + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model, hparams = get_model() + trainer_options = dict( + progress_bar=False, + max_nb_epochs=1, + train_percent_check=0.1, + val_percent_check=0.1, + gpus=[0, 1] + ) + + save_dir = init_save_dir() + + # exp file to get meta + exp = get_exp(False) + exp.argparse(hparams) + exp.save() + + # exp file to get weights + checkpoint = ModelCheckpoint(save_dir) + + # add these to the trainer options + trainer_options['checkpoint_callback'] = checkpoint + trainer_options['experiment'] = exp + + # fit model + trainer = Trainer(**trainer_options) + result = trainer.fit(model) + + # correct result and ok accuracy + assert result == 1, 'amp + ddp model failed to complete' + + trainer.hpc_save(save_dir, exp) + trainer.hpc_load(save_dir, on_gpu=True) + + clear_save_dir() + + def test_cpu_model(): """ Make sure model trains on CPU @@ -107,52 +155,6 @@ def test_single_gpu_model(): run_gpu_model_test(trainer_options, model, hparams) -def test_hpc_save_load_gpu_models(): - """ - Make sure DP works - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - model, hparams = get_model() - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, - gpus=[0, 1] - ) - - save_dir = init_save_dir() - - # exp file to get meta - exp = get_exp(False) - exp.argparse(hparams) - exp.save() - - # exp file to get weights - checkpoint = ModelCheckpoint(save_dir) - - # add these to the trainer options - trainer_options['checkpoint_callback'] = checkpoint - trainer_options['experiment'] = exp - - # fit model - trainer = Trainer(**trainer_options) - result = trainer.fit(model) - - # correct result and ok accuracy - assert result == 1, 'amp + ddp model failed to complete' - - trainer.hpc_save(save_dir, exp) - trainer.hpc_load(save_dir, on_gpu=True) - - clear_save_dir() - def test_multi_gpu_model_dp(): From 97980355e3cd3b180873a1b98d1d865d70a83324 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 17:58:00 -0400 Subject: [PATCH 173/222] testing hpc save load --- tests/test_models.py | 448 +++++++++++++++++++++---------------------- 1 file changed, 224 insertions(+), 224 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 83288f07..8119e34e 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -68,230 +68,230 @@ def test_hpc_save_load_gpu_models(): clear_save_dir() - -def test_cpu_model(): - """ - Make sure model trains on CPU - :return: - """ - - trainer_options = dict( - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4 - ) - - model, hparams = get_model() - - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - -def test_all_features_cpu_model(): - """ - Test each of the trainer options - :return: - """ - - trainer_options = dict( - gradient_clip=1.0, - overfit_pct=0.20, - track_grad_norm=2, - print_nan_grads=True, - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4 - ) - - model, hparams = get_model() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - -def test_early_stopping_cpu_model(): - """ - Test each of the trainer options - :return: - """ - - stopping = EarlyStopping() - trainer_options = dict( - early_stop_callback=stopping, - gradient_clip=1.0, - overfit_pct=0.20, - track_grad_norm=2, - print_nan_grads=True, - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4 - ) - - model, hparams = get_model() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - -def test_single_gpu_model(): - """ - Make sure single GPU works (DP mode) - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') - return - model, hparams = get_model() - - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, - gpus=[0] - ) - - run_gpu_model_test(trainer_options, model, hparams) - - - - -def test_multi_gpu_model_dp(): - """ - Make sure DP works - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - model, hparams = get_model() - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, - gpus=[0, 1] - ) - - run_gpu_model_test(trainer_options, model, hparams) - - # test memory helper functions - memory.get_gpu_memory_map() - - -def test_amp_gpu_dp(): - """ - Make sure DP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - model, hparams = get_model() - trainer_options = dict( - max_nb_epochs=1, - gpus='0, 1', # test init with gpu string - distributed_backend='dp', - use_amp=True - ) - with pytest.raises(MisconfigurationException): - run_gpu_model_test(trainer_options, model, hparams) - - -def test_multi_gpu_model_ddp(): - """ - Make sure DDP works - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - - os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - model, hparams = get_model() - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, - gpus=[0, 1], - distributed_backend='ddp' - ) - - run_gpu_model_test(trainer_options, model, hparams) - - -def test_amp_gpu_ddp(): - """ - Make sure DDP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - - os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - - hparams = get_hparams() - model = LightningTestModel(hparams) - - trainer_options = dict( - progress_bar=True, - max_nb_epochs=1, - gpus=[0, 1], - distributed_backend='ddp', - use_amp=True - ) - - run_gpu_model_test(trainer_options, model, hparams) - - -def test_ddp_sampler_error(): - """ - Make sure DDP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - - os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - - hparams = get_hparams() - model = LightningTestModel(hparams, force_remove_distributed_sampler=True) - - exp = get_exp(True) - exp.save() - - trainer = Trainer( - experiment=exp, - progress_bar=False, - max_nb_epochs=1, - gpus=[0, 1], - distributed_backend='ddp', - use_amp=True - ) - - with pytest.raises(MisconfigurationException): - trainer.get_dataloaders(model) - - clear_save_dir() +# +# def test_cpu_model(): +# """ +# Make sure model trains on CPU +# :return: +# """ +# +# trainer_options = dict( +# progress_bar=False, +# experiment=get_exp(), +# max_nb_epochs=1, +# train_percent_check=0.4, +# val_percent_check=0.4 +# ) +# +# model, hparams = get_model() +# +# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) +# +# +# def test_all_features_cpu_model(): +# """ +# Test each of the trainer options +# :return: +# """ +# +# trainer_options = dict( +# gradient_clip=1.0, +# overfit_pct=0.20, +# track_grad_norm=2, +# print_nan_grads=True, +# progress_bar=False, +# experiment=get_exp(), +# max_nb_epochs=1, +# train_percent_check=0.4, +# val_percent_check=0.4 +# ) +# +# model, hparams = get_model() +# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) +# +# +# def test_early_stopping_cpu_model(): +# """ +# Test each of the trainer options +# :return: +# """ +# +# stopping = EarlyStopping() +# trainer_options = dict( +# early_stop_callback=stopping, +# gradient_clip=1.0, +# overfit_pct=0.20, +# track_grad_norm=2, +# print_nan_grads=True, +# progress_bar=False, +# experiment=get_exp(), +# max_nb_epochs=1, +# train_percent_check=0.4, +# val_percent_check=0.4 +# ) +# +# model, hparams = get_model() +# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) +# +# +# def test_single_gpu_model(): +# """ +# Make sure single GPU works (DP mode) +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') +# return +# model, hparams = get_model() +# +# trainer_options = dict( +# progress_bar=False, +# max_nb_epochs=1, +# train_percent_check=0.1, +# val_percent_check=0.1, +# gpus=[0] +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# +# +# def test_multi_gpu_model_dp(): +# """ +# Make sure DP works +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# model, hparams = get_model() +# trainer_options = dict( +# progress_bar=False, +# max_nb_epochs=1, +# train_percent_check=0.1, +# val_percent_check=0.1, +# gpus=[0, 1] +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# # test memory helper functions +# memory.get_gpu_memory_map() +# +# +# def test_amp_gpu_dp(): +# """ +# Make sure DP + AMP work +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# model, hparams = get_model() +# trainer_options = dict( +# max_nb_epochs=1, +# gpus='0, 1', # test init with gpu string +# distributed_backend='dp', +# use_amp=True +# ) +# with pytest.raises(MisconfigurationException): +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_multi_gpu_model_ddp(): +# """ +# Make sure DDP works +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# +# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) +# model, hparams = get_model() +# trainer_options = dict( +# progress_bar=False, +# max_nb_epochs=1, +# train_percent_check=0.1, +# val_percent_check=0.1, +# gpus=[0, 1], +# distributed_backend='ddp' +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_amp_gpu_ddp(): +# """ +# Make sure DDP + AMP work +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# +# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) +# +# hparams = get_hparams() +# model = LightningTestModel(hparams) +# +# trainer_options = dict( +# progress_bar=True, +# max_nb_epochs=1, +# gpus=[0, 1], +# distributed_backend='ddp', +# use_amp=True +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_ddp_sampler_error(): +# """ +# Make sure DDP + AMP work +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# +# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) +# +# hparams = get_hparams() +# model = LightningTestModel(hparams, force_remove_distributed_sampler=True) +# +# exp = get_exp(True) +# exp.save() +# +# trainer = Trainer( +# experiment=exp, +# progress_bar=False, +# max_nb_epochs=1, +# gpus=[0, 1], +# distributed_backend='ddp', +# use_amp=True +# ) +# +# with pytest.raises(MisconfigurationException): +# trainer.get_dataloaders(model) +# +# clear_save_dir() # ------------------------------------------------------------------------ From 2408aa886dbf93c9755cca05c037ebb62a930da5 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:00:15 -0400 Subject: [PATCH 174/222] testing hpc save load --- pytorch_lightning/root_module/model_saving.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytorch_lightning/root_module/model_saving.py b/pytorch_lightning/root_module/model_saving.py index 818c1947..1e47e3e7 100644 --- a/pytorch_lightning/root_module/model_saving.py +++ b/pytorch_lightning/root_module/model_saving.py @@ -144,7 +144,7 @@ class TrainerIO(object): filepath = '{}/hpc_ckpt_{}.ckpt'.format(folderpath, ckpt_number) # give model a chance to do something on hpc_save - self.on_hpc_save() + self.model.on_hpc_save() # request what to save from the model checkpoint_dict = self.dump_checkpoint() @@ -168,7 +168,7 @@ class TrainerIO(object): model.load_model_specific(checkpoint) # call model hook - self.on_hpc_load() + self.model.on_hpc_load() def max_ckpt_in_folder(self, path): files = os.listdir(path) From 423bc5c6c9217dff44244731717b13a3d8252576 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:01:33 -0400 Subject: [PATCH 175/222] testing hpc save load --- pytorch_lightning/root_module/model_saving.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pytorch_lightning/root_module/model_saving.py b/pytorch_lightning/root_module/model_saving.py index 1e47e3e7..493aa05b 100644 --- a/pytorch_lightning/root_module/model_saving.py +++ b/pytorch_lightning/root_module/model_saving.py @@ -144,7 +144,8 @@ class TrainerIO(object): filepath = '{}/hpc_ckpt_{}.ckpt'.format(folderpath, ckpt_number) # give model a chance to do something on hpc_save - self.model.on_hpc_save() + model = self.model.module if type(self.model) is LightningDataParallel else self.model + model.on_hpc_save() # request what to save from the model checkpoint_dict = self.dump_checkpoint() @@ -168,7 +169,7 @@ class TrainerIO(object): model.load_model_specific(checkpoint) # call model hook - self.model.on_hpc_load() + model.on_hpc_load() def max_ckpt_in_folder(self, path): files = os.listdir(path) From a63f74281a12ebd947e5161b8d599c14840884e6 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:03:19 -0400 Subject: [PATCH 176/222] fixed correct module on hpc save --- pytorch_lightning/root_module/model_saving.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pytorch_lightning/root_module/model_saving.py b/pytorch_lightning/root_module/model_saving.py index 493aa05b..557b5d7d 100644 --- a/pytorch_lightning/root_module/model_saving.py +++ b/pytorch_lightning/root_module/model_saving.py @@ -41,6 +41,11 @@ class ModelIO(object): class TrainerIO(object): + def __get_model(self): + is_dp_module = type(self.model) is LightningDistributedDataParallel or type(self.model) is LightningDataParallel + model = self.model.module if is_dp_module else self.model + return model + # -------------------- # MODEL SAVE CHECKPOINT # -------------------- @@ -71,8 +76,7 @@ class TrainerIO(object): checkpoint['optimizer_states'] = optimizer_states # request what to save from the model - is_dp_module = type(self.model) is LightningDistributedDataParallel or type(self.model) is LightningDataParallel - model = self.model.module if is_dp_module else self.model + model = self.__get_model() checkpoint_dict = model.get_save_dict() # merge trainer and model saving items @@ -144,7 +148,7 @@ class TrainerIO(object): filepath = '{}/hpc_ckpt_{}.ckpt'.format(folderpath, ckpt_number) # give model a chance to do something on hpc_save - model = self.model.module if type(self.model) is LightningDataParallel else self.model + model = self.__get_model() model.on_hpc_save() # request what to save from the model @@ -165,7 +169,7 @@ class TrainerIO(object): self.restore_training_state(checkpoint) # load model state - model = self.model.module if type(self.model) is LightningDataParallel else self.model + model = self.__get_model() model.load_model_specific(checkpoint) # call model hook From 549a158ec031fb04cb776fc3402cc1e26c5f5f89 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:09:04 -0400 Subject: [PATCH 177/222] fixed correct module on hpc save --- tests/test_models.py | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index 8119e34e..b6459574 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -21,6 +21,51 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ +def test_hpc_save_load_cpu_models(): + """ + Make sure DP works + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model, hparams = get_model() + trainer_options = dict( + progress_bar=False, + max_nb_epochs=1, + train_percent_check=0.1, + val_percent_check=0.1, + ) + + save_dir = init_save_dir() + + # exp file to get meta + exp = get_exp(False) + exp.argparse(hparams) + exp.save() + + # exp file to get weights + checkpoint = ModelCheckpoint(save_dir) + + # add these to the trainer options + trainer_options['checkpoint_callback'] = checkpoint + trainer_options['experiment'] = exp + + # fit model + trainer = Trainer(**trainer_options) + result = trainer.fit(model) + + # correct result and ok accuracy + assert result == 1, 'amp + ddp model failed to complete' + + trainer.hpc_save(save_dir, exp) + trainer.hpc_load(save_dir, on_gpu=True) + + clear_save_dir() + def test_hpc_save_load_gpu_models(): """ From 10330f1991875d0bbddc0ac49ae42cd2dc8e1c5a Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:10:30 -0400 Subject: [PATCH 178/222] fixed correct module on hpc save --- tests/test_models.py | 461 +++++++++++++++++-------------------------- 1 file changed, 185 insertions(+), 276 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index b6459574..04ca68c6 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -21,53 +21,93 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ -def test_hpc_save_load_cpu_models(): +def test_cpu_model(): """ - Make sure DP works + Make sure model trains on CPU + :return: + """ + + trainer_options = dict( + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + model, hparams = get_model() + + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + +def test_all_features_cpu_model(): + """ + Test each of the trainer options + :return: + """ + + trainer_options = dict( + gradient_clip=1.0, + overfit_pct=0.20, + track_grad_norm=2, + print_nan_grads=True, + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + +def test_early_stopping_cpu_model(): + """ + Test each of the trainer options + :return: + """ + + stopping = EarlyStopping() + trainer_options = dict( + early_stop_callback=stopping, + gradient_clip=1.0, + overfit_pct=0.20, + track_grad_norm=2, + print_nan_grads=True, + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + +def test_single_gpu_model(): + """ + Make sure single GPU works (DP mode) :return: """ if not torch.cuda.is_available(): - warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') return model, hparams = get_model() + trainer_options = dict( progress_bar=False, max_nb_epochs=1, train_percent_check=0.1, val_percent_check=0.1, + gpus=[0] ) - save_dir = init_save_dir() - - # exp file to get meta - exp = get_exp(False) - exp.argparse(hparams) - exp.save() - - # exp file to get weights - checkpoint = ModelCheckpoint(save_dir) - - # add these to the trainer options - trainer_options['checkpoint_callback'] = checkpoint - trainer_options['experiment'] = exp - - # fit model - trainer = Trainer(**trainer_options) - result = trainer.fit(model) - - # correct result and ok accuracy - assert result == 1, 'amp + ddp model failed to complete' - - trainer.hpc_save(save_dir, exp) - trainer.hpc_load(save_dir, on_gpu=True) - - clear_save_dir() + run_gpu_model_test(trainer_options, model, hparams) -def test_hpc_save_load_gpu_models(): +def test_multi_gpu_model_dp(): """ Make sure DP works :return: @@ -87,257 +127,122 @@ def test_hpc_save_load_gpu_models(): gpus=[0, 1] ) - save_dir = init_save_dir() + run_gpu_model_test(trainer_options, model, hparams) - # exp file to get meta - exp = get_exp(False) - exp.argparse(hparams) + # test memory helper functions + memory.get_gpu_memory_map() + + +def test_amp_gpu_dp(): + """ + Make sure DP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model, hparams = get_model() + trainer_options = dict( + max_nb_epochs=1, + gpus='0, 1', # test init with gpu string + distributed_backend='dp', + use_amp=True + ) + with pytest.raises(MisconfigurationException): + run_gpu_model_test(trainer_options, model, hparams) + + +def test_multi_gpu_model_ddp(): + """ + Make sure DDP works + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + model, hparams = get_model() + trainer_options = dict( + progress_bar=False, + max_nb_epochs=1, + train_percent_check=0.1, + val_percent_check=0.1, + gpus=[0, 1], + distributed_backend='ddp' + ) + + run_gpu_model_test(trainer_options, model, hparams) + + +def test_amp_gpu_ddp(): + """ + Make sure DDP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + + hparams = get_hparams() + model = LightningTestModel(hparams) + + trainer_options = dict( + progress_bar=True, + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + run_gpu_model_test(trainer_options, model, hparams) + + +def test_ddp_sampler_error(): + """ + Make sure DDP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + + hparams = get_hparams() + model = LightningTestModel(hparams, force_remove_distributed_sampler=True) + + exp = get_exp(True) exp.save() - # exp file to get weights - checkpoint = ModelCheckpoint(save_dir) + trainer = Trainer( + experiment=exp, + progress_bar=False, + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) - # add these to the trainer options - trainer_options['checkpoint_callback'] = checkpoint - trainer_options['experiment'] = exp - - # fit model - trainer = Trainer(**trainer_options) - result = trainer.fit(model) - - # correct result and ok accuracy - assert result == 1, 'amp + ddp model failed to complete' - - trainer.hpc_save(save_dir, exp) - trainer.hpc_load(save_dir, on_gpu=True) + with pytest.raises(MisconfigurationException): + trainer.get_dataloaders(model) clear_save_dir() -# -# def test_cpu_model(): -# """ -# Make sure model trains on CPU -# :return: -# """ -# -# trainer_options = dict( -# progress_bar=False, -# experiment=get_exp(), -# max_nb_epochs=1, -# train_percent_check=0.4, -# val_percent_check=0.4 -# ) -# -# model, hparams = get_model() -# -# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -# -# -# def test_all_features_cpu_model(): -# """ -# Test each of the trainer options -# :return: -# """ -# -# trainer_options = dict( -# gradient_clip=1.0, -# overfit_pct=0.20, -# track_grad_norm=2, -# print_nan_grads=True, -# progress_bar=False, -# experiment=get_exp(), -# max_nb_epochs=1, -# train_percent_check=0.4, -# val_percent_check=0.4 -# ) -# -# model, hparams = get_model() -# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -# -# -# def test_early_stopping_cpu_model(): -# """ -# Test each of the trainer options -# :return: -# """ -# -# stopping = EarlyStopping() -# trainer_options = dict( -# early_stop_callback=stopping, -# gradient_clip=1.0, -# overfit_pct=0.20, -# track_grad_norm=2, -# print_nan_grads=True, -# progress_bar=False, -# experiment=get_exp(), -# max_nb_epochs=1, -# train_percent_check=0.4, -# val_percent_check=0.4 -# ) -# -# model, hparams = get_model() -# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -# -# -# def test_single_gpu_model(): -# """ -# Make sure single GPU works (DP mode) -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') -# return -# model, hparams = get_model() -# -# trainer_options = dict( -# progress_bar=False, -# max_nb_epochs=1, -# train_percent_check=0.1, -# val_percent_check=0.1, -# gpus=[0] -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# -# -# def test_multi_gpu_model_dp(): -# """ -# Make sure DP works -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# model, hparams = get_model() -# trainer_options = dict( -# progress_bar=False, -# max_nb_epochs=1, -# train_percent_check=0.1, -# val_percent_check=0.1, -# gpus=[0, 1] -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# # test memory helper functions -# memory.get_gpu_memory_map() -# -# -# def test_amp_gpu_dp(): -# """ -# Make sure DP + AMP work -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# model, hparams = get_model() -# trainer_options = dict( -# max_nb_epochs=1, -# gpus='0, 1', # test init with gpu string -# distributed_backend='dp', -# use_amp=True -# ) -# with pytest.raises(MisconfigurationException): -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_multi_gpu_model_ddp(): -# """ -# Make sure DDP works -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# -# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) -# model, hparams = get_model() -# trainer_options = dict( -# progress_bar=False, -# max_nb_epochs=1, -# train_percent_check=0.1, -# val_percent_check=0.1, -# gpus=[0, 1], -# distributed_backend='ddp' -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_amp_gpu_ddp(): -# """ -# Make sure DDP + AMP work -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# -# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) -# -# hparams = get_hparams() -# model = LightningTestModel(hparams) -# -# trainer_options = dict( -# progress_bar=True, -# max_nb_epochs=1, -# gpus=[0, 1], -# distributed_backend='ddp', -# use_amp=True -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_ddp_sampler_error(): -# """ -# Make sure DDP + AMP work -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# -# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) -# -# hparams = get_hparams() -# model = LightningTestModel(hparams, force_remove_distributed_sampler=True) -# -# exp = get_exp(True) -# exp.save() -# -# trainer = Trainer( -# experiment=exp, -# progress_bar=False, -# max_nb_epochs=1, -# gpus=[0, 1], -# distributed_backend='ddp', -# use_amp=True -# ) -# -# with pytest.raises(MisconfigurationException): -# trainer.get_dataloaders(model) -# -# clear_save_dir() - # ------------------------------------------------------------------------ # UTILS @@ -370,6 +275,10 @@ def run_gpu_model_test(trainer_options, model, hparams, on_gpu=True): # test model preds run_prediction(model.test_dataloader, pretrained_model) + # test HPC loading / saving + trainer.hpc_save(save_dir, exp) + trainer.hpc_load(save_dir, on_gpu=True) + clear_save_dir() From 2e0fde7da7520beff8c7384e7603e6b8278e224d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:11:29 -0400 Subject: [PATCH 179/222] fixed correct module on hpc save --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 04ca68c6..ccd63398 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -277,7 +277,7 @@ def run_gpu_model_test(trainer_options, model, hparams, on_gpu=True): # test HPC loading / saving trainer.hpc_save(save_dir, exp) - trainer.hpc_load(save_dir, on_gpu=True) + trainer.hpc_load(save_dir, on_gpu=on_gpu) clear_save_dir() From 7217ecdb184b22210c91cf042173b2fe81d64fcd Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:12:46 -0400 Subject: [PATCH 180/222] fixed correct module on hpc save --- tests/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/README.md b/tests/README.md index d7eb4f92..fc60a6e2 100644 --- a/tests/README.md +++ b/tests/README.md @@ -15,6 +15,10 @@ pip install -r requirements.txt # run tests py.test + +# or to generate coverage +pip install coverage +coverage run tests/test_models.py ``` To test models that require GPU make sure to run the above command on a GPU machine. From d7be0aae1c5ed4d03cf0e7e4f9b39b6c9d1d1d5b Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:16:02 -0400 Subject: [PATCH 181/222] fixed correct module on hpc save --- pytorch_lightning/root_module/model_saving.py | 1 + tests/README.md | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/pytorch_lightning/root_module/model_saving.py b/pytorch_lightning/root_module/model_saving.py index 557b5d7d..b34d64f7 100644 --- a/pytorch_lightning/root_module/model_saving.py +++ b/pytorch_lightning/root_module/model_saving.py @@ -42,6 +42,7 @@ class ModelIO(object): class TrainerIO(object): def __get_model(self): + print(type(self.model)) is_dp_module = type(self.model) is LightningDistributedDataParallel or type(self.model) is LightningDataParallel model = self.model.module if is_dp_module else self.model return model diff --git a/tests/README.md b/tests/README.md index fc60a6e2..0b747112 100644 --- a/tests/README.md +++ b/tests/README.md @@ -36,4 +36,11 @@ This file fits a tiny model on MNIST using these different set-ups. 3. Multiple (2) GPUs using DP + apex (for 16-bit precision). 3. Multiple (2) GPUs using DDP + apex (for 16-bit precision). +For each set up it also tests: +1. model saving. +2. model loading. +3. predicting with a loaded model. +4. simulated save from HPC signal. +5. simulated load from HPC signal. + From 3600535bc5be0ec6f5428292811e4b5762b40d07 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:16:22 -0400 Subject: [PATCH 182/222] fixed correct module on hpc save --- tests/test_models.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index ccd63398..59d4d6f5 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -21,6 +21,36 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ + +def test_amp_gpu_ddp(): + """ + Make sure DDP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + + hparams = get_hparams() + model = LightningTestModel(hparams) + + trainer_options = dict( + progress_bar=True, + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + run_gpu_model_test(trainer_options, model, hparams) + + + def test_cpu_model(): """ Make sure model trains on CPU From 7fa759ffed85f7760cad72c59594d4e22333712d Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:16:31 -0400 Subject: [PATCH 183/222] fixed correct module on hpc save --- tests/test_models.py | 444 +++++++++++++++++++++---------------------- 1 file changed, 222 insertions(+), 222 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 59d4d6f5..a559c339 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -50,228 +50,228 @@ def test_amp_gpu_ddp(): run_gpu_model_test(trainer_options, model, hparams) - -def test_cpu_model(): - """ - Make sure model trains on CPU - :return: - """ - - trainer_options = dict( - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4 - ) - - model, hparams = get_model() - - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - -def test_all_features_cpu_model(): - """ - Test each of the trainer options - :return: - """ - - trainer_options = dict( - gradient_clip=1.0, - overfit_pct=0.20, - track_grad_norm=2, - print_nan_grads=True, - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4 - ) - - model, hparams = get_model() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - -def test_early_stopping_cpu_model(): - """ - Test each of the trainer options - :return: - """ - - stopping = EarlyStopping() - trainer_options = dict( - early_stop_callback=stopping, - gradient_clip=1.0, - overfit_pct=0.20, - track_grad_norm=2, - print_nan_grads=True, - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4 - ) - - model, hparams = get_model() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - -def test_single_gpu_model(): - """ - Make sure single GPU works (DP mode) - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') - return - model, hparams = get_model() - - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, - gpus=[0] - ) - - run_gpu_model_test(trainer_options, model, hparams) - - -def test_multi_gpu_model_dp(): - """ - Make sure DP works - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - model, hparams = get_model() - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, - gpus=[0, 1] - ) - - run_gpu_model_test(trainer_options, model, hparams) - - # test memory helper functions - memory.get_gpu_memory_map() - - -def test_amp_gpu_dp(): - """ - Make sure DP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - model, hparams = get_model() - trainer_options = dict( - max_nb_epochs=1, - gpus='0, 1', # test init with gpu string - distributed_backend='dp', - use_amp=True - ) - with pytest.raises(MisconfigurationException): - run_gpu_model_test(trainer_options, model, hparams) - - -def test_multi_gpu_model_ddp(): - """ - Make sure DDP works - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - - os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - model, hparams = get_model() - trainer_options = dict( - progress_bar=False, - max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, - gpus=[0, 1], - distributed_backend='ddp' - ) - - run_gpu_model_test(trainer_options, model, hparams) - - -def test_amp_gpu_ddp(): - """ - Make sure DDP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - - os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - - hparams = get_hparams() - model = LightningTestModel(hparams) - - trainer_options = dict( - progress_bar=True, - max_nb_epochs=1, - gpus=[0, 1], - distributed_backend='ddp', - use_amp=True - ) - - run_gpu_model_test(trainer_options, model, hparams) - - -def test_ddp_sampler_error(): - """ - Make sure DDP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - - os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - - hparams = get_hparams() - model = LightningTestModel(hparams, force_remove_distributed_sampler=True) - - exp = get_exp(True) - exp.save() - - trainer = Trainer( - experiment=exp, - progress_bar=False, - max_nb_epochs=1, - gpus=[0, 1], - distributed_backend='ddp', - use_amp=True - ) - - with pytest.raises(MisconfigurationException): - trainer.get_dataloaders(model) - - clear_save_dir() +# +# def test_cpu_model(): +# """ +# Make sure model trains on CPU +# :return: +# """ +# +# trainer_options = dict( +# progress_bar=False, +# experiment=get_exp(), +# max_nb_epochs=1, +# train_percent_check=0.4, +# val_percent_check=0.4 +# ) +# +# model, hparams = get_model() +# +# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) +# +# +# def test_all_features_cpu_model(): +# """ +# Test each of the trainer options +# :return: +# """ +# +# trainer_options = dict( +# gradient_clip=1.0, +# overfit_pct=0.20, +# track_grad_norm=2, +# print_nan_grads=True, +# progress_bar=False, +# experiment=get_exp(), +# max_nb_epochs=1, +# train_percent_check=0.4, +# val_percent_check=0.4 +# ) +# +# model, hparams = get_model() +# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) +# +# +# def test_early_stopping_cpu_model(): +# """ +# Test each of the trainer options +# :return: +# """ +# +# stopping = EarlyStopping() +# trainer_options = dict( +# early_stop_callback=stopping, +# gradient_clip=1.0, +# overfit_pct=0.20, +# track_grad_norm=2, +# print_nan_grads=True, +# progress_bar=False, +# experiment=get_exp(), +# max_nb_epochs=1, +# train_percent_check=0.4, +# val_percent_check=0.4 +# ) +# +# model, hparams = get_model() +# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) +# +# +# def test_single_gpu_model(): +# """ +# Make sure single GPU works (DP mode) +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') +# return +# model, hparams = get_model() +# +# trainer_options = dict( +# progress_bar=False, +# max_nb_epochs=1, +# train_percent_check=0.1, +# val_percent_check=0.1, +# gpus=[0] +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_multi_gpu_model_dp(): +# """ +# Make sure DP works +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# model, hparams = get_model() +# trainer_options = dict( +# progress_bar=False, +# max_nb_epochs=1, +# train_percent_check=0.1, +# val_percent_check=0.1, +# gpus=[0, 1] +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# # test memory helper functions +# memory.get_gpu_memory_map() +# +# +# def test_amp_gpu_dp(): +# """ +# Make sure DP + AMP work +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# model, hparams = get_model() +# trainer_options = dict( +# max_nb_epochs=1, +# gpus='0, 1', # test init with gpu string +# distributed_backend='dp', +# use_amp=True +# ) +# with pytest.raises(MisconfigurationException): +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_multi_gpu_model_ddp(): +# """ +# Make sure DDP works +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# +# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) +# model, hparams = get_model() +# trainer_options = dict( +# progress_bar=False, +# max_nb_epochs=1, +# train_percent_check=0.1, +# val_percent_check=0.1, +# gpus=[0, 1], +# distributed_backend='ddp' +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_amp_gpu_ddp(): +# """ +# Make sure DDP + AMP work +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# +# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) +# +# hparams = get_hparams() +# model = LightningTestModel(hparams) +# +# trainer_options = dict( +# progress_bar=True, +# max_nb_epochs=1, +# gpus=[0, 1], +# distributed_backend='ddp', +# use_amp=True +# ) +# +# run_gpu_model_test(trainer_options, model, hparams) +# +# +# def test_ddp_sampler_error(): +# """ +# Make sure DDP + AMP work +# :return: +# """ +# if not torch.cuda.is_available(): +# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') +# return +# if not torch.cuda.device_count() > 1: +# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') +# return +# +# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) +# +# hparams = get_hparams() +# model = LightningTestModel(hparams, force_remove_distributed_sampler=True) +# +# exp = get_exp(True) +# exp.save() +# +# trainer = Trainer( +# experiment=exp, +# progress_bar=False, +# max_nb_epochs=1, +# gpus=[0, 1], +# distributed_backend='ddp', +# use_amp=True +# ) +# +# with pytest.raises(MisconfigurationException): +# trainer.get_dataloaders(model) +# +# clear_save_dir() # ------------------------------------------------------------------------ From 8f0d9af16828688be3e64fe5be93549a02b4d836 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:18:58 -0400 Subject: [PATCH 184/222] fixed correct module on hpc save --- tests/test_models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index a559c339..3a364aea 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -305,6 +305,9 @@ def run_gpu_model_test(trainer_options, model, hparams, on_gpu=True): # test model preds run_prediction(model.test_dataloader, pretrained_model) + if trainer.use_ddp: + trainer.model = pretrained_model + # test HPC loading / saving trainer.hpc_save(save_dir, exp) trainer.hpc_load(save_dir, on_gpu=on_gpu) From a0e2b5ee54af289c050ce996e5ca5d1f81177706 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:20:56 -0400 Subject: [PATCH 185/222] fixed correct module on hpc save --- tests/test_models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_models.py b/tests/test_models.py index 3a364aea..63d38b4d 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -307,6 +307,7 @@ def run_gpu_model_test(trainer_options, model, hparams, on_gpu=True): if trainer.use_ddp: trainer.model = pretrained_model + trainer.optimizers = pretrained_model.configure_optimizers() # test HPC loading / saving trainer.hpc_save(save_dir, exp) From 6e2bf991f0f2491901ce82c043797cd9a5a89081 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:21:22 -0400 Subject: [PATCH 186/222] fixed correct module on hpc save --- tests/test_models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_models.py b/tests/test_models.py index 63d38b4d..1c6693b5 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -306,6 +306,7 @@ def run_gpu_model_test(trainer_options, model, hparams, on_gpu=True): run_prediction(model.test_dataloader, pretrained_model) if trainer.use_ddp: + # on hpc this would work fine... but need to hack it for the purpose of the test trainer.model = pretrained_model trainer.optimizers = pretrained_model.configure_optimizers() From 1313a7f3974c2dcd57c301ea9667a25a0ca940d8 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:22:49 -0400 Subject: [PATCH 187/222] fixed correct module on hpc save --- tests/test_models.py | 444 +++++++++++++++++++++---------------------- 1 file changed, 222 insertions(+), 222 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 1c6693b5..bbde7cb2 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -50,228 +50,228 @@ def test_amp_gpu_ddp(): run_gpu_model_test(trainer_options, model, hparams) -# -# def test_cpu_model(): -# """ -# Make sure model trains on CPU -# :return: -# """ -# -# trainer_options = dict( -# progress_bar=False, -# experiment=get_exp(), -# max_nb_epochs=1, -# train_percent_check=0.4, -# val_percent_check=0.4 -# ) -# -# model, hparams = get_model() -# -# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -# -# -# def test_all_features_cpu_model(): -# """ -# Test each of the trainer options -# :return: -# """ -# -# trainer_options = dict( -# gradient_clip=1.0, -# overfit_pct=0.20, -# track_grad_norm=2, -# print_nan_grads=True, -# progress_bar=False, -# experiment=get_exp(), -# max_nb_epochs=1, -# train_percent_check=0.4, -# val_percent_check=0.4 -# ) -# -# model, hparams = get_model() -# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -# -# -# def test_early_stopping_cpu_model(): -# """ -# Test each of the trainer options -# :return: -# """ -# -# stopping = EarlyStopping() -# trainer_options = dict( -# early_stop_callback=stopping, -# gradient_clip=1.0, -# overfit_pct=0.20, -# track_grad_norm=2, -# print_nan_grads=True, -# progress_bar=False, -# experiment=get_exp(), -# max_nb_epochs=1, -# train_percent_check=0.4, -# val_percent_check=0.4 -# ) -# -# model, hparams = get_model() -# run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -# -# -# def test_single_gpu_model(): -# """ -# Make sure single GPU works (DP mode) -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') -# return -# model, hparams = get_model() -# -# trainer_options = dict( -# progress_bar=False, -# max_nb_epochs=1, -# train_percent_check=0.1, -# val_percent_check=0.1, -# gpus=[0] -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_multi_gpu_model_dp(): -# """ -# Make sure DP works -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# model, hparams = get_model() -# trainer_options = dict( -# progress_bar=False, -# max_nb_epochs=1, -# train_percent_check=0.1, -# val_percent_check=0.1, -# gpus=[0, 1] -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# # test memory helper functions -# memory.get_gpu_memory_map() -# -# -# def test_amp_gpu_dp(): -# """ -# Make sure DP + AMP work -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# model, hparams = get_model() -# trainer_options = dict( -# max_nb_epochs=1, -# gpus='0, 1', # test init with gpu string -# distributed_backend='dp', -# use_amp=True -# ) -# with pytest.raises(MisconfigurationException): -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_multi_gpu_model_ddp(): -# """ -# Make sure DDP works -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# -# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) -# model, hparams = get_model() -# trainer_options = dict( -# progress_bar=False, -# max_nb_epochs=1, -# train_percent_check=0.1, -# val_percent_check=0.1, -# gpus=[0, 1], -# distributed_backend='ddp' -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_amp_gpu_ddp(): -# """ -# Make sure DDP + AMP work -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# -# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) -# -# hparams = get_hparams() -# model = LightningTestModel(hparams) -# -# trainer_options = dict( -# progress_bar=True, -# max_nb_epochs=1, -# gpus=[0, 1], -# distributed_backend='ddp', -# use_amp=True -# ) -# -# run_gpu_model_test(trainer_options, model, hparams) -# -# -# def test_ddp_sampler_error(): -# """ -# Make sure DDP + AMP work -# :return: -# """ -# if not torch.cuda.is_available(): -# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') -# return -# if not torch.cuda.device_count() > 1: -# warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') -# return -# -# os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) -# -# hparams = get_hparams() -# model = LightningTestModel(hparams, force_remove_distributed_sampler=True) -# -# exp = get_exp(True) -# exp.save() -# -# trainer = Trainer( -# experiment=exp, -# progress_bar=False, -# max_nb_epochs=1, -# gpus=[0, 1], -# distributed_backend='ddp', -# use_amp=True -# ) -# -# with pytest.raises(MisconfigurationException): -# trainer.get_dataloaders(model) -# -# clear_save_dir() + +def test_cpu_model(): + """ + Make sure model trains on CPU + :return: + """ + + trainer_options = dict( + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + model, hparams = get_model() + + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + +def test_all_features_cpu_model(): + """ + Test each of the trainer options + :return: + """ + + trainer_options = dict( + gradient_clip=1.0, + overfit_pct=0.20, + track_grad_norm=2, + print_nan_grads=True, + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + +def test_early_stopping_cpu_model(): + """ + Test each of the trainer options + :return: + """ + + stopping = EarlyStopping() + trainer_options = dict( + early_stop_callback=stopping, + gradient_clip=1.0, + overfit_pct=0.20, + track_grad_norm=2, + print_nan_grads=True, + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4 + ) + + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + +def test_single_gpu_model(): + """ + Make sure single GPU works (DP mode) + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_single_gpu_model cannot run. Rerun on a GPU node to run this test') + return + model, hparams = get_model() + + trainer_options = dict( + progress_bar=False, + max_nb_epochs=1, + train_percent_check=0.1, + val_percent_check=0.1, + gpus=[0] + ) + + run_gpu_model_test(trainer_options, model, hparams) + + +def test_multi_gpu_model_dp(): + """ + Make sure DP works + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_multi_gpu_model_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model, hparams = get_model() + trainer_options = dict( + progress_bar=False, + max_nb_epochs=1, + train_percent_check=0.1, + val_percent_check=0.1, + gpus=[0, 1] + ) + + run_gpu_model_test(trainer_options, model, hparams) + + # test memory helper functions + memory.get_gpu_memory_map() + + +def test_amp_gpu_dp(): + """ + Make sure DP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model, hparams = get_model() + trainer_options = dict( + max_nb_epochs=1, + gpus='0, 1', # test init with gpu string + distributed_backend='dp', + use_amp=True + ) + with pytest.raises(MisconfigurationException): + run_gpu_model_test(trainer_options, model, hparams) + + +def test_multi_gpu_model_ddp(): + """ + Make sure DDP works + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_multi_gpu_model_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + model, hparams = get_model() + trainer_options = dict( + progress_bar=False, + max_nb_epochs=1, + train_percent_check=0.1, + val_percent_check=0.1, + gpus=[0, 1], + distributed_backend='ddp' + ) + + run_gpu_model_test(trainer_options, model, hparams) + + +def test_amp_gpu_ddp(): + """ + Make sure DDP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + + hparams = get_hparams() + model = LightningTestModel(hparams) + + trainer_options = dict( + progress_bar=True, + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + run_gpu_model_test(trainer_options, model, hparams) + + +def test_ddp_sampler_error(): + """ + Make sure DDP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + + hparams = get_hparams() + model = LightningTestModel(hparams, force_remove_distributed_sampler=True) + + exp = get_exp(True) + exp.save() + + trainer = Trainer( + experiment=exp, + progress_bar=False, + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + with pytest.raises(MisconfigurationException): + trainer.get_dataloaders(model) + + clear_save_dir() # ------------------------------------------------------------------------ From 3451a62650e8a373279c82da2653e16ccfdcaec8 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:27:40 -0400 Subject: [PATCH 188/222] running ddp tests --- tests/test_models.py | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index bbde7cb2..45885f91 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -22,35 +22,6 @@ np.random.seed(SEED) # TESTS # ------------------------------------------------------------------------ -def test_amp_gpu_ddp(): - """ - Make sure DDP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - - os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) - - hparams = get_hparams() - model = LightningTestModel(hparams) - - trainer_options = dict( - progress_bar=True, - max_nb_epochs=1, - gpus=[0, 1], - distributed_backend='ddp', - use_amp=True - ) - - run_gpu_model_test(trainer_options, model, hparams) - - - def test_cpu_model(): """ Make sure model trains on CPU From 9d588f337f22d3ab1c0ba49042c2a10c79cbcc15 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:30:08 -0400 Subject: [PATCH 189/222] running ddp tests --- pytorch_lightning/models/trainer.py | 2 +- setup.cfg | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 0cd4d89a..c6ddbaaf 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -24,7 +24,7 @@ from pytorch_lightning.utils.debugging import MisconfigurationException try: from apex import amp APEX_AVAILABLE = True -except ModuleNotFoundError: +except ModuleNotFoundError: # pragma: no cover APEX_AVAILABLE = False diff --git a/setup.cfg b/setup.cfg index 8d4afaee..1efb021f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,6 +30,7 @@ exclude_lines = print(e) print(traceback.print_exc()) return * + raise Exception omit = pytorch_lightning/callbacks/pt_callbacks.py From abbbcac9fa9f448f667d463418003ede0da82c50 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:30:35 -0400 Subject: [PATCH 190/222] running ddp tests --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 1efb021f..1ce67f2a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,6 +31,7 @@ exclude_lines = print(traceback.print_exc()) return * raise Exception + warnings omit = pytorch_lightning/callbacks/pt_callbacks.py From 70a2e66ae9e590859adadebd1479d4558c41434c Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:30:47 -0400 Subject: [PATCH 191/222] running ddp tests --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 1ce67f2a..01c0b049 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,6 +32,7 @@ exclude_lines = return * raise Exception warnings + print omit = pytorch_lightning/callbacks/pt_callbacks.py From 40b86808c86fd13f7bedae47a61e4b626ca2bf48 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:32:48 -0400 Subject: [PATCH 192/222] running ddp tests --- pytorch_lightning/pt_overrides/override_data_parallel.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pytorch_lightning/pt_overrides/override_data_parallel.py b/pytorch_lightning/pt_overrides/override_data_parallel.py index 9b287de1..9d34d455 100644 --- a/pytorch_lightning/pt_overrides/override_data_parallel.py +++ b/pytorch_lightning/pt_overrides/override_data_parallel.py @@ -9,7 +9,7 @@ from torch.cuda._utils import _get_device_index import pdb -def _find_tensors(obj): +def _find_tensors(obj): # pragma: no cover r""" Recursively find all tensors contained in the specified object. """ @@ -22,8 +22,7 @@ def _find_tensors(obj): return [] - -def get_a_var(obj): +def get_a_var(obj): # pragma: no cover if isinstance(obj, torch.Tensor): return obj From 982f0d4b3a286518cc7a8e579126d54c3019dd5b Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:33:54 -0400 Subject: [PATCH 193/222] running ddp tests --- tests/test_models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 45885f91..e314cbb2 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -173,8 +173,8 @@ def test_multi_gpu_model_ddp(): trainer_options = dict( progress_bar=False, max_nb_epochs=1, - train_percent_check=0.1, - val_percent_check=0.1, + train_percent_check=0.4, + val_percent_check=0.2, gpus=[0, 1], distributed_backend='ddp' ) From fb8b03b0421d868bc5ca8e7a1270ca7b4c3da917 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:39:27 -0400 Subject: [PATCH 194/222] moved slurm flag resolution to init --- pytorch_lightning/models/trainer.py | 31 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index c6ddbaaf..1a0b5e2b 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -161,6 +161,18 @@ class Trainer(TrainerIO): self.nb_tng_batches = None self.nb_test_batches = None + # manages slurm task + # whenever we have the correct number of tasks, we let slurm manage processes + # otherwise we launch the required number of processes + self.nb_requested_gpus = len(self.data_parallel_device_ids) * self.nb_gpu_nodes + self.nb_slurm_tasks = 0 + try: + self.nb_slurm_tasks = int(os.environ['SLURM_NTASKS']) + self.is_slurm_managing_tasks = self.nb_slurm_tasks == self.nb_requested_gpus + except Exception as e: + # likely not on slurm, so set the slurm managed flag to false + self.is_slurm_managing_tasks = False + # gpus come in as a string. # if gpus = -1 then use all available devices # otherwise, split the string using commas @@ -404,25 +416,14 @@ class Trainer(TrainerIO): # must copy only the meta of the exp so it survives pickle/unpickle when going to new process self.experiment = self.experiment.get_meta_copy() - # whenever we have the correct number of tasks, we let slurm manage processes - # otherwise we launch the required number of processes - nb_requested_gpus = len(self.data_parallel_device_ids) * self.nb_gpu_nodes - nb_slurm_tasks = 0 - try: - nb_slurm_tasks = int(os.environ['SLURM_NTASKS']) - is_slurm_managing_tasks = nb_slurm_tasks == nb_requested_gpus - except Exception as e: - # likely not on slurm, so set the slurm managed flag to false - is_slurm_managing_tasks = False - - if is_slurm_managing_tasks: + if self.is_slurm_managing_tasks: task = int(os.environ['SLURM_LOCALID']) self.ddp_train(task, model) else: msg = f""" - You requested {nb_requested_gpus} GPUs but launched {nb_slurm_tasks} slurm tasks. - We will launch {nb_requested_gpus} processes for you. - We recommend you let slurm manage the processes by setting: --ntasks-per-node={nb_requested_gpus} + You requested {self.nb_requested_gpus} GPUs but launched {self.nb_slurm_tasks} slurm tasks. + We will launch {self.nb_requested_gpus} processes for you. + We recommend you let slurm manage the processes by setting: --ntasks-per-node={self.nb_requested_gpus} If you're not using SLURM, ignore this message! """ warnings.warn(msg) From 18ce3e5a23c9d1bb72cb36a347766b816a0b81c7 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:40:54 -0400 Subject: [PATCH 195/222] moved slurm flag resolution to init --- tests/test_models.py | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index e314cbb2..15827a32 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -21,6 +21,70 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ +def test_amp_gpu_ddp_slurm_managed(): + """ + Make sure DDP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_ddp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + + os.environ['MASTER_PORT'] = str(np.random.randint(12000, 19000, 1)[0]) + + hparams = get_hparams() + model = LightningTestModel(hparams) + + trainer_options = dict( + progress_bar=True, + max_nb_epochs=1, + gpus=[0, 1], + distributed_backend='ddp', + use_amp=True + ) + + save_dir = init_save_dir() + + # exp file to get meta + exp = get_exp(False) + exp.argparse(hparams) + exp.save() + + # exp file to get weights + checkpoint = ModelCheckpoint(save_dir) + + # add these to the trainer options + trainer_options['checkpoint_callback'] = checkpoint + trainer_options['experiment'] = exp + + # fit model + trainer = Trainer(**trainer_options) + trainer.is_slurm_managing_tasks = True + result = trainer.fit(model) + + # correct result and ok accuracy + assert result == 1, 'amp + ddp model failed to complete' + + # test model loading + pretrained_model = load_model(exp, save_dir, True) + + # test model preds + run_prediction(model.test_dataloader, pretrained_model) + + if trainer.use_ddp: + # on hpc this would work fine... but need to hack it for the purpose of the test + trainer.model = pretrained_model + trainer.optimizers = pretrained_model.configure_optimizers() + + # test HPC loading / saving + trainer.hpc_save(save_dir, exp) + trainer.hpc_load(save_dir, on_gpu=True) + + clear_save_dir() + def test_cpu_model(): """ From f4d8fe5d77d0e1450f816957d6308ce8a6ac04ee Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:42:22 -0400 Subject: [PATCH 196/222] moved slurm flag resolution to init --- pytorch_lightning/models/trainer.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 1a0b5e2b..db8f2861 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -161,17 +161,6 @@ class Trainer(TrainerIO): self.nb_tng_batches = None self.nb_test_batches = None - # manages slurm task - # whenever we have the correct number of tasks, we let slurm manage processes - # otherwise we launch the required number of processes - self.nb_requested_gpus = len(self.data_parallel_device_ids) * self.nb_gpu_nodes - self.nb_slurm_tasks = 0 - try: - self.nb_slurm_tasks = int(os.environ['SLURM_NTASKS']) - self.is_slurm_managing_tasks = self.nb_slurm_tasks == self.nb_requested_gpus - except Exception as e: - # likely not on slurm, so set the slurm managed flag to false - self.is_slurm_managing_tasks = False # gpus come in as a string. # if gpus = -1 then use all available devices @@ -208,6 +197,19 @@ class Trainer(TrainerIO): 'To silence this warning set distributed_backend=ddp' warnings.warn(w) + # extract SLURM flag vars + # whenever we have the correct number of tasks, we let slurm manage processes + # otherwise we launch the required number of processes + if self.use_ddp: + self.nb_requested_gpus = len(self.data_parallel_device_ids) * self.nb_gpu_nodes + self.nb_slurm_tasks = 0 + try: + self.nb_slurm_tasks = int(os.environ['SLURM_NTASKS']) + self.is_slurm_managing_tasks = self.nb_slurm_tasks == self.nb_requested_gpus + except Exception as e: + # likely not on slurm, so set the slurm managed flag to false + self.is_slurm_managing_tasks = False + # process info self.proc_rank = 0 From 53a0b9f365cd4219cb2d63bc53e8c54505664343 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:46:21 -0400 Subject: [PATCH 197/222] moved slurm flag resolution to init --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 15827a32..4b9ec68b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -41,7 +41,7 @@ def test_amp_gpu_ddp_slurm_managed(): trainer_options = dict( progress_bar=True, max_nb_epochs=1, - gpus=[0, 1], + gpus=[0], distributed_backend='ddp', use_amp=True ) From ccd4018dd90f9d028a2f51c680401ef51aedd856 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:53:12 -0400 Subject: [PATCH 198/222] made root note address individually testable --- pytorch_lightning/models/trainer.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index db8f2861..0be187d0 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -556,14 +556,15 @@ class Trainer(TrainerIO): port = 12910 os.environ['MASTER_PORT'] = f'{port}' - root_node = self.__resolve_root_node_address() + # figure out the root node addr + root_node = os.environ['SLURM_NODELIST'].split(' ')[0] + root_node = self.resolve_root_node_address(root_node) os.environ['MASTER_ADDR'] = root_node + dist.init_process_group("nccl", rank=self.proc_rank, world_size=self.world_size) - def __resolve_root_node_address(self): + def resolve_root_node_address(self, root_node): try: - root_node = os.environ['SLURM_NODELIST'].split(' ')[0] - if '[' in root_node: name = root_node.split('[')[0] number = root_node.split(',')[0] From 750fefac0cc4d6cf7d97087480f4afe688fb3a8b Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:55:38 -0400 Subject: [PATCH 199/222] made root note address individually testable --- tests/test_models.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index 4b9ec68b..33adb561 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -68,6 +68,12 @@ def test_amp_gpu_ddp_slurm_managed(): # correct result and ok accuracy assert result == 1, 'amp + ddp model failed to complete' + # test root model address + assert trainer.resolve_root_node_address('abc') == 'abc' + assert trainer.resolve_root_node_address('abc[23]') == 'abc23' + assert trainer.resolve_root_node_address('abc[23-24]') == 'abc24' + assert trainer.resolve_root_node_address('abc[23-24, 45-40, 40]') == 'abc23' + # test model loading pretrained_model = load_model(exp, save_dir, True) From f58c83b399bd1cb92d0713937214232730dc6330 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 18:57:42 -0400 Subject: [PATCH 200/222] made root note address individually testable --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 33adb561..3179b271 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -71,7 +71,7 @@ def test_amp_gpu_ddp_slurm_managed(): # test root model address assert trainer.resolve_root_node_address('abc') == 'abc' assert trainer.resolve_root_node_address('abc[23]') == 'abc23' - assert trainer.resolve_root_node_address('abc[23-24]') == 'abc24' + assert trainer.resolve_root_node_address('abc[23-24]') == 'abc23' assert trainer.resolve_root_node_address('abc[23-24, 45-40, 40]') == 'abc23' # test model loading From 65ce10c255934e136288fe47d40ba7c87a83576a Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:02:19 -0400 Subject: [PATCH 201/222] testing -1 gpu option --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 3179b271..ed627fcc 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -195,7 +195,7 @@ def test_multi_gpu_model_dp(): max_nb_epochs=1, train_percent_check=0.1, val_percent_check=0.1, - gpus=[0, 1] + gpus='-1' ) run_gpu_model_test(trainer_options, model, hparams) From ed9d977c4addf708c7cd4cdcae2ef8c292e0461e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:05:20 -0400 Subject: [PATCH 202/222] added cpu 16 bit --- pytorch_lightning/models/trainer.py | 2 +- tests/test_models.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index 0be187d0..ab1d8565 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -344,7 +344,7 @@ class Trainer(TrainerIO): # run training for batch_i, data_batch in enumerate(dataloader): - if data_batch is None: + if data_batch is None: # pragma: no cover continue # stop short when on fast dev run diff --git a/tests/test_models.py b/tests/test_models.py index ed627fcc..84383b45 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -111,6 +111,26 @@ def test_cpu_model(): run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) +def test_cpu_model_with_amp(): + """ + Make sure model trains on CPU + :return: + """ + + trainer_options = dict( + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4, + use_amp=True + ) + + model, hparams = get_model() + + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + def test_all_features_cpu_model(): """ Test each of the trainer options From efbd1a1c185c508c4c0fa206a3268a36065595d0 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:05:46 -0400 Subject: [PATCH 203/222] added cpu 16 bit --- tests/test_models.py | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 84383b45..15a41e9c 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -21,6 +21,28 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ + + +def test_cpu_model_with_amp(): + """ + Make sure model trains on CPU + :return: + """ + + trainer_options = dict( + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4, + use_amp=True + ) + + model, hparams = get_model() + + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + def test_amp_gpu_ddp_slurm_managed(): """ Make sure DDP + AMP work @@ -111,26 +133,6 @@ def test_cpu_model(): run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -def test_cpu_model_with_amp(): - """ - Make sure model trains on CPU - :return: - """ - - trainer_options = dict( - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4, - use_amp=True - ) - - model, hparams = get_model() - - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - def test_all_features_cpu_model(): """ Test each of the trainer options From fcda19aa259fa17092e385d270631fcdcc8c0fce Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:07:53 -0400 Subject: [PATCH 204/222] added cpu + amp error --- pytorch_lightning/models/trainer.py | 6 +----- tests/test_models.py | 3 ++- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index ab1d8565..a6d6fe6d 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -444,11 +444,7 @@ class Trainer(TrainerIO): # run through amp wrapper if self.use_amp: - # An example - model, optimizers = amp.initialize( - model, self.optimizers, opt_level=self.amp_level, - ) - self.optimizers = optimizers + raise MisconfigurationException('amp + cpu is not supported. Please use a GPU option') self.__run_pretrain_routine(model) diff --git a/tests/test_models.py b/tests/test_models.py index 15a41e9c..0e933382 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -40,7 +40,8 @@ def test_cpu_model_with_amp(): model, hparams = get_model() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + with pytest.raises(MisconfigurationException): + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) def test_amp_gpu_ddp_slurm_managed(): From a5756d91beeeeb22df9a80c4f2ef5faf5a3e81a5 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:12:03 -0400 Subject: [PATCH 205/222] added cpu + amp error --- tests/test_models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 0e933382..152fdfef 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -462,13 +462,13 @@ def run_prediction(dataloader, trained_model): print(val_acc) - assert val_acc > 0.55, f'this model is expected to get > 0.55 in test set (it got {val_acc})' + assert val_acc > 0.50, f'this model is expected to get > 0.50 in test set (it got {val_acc})' def assert_ok_acc(trainer): # this model should get 0.80+ acc acc = trainer.tng_tqdm_dic['val_acc'] - assert acc > 0.55, f'model failed to get expected 0.55 validation accuracy. Got: {acc}' + assert acc > 0.50, f'model failed to get expected 0.50 validation accuracy. Got: {acc}' if __name__ == '__main__': From 9be15aa29f59a0f1dc053e433eb10c7badb094c9 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:17:08 -0400 Subject: [PATCH 206/222] added cpu + amp error --- tests/test_models.py | 45 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 152fdfef..e4ca171b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -21,6 +21,27 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ +def test_early_stopping_cpu_model(): + """ + Test each of the trainer options + :return: + """ + + stopping = EarlyStopping() + trainer_options = dict( + early_stop_callback=stopping, + gradient_clip=1.0, + overfit_pct=0.20, + track_grad_norm=2, + print_nan_grads=True, + progress_bar=False, + experiment=get_exp(), + train_percent_check=0.1, + val_percent_check=0.1 + ) + + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) def test_cpu_model_with_amp(): @@ -156,30 +177,6 @@ def test_all_features_cpu_model(): run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) -def test_early_stopping_cpu_model(): - """ - Test each of the trainer options - :return: - """ - - stopping = EarlyStopping() - trainer_options = dict( - early_stop_callback=stopping, - gradient_clip=1.0, - overfit_pct=0.20, - track_grad_norm=2, - print_nan_grads=True, - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4 - ) - - model, hparams = get_model() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - def test_single_gpu_model(): """ Make sure single GPU works (DP mode) From 4260769e149bbff2d509d8f304dbc19d638ad386 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:18:23 -0400 Subject: [PATCH 207/222] ignoring dist parallel forward --- pytorch_lightning/pt_overrides/override_data_parallel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/pt_overrides/override_data_parallel.py b/pytorch_lightning/pt_overrides/override_data_parallel.py index 9d34d455..522955e8 100644 --- a/pytorch_lightning/pt_overrides/override_data_parallel.py +++ b/pytorch_lightning/pt_overrides/override_data_parallel.py @@ -77,7 +77,7 @@ class LightningDistributedDataParallel(DistributedDataParallel): def parallel_apply(self, replicas, inputs, kwargs): return parallel_apply(replicas, inputs, kwargs, self.device_ids[:len(replicas)]) - def forward(self, *inputs, **kwargs): + def forward(self, *inputs, **kwargs): # pragma: no cover self._sync_params() if self.device_ids: inputs, kwargs = self.scatter(inputs, kwargs, self.device_ids) From a3ad0e0ac1dbc27642aa1f10f17302905f4fe03e Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:23:11 -0400 Subject: [PATCH 208/222] ignoring dist parallel forward --- pytorch_lightning/root_module/root_module.py | 1 - tests/test_models.py | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/root_module/root_module.py b/pytorch_lightning/root_module/root_module.py index 7f99ef98..b2a08830 100644 --- a/pytorch_lightning/root_module/root_module.py +++ b/pytorch_lightning/root_module/root_module.py @@ -92,7 +92,6 @@ class LightningModule(GradInformation, ModelIO, ModelHooks): model_summary = ModelSummary(self) print(model_summary) - def freeze(self): for param in self.parameters(): param.requires_grad = False diff --git a/tests/test_models.py b/tests/test_models.py index e4ca171b..fd5fcf51 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -43,6 +43,10 @@ def test_early_stopping_cpu_model(): model, hparams = get_model() run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + # test freeze on cpu + model.freeze() + model.unfreeze() + def test_cpu_model_with_amp(): """ @@ -133,6 +137,10 @@ def test_amp_gpu_ddp_slurm_managed(): trainer.hpc_save(save_dir, exp) trainer.hpc_load(save_dir, on_gpu=True) + # test freeze on gpu + model.freeze() + model.unfreeze() + clear_save_dir() From db9a8cfe788835940db3bd1775e0933018b8e7dc Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:24:58 -0400 Subject: [PATCH 209/222] ignoring dist parallel forward --- pytorch_lightning/root_module/memory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index ffcf8572..44f45f35 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -50,7 +50,7 @@ class ModelSummary(object): else: out = m(input_) - if type(input_) is tuple or type(input_) is list: + if type(input_) is tuple or type(input_) is list: # pragma: no cover in_size = [] for x in input_: if type(x) is list: From 6fb27c45263bd184b155d7ade593abf41c80cc35 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:29:51 -0400 Subject: [PATCH 210/222] pt dpp some ignores --- pytorch_lightning/pt_overrides/override_data_parallel.py | 2 +- setup.cfg | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pytorch_lightning/pt_overrides/override_data_parallel.py b/pytorch_lightning/pt_overrides/override_data_parallel.py index 522955e8..89b550fd 100644 --- a/pytorch_lightning/pt_overrides/override_data_parallel.py +++ b/pytorch_lightning/pt_overrides/override_data_parallel.py @@ -112,7 +112,7 @@ class LightningDistributedDataParallel(DistributedDataParallel): return output -def parallel_apply(modules, inputs, kwargs_tup=None, devices=None): +def parallel_apply(modules, inputs, kwargs_tup=None, devices=None): # pragma: no cover r"""Applies each `module` in :attr:`modules` in parallel on arguments contained in :attr:`inputs` (positional) and :attr:`kwargs_tup` (keyword) on each of :attr:`devices`. diff --git a/setup.cfg b/setup.cfg index 01c0b049..f0904742 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,6 +33,7 @@ exclude_lines = raise Exception warnings print + raise RuntimeError omit = pytorch_lightning/callbacks/pt_callbacks.py From 10c3266ed4a85a905f02f63df80d465c6ded9814 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:30:27 -0400 Subject: [PATCH 211/222] pt dpp some ignores --- pytorch_lightning/root_module/model_saving.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/root_module/model_saving.py b/pytorch_lightning/root_module/model_saving.py index b34d64f7..68be6fcf 100644 --- a/pytorch_lightning/root_module/model_saving.py +++ b/pytorch_lightning/root_module/model_saving.py @@ -87,7 +87,7 @@ class TrainerIO(object): # -------------------- # HPC IO # -------------------- - def enable_auto_hpc_walltime_manager(self): + def enable_auto_hpc_walltime_manager(self): # pragma: no cover if self.cluster is None: return From a8d126b2a2edbd9ede59b656215f9ecbc3048910 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:32:41 -0400 Subject: [PATCH 212/222] pt dpp some ignores --- pytorch_lightning/root_module/memory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytorch_lightning/root_module/memory.py b/pytorch_lightning/root_module/memory.py index 44f45f35..389c8680 100644 --- a/pytorch_lightning/root_module/memory.py +++ b/pytorch_lightning/root_module/memory.py @@ -45,7 +45,7 @@ class ModelSummary(object): for i in range(1, len(mods)): m = mods[i] - if type(input_) is list or type(input_) is tuple: + if type(input_) is list or type(input_) is tuple: # pragma: no cover out = m(*input_) else: out = m(input_) @@ -62,7 +62,7 @@ class ModelSummary(object): in_sizes.append(in_size) - if type(out) is tuple or type(out) is list: + if type(out) is tuple or type(out) is list: # pragma: no cover out_size = np.asarray([x.size() for x in out]) else: out_size = np.array(out.size()) From e3463c8fe37ecd566e5e3d20f1fea52a888f4ecc Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:35:31 -0400 Subject: [PATCH 213/222] pt dpp some ignores --- setup.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.cfg b/setup.cfg index f0904742..5d456a3d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -34,6 +34,8 @@ exclude_lines = warnings print raise RuntimeError + break + pass omit = pytorch_lightning/callbacks/pt_callbacks.py From 8391b744c02661795ce38f6e3d834eaf1a1971fc Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:36:35 -0400 Subject: [PATCH 214/222] pt dpp some ignores --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 5d456a3d..5b21c683 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,6 +36,7 @@ exclude_lines = raise RuntimeError break pass + os.makedirs omit = pytorch_lightning/callbacks/pt_callbacks.py From 1361d37598364fbbda800b122097ee3314aef271 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:37:04 -0400 Subject: [PATCH 215/222] pt dpp some ignores --- pytorch_lightning/models/trainer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index a6d6fe6d..e58735dc 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -618,7 +618,7 @@ class Trainer(TrainerIO): self.experiment.save() # enable cluster checkpointing - if self.cluster is not None: + if self.cluster is not None: # pragma: no cover self.enable_auto_hpc_walltime_manager() # --------------------------- From 5a1b3d17d2f338d49d9fd2c6778fd7482a343417 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:39:18 -0400 Subject: [PATCH 216/222] pt dpp some ignores --- tests/test_models.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index fd5fcf51..68c97d4e 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -21,6 +21,28 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ +def test_amp_gpu_dp_ok_1(): + """ + Make sure DP + AMP work + :return: + """ + if not torch.cuda.is_available(): + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') + return + if not torch.cuda.device_count() > 1: + warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') + return + model, hparams = get_model() + trainer_options = dict( + max_nb_epochs=1, + gpus='0, 1', # test init with gpu string + distributed_backend='dp', + amp_level='O1', + use_amp=True + ) + run_gpu_model_test(trainer_options, model, hparams) + + def test_early_stopping_cpu_model(): """ Test each of the trainer options From a4bb80b936208b8123f46d3c4ed99dbe95393f4c Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:43:38 -0400 Subject: [PATCH 217/222] dp doesnt support amp with any setting --- pytorch_lightning/models/trainer.py | 11 +---------- tests/test_models.py | 22 ---------------------- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index e58735dc..a575a316 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -462,21 +462,12 @@ class Trainer(TrainerIO): # check for this bug (amp + dp + !01 doesn't work) # https://github.com/NVIDIA/apex/issues/227 - if self.use_dp and self.use_amp and self.amp_level != 'O1': + if self.use_dp and self.use_amp: m = f'amp level {self.amp_level} with DataParallel is not supported. ' \ f'See this note from NVIDIA for more info: https://github.com/NVIDIA/apex/issues/227. ' \ f'We recommend you switch to ddp if you want to use amp' raise MisconfigurationException(m) - # run through amp wrapper - if self.use_amp: - - # An example - model, optimizers = amp.initialize( - model, self.optimizers, opt_level=self.amp_level, - ) - self.optimizers = optimizers - model = LightningDataParallel(model, device_ids=self.data_parallel_device_ids) self.__run_pretrain_routine(model) diff --git a/tests/test_models.py b/tests/test_models.py index 68c97d4e..fd5fcf51 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -21,28 +21,6 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ -def test_amp_gpu_dp_ok_1(): - """ - Make sure DP + AMP work - :return: - """ - if not torch.cuda.is_available(): - warnings.warn('test_amp_gpu_dp cannot run. Rerun on a GPU node to run this test') - return - if not torch.cuda.device_count() > 1: - warnings.warn('test_amp_gpu_dp cannot run. Rerun on a node with 2+ GPUs to run this test') - return - model, hparams = get_model() - trainer_options = dict( - max_nb_epochs=1, - gpus='0, 1', # test init with gpu string - distributed_backend='dp', - amp_level='O1', - use_amp=True - ) - run_gpu_model_test(trainer_options, model, hparams) - - def test_early_stopping_cpu_model(): """ Test each of the trainer options From c72a189c5449b363d30014ef3263c742435c2504 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 19:48:48 -0400 Subject: [PATCH 218/222] dp doesnt support amp with any setting --- pytorch_lightning/root_module/root_module.py | 10 ---------- pytorch_lightning/trainer_main.py | 4 ---- 2 files changed, 14 deletions(-) diff --git a/pytorch_lightning/root_module/root_module.py b/pytorch_lightning/root_module/root_module.py index b2a08830..945a15a6 100644 --- a/pytorch_lightning/root_module/root_module.py +++ b/pytorch_lightning/root_module/root_module.py @@ -124,16 +124,6 @@ class LightningModule(GradInformation, ModelIO, ModelHooks): """ raise NotImplementedError - @staticmethod - def get_process_position(gpus): - try: - current_gpu = os.environ["CUDA_VISIBLE_DEVICES"] - gpu_ids = gpus.split(',') - process_position = gpu_ids.index(current_gpu) - return process_position, current_gpu - except Exception as e: - return 0, 0 - @classmethod def load_from_metrics(cls, weights_path, tags_csv, on_gpu, map_location=None): """ diff --git a/pytorch_lightning/trainer_main.py b/pytorch_lightning/trainer_main.py index 8389b5ec..0c30a419 100644 --- a/pytorch_lightning/trainer_main.py +++ b/pytorch_lightning/trainer_main.py @@ -52,10 +52,6 @@ def main(hparams, cluster, results_dict): hparams.__setattr__('nb_gpus', torch.cuda.device_count()) hparams.__setattr__('inference_mode', hparams.model_load_weights_path is not None) - # delay each training start to not overwrite logs - process_position, current_gpu = TRAINING_MODEL.get_process_position(hparams.gpus) - sleep(process_position + 1) - # init experiment exp = Experiment( name=hparams.tt_name, From 37a26741cc3dd65ddcb0952b5838766acddcd96a Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 20:08:17 -0400 Subject: [PATCH 219/222] testing map location --- tests/test_models.py | 105 ++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index fd5fcf51..40808961 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -21,53 +21,6 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ -def test_early_stopping_cpu_model(): - """ - Test each of the trainer options - :return: - """ - - stopping = EarlyStopping() - trainer_options = dict( - early_stop_callback=stopping, - gradient_clip=1.0, - overfit_pct=0.20, - track_grad_norm=2, - print_nan_grads=True, - progress_bar=False, - experiment=get_exp(), - train_percent_check=0.1, - val_percent_check=0.1 - ) - - model, hparams = get_model() - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - - # test freeze on cpu - model.freeze() - model.unfreeze() - - -def test_cpu_model_with_amp(): - """ - Make sure model trains on CPU - :return: - """ - - trainer_options = dict( - progress_bar=False, - experiment=get_exp(), - max_nb_epochs=1, - train_percent_check=0.4, - val_percent_check=0.4, - use_amp=True - ) - - model, hparams = get_model() - - with pytest.raises(MisconfigurationException): - run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) - def test_amp_gpu_ddp_slurm_managed(): """ @@ -123,7 +76,8 @@ def test_amp_gpu_ddp_slurm_managed(): assert trainer.resolve_root_node_address('abc[23-24, 45-40, 40]') == 'abc23' # test model loading - pretrained_model = load_model(exp, save_dir, True) + map_location = 'cuda:1' + pretrained_model = load_model(exp, save_dir, True, map_location) # test model preds run_prediction(model.test_dataloader, pretrained_model) @@ -144,6 +98,54 @@ def test_amp_gpu_ddp_slurm_managed(): clear_save_dir() +def test_early_stopping_cpu_model(): + """ + Test each of the trainer options + :return: + """ + + stopping = EarlyStopping() + trainer_options = dict( + early_stop_callback=stopping, + gradient_clip=1.0, + overfit_pct=0.20, + track_grad_norm=2, + print_nan_grads=True, + progress_bar=False, + experiment=get_exp(), + train_percent_check=0.1, + val_percent_check=0.1 + ) + + model, hparams = get_model() + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + # test freeze on cpu + model.freeze() + model.unfreeze() + + +def test_cpu_model_with_amp(): + """ + Make sure model trains on CPU + :return: + """ + + trainer_options = dict( + progress_bar=False, + experiment=get_exp(), + max_nb_epochs=1, + train_percent_check=0.4, + val_percent_check=0.4, + use_amp=True + ) + + model, hparams = get_model() + + with pytest.raises(MisconfigurationException): + run_gpu_model_test(trainer_options, model, hparams, on_gpu=False) + + def test_cpu_model(): """ Make sure model trains on CPU @@ -433,7 +435,7 @@ def clear_save_dir(): shutil.rmtree(save_dir) -def load_model(exp, save_dir, on_gpu): +def load_model(exp, save_dir, on_gpu, map_location=None): # load trained model tags_path = exp.get_data_path(exp.name, exp.version) @@ -442,7 +444,10 @@ def load_model(exp, save_dir, on_gpu): checkpoints = [x for x in os.listdir(save_dir) if '.ckpt' in x] weights_dir = os.path.join(save_dir, checkpoints[0]) - trained_model = LightningTemplateModel.load_from_metrics(weights_path=weights_dir, tags_csv=tags_path, on_gpu=on_gpu) + trained_model = LightningTemplateModel.load_from_metrics(weights_path=weights_dir, + tags_csv=tags_path, + on_gpu=on_gpu, + map_location=map_location) assert trained_model is not None, 'loading model failed' From d6e7994922d60f8dd6cf7f23a20ed834120f0448 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 20:21:57 -0400 Subject: [PATCH 220/222] added dp reduce out test --- tests/test_models.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 40808961..590caa8f 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -7,6 +7,7 @@ from test_tube import Experiment from pytorch_lightning.callbacks import ModelCheckpoint, EarlyStopping from pytorch_lightning.utils.debugging import MisconfigurationException from pytorch_lightning.root_module import memory +from pytorch_lightning.models.trainer import reduce_distributed_output import numpy as np import warnings import torch @@ -21,6 +22,26 @@ np.random.seed(SEED) # ------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------ +def test_dp_output_reduce(): + + # test identity when we have a single gpu + out = torch.rand(3, 1) + assert reduce_distributed_output(out, nb_gpus=1) == out + + # average when we have multiples + assert reduce_distributed_output(out, nb_gpus=2) == out.mean() + + # when we have a dict of vals + out = { + 'a': out, + 'b': { + 'c': out + } + } + reduced = reduce_distributed_output(out, nb_gpus=3) + assert reduced['a'] == out['a'] + assert reduced['b']['c'] == out['b']['c'] + def test_amp_gpu_ddp_slurm_managed(): """ @@ -75,7 +96,7 @@ def test_amp_gpu_ddp_slurm_managed(): assert trainer.resolve_root_node_address('abc[23-24]') == 'abc23' assert trainer.resolve_root_node_address('abc[23-24, 45-40, 40]') == 'abc23' - # test model loading + # test model loading with a map_location map_location = 'cuda:1' pretrained_model = load_model(exp, save_dir, True, map_location) From 23e7521300e6f7bd236756ce9c83d89ed98719b6 Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 20:22:54 -0400 Subject: [PATCH 221/222] added dp reduce out test --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 590caa8f..552739eb 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -26,7 +26,7 @@ def test_dp_output_reduce(): # test identity when we have a single gpu out = torch.rand(3, 1) - assert reduce_distributed_output(out, nb_gpus=1) == out + assert reduce_distributed_output(out, nb_gpus=1) is out # average when we have multiples assert reduce_distributed_output(out, nb_gpus=2) == out.mean() From 63a4af3ba771707c4d3860bc3ba35e98bbf129fa Mon Sep 17 00:00:00 2001 From: William Falcon Date: Wed, 24 Jul 2019 20:33:31 -0400 Subject: [PATCH 222/222] added testing for metrics --- .../new_project_templates/lightning_module_template.py | 3 --- pytorch_lightning/models/trainer.py | 2 +- pytorch_lightning/root_module/root_module.py | 9 --------- pytorch_lightning/testing_models/lm_test_module.py | 4 ++-- 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py index 0f28e181..c6b5ccd1 100644 --- a/pytorch_lightning/examples/new_project_templates/lightning_module_template.py +++ b/pytorch_lightning/examples/new_project_templates/lightning_module_template.py @@ -152,9 +152,6 @@ class LightningTemplateModel(LightningModule): tqdm_dic = {'val_loss': val_loss_mean.item(), 'val_acc': val_acc_mean.item()} return tqdm_dic - def update_tng_log_metrics(self, logs): - return logs - # --------------------- # MODEL SAVING # --------------------- diff --git a/pytorch_lightning/models/trainer.py b/pytorch_lightning/models/trainer.py index a575a316..7f294a71 100644 --- a/pytorch_lightning/models/trainer.py +++ b/pytorch_lightning/models/trainer.py @@ -678,7 +678,7 @@ class Trainer(TrainerIO): # nb_params, nb_tensors = count_mem_items() model = self.__get_model() - metrics = model.update_tng_log_metrics(self.__tng_tqdm_dic) + metrics = self.__tng_tqdm_dic # add gpu memory if self.on_gpu: diff --git a/pytorch_lightning/root_module/root_module.py b/pytorch_lightning/root_module/root_module.py index 945a15a6..c0f40184 100644 --- a/pytorch_lightning/root_module/root_module.py +++ b/pytorch_lightning/root_module/root_module.py @@ -71,15 +71,6 @@ class LightningModule(GradInformation, ModelIO, ModelHooks): """ raise NotImplementedError - def update_tng_log_metrics(self, logs): - """ - Chance to update metrics to be logged for training step. - For example, add music, images, etc... to log - :param logs: - :return: - """ - return logs - def loss(self, *args, **kwargs): """ Expand model_out into your components diff --git a/pytorch_lightning/testing_models/lm_test_module.py b/pytorch_lightning/testing_models/lm_test_module.py index 685bb30b..eba8882d 100644 --- a/pytorch_lightning/testing_models/lm_test_module.py +++ b/pytorch_lightning/testing_models/lm_test_module.py @@ -166,8 +166,8 @@ class LightningTestModel(LightningModule): tqdm_dic = {'val_loss': val_loss_mean.item(), 'val_acc': val_acc_mean.item()} return tqdm_dic - def update_tng_log_metrics(self, logs): - return logs + def on_tng_metrics(self, logs): + logs['some_tensor_to_test'] = torch.rand(1) # --------------------- # MODEL SAVING