2021-01-08 15:36:49 +00:00
|
|
|
# Copyright The PyTorch Lightning team.
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
import glob
|
|
|
|
import os
|
|
|
|
import sys
|
2022-04-28 20:37:58 +00:00
|
|
|
import threading
|
2021-08-10 08:13:31 +00:00
|
|
|
from unittest.mock import patch
|
2021-01-08 15:36:49 +00:00
|
|
|
|
|
|
|
import pytest
|
2021-08-10 08:13:31 +00:00
|
|
|
import torch
|
2021-01-08 15:36:49 +00:00
|
|
|
|
2021-08-10 08:13:31 +00:00
|
|
|
import pytorch_lightning as pl
|
|
|
|
from pytorch_lightning import Callback, Trainer
|
|
|
|
from tests import _PATH_LEGACY, _PROJECT_ROOT
|
2021-01-08 15:36:49 +00:00
|
|
|
|
2021-07-26 11:37:35 +00:00
|
|
|
LEGACY_CHECKPOINTS_PATH = os.path.join(_PATH_LEGACY, "checkpoints")
|
2021-01-08 15:36:49 +00:00
|
|
|
CHECKPOINT_EXTENSION = ".ckpt"
|
2021-08-10 08:13:31 +00:00
|
|
|
# load list of all back compatible versions
|
|
|
|
with open(os.path.join(_PROJECT_ROOT, "legacy", "back-compatible-versions.txt")) as fp:
|
|
|
|
LEGACY_BACK_COMPATIBLE_PL_VERSIONS = [ln.strip() for ln in fp.readlines()]
|
2021-01-08 15:36:49 +00:00
|
|
|
|
|
|
|
|
2021-08-10 08:13:31 +00:00
|
|
|
@pytest.mark.parametrize("pl_version", LEGACY_BACK_COMPATIBLE_PL_VERSIONS)
|
|
|
|
def test_load_legacy_checkpoints(tmpdir, pl_version: str):
|
|
|
|
PATH_LEGACY = os.path.join(LEGACY_CHECKPOINTS_PATH, pl_version)
|
|
|
|
with patch("sys.path", [PATH_LEGACY] + sys.path):
|
|
|
|
from simple_classif_training import ClassifDataModule, ClassificationModel
|
|
|
|
|
|
|
|
path_ckpts = sorted(glob.glob(os.path.join(PATH_LEGACY, f"*{CHECKPOINT_EXTENSION}")))
|
|
|
|
assert path_ckpts, f'No checkpoints found in folder "{PATH_LEGACY}"'
|
|
|
|
path_ckpt = path_ckpts[-1]
|
|
|
|
|
|
|
|
model = ClassificationModel.load_from_checkpoint(path_ckpt)
|
|
|
|
trainer = Trainer(default_root_dir=str(tmpdir))
|
|
|
|
dm = ClassifDataModule()
|
|
|
|
res = trainer.test(model, datamodule=dm)
|
|
|
|
assert res[0]["test_loss"] <= 0.7
|
|
|
|
assert res[0]["test_acc"] >= 0.85
|
|
|
|
print(res)
|
2021-01-08 15:36:49 +00:00
|
|
|
|
|
|
|
|
2021-08-10 08:13:31 +00:00
|
|
|
class LimitNbEpochs(Callback):
|
|
|
|
def __init__(self, nb: int):
|
|
|
|
self.limit = nb
|
|
|
|
self._count = 0
|
2021-01-08 15:36:49 +00:00
|
|
|
|
2022-02-07 14:15:27 +00:00
|
|
|
def on_train_epoch_start(self, trainer: "pl.Trainer", pl_module: "pl.LightningModule") -> None:
|
2021-08-10 08:13:31 +00:00
|
|
|
self._count += 1
|
|
|
|
if self._count >= self.limit:
|
|
|
|
trainer.should_stop = True
|
|
|
|
|
|
|
|
|
2022-04-28 20:37:58 +00:00
|
|
|
@pytest.mark.parametrize("pl_version", LEGACY_BACK_COMPATIBLE_PL_VERSIONS)
|
|
|
|
def test_legacy_ckpt_threading(tmpdir, pl_version: str):
|
|
|
|
def load_model():
|
|
|
|
import torch
|
|
|
|
|
|
|
|
from pytorch_lightning.utilities.migration import pl_legacy_patch
|
|
|
|
|
|
|
|
with pl_legacy_patch():
|
|
|
|
_ = torch.load(PATH_LEGACY)
|
|
|
|
|
|
|
|
PATH_LEGACY = os.path.join(LEGACY_CHECKPOINTS_PATH, pl_version)
|
|
|
|
with patch("sys.path", [PATH_LEGACY] + sys.path):
|
|
|
|
t1 = threading.Thread(target=load_model)
|
|
|
|
t2 = threading.Thread(target=load_model)
|
|
|
|
|
|
|
|
t1.start()
|
|
|
|
t2.start()
|
|
|
|
|
|
|
|
t1.join()
|
|
|
|
t2.join()
|
|
|
|
|
|
|
|
|
2021-08-10 08:13:31 +00:00
|
|
|
@pytest.mark.parametrize("pl_version", LEGACY_BACK_COMPATIBLE_PL_VERSIONS)
|
|
|
|
def test_resume_legacy_checkpoints(tmpdir, pl_version: str):
|
|
|
|
PATH_LEGACY = os.path.join(LEGACY_CHECKPOINTS_PATH, pl_version)
|
|
|
|
with patch("sys.path", [PATH_LEGACY] + sys.path):
|
|
|
|
from simple_classif_training import ClassifDataModule, ClassificationModel
|
2021-01-08 15:36:49 +00:00
|
|
|
|
2021-08-10 08:13:31 +00:00
|
|
|
path_ckpts = sorted(glob.glob(os.path.join(PATH_LEGACY, f"*{CHECKPOINT_EXTENSION}")))
|
|
|
|
assert path_ckpts, f'No checkpoints found in folder "{PATH_LEGACY}"'
|
|
|
|
path_ckpt = path_ckpts[-1]
|
2021-01-08 15:36:49 +00:00
|
|
|
|
2021-08-10 08:13:31 +00:00
|
|
|
dm = ClassifDataModule()
|
|
|
|
model = ClassificationModel()
|
|
|
|
stop = LimitNbEpochs(1)
|
2022-01-12 05:47:01 +00:00
|
|
|
|
2021-08-10 08:13:31 +00:00
|
|
|
trainer = Trainer(
|
|
|
|
default_root_dir=str(tmpdir),
|
2022-01-12 05:47:01 +00:00
|
|
|
accelerator="auto",
|
|
|
|
devices=1,
|
2021-08-10 08:13:31 +00:00
|
|
|
precision=(16 if torch.cuda.is_available() else 32),
|
2022-02-07 14:15:27 +00:00
|
|
|
callbacks=[stop],
|
2021-08-10 08:13:31 +00:00
|
|
|
max_epochs=21,
|
|
|
|
accumulate_grad_batches=2,
|
|
|
|
)
|
2021-09-30 04:40:09 +00:00
|
|
|
torch.backends.cudnn.deterministic = True
|
2021-10-25 19:05:31 +00:00
|
|
|
trainer.fit(model, datamodule=dm, ckpt_path=path_ckpt)
|
2021-08-10 08:13:31 +00:00
|
|
|
res = trainer.test(model, datamodule=dm)
|
|
|
|
assert res[0]["test_loss"] <= 0.7
|
|
|
|
assert res[0]["test_acc"] >= 0.85
|