lightning/pytorch_lightning/callbacks/prediction_writer.py

123 lines
4.2 KiB
Python
Raw Normal View History

2021-04-27 20:23:55 +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.
r"""
BasePredictionWriter
====================
Aids in saving predictions
"""
from typing import Any, Optional, Sequence
import pytorch_lightning as pl
from pytorch_lightning.callbacks.base import Callback
from pytorch_lightning.utilities import LightningEnum
from pytorch_lightning.utilities.exceptions import MisconfigurationException
class WriteInterval(LightningEnum):
BATCH = "batch"
EPOCH = "epoch"
BATCH_AND_EPOCH = "batch_and_epoch"
@property
def on_batch(self) -> bool:
return self in (self.BATCH, self.BATCH_AND_EPOCH)
@property
def on_epoch(self) -> bool:
return self in (self.EPOCH, self.BATCH_AND_EPOCH)
class BasePredictionWriter(Callback):
"""
Base class to implement how the predictions should be stored.
Args:
write_interval: When to write.
Example::
import torch
from pytorch_lightning.callbacks import BasePredictionWriter
class CustomWriter(BasePredictionWriter):
def __init__(self, output_dir: str, write_interval: str):
super().__init__(write_interval)
self.output_dir
def write_on_batch_end(
self, trainer, pl_module: 'LightningModule', prediction: Any, batch_indices: List[int], batch: Any,
batch_idx: int, dataloader_idx: int
):
torch.save(prediction, os.path.join(self.output_dir, dataloader_idx, f"{batch_idx}.pt"))
def write_on_epoch_end(
self, trainer, pl_module: 'LightningModule', predictions: List[Any], batch_indices: List[Any]
):
torch.save(predictions, os.path.join(self.output_dir, "predictions.pt"))
"""
def __init__(self, write_interval: str = "batch") -> None:
if write_interval not in list(WriteInterval):
raise MisconfigurationException(f"`write_interval` should be one of {[i.value for i in WriteInterval]}.")
self.interval = WriteInterval(write_interval)
def write_on_batch_end(
self,
trainer: "pl.Trainer",
pl_module: "pl.LightningModule",
2021-04-27 20:23:55 +00:00
prediction: Any,
batch_indices: Optional[Sequence[int]],
batch: Any,
batch_idx: int,
dataloader_idx: int,
) -> None:
"""Override with the logic to write a single batch."""
raise NotImplementedError()
def write_on_epoch_end(
self,
trainer: "pl.Trainer",
pl_module: "pl.LightningModule",
2021-04-27 20:23:55 +00:00
predictions: Sequence[Any],
batch_indices: Optional[Sequence[Any]],
) -> None:
"""Override with the logic to write all batches."""
raise NotImplementedError()
def on_predict_batch_end(
self,
trainer: "pl.Trainer",
pl_module: "pl.LightningModule",
2021-04-27 20:23:55 +00:00
outputs: Any,
batch: Any,
batch_idx: int,
dataloader_idx: int,
) -> None:
if not self.interval.on_batch:
return
is_distributed = trainer.accelerator_connector.is_distributed
Loop Refactor 5/N - Prediction Loop (#7700) * integrate d180bb2 * Minor changes * Refactor loop logic into logger connector * Refactor test * Tighter fx validator * Add back split idx * Typing * update * Conflict * Fix tests * resolve grad_norm * update * move to train loop * Bye grad_norm_dict parameter * Fix sync test * update * Fix bug when validation is run mid epoch * fix grad_norm_dict test * Fix fx_validator test * fix grad_norm_dict test * Fix order bug * Detach tensors in test * resolve some tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove pdb * resolve flake8 * Update test * more tests * Revert last thomas' changes * resolve 1 test * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Refactor context restoration * integrate latest changes from logger connector refactor poc * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * integrate latest changes from logger connector refactor poc * Minor changes * update changelog * Remove unused argument * Update CHANGELOG * Copy call_hook changes * Docs * Fix ref * move to cpu * Bad merge * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove pdb * remove pdb * Refactor to * Avoid partial * trigger ci * Bad merge * integrate latest logger connector changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove grad norm dicts list * Diff * properties first * Bad merge * Reuse metrics_to_scalars * Use active loop * Move to device * resolve test * integrate latest changes from logger connector poc * define union * define union * Update logger connector * Update result * Update imports * Update after rename * Refactor reduce_fx and op * Fix test after rename * mypy * integrate latest logger connector refactor poc changes * Fix test * Refactor test * Deprecate `self.log(sync_dist_op)` in favor of `self.log(reduce_fx)` * Undo field * add redundant return * rename rename files and classes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * rename * Replace code * Fix names and imports * Remove metric_attribute * imports * loop hygiene * yapf on loops * protected new loop trigger * rename NEW LOOP guard * integrate latest logger connector changes * integrate latest logger connector changes (eval loop) * resolve todo dataloading reset * re-add notebooks * add missing init * bad merge * remove NEW_LOOP guard * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * flake8 * exclude coverage coverage * integrate #7917, remove teardown from training loop * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * update "accumulated_batches_reached" condition based on if iter count was updated or not * remove public loop properties * make skip backward protected again * typing base loop * typing fit loop * typing training_batch_loop * typing evaluation loop * typing prediction loop * typing training epoch loop * dataloader_loop * evaluation_dataloader_loop * prediction_dataloader_loop * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * integrate train loop changes from master * integrate eval loop changes from master * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix tpipes moving model to cpu and leaving it there. * don't reset fit loop don't reset fit loop * fix test iteration count <-> batch_idx reset * replace torch.Tensor -> Tensor * fix attribute error to block_ddp_sync_behaviour * fix flake8 and yapf conflict * remove redundant override * add classes Co-authored-by: Justus Schock <justus.schock@rwth-aachen.de> Co-authored-by: Justus Schock <justus.schock@posteo.de> Co-authored-by: Justus Schock <12886177+justusschock@users.noreply.github.com> * trainer changes * connect * clean up * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * update test renaming * rename evaluation loop to evaluation epoch loop * minor docstring improvements * update chlog * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * try ci fix * update code owners for pl/loops * update mock path * re-order * simplify dataloader reset * simplify get_dataloaders() * save predictions on_run_end() * improve skip condition re-routing * re-order * remove unused type import * check which assert is failing * pig * hobbit * teardown for evaluation * Revert "hobbit" This reverts commit e81b0dbee31da813ba6ad58f74d236863c86d18e. * Revert "pig" This reverts commit 33d89e0720ce7380af80917b15a79362d9416ae7. * Revert "check which assert is failing" This reverts commit b7483b425cab95290eb2cbf354ccb0a77004df83. * free memory in fit loop teardown * update docstring * period * remove dead code * else carlos Co-authored-by: Carlos Mocholí <carlossmocholi@gmail.com> * Update pytorch_lightning/loops/dataloader/evaluation_dataloader_loop.py Co-authored-by: Carlos Mocholí <carlossmocholi@gmail.com> * update chlog * unused imp * move default construction in run_evaluation * add something for lawyer to read * switch typehint for eval loop trainer property * add missing imports * remove a todo that needs more discussion * combine _get_num_dataloaders with the property * Update pytorch_lightning/loops/dataloader/dataloader_loop.py Co-authored-by: Carlos Mocholí <carlossmocholi@gmail.com> * black + yapf * avoid coverage on old unused eval loop * empty space in docstring Co-authored-by: Ethan Harris <ewah1g13@soton.ac.uk> * resolve todo for args forwarding * weekproxy trainer * fix check for num dataloaders kwargs * clean up num prediction dataloaders property * free memory * rm notebooks folder * rm old file * revert changes to old eval loop * bad merge * undo teardown * setup signature * remove file for notes * free memory * chlog * Revert "weekproxy trainer" This reverts commit d4e6969170b80db4c9e6111fa9af507c740cde4a. * connect trainer * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * clean up max batches and dataloaders * max batches handling * no grad handling * unused argument * protected attrs * unused imports * undo unintentional rename * consistent naming * capitalization in docstring * list all args * Update pytorch_lightning/loops/prediction_epoch_loop.py Co-authored-by: Carlos Mocholí <carlossmocholi@gmail.com> * Update pytorch_lightning/loops/prediction_epoch_loop.py Co-authored-by: Carlos Mocholí <carlossmocholi@gmail.com> * Update pytorch_lightning/loops/dataloader/prediction_dataloader_loop.py Co-authored-by: Carlos Mocholí <carlossmocholi@gmail.com> * Update pytorch_lightning/loops/dataloader/prediction_dataloader_loop.py Co-authored-by: Carlos Mocholí <carlossmocholi@gmail.com> * Update pytorch_lightning/loops/prediction_epoch_loop.py Co-authored-by: Carlos Mocholí <carlossmocholi@gmail.com> Co-authored-by: Carlos Mocholi <carlossmocholi@gmail.com> Co-authored-by: tchaton <thomas@grid.ai> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Justus Schock <justus.schock@posteo.de> Co-authored-by: Justus Schock <justus.schock@rwth-aachen.de> Co-authored-by: Justus Schock <12886177+justusschock@users.noreply.github.com> Co-authored-by: Ethan Harris <ewah1g13@soton.ac.uk>
2021-06-23 09:17:04 +00:00
batch_indices = trainer.predict_loop.epoch_loop.current_batch_indices if is_distributed else None
2021-04-27 20:23:55 +00:00
self.write_on_batch_end(trainer, pl_module, outputs, batch_indices, batch, batch_idx, dataloader_idx)
def on_predict_epoch_end(
self, trainer: "pl.Trainer", pl_module: "pl.LightningModule", outputs: Sequence[Any]
2021-04-27 20:23:55 +00:00
) -> None:
if not self.interval.on_epoch:
return
is_distributed = trainer.accelerator_connector.is_distributed
epoch_batch_indices = trainer.predict_loop.epoch_batch_indices if is_distributed else None
self.write_on_epoch_end(trainer, pl_module, trainer.predict_loop.predictions, epoch_batch_indices)