From 5de13193feeac1644daa81083e0ce6e240cd9b34 Mon Sep 17 00:00:00 2001 From: Olivier Date: Tue, 3 Jun 2025 14:12:00 +0200 Subject: [PATCH 1/5] :hammer: Rework Frost with external dep --- pyproject.toml | 2 +- torch_uncertainty/datasets/frost.py | 65 +++++------------------------ 2 files changed, 12 insertions(+), 55 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5abc280b..ffb4798c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ dependencies = [ [project.optional-dependencies] experiments = ["tensorboard", "huggingface-hub>=0.31", "safetensors"] -image = ["kornia", "h5py", "opencv-python"] +image = ["kornia", "h5py", "opencv-python", "torch-uncertainty-assets"] tabular = ["pandas"] dev = [ "torch_uncertainty[experiments,image]", diff --git a/torch_uncertainty/datasets/frost.py b/torch_uncertainty/datasets/frost.py index 6aa069bb..a750450f 100644 --- a/torch_uncertainty/datasets/frost.py +++ b/torch_uncertainty/datasets/frost.py @@ -1,78 +1,36 @@ -import logging from collections.abc import Callable +from importlib.abc import Traversable +from importlib.resources import files from pathlib import Path from typing import Any from PIL import Image from torchvision.datasets import VisionDataset -from torchvision.datasets.utils import ( - check_integrity, - download_and_extract_archive, -) -def pil_loader(path: Path) -> Image.Image: - # open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835) +def pil_loader(path: Path | Traversable) -> Image.Image: with path.open("rb") as f: img = Image.open(f) return img.convert("RGB") -class FrostImages(VisionDataset): # TODO: Use ImageFolder - url = "https://zenodo.org/records/10438904/files/frost.zip" - zip_md5 = "d82f29f620d43a68e71e34b28f7c35cb" - filename = "frost.zip" - samples = [ - "frost1.png", - "frost2.png", - "frost3.jpg", - "frost4.jpg", - "frost5.jpg", - ] +FROST_ASSETS_MOD = "torch_uncertainty_assets.frost" + +class FrostImages(VisionDataset): def __init__( self, - root: str | Path, - transform: Callable[..., Any] | None, + transform: Callable[..., Any] | None = None, target_transform: Callable[..., Any] | None = None, - download: bool = False, ) -> None: - self.root = Path(root) - - if download: - self.download() - - if not self._check_integrity(): - raise RuntimeError( - "Dataset not found or corrupted. You can use download=True to download it." - ) - super().__init__( - self.root / "frost", + FROST_ASSETS_MOD, transform=transform, target_transform=target_transform, ) self.loader = pil_loader - - def _check_integrity(self) -> bool: - fpath = self.root / self.filename - return check_integrity( - fpath, - self.zip_md5, - ) - - def download(self) -> None: - if self._check_integrity(): - logging.info("Files already downloaded and verified") - return - - download_and_extract_archive( - self.url, - download_root=self.root, - filename=self.filename, - md5=self.zip_md5, - ) - logging.info("Downloaded %s to %s.", self.filename, self.root) + sample_path = files(FROST_ASSETS_MOD) + self.samples = [sample_path.joinpath(f"frost{i}.jpg") for i in range(1, 6)] def __getitem__(self, index: int) -> Any: """Get the samples of the dataset. @@ -83,8 +41,7 @@ def __getitem__(self, index: int) -> Any: Returns: tuple: (sample, target) where target is class_index of the target class. """ - path = self.root / self.samples[index] - sample = self.loader(path) + sample = self.loader(self.samples[index]) if self.transform is not None: sample = self.transform(sample) return sample From 40c97259d4d864c6f5c9253bc16b4a028bb076f3 Mon Sep 17 00:00:00 2001 From: Olivier Date: Tue, 3 Jun 2025 14:14:48 +0200 Subject: [PATCH 2/5] :zap: Update version --- auto_tutorial_source/Bayesian_Methods/tutorial_bayesian.py | 2 +- docs/source/conf.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/auto_tutorial_source/Bayesian_Methods/tutorial_bayesian.py b/auto_tutorial_source/Bayesian_Methods/tutorial_bayesian.py index ffb52c4e..7d014c0c 100644 --- a/auto_tutorial_source/Bayesian_Methods/tutorial_bayesian.py +++ b/auto_tutorial_source/Bayesian_Methods/tutorial_bayesian.py @@ -119,7 +119,7 @@ # # Now that the model is trained, let's test it on MNIST. # Please note that we apply a reshape to the logits to determine the dimension corresponding to the ensemble -# and to the batch. As for TorchUncertainty 0.5.1, the ensemble dimension is merged with the batch dimension +# and to the batch. As for TorchUncertainty 0.5.2, the ensemble dimension is merged with the batch dimension # in this order (num_estimator x batch, classes). import matplotlib.pyplot as plt diff --git a/docs/source/conf.py b/docs/source/conf.py index bf3a55bc..518d3972 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,7 +20,7 @@ f"{datetime.now().year!s}, Adrien Lafage and Olivier Laurent" ) author = "Adrien Lafage and Olivier Laurent" -release = "0.5.1" +release = "0.5.2" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/pyproject.toml b/pyproject.toml index ffb4798c..3ab1113b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi" [project] name = "torch_uncertainty" -version = "0.5.1" +version = "0.5.2" authors = [ { name = "ENSTA U2IS", email = "olivier.laurent@ensta-paris.fr" }, { name = "Adrien Lafage", email = "adrienlafage@outlook.com" }, From 510d071bfcd79ce72d872f75afc8dcc8e792a680 Mon Sep 17 00:00:00 2001 From: Olivier Date: Tue, 3 Jun 2025 14:18:11 +0200 Subject: [PATCH 3/5] :shirt: Add safety --- torch_uncertainty/datasets/frost.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/torch_uncertainty/datasets/frost.py b/torch_uncertainty/datasets/frost.py index a750450f..a757cf8a 100644 --- a/torch_uncertainty/datasets/frost.py +++ b/torch_uncertainty/datasets/frost.py @@ -1,4 +1,5 @@ from collections.abc import Callable +from importlib import util from importlib.abc import Traversable from importlib.resources import files from pathlib import Path @@ -7,6 +8,9 @@ from PIL import Image from torchvision.datasets import VisionDataset +FROST_ASSETS_MOD = "torch_uncertainty_assets.frost" +tu_assets_installed = util.find_spec("torch_uncertainty_assets") + def pil_loader(path: Path | Traversable) -> Image.Image: with path.open("rb") as f: @@ -14,15 +18,18 @@ def pil_loader(path: Path | Traversable) -> Image.Image: return img.convert("RGB") -FROST_ASSETS_MOD = "torch_uncertainty_assets.frost" - - class FrostImages(VisionDataset): def __init__( self, transform: Callable[..., Any] | None = None, target_transform: Callable[..., Any] | None = None, ) -> None: + if not tu_assets_installed: # coverage: ignore + raise ImportError( + "The torch-uncertainty-assets library is not installed. Please install" + "torch_uncertainty with the image option:" + """pip install -U "torch_uncertainty[image]".""" + ) super().__init__( FROST_ASSETS_MOD, transform=transform, @@ -49,3 +56,7 @@ def __getitem__(self, index: int) -> Any: def __len__(self) -> int: """Get the length of the dataset.""" return len(self.samples) + + +if __name__ == "__main__": + ds = FrostImages() From a612d8e4647fa2fb81b96619237388839380acec Mon Sep 17 00:00:00 2001 From: Olivier Date: Tue, 3 Jun 2025 14:20:59 +0200 Subject: [PATCH 4/5] :white_check_mark: Fix Frost corruption --- torch_uncertainty/transforms/corruption.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torch_uncertainty/transforms/corruption.py b/torch_uncertainty/transforms/corruption.py index 0c63af49..e4297fa5 100644 --- a/torch_uncertainty/transforms/corruption.py +++ b/torch_uncertainty/transforms/corruption.py @@ -584,7 +584,7 @@ def __init__(self, severity: int, seed: int | None = None) -> None: super().__init__(severity) self.rng = np.random.default_rng(seed) self.mix = [(1, 0.4), (0.8, 0.6), (0.7, 0.7), (0.65, 0.7), (0.6, 0.75)][severity - 1] - self.frost_ds = FrostImages("./data", download=True, transform=ToTensor()) + self.frost_ds = FrostImages(transform=ToTensor()) def forward(self, img: Tensor) -> Tensor: if self.severity == 0: From abf8824fc554d971d06523e8932269e8ba600504 Mon Sep 17 00:00:00 2001 From: Olivier Laurent <62881275+o-laurent@users.noreply.github.com> Date: Tue, 3 Jun 2025 14:27:50 +0200 Subject: [PATCH 5/5] :fire: Remove main code --- torch_uncertainty/datasets/frost.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/torch_uncertainty/datasets/frost.py b/torch_uncertainty/datasets/frost.py index a757cf8a..4ca848a3 100644 --- a/torch_uncertainty/datasets/frost.py +++ b/torch_uncertainty/datasets/frost.py @@ -56,7 +56,3 @@ def __getitem__(self, index: int) -> Any: def __len__(self) -> int: """Get the length of the dataset.""" return len(self.samples) - - -if __name__ == "__main__": - ds = FrostImages()