Files
pytorch-lightning/tests/test_models.py
T
Vismantas 2aba70e228 parse_gpu_ids fix (#382)
* Unit tests for num_gpu property as proxy for __parse_gpu_ids.

* Refactoring __parse_gpu_ids

* Moved the function outside the class as it is
an utility function and did not depend on class in any way.
* Added unit tests for it.

* Mocked torch.cuda.device_count function in tests.

This allows the tests to be run on machines that do not have gpus.

* Fixed the parse_gpu_ids function to handle -1 case.

Function now handles -1 the same way as it does for '-1'.

* Unit tests for root_gpu added.

Added backend as a parameter as currently depending on backend set
or not, code fails with exception in certain circumstances, before
giving a wrong answer.

* Moved __set_root_gpu function out of the class.

This function does not depend on the class and can be tested
more easily this way.
Also added unit tests for this function. They simply reuse
data for the root_gpu property.

* determine_root_gpu_device passes unit tests.

* num_gpus passes unit tests.

Also added a None test for this function.

* parse_gpu_ids tests changed to reflect desired state after refactoring.

Planning to refactor parse_gpu_ids to always return list of ints.
This will simplify code that use output of this function.

* * parse_gpu_ids always returns lists
* parse_gpu_ids checks given ids against available ids
* parse_gpu_ids raises exception for non existant ids
* parse_gpu_ids returns None when no gpus are available
* cleaned up determine_root_gpu_device
* cleaned up num_gpus property
* Updated unit tests to reflect changes in the functions

* Flake8 fixes

* Moved fixture code up before where it is used.

* Updated documentation.

* Changed tests to match the API:
* gpus=-1 or gpus='-1' should use all available gpu devices
* gpus=N
    * N=0: no gpus should be used.
    * N>0: N gpus should be used
* gpus=list of ints or a comma separated string of numbers:
    Use the gpus indicated by the list or the string.

* Fixed code to pass all the changed tests for parsing gpus param.

* Refactoring parse_gpu_ids function.

* flake8 fixes.

* Updating documentation.

* flake8 fixes.

* flake8 fixes.

* flake8 fixes

* Update trainer.py

* Update dp_mixin.py

* Make reduce_distributed_output a stand alone function.
Fix imports.
Fix flake8.

* Add comet_ml dependency to tests requirements.txt

* Revert "Make reduce_distributed_output a stand alone function. Fix imports. Fix flake8."

This reverts commit eac0338

* Merge with master.
2019-10-23 05:05:09 -04:00

1844 lines
50 KiB
Python

import os
import shutil
import warnings
from argparse import Namespace
import numpy as np
import pytest
import torch
from pl_examples import LightningTemplateModel
# sys.path += [os.path.abspath('..'), os.path.abspath('../..')]
from pytorch_lightning import Trainer
from pytorch_lightning.callbacks import (
ModelCheckpoint,
EarlyStopping,
)
from pytorch_lightning.logging import TestTubeLogger
from pytorch_lightning.root_module import memory
from pytorch_lightning.testing import (
LightningTestModel,
LightningTestModelBase,
LightningValidationStepMixin,
LightningValidationMultipleDataloadersMixin,
LightningTestMixin,
LightningTestMultipleDataloadersMixin,
)
from pytorch_lightning.trainer import trainer_io
from pytorch_lightning.trainer.dp_mixin import (
parse_gpu_ids,
determine_root_gpu_device,
)
from pytorch_lightning.trainer.logging_mixin import TrainerLoggingMixin
from pytorch_lightning.utilities.debugging import MisconfigurationException
# generate a list of random seeds for each test
RANDOM_FILE_PATHS = list(np.random.randint(12000, 19000, 1000))
RANDOM_PORTS = list(np.random.randint(12000, 19000, 1000))
ROOT_SEED = 1234
torch.manual_seed(ROOT_SEED)
np.random.seed(ROOT_SEED)
RANDOM_SEEDS = list(np.random.randint(0, 10000, 1000))
PRETEND_N_OF_GPUS = 16
# ------------------------------------------------------------------------
# TESTS
# ------------------------------------------------------------------------
def test_multi_gpu_model_ddp2():
"""
Make sure DDP2 works
:return:
"""
if not can_run_gpu_test():
return
reset_seed()
set_random_master_port()
model, hparams = get_model()
trainer_options = dict(
show_progress_bar=True,
max_nb_epochs=1,
train_percent_check=0.4,
val_percent_check=0.2,
gpus=2,
weights_summary=None,
distributed_backend='ddp2'
)
run_gpu_model_test(trainer_options, model, hparams)
def test_early_stopping_cpu_model():
"""
Test each of the trainer options
:return:
"""
reset_seed()
stopping = EarlyStopping(monitor='val_loss')
trainer_options = dict(
early_stop_callback=stopping,
gradient_clip_val=1.0,
overfit_pct=0.20,
track_grad_norm=2,
print_nan_grads=True,
show_progress_bar=True,
logger=get_test_tube_logger(),
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_running_test_pretrained_model_ddp():
"""Verify test() on pretrained model"""
if not can_run_gpu_test():
return
reset_seed()
set_random_master_port()
hparams = get_hparams()
model = LightningTestModel(hparams)
save_dir = init_save_dir()
# exp file to get meta
logger = get_test_tube_logger(False)
# exp file to get weights
checkpoint = init_checkpoint_callback(logger)
trainer_options = dict(
show_progress_bar=False,
max_nb_epochs=1,
train_percent_check=0.4,
val_percent_check=0.2,
checkpoint_callback=checkpoint,
logger=logger,
gpus=[0, 1],
distributed_backend='ddp'
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
exp = logger.experiment
print(os.listdir(exp.get_data_path(exp.name, exp.version)))
# correct result and ok accuracy
assert result == 1, 'training failed to complete'
pretrained_model = load_model(logger.experiment, trainer.checkpoint_callback.filepath,
module_class=LightningTestModel)
# run test set
new_trainer = Trainer(**trainer_options)
new_trainer.test(pretrained_model)
[run_prediction(dataloader, pretrained_model) for dataloader in model.test_dataloader()]
clear_save_dir()
def test_lbfgs_cpu_model():
"""
Test each of the trainer options
:return:
"""
reset_seed()
trainer_options = dict(
max_nb_epochs=1,
print_nan_grads=True,
show_progress_bar=False,
weights_summary='top',
train_percent_check=1.0,
val_percent_check=0.2
)
model, hparams = get_model(use_test_model=True, lbfgs=True)
run_model_test_no_loggers(trainer_options, model, hparams, on_gpu=False, min_acc=0.30)
clear_save_dir()
def test_default_logger_callbacks_cpu_model():
"""
Test each of the trainer options
:return:
"""
reset_seed()
trainer_options = dict(
max_nb_epochs=1,
gradient_clip_val=1.0,
overfit_pct=0.20,
print_nan_grads=True,
show_progress_bar=False,
train_percent_check=0.01,
val_percent_check=0.01
)
model, hparams = get_model()
run_model_test_no_loggers(trainer_options, model, hparams, on_gpu=False)
# test freeze on cpu
model.freeze()
model.unfreeze()
clear_save_dir()
def test_dp_resume():
"""
Make sure DP continues training correctly
:return:
"""
if not can_run_gpu_test():
return
reset_seed()
hparams = get_hparams()
model = LightningTestModel(hparams)
trainer_options = dict(
show_progress_bar=True,
max_nb_epochs=2,
gpus=2,
distributed_backend='dp',
)
save_dir = init_save_dir()
# get logger
logger = get_test_tube_logger(debug=False)
# exp file to get weights
# logger file to get weights
checkpoint = init_checkpoint_callback(logger)
# add these to the trainer options
trainer_options['logger'] = logger
trainer_options['checkpoint_callback'] = checkpoint
# fit model
trainer = Trainer(**trainer_options)
trainer.is_slurm_managing_tasks = True
result = trainer.fit(model)
# track epoch before saving
real_global_epoch = trainer.current_epoch
# correct result and ok accuracy
assert result == 1, 'amp + dp model failed to complete'
# ---------------------------
# HPC LOAD/SAVE
# ---------------------------
# save
trainer.hpc_save(save_dir, logger)
# init new trainer
new_logger = get_test_tube_logger(version=logger.version)
trainer_options['logger'] = new_logger
trainer_options['checkpoint_callback'] = ModelCheckpoint(save_dir)
trainer_options['train_percent_check'] = 0.2
trainer_options['val_percent_check'] = 0.2
trainer_options['max_nb_epochs'] = 1
new_trainer = Trainer(**trainer_options)
# set the epoch start hook so we can predict before the model does the full training
def assert_good_acc():
assert new_trainer.current_epoch == real_global_epoch and new_trainer.current_epoch > 0
# if model and state loaded correctly, predictions will be good even though we
# haven't trained with the new loaded model
dp_model = new_trainer.model
dp_model.eval()
dataloader = trainer.get_train_dataloader()
run_prediction(dataloader, dp_model, dp=True)
# new model
model = LightningTestModel(hparams)
model.on_sanity_check_start = assert_good_acc
# fit new model which should load hpc weights
new_trainer.fit(model)
# test freeze on gpu
model.freeze()
model.unfreeze()
clear_save_dir()
def test_running_test_after_fitting():
"""Verify test() on fitted model"""
reset_seed()
hparams = get_hparams()
model = LightningTestModel(hparams)
save_dir = init_save_dir()
# logger file to get meta
logger = get_test_tube_logger(False)
# logger file to get weights
checkpoint = init_checkpoint_callback(logger)
trainer_options = dict(
show_progress_bar=False,
max_nb_epochs=1,
train_percent_check=0.4,
val_percent_check=0.2,
test_percent_check=0.2,
checkpoint_callback=checkpoint,
logger=logger
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
assert result == 1, 'training failed to complete'
trainer.test()
# test we have good test accuracy
assert_ok_test_acc(trainer)
clear_save_dir()
def test_running_test_without_val():
reset_seed()
"""Verify test() works on a model with no val_loader"""
class CurrentTestModel(LightningTestMixin, LightningTestModelBase):
pass
hparams = get_hparams()
model = CurrentTestModel(hparams)
save_dir = init_save_dir()
# logger file to get meta
logger = get_test_tube_logger(False)
# logger file to get weights
checkpoint = init_checkpoint_callback(logger)
trainer_options = dict(
show_progress_bar=False,
max_nb_epochs=1,
train_percent_check=0.4,
val_percent_check=0.2,
test_percent_check=0.2,
checkpoint_callback=checkpoint,
logger=logger
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
assert result == 1, 'training failed to complete'
trainer.test()
# test we have good test accuracy
assert_ok_test_acc(trainer)
clear_save_dir()
def test_running_test_pretrained_model():
reset_seed()
"""Verify test() on pretrained model"""
hparams = get_hparams()
model = LightningTestModel(hparams)
save_dir = init_save_dir()
# logger file to get meta
logger = get_test_tube_logger(False)
# logger file to get weights
checkpoint = init_checkpoint_callback(logger)
trainer_options = dict(
show_progress_bar=False,
max_nb_epochs=1,
train_percent_check=0.4,
val_percent_check=0.2,
checkpoint_callback=checkpoint,
logger=logger
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
# correct result and ok accuracy
assert result == 1, 'training failed to complete'
pretrained_model = load_model(
logger.experiment, trainer.checkpoint_callback.filepath, module_class=LightningTestModel
)
new_trainer = Trainer(**trainer_options)
new_trainer.test(pretrained_model)
# test we have good test accuracy
assert_ok_test_acc(new_trainer)
clear_save_dir()
def test_load_model_from_checkpoint():
reset_seed()
"""Verify test() on pretrained model"""
hparams = get_hparams()
model = LightningTestModel(hparams)
save_dir = init_save_dir()
trainer_options = dict(
show_progress_bar=False,
max_nb_epochs=1,
train_percent_check=0.4,
val_percent_check=0.2,
checkpoint_callback=True,
logger=False,
default_save_path=save_dir
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
# correct result and ok accuracy
assert result == 1, 'training failed to complete'
pretrained_model = LightningTestModel.load_from_checkpoint(
os.path.join(trainer.checkpoint_callback.filepath, "_ckpt_epoch_1.ckpt")
)
# test that hparams loaded correctly
for k, v in vars(hparams).items():
assert getattr(pretrained_model.hparams, k) == v
new_trainer = Trainer(**trainer_options)
new_trainer.test(pretrained_model)
# test we have good test accuracy
assert_ok_test_acc(new_trainer)
clear_save_dir()
def test_running_test_pretrained_model_dp():
reset_seed()
"""Verify test() on pretrained model"""
if not can_run_gpu_test():
return
hparams = get_hparams()
model = LightningTestModel(hparams)
save_dir = init_save_dir()
# logger file to get meta
logger = get_test_tube_logger(False)
# logger file to get weights
checkpoint = init_checkpoint_callback(logger)
trainer_options = dict(
show_progress_bar=True,
max_nb_epochs=1,
train_percent_check=0.4,
val_percent_check=0.2,
checkpoint_callback=checkpoint,
logger=logger,
gpus=[0, 1],
distributed_backend='dp'
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
# correct result and ok accuracy
assert result == 1, 'training failed to complete'
pretrained_model = load_model(logger.experiment, trainer.checkpoint_callback.filepath,
module_class=LightningTestModel)
new_trainer = Trainer(**trainer_options)
new_trainer.test(pretrained_model)
# test we have good test accuracy
assert_ok_test_acc(new_trainer)
clear_save_dir()
def test_gradient_accumulation_scheduling():
reset_seed()
"""
Test grad accumulation by the freq of optimizer updates
"""
# test incorrect configs
with pytest.raises(IndexError):
assert Trainer(accumulate_grad_batches={0: 3, 1: 4, 4: 6})
assert Trainer(accumulate_grad_batches={-2: 3})
with pytest.raises(TypeError):
assert Trainer(accumulate_grad_batches={})
assert Trainer(accumulate_grad_batches=[[2, 3], [4, 6]])
assert Trainer(accumulate_grad_batches={1: 2, 3.: 4})
assert Trainer(accumulate_grad_batches={1: 2.5, 3: 5})
# test optimizer call freq matches scheduler
def optimizer_step(self, epoch_nb, batch_nb, optimizer, optimizer_i, second_order_closure=None):
# only test the first 12 batches in epoch
if batch_nb < 12:
if epoch_nb == 0:
# reset counter when starting epoch
if batch_nb == 0:
self.prev_called_batch_nb = 0
# use this opportunity to test once
assert self.trainer.accumulate_grad_batches == 1
assert batch_nb == self.prev_called_batch_nb
self.prev_called_batch_nb += 1
elif 1 <= epoch_nb <= 2:
# reset counter when starting epoch
if batch_nb == 1:
self.prev_called_batch_nb = 1
# use this opportunity to test once
assert self.trainer.accumulate_grad_batches == 2
assert batch_nb == self.prev_called_batch_nb
self.prev_called_batch_nb += 2
else:
if batch_nb == 3:
self.prev_called_batch_nb = 3
# use this opportunity to test once
assert self.trainer.accumulate_grad_batches == 4
assert batch_nb == self.prev_called_batch_nb
self.prev_called_batch_nb += 3
optimizer.step()
# clear gradients
optimizer.zero_grad()
hparams = get_hparams()
model = LightningTestModel(hparams)
schedule = {1: 2, 3: 4}
trainer = Trainer(accumulate_grad_batches=schedule,
train_percent_check=0.1,
val_percent_check=0.1,
max_nb_epochs=4)
# for the test
trainer.optimizer_step = optimizer_step
model.prev_called_batch_nb = 0
trainer.fit(model)
def test_multi_gpu_model_ddp():
"""
Make sure DDP works
:return:
"""
if not can_run_gpu_test():
return
reset_seed()
set_random_master_port()
model, hparams = get_model()
trainer_options = dict(
show_progress_bar=False,
max_nb_epochs=1,
train_percent_check=0.4,
val_percent_check=0.2,
gpus=[0, 1],
distributed_backend='ddp'
)
run_gpu_model_test(trainer_options, model, hparams)
def test_optimizer_return_options():
reset_seed()
trainer = Trainer()
model, hparams = get_model()
# single optimizer
opt_a = torch.optim.Adam(model.parameters(), lr=0.002)
opt_b = torch.optim.SGD(model.parameters(), lr=0.002)
optim, lr_sched = trainer.init_optimizers(opt_a)
assert len(optim) == 1 and len(lr_sched) == 0
# opt tuple
opts = (opt_a, opt_b)
optim, lr_sched = trainer.init_optimizers(opts)
assert len(optim) == 2 and optim[0] == opts[0] and optim[1] == opts[1]
assert len(lr_sched) == 0
# opt list
opts = [opt_a, opt_b]
optim, lr_sched = trainer.init_optimizers(opts)
assert len(optim) == 2 and optim[0] == opts[0] and optim[1] == opts[1]
assert len(lr_sched) == 0
# opt tuple of lists
opts = ([opt_a], ['lr_scheduler'])
optim, lr_sched = trainer.init_optimizers(opts)
assert len(optim) == 1 and len(lr_sched) == 1
assert optim[0] == opts[0][0] and lr_sched[0] == 'lr_scheduler'
def test_single_gpu_batch_parse():
reset_seed()
if not can_run_gpu_test():
return
trainer = Trainer()
# batch is just a tensor
batch = torch.rand(2, 3)
batch = trainer.transfer_batch_to_gpu(batch, 0)
assert batch.device.index == 0 and batch.type() == 'torch.cuda.FloatTensor'
# tensor list
batch = [torch.rand(2, 3), torch.rand(2, 3)]
batch = trainer.transfer_batch_to_gpu(batch, 0)
assert batch[0].device.index == 0 and batch[0].type() == 'torch.cuda.FloatTensor'
assert batch[1].device.index == 0 and batch[1].type() == 'torch.cuda.FloatTensor'
# tensor list of lists
batch = [[torch.rand(2, 3), torch.rand(2, 3)]]
batch = trainer.transfer_batch_to_gpu(batch, 0)
assert batch[0][0].device.index == 0 and batch[0][0].type() == 'torch.cuda.FloatTensor'
assert batch[0][1].device.index == 0 and batch[0][1].type() == 'torch.cuda.FloatTensor'
# tensor dict
batch = [{'a': torch.rand(2, 3), 'b': torch.rand(2, 3)}]
batch = trainer.transfer_batch_to_gpu(batch, 0)
assert batch[0]['a'].device.index == 0 and batch[0]['a'].type() == 'torch.cuda.FloatTensor'
assert batch[0]['b'].device.index == 0 and batch[0]['b'].type() == 'torch.cuda.FloatTensor'
# tuple of tensor list and list of tensor dict
batch = ([torch.rand(2, 3) for _ in range(2)],
[{'a': torch.rand(2, 3), 'b': torch.rand(2, 3)} for _ in range(2)])
batch = trainer.transfer_batch_to_gpu(batch, 0)
assert batch[0][0].device.index == 0 and batch[0][0].type() == 'torch.cuda.FloatTensor'
assert batch[1][0]['a'].device.index == 0
assert batch[1][0]['a'].type() == 'torch.cuda.FloatTensor'
assert batch[1][0]['b'].device.index == 0
assert batch[1][0]['b'].type() == 'torch.cuda.FloatTensor'
def test_no_val_module():
"""
Tests use case where trainer saves the model, and user loads it from tags independently
:return:
"""
reset_seed()
hparams = get_hparams()
class CurrentTestModel(LightningTestModelBase):
pass
model = CurrentTestModel(hparams)
save_dir = init_save_dir()
# logger file to get meta
logger = get_test_tube_logger(False)
trainer_options = dict(
max_nb_epochs=1,
logger=logger,
checkpoint_callback=ModelCheckpoint(save_dir)
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
# training complete
assert result == 1, 'amp + ddp model failed to complete'
# save model
new_weights_path = os.path.join(save_dir, 'save_test.ckpt')
trainer.save_checkpoint(new_weights_path)
# load new model
tags_path = logger.experiment.get_data_path(logger.experiment.name, logger.experiment.version)
tags_path = os.path.join(tags_path, 'meta_tags.csv')
model_2 = LightningTestModel.load_from_metrics(weights_path=new_weights_path,
tags_csv=tags_path)
model_2.eval()
# make prediction
clear_save_dir()
def test_no_val_end_module():
"""
Tests use case where trainer saves the model, and user loads it from tags independently
:return:
"""
reset_seed()
class CurrentTestModel(LightningValidationStepMixin, LightningTestModelBase):
pass
hparams = get_hparams()
model = CurrentTestModel(hparams)
save_dir = init_save_dir()
# logger file to get meta
logger = get_test_tube_logger(False)
trainer_options = dict(
max_nb_epochs=1,
logger=logger,
checkpoint_callback=ModelCheckpoint(save_dir)
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
# traning complete
assert result == 1, 'amp + ddp model failed to complete'
# save model
new_weights_path = os.path.join(save_dir, 'save_test.ckpt')
trainer.save_checkpoint(new_weights_path)
# load new model
tags_path = logger.experiment.get_data_path(logger.experiment.name, logger.experiment.version)
tags_path = os.path.join(tags_path, 'meta_tags.csv')
model_2 = LightningTestModel.load_from_metrics(weights_path=new_weights_path,
tags_csv=tags_path)
model_2.eval()
# make prediction
clear_save_dir()
def test_simple_cpu():
"""
Verify continue training session on CPU
:return:
"""
reset_seed()
hparams = get_hparams()
model = LightningTestModel(hparams)
save_dir = init_save_dir()
# logger file to get meta
trainer_options = dict(
max_nb_epochs=1,
val_percent_check=0.1,
train_percent_check=0.1,
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
# traning complete
assert result == 1, 'amp + ddp model failed to complete'
clear_save_dir()
def test_amp_single_gpu():
"""
Make sure DDP + AMP work
:return:
"""
reset_seed()
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
hparams = get_hparams()
model = LightningTestModel(hparams)
trainer_options = dict(
show_progress_bar=True,
max_nb_epochs=1,
gpus=1,
distributed_backend='ddp',
use_amp=True
)
run_gpu_model_test(trainer_options, model, hparams)
def test_no_amp_single_gpu():
"""
Make sure DDP + AMP work
:return:
"""
reset_seed()
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
hparams = get_hparams()
model = LightningTestModel(hparams)
trainer_options = dict(
show_progress_bar=True,
max_nb_epochs=1,
gpus=1,
distributed_backend='dp',
use_amp=True
)
with pytest.raises((MisconfigurationException, ModuleNotFoundError)):
run_gpu_model_test(trainer_options, model, hparams)
def test_cpu_restore_training():
"""
Verify continue training session on CPU
:return:
"""
reset_seed()
hparams = get_hparams()
model = LightningTestModel(hparams)
save_dir = init_save_dir()
# logger file to get meta
test_logger_version = 10
logger = get_test_tube_logger(False, version=test_logger_version)
trainer_options = dict(
max_nb_epochs=2,
val_check_interval=0.50,
val_percent_check=0.2,
train_percent_check=0.2,
logger=logger,
checkpoint_callback=ModelCheckpoint(save_dir)
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
real_global_epoch = trainer.current_epoch
# traning complete
assert result == 1, 'amp + ddp model failed to complete'
# wipe-out trainer and model
# retrain with not much data... this simulates picking training back up after slurm
# we want to see if the weights come back correctly
new_logger = get_test_tube_logger(False, version=test_logger_version)
trainer_options = dict(
max_nb_epochs=2,
val_check_interval=0.50,
val_percent_check=0.2,
train_percent_check=0.2,
logger=new_logger,
checkpoint_callback=ModelCheckpoint(save_dir),
)
trainer = Trainer(**trainer_options)
model = LightningTestModel(hparams)
# set the epoch start hook so we can predict before the model does the full training
def assert_good_acc():
assert trainer.current_epoch == real_global_epoch and trainer.current_epoch > 0
# if model and state loaded correctly, predictions will be good even though we
# haven't trained with the new loaded model
trainer.model.eval()
for dataloader in trainer.get_val_dataloaders():
run_prediction(dataloader, trainer.model)
model.on_sanity_check_start = assert_good_acc
# by calling fit again, we trigger training, loading weights from the cluster
# and our hook to predict using current model before any more weight updates
trainer.fit(model)
clear_save_dir()
def test_amp_gpu_ddp():
"""
Make sure DDP + AMP work
:return:
"""
if not can_run_gpu_test():
return
reset_seed()
set_random_master_port()
hparams = get_hparams()
model = LightningTestModel(hparams)
trainer_options = dict(
show_progress_bar=True,
max_nb_epochs=1,
gpus=2,
distributed_backend='ddp',
use_amp=True
)
run_gpu_model_test(trainer_options, model, hparams)
def test_cpu_slurm_save_load():
"""
Verify model save/load/checkpoint on CPU
:return:
"""
reset_seed()
hparams = get_hparams()
model = LightningTestModel(hparams)
save_dir = init_save_dir()
# logger file to get meta
logger = get_test_tube_logger(False)
version = logger.version
trainer_options = dict(
max_nb_epochs=1,
logger=logger,
checkpoint_callback=ModelCheckpoint(save_dir)
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
real_global_step = trainer.global_step
# traning complete
assert result == 1, 'amp + ddp model failed to complete'
# predict with trained model before saving
# make a prediction
for dataloader in model.test_dataloader():
for batch in dataloader:
break
x, y = batch
x = x.view(x.size(0), -1)
model.eval()
pred_before_saving = model(x)
# test HPC saving
# simulate snapshot on slurm
saved_filepath = trainer.hpc_save(save_dir, logger)
assert os.path.exists(saved_filepath)
# new logger file to get meta
logger = get_test_tube_logger(False, version=version)
trainer_options = dict(
max_nb_epochs=1,
logger=logger,
checkpoint_callback=ModelCheckpoint(save_dir),
)
trainer = Trainer(**trainer_options)
model = LightningTestModel(hparams)
# set the epoch start hook so we can predict before the model does the full training
def assert_pred_same():
assert trainer.global_step == real_global_step and trainer.global_step > 0
# predict with loaded model to make sure answers are the same
trainer.model.eval()
new_pred = trainer.model(x)
assert torch.all(torch.eq(pred_before_saving, new_pred)).item() == 1
model.on_epoch_start = assert_pred_same
# by calling fit again, we trigger training, loading weights from the cluster
# and our hook to predict using current model before any more weight updates
trainer.fit(model)
clear_save_dir()
def test_loading_meta_tags():
reset_seed()
from argparse import Namespace
hparams = get_hparams()
# save tags
logger = get_test_tube_logger(False)
logger.log_hyperparams(Namespace(some_str='a_str', an_int=1, a_float=2.0))
logger.log_hyperparams(hparams)
logger.save()
# load tags
tags_path = logger.experiment.get_data_path(
logger.experiment.name, logger.experiment.version
) + '/meta_tags.csv'
tags = trainer_io.load_hparams_from_tags_csv(tags_path)
assert tags.batch_size == 32 and tags.hidden_dim == 1000
clear_save_dir()
def test_dp_output_reduce():
mixin = TrainerLoggingMixin()
reset_seed()
# test identity when we have a single gpu
out = torch.rand(3, 1)
assert mixin.reduce_distributed_output(out, nb_gpus=1) is out
# average when we have multiples
assert mixin.reduce_distributed_output(out, nb_gpus=2) == out.mean()
# when we have a dict of vals
out = {
'a': out,
'b': {
'c': out
}
}
reduced = mixin.reduce_distributed_output(out, nb_gpus=3)
assert reduced['a'] == out['a']
assert reduced['b']['c'] == out['b']['c']
def test_model_saving_loading():
"""
Tests use case where trainer saves the model, and user loads it from tags independently
:return:
"""
reset_seed()
hparams = get_hparams()
model = LightningTestModel(hparams)
save_dir = init_save_dir()
# logger file to get meta
logger = get_test_tube_logger(False)
trainer_options = dict(
max_nb_epochs=1,
logger=logger,
checkpoint_callback=ModelCheckpoint(save_dir)
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
# traning complete
assert result == 1, 'amp + ddp model failed to complete'
# make a prediction
for dataloader in model.test_dataloader():
for batch in dataloader:
break
x, y = batch
x = x.view(x.size(0), -1)
# generate preds before saving model
model.eval()
pred_before_saving = model(x)
# save model
new_weights_path = os.path.join(save_dir, 'save_test.ckpt')
trainer.save_checkpoint(new_weights_path)
# load new model
tags_path = logger.experiment.get_data_path(logger.experiment.name, logger.experiment.version)
tags_path = os.path.join(tags_path, 'meta_tags.csv')
model_2 = LightningTestModel.load_from_metrics(weights_path=new_weights_path,
tags_csv=tags_path)
model_2.eval()
# make prediction
# assert that both predictions are the same
new_pred = model_2(x)
assert torch.all(torch.eq(pred_before_saving, new_pred)).item() == 1
clear_save_dir()
def test_model_freeze_unfreeze():
reset_seed()
hparams = get_hparams()
model = LightningTestModel(hparams)
model.freeze()
model.unfreeze()
def test_amp_gpu_ddp_slurm_managed():
"""
Make sure DDP + AMP work
:return:
"""
if not can_run_gpu_test():
return
reset_seed()
# simulate setting slurm flags
set_random_master_port()
os.environ['SLURM_LOCALID'] = str(0)
hparams = get_hparams()
model = LightningTestModel(hparams)
trainer_options = dict(
show_progress_bar=True,
max_nb_epochs=1,
gpus=[0],
distributed_backend='ddp',
use_amp=True
)
save_dir = init_save_dir()
# exp file to get meta
logger = get_test_tube_logger(False)
# exp file to get weights
checkpoint = init_checkpoint_callback(logger)
# add these to the trainer options
trainer_options['checkpoint_callback'] = checkpoint
trainer_options['logger'] = logger
# 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 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]') == 'abc23'
assert trainer.resolve_root_node_address('abc[23-24, 45-40, 40]') == 'abc23'
# test model loading with a map_location
pretrained_model = load_model(logger.experiment, trainer.checkpoint_callback.filepath)
# test model preds
[run_prediction(dataloader, pretrained_model) for dataloader in trainer.get_test_dataloaders()]
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, trainer.lr_schedulers = pretrained_model.configure_optimizers()
# test HPC loading / saving
trainer.hpc_save(save_dir, logger)
trainer.hpc_load(save_dir, on_gpu=True)
# test freeze on gpu
model.freeze()
model.unfreeze()
clear_save_dir()
def test_cpu_model_with_amp():
"""
Make sure model trains on CPU
:return:
"""
reset_seed()
trainer_options = dict(
show_progress_bar=False,
logger=get_test_tube_logger(),
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, ModuleNotFoundError)):
run_gpu_model_test(trainer_options, model, hparams, on_gpu=False)
def test_cpu_model():
"""
Make sure model trains on CPU
:return:
"""
reset_seed()
trainer_options = dict(
show_progress_bar=False,
logger=get_test_tube_logger(),
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:
"""
reset_seed()
trainer_options = dict(
gradient_clip_val=1.0,
overfit_pct=0.20,
track_grad_norm=2,
print_nan_grads=True,
show_progress_bar=False,
logger=get_test_tube_logger(),
accumulate_grad_batches=2,
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:
"""
reset_seed()
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(
show_progress_bar=False,
max_nb_epochs=1,
train_percent_check=0.1,
val_percent_check=0.1,
gpus=1
)
run_gpu_model_test(trainer_options, model, hparams)
def test_multi_gpu_none_backend():
"""
Make sure when using multiple GPUs the user can't use
distributed_backend = None
:return:
"""
reset_seed()
if not can_run_gpu_test():
return
model, hparams = get_model()
trainer_options = dict(
show_progress_bar=False,
max_nb_epochs=1,
train_percent_check=0.1,
val_percent_check=0.1,
gpus='-1'
)
with pytest.raises(MisconfigurationException):
run_gpu_model_test(trainer_options, model, hparams)
def test_multi_gpu_model_dp():
"""
Make sure DP works
:return:
"""
reset_seed()
if not can_run_gpu_test():
return
model, hparams = get_model()
trainer_options = dict(
show_progress_bar=False,
distributed_backend='dp',
max_nb_epochs=1,
train_percent_check=0.1,
val_percent_check=0.1,
gpus='-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:
"""
reset_seed()
if not can_run_gpu_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_ddp_sampler_error():
"""
Make sure DDP + AMP work
:return:
"""
if not can_run_gpu_test():
return
reset_seed()
set_random_master_port()
hparams = get_hparams()
model = LightningTestModel(hparams, force_remove_distributed_sampler=True)
logger = get_test_tube_logger(True)
trainer = Trainer(
logger=logger,
show_progress_bar=False,
max_nb_epochs=1,
gpus=[0, 1],
distributed_backend='ddp',
use_amp=True
)
with pytest.warns(UserWarning):
trainer.get_dataloaders(model)
clear_save_dir()
def test_multiple_val_dataloader():
"""
Verify multiple val_dataloader
:return:
"""
reset_seed()
class CurrentTestModel(
LightningValidationMultipleDataloadersMixin,
LightningTestModelBase
):
pass
hparams = get_hparams()
model = CurrentTestModel(hparams)
# logger file to get meta
trainer_options = dict(
max_nb_epochs=1,
val_percent_check=0.1,
train_percent_check=1.0,
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
# verify training completed
assert result == 1
# verify there are 2 val loaders
assert len(trainer.get_val_dataloaders()) == 2, \
'Multiple val_dataloaders not initiated properly'
# make sure predictions are good for each val set
[run_prediction(dataloader, trainer.model) for dataloader in trainer.get_val_dataloaders()]
def test_multiple_test_dataloader():
"""
Verify multiple test_dataloader
:return:
"""
reset_seed()
class CurrentTestModel(
LightningTestMultipleDataloadersMixin,
LightningTestModelBase
):
pass
hparams = get_hparams()
model = CurrentTestModel(hparams)
# logger file to get meta
trainer_options = dict(
max_nb_epochs=1,
val_percent_check=0.1,
train_percent_check=0.1,
)
# fit model
trainer = Trainer(**trainer_options)
result = trainer.fit(model)
# verify there are 2 val loaders
assert len(trainer.get_test_dataloaders()) == 2, \
'Multiple test_dataloaders not initiated properly'
# make sure predictions are good for each test set
[run_prediction(dataloader, trainer.model) for dataloader in trainer.get_test_dataloaders()]
# run the test method
trainer.test()
@pytest.fixture
def mocked_device_count(monkeypatch):
def device_count():
return PRETEND_N_OF_GPUS
monkeypatch.setattr(torch.cuda, 'device_count', device_count)
@pytest.fixture
def mocked_device_count_0(monkeypatch):
def device_count():
return 0
monkeypatch.setattr(torch.cuda, 'device_count', device_count)
test_num_gpus_data = [
pytest.param(None, 0, None, id="None - expect 0 gpu to use."),
pytest.param(0, 0, None, id="Oth gpu, expect 1 gpu to use."),
pytest.param(1, 1, None, id="1st gpu, expect 1 gpu to use."),
pytest.param(-1, PRETEND_N_OF_GPUS, "ddp", id="-1 - use all gpus"),
pytest.param('-1', PRETEND_N_OF_GPUS, "ddp", id="'-1' - use all gpus"),
pytest.param(3, 3, "ddp", id="3rd gpu - 1 gpu to use (backend:ddp)")
]
@pytest.mark.gpus_param_tests
@pytest.mark.parametrize(["gpus", "expected_num_gpus", "distributed_backend"], test_num_gpus_data)
def test_trainer_gpu_parse(mocked_device_count, gpus, expected_num_gpus, distributed_backend):
assert Trainer(gpus=gpus, distributed_backend=distributed_backend).num_gpus == expected_num_gpus
test_num_gpus_data_0 = [
pytest.param(None, 0, None, id="None - expect 0 gpu to use."),
pytest.param(None, 0, "ddp", id="None - expect 0 gpu to use."),
]
@pytest.mark.gpus_param_tests
@pytest.mark.parametrize(["gpus", "expected_num_gpus", "distributed_backend"], test_num_gpus_data_0)
def test_trainer_num_gpu_0(mocked_device_count_0, gpus, expected_num_gpus, distributed_backend):
assert Trainer(gpus=gpus, distributed_backend=distributed_backend).num_gpus == expected_num_gpus
test_root_gpu_data = [
pytest.param(None, None, "ddp", id="None is None"),
pytest.param(0, None, "ddp", id="O gpus, expect gpu root device to be None."),
pytest.param(1, 0, "ddp", id="1 gpu, expect gpu root device to be 0."),
pytest.param(-1, 0, "ddp", id="-1 - use all gpus, expect gpu root device to be 0."),
pytest.param('-1', 0, "ddp", id="'-1' - use all gpus, expect gpu root device to be 0."),
pytest.param(3, 0, "ddp", id="3 gpus, expect gpu root device to be 0.(backend:ddp)")]
@pytest.mark.gpus_param_tests
@pytest.mark.parametrize(['gpus', 'expected_root_gpu', "distributed_backend"], test_root_gpu_data)
def test_root_gpu_property(mocked_device_count, gpus, expected_root_gpu, distributed_backend):
assert Trainer(gpus=gpus, distributed_backend=distributed_backend).root_gpu == expected_root_gpu
test_root_gpu_data_for_0_devices_passing = [
pytest.param(None, None, None, id="None is None"),
pytest.param(None, None, "ddp", id="None is None"),
pytest.param(0, None, "ddp", id="None is None"),
]
@pytest.mark.gpus_param_tests
@pytest.mark.parametrize([
'gpus', 'expected_root_gpu', "distributed_backend"], test_root_gpu_data_for_0_devices_passing)
def test_root_gpu_property_0_passing(
mocked_device_count_0, gpus, expected_root_gpu, distributed_backend):
assert Trainer(gpus=gpus, distributed_backend=distributed_backend).root_gpu == expected_root_gpu
# Asking for a gpu when non are available will result in a MisconfigurationException
test_root_gpu_data_for_0_devices_raising = [
pytest.param(1, None, "ddp"),
pytest.param(3, None, "ddp"),
pytest.param(3, None, "ddp"),
pytest.param([1, 2], None, "ddp"),
pytest.param([0, 1], None, "ddp"),
pytest.param(-1, None, "ddp"),
pytest.param('-1', None, "ddp")
]
@pytest.mark.gpus_param_tests
@pytest.mark.parametrize([
'gpus', 'expected_root_gpu', "distributed_backend"], test_root_gpu_data_for_0_devices_raising)
def test_root_gpu_property_0_raising(
mocked_device_count_0, gpus, expected_root_gpu, distributed_backend):
with pytest.raises(MisconfigurationException):
Trainer(gpus=gpus, distributed_backend=distributed_backend).root_gpu
test_determine_root_gpu_device_data = [
pytest.param(None, None, id="No gpus, expect gpu root device to be None"),
pytest.param([0], 0, id="Oth gpu, expect gpu root device to be 0."),
pytest.param([1], 1, id="1st gpu, expect gpu root device to be 1."),
pytest.param([3], 3, id="3rd gpu, expect gpu root device to be 3."),
pytest.param([1, 2], 1, id="[1, 2] gpus, expect gpu root device to be 1."),
]
@pytest.mark.gpus_param_tests
@pytest.mark.parametrize(['gpus', 'expected_root_gpu'], test_determine_root_gpu_device_data)
def test_determine_root_gpu_device(gpus, expected_root_gpu):
assert determine_root_gpu_device(gpus) == expected_root_gpu
test_parse_gpu_ids_data = [
pytest.param(None, None),
pytest.param(0, None),
pytest.param(1, [0]),
pytest.param(-1, list(range(PRETEND_N_OF_GPUS)), id="-1 - use all gpus"),
pytest.param('-1', list(range(PRETEND_N_OF_GPUS)), id="'-1' - use all gpus"),
pytest.param(3, [0, 1, 2])]
@pytest.mark.gpus_param_tests
@pytest.mark.parametrize(['gpus', 'expected_gpu_ids'], test_parse_gpu_ids_data)
def test_parse_gpu_ids(mocked_device_count, gpus, expected_gpu_ids):
assert parse_gpu_ids(gpus) == expected_gpu_ids
@pytest.mark.gpus_param_tests
@pytest.mark.parametrize("gpus", [[1, 2, 19], -1, '-1'])
def test_parse_gpu_fail_on_non_existant_id(mocked_device_count_0, gpus):
with pytest.raises(MisconfigurationException):
parse_gpu_ids(gpus)
@pytest.mark.gpus_param_tests
def test_parse_gpu_fail_on_non_existant_id_2(mocked_device_count):
with pytest.raises(MisconfigurationException):
parse_gpu_ids([1, 2, 19])
@pytest.mark.gpus_param_tests
@pytest.mark.parametrize("gpus", [-1, '-1'])
def test_parse_gpu_returns_None_when_no_devices_are_available(mocked_device_count_0, gpus):
with pytest.raises(MisconfigurationException):
parse_gpu_ids(gpus)
# ------------------------------------------------------------------------
# UTILS
# ------------------------------------------------------------------------
def run_model_test_no_loggers(trainer_options, model, hparams, on_gpu=True, min_acc=0.50):
save_dir = init_save_dir()
trainer_options['default_save_path'] = save_dir
# fit model
trainer = Trainer(**trainer_options)
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(trainer.logger.experiment,
trainer.checkpoint_callback.filepath)
# test new model accuracy
for dataloader in model.test_dataloader():
run_prediction(dataloader, pretrained_model, min_acc=min_acc)
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, trainer.lr_schedulers = pretrained_model.configure_optimizers()
clear_save_dir()
def run_gpu_model_test(trainer_options, model, hparams, on_gpu=True):
save_dir = init_save_dir()
# logger file to get meta
logger = get_test_tube_logger(False)
# logger file to get weights
checkpoint = init_checkpoint_callback(logger)
# add these to the trainer options
trainer_options['checkpoint_callback'] = checkpoint
trainer_options['logger'] = logger
# fit model
trainer = Trainer(**trainer_options)
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(logger.experiment, trainer.checkpoint_callback.filepath)
# test new model accuracy
[run_prediction(dataloader, pretrained_model) for dataloader in model.test_dataloader()]
if trainer.use_ddp or trainer.use_ddp2:
# on hpc this would work fine... but need to hack it for the purpose of the test
trainer.model = pretrained_model
trainer.optimizers, trainer.lr_schedulers = pretrained_model.configure_optimizers()
# test HPC loading / saving
trainer.hpc_save(save_dir, logger)
trainer.hpc_load(save_dir, on_gpu=on_gpu)
clear_save_dir()
def get_hparams(continue_training=False, hpc_exp_number=0):
root_dir = os.path.dirname(os.path.realpath(__file__))
args = {
'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}
if continue_training:
args['test_tube_do_checkpoint_load'] = True
args['hpc_exp_number'] = hpc_exp_number
hparams = Namespace(**args)
return hparams
def get_model(use_test_model=False, lbfgs=False):
# set up model with these hyperparams
hparams = get_hparams()
if lbfgs:
setattr(hparams, 'optimizer_name', 'lbfgs')
setattr(hparams, 'learning_rate', 0.002)
if use_test_model:
model = LightningTestModel(hparams)
else:
model = LightningTemplateModel(hparams)
return model, hparams
def get_test_tube_logger(debug=True, version=None):
# set up logger object without actually saving logs
root_dir = os.path.dirname(os.path.realpath(__file__))
save_dir = os.path.join(root_dir, 'save_dir')
logger = TestTubeLogger(save_dir, name='lightning_logs', debug=False, version=version)
return logger
def init_save_dir():
root_dir = os.path.dirname(os.path.realpath(__file__))
save_dir = os.path.join(root_dir, 'tests', 'save_dir')
if os.path.exists(save_dir):
n = RANDOM_FILE_PATHS.pop()
shutil.move(save_dir, save_dir + f'_{n}')
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):
n = RANDOM_FILE_PATHS.pop()
shutil.move(save_dir, save_dir + f'_{n}')
def load_model(exp, root_weights_dir, module_class=LightningTemplateModel):
# 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(root_weights_dir) if '.ckpt' in x]
weights_dir = os.path.join(root_weights_dir, checkpoints[0])
trained_model = module_class.load_from_metrics(weights_path=weights_dir,
tags_csv=tags_path)
assert trained_model is not None, 'loading model failed'
return trained_model
def run_prediction(dataloader, trained_model, dp=False, min_acc=0.50):
# run prediction on 1 batch
for batch in dataloader:
break
x, y = batch
x = x.view(x.size(0), -1)
if dp:
output = trained_model(batch, 0)
acc = output['val_acc']
acc = torch.mean(acc).item()
else:
y_hat = trained_model(x)
# acc
labels_hat = torch.argmax(y_hat, dim=1)
acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0)
acc = torch.tensor(acc)
acc = acc.item()
assert acc > min_acc, f'this model is expected to get > {min_acc} in test set (it got {acc})'
def assert_ok_val_acc(trainer):
# this model should get 0.80+ acc
acc = trainer.training_tqdm_dict['val_acc']
assert acc > 0.50, f'model failed to get expected 0.50 validation accuracy. Got: {acc}'
def assert_ok_test_acc(trainer):
# this model should get 0.80+ acc
acc = trainer.training_tqdm_dict['test_acc']
assert acc > 0.50, f'model failed to get expected 0.50 validation accuracy. Got: {acc}'
def can_run_gpu_test():
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 False
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 False
return True
def reset_seed():
SEED = RANDOM_SEEDS.pop()
torch.manual_seed(SEED)
np.random.seed(SEED)
def set_random_master_port():
port = RANDOM_PORTS.pop()
os.environ['MASTER_PORT'] = str(port)
def init_checkpoint_callback(logger):
exp = logger.experiment
exp_path = exp.get_data_path(exp.name, exp.version)
ckpt_dir = os.path.join(exp_path, 'checkpoints')
checkpoint = ModelCheckpoint(ckpt_dir)
return checkpoint
if __name__ == '__main__':
pytest.main([__file__])