|
|
|
|
|
|
|
|
|
|
|
|
|
import os |
|
import tempfile |
|
import unittest |
|
from pathlib import Path |
|
|
|
import torch |
|
|
|
from hydra import compose, initialize_config_dir |
|
from omegaconf import OmegaConf |
|
from projects.implicitron_trainer.impl.optimizer_factory import ( |
|
ImplicitronOptimizerFactory, |
|
) |
|
|
|
from .. import experiment |
|
from .utils import interactive_testing_requested, intercept_logs |
|
|
|
internal = os.environ.get("FB_TEST", False) |
|
|
|
|
|
DATA_DIR = Path(__file__).resolve().parent |
|
IMPLICITRON_CONFIGS_DIR = Path(__file__).resolve().parent.parent / "configs" |
|
DEBUG: bool = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
def _parse_float_from_log(line): |
|
return float(line.split()[-1]) |
|
|
|
|
|
class TestExperiment(unittest.TestCase): |
|
def setUp(self): |
|
self.maxDiff = None |
|
|
|
def test_from_defaults(self): |
|
|
|
if not interactive_testing_requested() or not internal: |
|
return |
|
|
|
|
|
|
|
cfg = OmegaConf.structured(experiment.Experiment) |
|
cfg.data_source_ImplicitronDataSource_args.dataset_map_provider_class_type = ( |
|
"JsonIndexDatasetMapProvider" |
|
) |
|
dataset_args = ( |
|
cfg.data_source_ImplicitronDataSource_args.dataset_map_provider_JsonIndexDatasetMapProvider_args |
|
) |
|
dataloader_args = ( |
|
cfg.data_source_ImplicitronDataSource_args.data_loader_map_provider_SequenceDataLoaderMapProvider_args |
|
) |
|
dataset_args.category = "skateboard" |
|
dataset_args.test_restrict_sequence_id = 0 |
|
dataset_args.dataset_root = "manifold://co3d/tree/extracted" |
|
dataset_args.dataset_JsonIndexDataset_args.limit_sequences_to = 5 |
|
dataset_args.dataset_JsonIndexDataset_args.image_height = 80 |
|
dataset_args.dataset_JsonIndexDataset_args.image_width = 80 |
|
dataloader_args.dataset_length_train = 1 |
|
dataloader_args.dataset_length_val = 1 |
|
cfg.training_loop_ImplicitronTrainingLoop_args.max_epochs = 2 |
|
cfg.training_loop_ImplicitronTrainingLoop_args.store_checkpoints = False |
|
cfg.optimizer_factory_ImplicitronOptimizerFactory_args.multistep_lr_milestones = [ |
|
0, |
|
1, |
|
] |
|
|
|
if DEBUG: |
|
experiment.dump_cfg(cfg) |
|
with intercept_logs( |
|
logger_name="projects.implicitron_trainer.impl.training_loop", |
|
regexp="LR change!", |
|
) as intercepted_logs: |
|
experiment_runner = experiment.Experiment(**cfg) |
|
experiment_runner.run() |
|
|
|
|
|
self.assertEqual(intercepted_logs[0].split()[-1], "5e-06") |
|
|
|
def test_exponential_lr(self): |
|
|
|
if not interactive_testing_requested(): |
|
return |
|
cfg = OmegaConf.structured(experiment.Experiment) |
|
cfg.data_source_ImplicitronDataSource_args.dataset_map_provider_class_type = ( |
|
"JsonIndexDatasetMapProvider" |
|
) |
|
dataset_args = ( |
|
cfg.data_source_ImplicitronDataSource_args.dataset_map_provider_JsonIndexDatasetMapProvider_args |
|
) |
|
dataloader_args = ( |
|
cfg.data_source_ImplicitronDataSource_args.data_loader_map_provider_SequenceDataLoaderMapProvider_args |
|
) |
|
dataset_args.category = "skateboard" |
|
dataset_args.test_restrict_sequence_id = 0 |
|
dataset_args.dataset_root = "manifold://co3d/tree/extracted" |
|
dataset_args.dataset_JsonIndexDataset_args.limit_sequences_to = 5 |
|
dataset_args.dataset_JsonIndexDataset_args.image_height = 80 |
|
dataset_args.dataset_JsonIndexDataset_args.image_width = 80 |
|
dataloader_args.dataset_length_train = 1 |
|
dataloader_args.dataset_length_val = 1 |
|
cfg.training_loop_ImplicitronTrainingLoop_args.max_epochs = 2 |
|
cfg.training_loop_ImplicitronTrainingLoop_args.store_checkpoints = False |
|
cfg.optimizer_factory_ImplicitronOptimizerFactory_args.lr_policy = "Exponential" |
|
cfg.optimizer_factory_ImplicitronOptimizerFactory_args.exponential_lr_step_size = ( |
|
2 |
|
) |
|
|
|
if DEBUG: |
|
experiment.dump_cfg(cfg) |
|
with intercept_logs( |
|
logger_name="projects.implicitron_trainer.impl.training_loop", |
|
regexp="LR change!", |
|
) as intercepted_logs: |
|
experiment_runner = experiment.Experiment(**cfg) |
|
experiment_runner.run() |
|
|
|
|
|
|
|
|
|
self.assertEqual(intercepted_logs[0].split()[-1], "0.00015811388300841897") |
|
self.assertEqual(intercepted_logs[1].split()[-1], "5e-05") |
|
|
|
def test_yaml_contents(self): |
|
|
|
|
|
cfg = OmegaConf.structured(experiment.Experiment) |
|
|
|
ds_arg = cfg.data_source_ImplicitronDataSource_args |
|
ds_arg.dataset_map_provider_JsonIndexDatasetMapProvider_args.dataset_root = "" |
|
ds_arg.dataset_map_provider_JsonIndexDatasetMapProviderV2_args.dataset_root = "" |
|
if "dataset_map_provider_SqlIndexDatasetMapProvider_args" in ds_arg: |
|
del ds_arg.dataset_map_provider_SqlIndexDatasetMapProvider_args |
|
cfg.training_loop_ImplicitronTrainingLoop_args.visdom_port = 8097 |
|
yaml = OmegaConf.to_yaml(cfg, sort_keys=False) |
|
if DEBUG: |
|
(DATA_DIR / "experiment.yaml").write_text(yaml) |
|
self.assertEqual(yaml, (DATA_DIR / "experiment.yaml").read_text()) |
|
|
|
def test_load_configs(self): |
|
|
|
config_files = [] |
|
|
|
for pattern in ( |
|
"repro_singleseq*.yaml", |
|
"repro_multiseq*.yaml", |
|
"overfit_singleseq*.yaml", |
|
): |
|
config_files.extend( |
|
[ |
|
f |
|
for f in IMPLICITRON_CONFIGS_DIR.glob(pattern) |
|
if not f.name.endswith("_base.yaml") |
|
] |
|
) |
|
|
|
for file in config_files: |
|
with self.subTest(file.name): |
|
with initialize_config_dir(config_dir=str(IMPLICITRON_CONFIGS_DIR)): |
|
compose(file.name) |
|
|
|
def test_optimizer_factory(self): |
|
model = torch.nn.Linear(2, 2) |
|
|
|
adam, sched = ImplicitronOptimizerFactory(breed="Adam")(0, model) |
|
self.assertIsInstance(adam, torch.optim.Adam) |
|
sgd, sched = ImplicitronOptimizerFactory(breed="SGD")(0, model) |
|
self.assertIsInstance(sgd, torch.optim.SGD) |
|
adagrad, sched = ImplicitronOptimizerFactory(breed="Adagrad")(0, model) |
|
self.assertIsInstance(adagrad, torch.optim.Adagrad) |
|
|
|
|
|
class TestNerfRepro(unittest.TestCase): |
|
@unittest.skip("This test runs full blender training.") |
|
def test_nerf_blender(self): |
|
|
|
|
|
if not interactive_testing_requested(): |
|
return |
|
with initialize_config_dir(config_dir=str(IMPLICITRON_CONFIGS_DIR)): |
|
cfg = compose(config_name="repro_singleseq_nerf_blender", overrides=[]) |
|
experiment_runner = experiment.Experiment(**cfg) |
|
experiment.dump_cfg(cfg) |
|
experiment_runner.run() |
|
|
|
@unittest.skip("This test runs full llff training.") |
|
def test_nerf_llff(self): |
|
|
|
|
|
LLFF_SINGLESEQ_CLASS = os.environ["LLFF_SINGLESEQ_CLASS"] |
|
if not interactive_testing_requested(): |
|
return |
|
with initialize_config_dir(config_dir=str(IMPLICITRON_CONFIGS_DIR)): |
|
cfg = compose( |
|
config_name=f"repro_singleseq_nerf_llff_{LLFF_SINGLESEQ_CLASS}", |
|
overrides=[], |
|
) |
|
experiment_runner = experiment.Experiment(**cfg) |
|
experiment.dump_cfg(cfg) |
|
experiment_runner.run() |
|
|
|
@unittest.skip("This test runs nerf training on co3d v2 - manyview.") |
|
def test_nerf_co3dv2_manyview(self): |
|
|
|
if not interactive_testing_requested(): |
|
return |
|
with initialize_config_dir(config_dir=str(IMPLICITRON_CONFIGS_DIR)): |
|
cfg = compose( |
|
config_name="repro_singleseq_v2_nerf", |
|
overrides=[], |
|
) |
|
experiment_runner = experiment.Experiment(**cfg) |
|
experiment.dump_cfg(cfg) |
|
experiment_runner.run() |
|
|
|
@unittest.skip("This test runs nerformer training on co3d v2 - fewview.") |
|
def test_nerformer_co3dv2_fewview(self): |
|
|
|
if not interactive_testing_requested(): |
|
return |
|
with initialize_config_dir(config_dir=str(IMPLICITRON_CONFIGS_DIR)): |
|
cfg = compose( |
|
config_name="repro_multiseq_v2_nerformer", |
|
overrides=[], |
|
) |
|
experiment_runner = experiment.Experiment(**cfg) |
|
experiment.dump_cfg(cfg) |
|
experiment_runner.run() |
|
|
|
@unittest.skip("This test checks resuming of the NeRF training.") |
|
def test_nerf_blender_resume(self): |
|
|
|
|
|
if not interactive_testing_requested(): |
|
return |
|
with initialize_config_dir(config_dir=str(IMPLICITRON_CONFIGS_DIR)): |
|
with tempfile.TemporaryDirectory() as exp_dir: |
|
cfg = compose(config_name="repro_singleseq_nerf_blender", overrides=[]) |
|
cfg.exp_dir = exp_dir |
|
|
|
|
|
|
|
|
|
( |
|
cfg |
|
.data_source_ImplicitronDataSource_args |
|
.data_loader_map_provider_SequenceDataLoaderMapProvider_args |
|
.dataset_length_train |
|
) = 1 |
|
|
|
|
|
|
|
cfg.training_loop_ImplicitronTrainingLoop_args.max_epochs = 1 |
|
experiment_runner = experiment.Experiment(**cfg) |
|
experiment.dump_cfg(cfg) |
|
experiment_runner.run() |
|
|
|
|
|
cfg.training_loop_ImplicitronTrainingLoop_args.max_epochs = 3 |
|
experiment_runner = experiment.Experiment(**cfg) |
|
experiment_runner.run() |
|
|
|
|
|
cfg.model_factory_ImplicitronModelFactory_args.resume = False |
|
experiment_runner = experiment.Experiment(**cfg) |
|
experiment_runner.run() |
|
|
|
|
|
cfg.model_factory_ImplicitronModelFactory_args.resume = True |
|
cfg.model_factory_ImplicitronModelFactory_args.force_resume = True |
|
cfg.model_factory_ImplicitronModelFactory_args.resume_epoch = 1 |
|
experiment_runner = experiment.Experiment(**cfg) |
|
experiment_runner.run() |
|
|