Skip to content

Commit 4f0a596

Browse files
authored
Merge branch 'main' into fix/exportable_center_crop
2 parents 18824db + 775f5a8 commit 4f0a596

File tree

8 files changed

+84
-121
lines changed

8 files changed

+84
-121
lines changed

CHANGELOG.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,46 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1010

1111
### Changed
1212

13-
- 🔨 Replace "./dtasets/BTech" to "./dtasets/BTech"
13+
### Deprecated
14+
15+
### Fixed
16+
17+
### New Contributors
18+
19+
**Full Changelog**:
20+
21+
## [v1.1.1]
22+
23+
### Added
24+
25+
- 📚Ppipelines how-to guide by @ashwinvaidya17 in https://github.com/openvinotoolkit/anomalib/pull/2109
26+
27+
### Changed
28+
29+
- Set permissions for github workflows by @djdameln in https://github.com/openvinotoolkit/anomalib/pull/2127
30+
- Update timm requirement from <=1.0.3,>=0.5.4 to >=0.5.4,<=1.0.7 by @dependabot in https://github.com/openvinotoolkit/anomalib/pull/2151
31+
- 🚀 Use gh actions runners for pre-commit checks by @ashwinvaidya17 in https://github.com/openvinotoolkit/anomalib/pull/2160
32+
- Bump AlexanderDokuchaev/md-dead-link-check from 0.8 to 0.9 by @dependabot in https://github.com/openvinotoolkit/anomalib/pull/2162
33+
- Added accuracy control quantization by @adrianboguszewski in https://github.com/openvinotoolkit/anomalib/pull/2070
1434

1535
### Deprecated
1636

37+
- 🔨Remove device postfix by @ashwinvaidya17 in https://github.com/openvinotoolkit/anomalib/pull/2233
38+
1739
### Fixed
1840

19-
- 🔨 Fix uncorrect download path of btech dataset
41+
- Fix: get MLFLOW_TRACKING_UTI from env variables as default by @CarlosNacher in https://github.com/openvinotoolkit/anomalib/pull/2107
42+
- Fix normalization by @alexriedel1 in https://github.com/openvinotoolkit/anomalib/pull/2130
43+
- Fix image-level heatmap normalization by @djdameln in https://github.com/openvinotoolkit/anomalib/pull/2131
44+
- Fix: efficient ad model_size str fixes by @Gornoka in https://github.com/openvinotoolkit/anomalib/pull/2159
45+
- Fix the CI by @samet-akcay in https://github.com/openvinotoolkit/anomalib/pull/2178
46+
- Fix BTech Dataset by @samet-akcay in https://github.com/openvinotoolkit/anomalib/pull/2180
2047

2148
### New Contributors
2249

23-
**Full Changelog**:
50+
- @CarlosNacher made their first contribution in https://github.com/openvinotoolkit/anomalib/pull/2107
51+
52+
**Full Changelog**: https://github.com/openvinotoolkit/anomalib/compare/v1.1.0...v1.1.1
2453

2554
## [v1.1.0]
2655

notebooks/500_use_cases/501_dobot/501a_training_a_model_with_cubes_from_a_robotic_arm.ipynb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,45 @@
437437
")"
438438
]
439439
},
440+
{
441+
"cell_type": "markdown",
442+
"metadata": {},
443+
"source": [
444+
"For optimization and quantization process, we are using a seamless integration with [NNCF Library](https://github.com/openvinotoolkit/nncf) in the backend of Anomalib. Select one of the following options for optimization or quantization. Replace the openvino_model_path line above in order to export the optimized/quantized model:\n",
445+
"\n",
446+
"```\n",
447+
"# Exporting optimized/quantized models\n",
448+
"\n",
449+
"# Post Training Quantization\n",
450+
"openvino_model_path = engine.export(\n",
451+
" model, \n",
452+
" ExportType.OPENVINO, \n",
453+
" str(Path.cwd()) + \"_optimized\", \n",
454+
" compression_type=CompressionType.INT8_PTQ, \n",
455+
" datamodule=datamodule\n",
456+
" )\n",
457+
"\n",
458+
"# Accuracy-Control Quantization\n",
459+
"openvino_model_path=engine.export(\n",
460+
" model, \n",
461+
" ExportType.OPENVINO, \n",
462+
" str(Path.cwd()) + \"_optimized\", \n",
463+
" compression_type=CompressionType.INT8_ACQ, \n",
464+
" datamodule=datamodule, \n",
465+
" metric=\"F1Score\"\n",
466+
" )\n",
467+
"\n",
468+
"# Weight Compression\n",
469+
"openvino_model_path=engine.export(\n",
470+
" model, \n",
471+
" ExportType.OPENVINO, \n",
472+
" str(Path.cwd()) + \"_WEIGHTS\", \n",
473+
" compression_type=CompressionType.FP16, \n",
474+
" datamodule=datamodule\n",
475+
" )\n",
476+
"```"
477+
]
478+
},
440479
{
441480
"attachments": {},
442481
"cell_type": "markdown",

src/anomalib/callbacks/checkpoint.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def _should_skip_saving_checkpoint(self, trainer: Trainer) -> bool:
3535
Overrides the parent method to allow saving during both the ``FITTING`` and ``VALIDATING`` states, and to allow
3636
saving when the global step and last_global_step_saved are both 0 (only for zero-/few-shot models).
3737
"""
38-
is_zero_or_few_shot = trainer.model.learning_type in [LearningType.ZERO_SHOT, LearningType.FEW_SHOT]
38+
is_zero_or_few_shot = trainer.lightning_module.learning_type in [LearningType.ZERO_SHOT, LearningType.FEW_SHOT]
3939
return (
4040
bool(trainer.fast_dev_run) # disable checkpointing with fast_dev_run
4141
or trainer.state.fn not in [TrainerFn.FITTING, TrainerFn.VALIDATING] # don't save anything during non-fit
@@ -52,7 +52,7 @@ def _should_save_on_train_epoch_end(self, trainer: Trainer) -> bool:
5252
if self._save_on_train_epoch_end is not None:
5353
return self._save_on_train_epoch_end
5454

55-
if trainer.model.learning_type in [LearningType.ZERO_SHOT, LearningType.FEW_SHOT]:
55+
if trainer.lightning_module.learning_type in [LearningType.ZERO_SHOT, LearningType.FEW_SHOT]:
5656
return False
5757

5858
return super()._should_save_on_train_epoch_end(trainer)

src/anomalib/cli/utils/installation.py

Lines changed: 2 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -276,81 +276,6 @@ def get_hardware_suffix(with_available_torch_build: bool = False, torch_version:
276276
return hardware_suffix
277277

278278

279-
def add_hardware_suffix_to_torch(
280-
requirement: Requirement,
281-
hardware_suffix: str | None = None,
282-
with_available_torch_build: bool = False,
283-
) -> str:
284-
"""Add hardware suffix to the torch requirement.
285-
286-
Args:
287-
requirement (Requirement): Requirement object comprising requirement
288-
details.
289-
hardware_suffix (str | None): Hardware suffix. If None, it will be set
290-
to the correct hardware suffix. Defaults to None.
291-
with_available_torch_build (bool): To check whether the installed
292-
CUDA version is supported by the latest available PyTorch build.
293-
Defaults to False.
294-
295-
Examples:
296-
>>> from pkg_resources import Requirement
297-
>>> req = "torch>=1.13.0, <=2.0.1"
298-
>>> requirement = Requirement.parse(req)
299-
>>> requirement.name, requirement.specs
300-
('torch', [('>=', '1.13.0'), ('<=', '2.0.1')])
301-
302-
>>> add_hardware_suffix_to_torch(requirement)
303-
'torch>=1.13.0+cu121, <=2.0.1+cu121'
304-
305-
``with_available_torch_build=True`` will use the latest available PyTorch build.
306-
>>> req = "torch==2.0.1"
307-
>>> requirement = Requirement.parse(req)
308-
>>> add_hardware_suffix_to_torch(requirement, with_available_torch_build=True)
309-
'torch==2.0.1+cu118'
310-
311-
It is possible to pass the ``hardware_suffix`` manually.
312-
>>> req = "torch==2.0.1"
313-
>>> requirement = Requirement.parse(req)
314-
>>> add_hardware_suffix_to_torch(requirement, hardware_suffix="cu121")
315-
'torch==2.0.1+cu111'
316-
317-
Raises:
318-
ValueError: When the requirement has more than two version criterion.
319-
320-
Returns:
321-
str: Updated torch package with the right cuda suffix.
322-
"""
323-
name = requirement.unsafe_name
324-
updated_specs: list[str] = []
325-
326-
for operator, version in requirement.specs:
327-
hardware_suffix = hardware_suffix or get_hardware_suffix(with_available_torch_build, version)
328-
updated_version = version + f"+{hardware_suffix}" if not version.startswith(("2.1", "2.2")) else version
329-
330-
# ``specs`` contains operators and versions as follows:
331-
# These are to be concatenated again for the updated version.
332-
updated_specs.append(operator + updated_version)
333-
334-
updated_requirement: str = ""
335-
336-
if updated_specs:
337-
# This is the case when specs are e.g. ['<=1.9.1+cu111']
338-
if len(updated_specs) == 1:
339-
updated_requirement = name + updated_specs[0]
340-
# This is the case when specs are e.g., ['<=1.9.1+cu111', '>=1.8.1+cu111']
341-
elif len(updated_specs) == 2:
342-
updated_requirement = name + updated_specs[0] + ", " + updated_specs[1]
343-
else:
344-
msg = (
345-
"Requirement version can be a single value or a range. \n"
346-
"For example it could be torch>=1.8.1 "
347-
"or torch>=1.8.1, <=1.9.1\n"
348-
f"Got {updated_specs} instead."
349-
)
350-
raise ValueError(msg)
351-
return updated_requirement
352-
353-
354279
def get_torch_install_args(requirement: str | Requirement) -> list[str]:
355280
"""Get the install arguments for Torch requirement.
356281
@@ -368,7 +293,7 @@ def get_torch_install_args(requirement: str | Requirement) -> list[str]:
368293
>>> requriment = "torch>=1.13.0"
369294
>>> get_torch_install_args(requirement)
370295
['--extra-index-url', 'https://download.pytorch.org/whl/cpu',
371-
'torch==1.13.0+cpu', 'torchvision==0.14.0+cpu']
296+
'torch>=1.13.0', 'torchvision==0.14.0']
372297
373298
Returns:
374299
list[str]: The install arguments.
@@ -401,21 +326,15 @@ def get_torch_install_args(requirement: str | Requirement) -> list[str]:
401326
# Create the PyTorch Index URL to download the correct wheel.
402327
index_url = f"https://download.pytorch.org/whl/{hardware_suffix}"
403328

404-
# Create the PyTorch version depending on the CUDA version. For example,
405-
# If CUDA version is 11.2, then the PyTorch version is 1.8.0+cu112.
406-
# If CUDA version is None, then the PyTorch version is 1.8.0+cpu.
407-
torch_version = add_hardware_suffix_to_torch(requirement, hardware_suffix, with_available_torch_build=True)
329+
torch_version = f"{requirement.name}{operator}{version}" # eg: torch==1.13.0
408330

409331
# Get the torchvision version depending on the torch version.
410332
torchvision_version = AVAILABLE_TORCH_VERSIONS[version]["torchvision"]
411333
torchvision_requirement = f"torchvision{operator}{torchvision_version}"
412-
if isinstance(torchvision_version, str) and not torchvision_version.startswith("0.16"):
413-
torchvision_requirement += f"+{hardware_suffix}"
414334

415335
# Return the install arguments.
416336
install_args += [
417337
"--extra-index-url",
418-
# "--index-url",
419338
index_url,
420339
torch_version,
421340
torchvision_requirement,

src/anomalib/data/base/datamodule.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,8 @@ def train_transform(self) -> Transform:
270270
"""
271271
if self._train_transform:
272272
return self._train_transform
273-
if getattr(self, "trainer", None) and self.trainer.model and self.trainer.model.transform:
274-
return self.trainer.model.transform
273+
if getattr(self, "trainer", None) and self.trainer.lightning_module and self.trainer.lightning_module.transform:
274+
return self.trainer.lightning_module.transform
275275
if self.image_size:
276276
return Resize(self.image_size, antialias=True)
277277
return None
@@ -284,8 +284,8 @@ def eval_transform(self) -> Transform:
284284
"""
285285
if self._eval_transform:
286286
return self._eval_transform
287-
if getattr(self, "trainer", None) and self.trainer.model and self.trainer.model.transform:
288-
return self.trainer.model.transform
287+
if getattr(self, "trainer", None) and self.trainer.lightning_module and self.trainer.lightning_module.transform:
288+
return self.trainer.lightning_module.transform
289289
if self.image_size:
290290
return Resize(self.image_size, antialias=True)
291291
return None

src/anomalib/engine/engine.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def model(self) -> AnomalyModule:
183183
Returns:
184184
AnomalyModule: Anomaly model.
185185
"""
186-
if not self.trainer.model:
186+
if not self.trainer.lightning_module:
187187
msg = "Trainer does not have a model assigned yet."
188188
raise UnassignedError(msg)
189189
return self.trainer.lightning_module

tests/unit/cli/test_installation.py

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from pytest_mock import MockerFixture
1313

1414
from anomalib.cli.utils.installation import (
15-
add_hardware_suffix_to_torch,
1615
get_cuda_suffix,
1716
get_cuda_version,
1817
get_hardware_suffix,
@@ -122,29 +121,6 @@ def test_get_hardware_suffix(mocker: MockerFixture) -> None:
122121
assert get_hardware_suffix() == "cpu"
123122

124123

125-
def test_add_hardware_suffix_to_torch(mocker: MockerFixture) -> None:
126-
"""Test that add_hardware_suffix_to_torch returns the expected updated requirement."""
127-
mocker.patch("anomalib.cli.utils.installation.get_hardware_suffix", return_value="cu121")
128-
requirement = Requirement.parse("torch>=1.13.0, <=2.0.1")
129-
updated_requirement = add_hardware_suffix_to_torch(requirement)
130-
assert "torch" in updated_requirement
131-
assert ">=1.13.0+cu121" in updated_requirement
132-
assert "<=2.0.1+cu121" in updated_requirement
133-
134-
requirement = Requirement.parse("torch==2.0.1")
135-
mocker.patch("anomalib.cli.utils.installation.get_hardware_suffix", return_value="cu118")
136-
updated_requirement = add_hardware_suffix_to_torch(requirement, with_available_torch_build=True)
137-
assert updated_requirement == "torch==2.0.1+cu118"
138-
139-
requirement = Requirement.parse("torch==2.0.1")
140-
updated_requirement = add_hardware_suffix_to_torch(requirement, hardware_suffix="cu111")
141-
assert updated_requirement == "torch==2.0.1+cu111"
142-
143-
requirement = Requirement.parse("torch>=1.13.0, <=2.0.1, !=1.14.0")
144-
with pytest.raises(ValueError, match="Requirement version can be a single value or a range."):
145-
add_hardware_suffix_to_torch(requirement)
146-
147-
148124
def test_get_torch_install_args(mocker: MockerFixture) -> None:
149125
"""Test that get_torch_install_args returns the expected install arguments."""
150126
requirement = Requirement.parse("torch>=2.1.1")
@@ -174,8 +150,8 @@ def test_get_torch_install_args(mocker: MockerFixture) -> None:
174150
expected_args = [
175151
"--extra-index-url",
176152
"https://download.pytorch.org/whl/cu111",
177-
"torch==2.0.1+cu111",
178-
"torchvision==0.15.2+cu111",
153+
"torch==2.0.1",
154+
"torchvision==0.15.2",
179155
]
180156
install_args = get_torch_install_args(requirement)
181157
for arg in expected_args:

tests/unit/metrics/test_adaptive_threshold.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@ def test_manual_threshold() -> None:
5555
devices=1,
5656
)
5757
engine.fit(model=model, datamodule=datamodule)
58-
assert engine.trainer.model.image_metrics.F1Score.threshold == image_threshold
59-
assert engine.trainer.model.pixel_metrics.F1Score.threshold == pixel_threshold
58+
assert engine.trainer.lightning_module.image_metrics.F1Score.threshold == image_threshold
59+
assert engine.trainer.lightning_module.pixel_metrics.F1Score.threshold == pixel_threshold

0 commit comments

Comments
 (0)