From 4e4a5a6594b11f916a589b695215c416ef9b62a2 Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 18:18:16 +0200 Subject: [PATCH 01/13] updated --- .circleci/config.yml | 10 +++++----- .github/workflows/workflow.yml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1768f87..8829c14 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,7 +9,7 @@ version: 2.1 # ------------------------------------------------------------------------------------- cpu: &cpu docker: - - image: circleci/python:3.7 + - image: cimg/python:3.11.4 auth: username: $DOCKERHUB_USERNAME password: $DOCKERHUB_TOKEN @@ -17,7 +17,7 @@ cpu: &cpu gpu: &gpu machine: - image: ubuntu-2004-cuda-11.4:202110-01 + image: linux-cuda-12:2023.05.1 docker_layer_caching: true resource_class: gpu.nvidia.small @@ -74,14 +74,14 @@ jobs: # Cache the venv directory that contains dependencies - restore_cache: keys: - - cache-key-{{ .Branch }}-ID-20200130 + - cache-key-{{ .Branch }}-ID-20230617 - <<: *install_dep - save_cache: paths: - ~/venv - key: cache-key-{{ .Branch }}-ID-20200130 + key: cache-key-{{ .Branch }}-ID-20230617 - <<: *install_fvcore @@ -134,7 +134,7 @@ jobs: upload_wheel: docker: - - image: circleci/python:3.7 + - image: cimg/python:3.11.4 auth: username: $DOCKERHUB_USERNAME password: $DOCKERHUB_TOKEN diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index d92aa1a..c178114 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -9,18 +9,18 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.8, 3.9] # importlib-metadata v5 requires 3.8+ + python-version: [3.8, 3.9, 3.10, 3.11] # importlib-metadata v5 requires 3.8+ steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flake8==3.8.1 flake8-bugbear flake8-comprehensions isort==4.3.21 - pip install black==22.3.0 + pip install flake8==6.0.0 flake8-bugbear flake8-comprehensions isort==5.12.0 + pip install black==23.3.0 flake8 --version - name: Lint run: | From 84bf3bce03d911295ba7cbfe60e2e2262e3bbd2d Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 18:19:14 +0200 Subject: [PATCH 02/13] fix --- .github/workflows/workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index c178114..b45ebe5 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -9,7 +9,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.8, 3.9, 3.10, 3.11] # importlib-metadata v5 requires 3.8+ + python-version: ["3.8", "3.9", "3.10", "3.11"] # importlib-metadata v5 requires 3.8+ steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} From c40659f7c5915f0940a7fa18b34e3a0e60192d08 Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 18:20:34 +0200 Subject: [PATCH 03/13] fix --- .github/workflows/workflow.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index b45ebe5..a084fc2 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -25,8 +25,8 @@ jobs: - name: Lint run: | echo "Running isort" - isort -c -sp . + isort -c --sp . . echo "Running black" - black --check . + black -l 100 --check . echo "Running flake8" flake8 . From ac0e787e20540724e4d8464051b95cd10de23afb Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 18:24:07 +0200 Subject: [PATCH 04/13] fix --- fvcore/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fvcore/__init__.py b/fvcore/__init__.py index 1d78872..ddae10b 100644 --- a/fvcore/__init__.py +++ b/fvcore/__init__.py @@ -2,4 +2,4 @@ # This line will be programatically read/write by setup.py. # Leave them at the bottom of this file and don't touch them. -__version__ = "0.1.6" +__version__ = "0.1.7" From 2a7a228c9b2651e016e64c02277ac3716a6905e3 Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 18:36:00 +0200 Subject: [PATCH 05/13] fix --- .circleci/config.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8829c14..5e65a66 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -58,6 +58,11 @@ run_unittests: &run_unittests python -m unittest discover -v -s tests python -m unittest discover -v -s io_tests +select_cuda: &select_cuda + - run: + name: Select CUDA + command: | + sudo update-alternatives --set cuda /usr/local/cuda-<< parameters.cuda_version >> # ------------------------------------------------------------------------------------- # Jobs to run # ------------------------------------------------------------------------------------- @@ -101,6 +106,7 @@ jobs: steps: - checkout + - <<: *select_cuda - run: name: Install nvidia-docker working_directory: ~/ @@ -184,6 +190,7 @@ workflows: context: - DOCKERHUB_TOKEN - gpu_tests: + cuda_version: '12.1' context: - DOCKERHUB_TOKEN From d7326cb155de797c4a9805e96e79e27b85e0fe36 Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 18:41:22 +0200 Subject: [PATCH 06/13] fix --- .circleci/config.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5e65a66..95cf4f2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,6 +21,15 @@ gpu: &gpu docker_layer_caching: true resource_class: gpu.nvidia.small +version_parameters: &version_parameters + parameters: + cuda_version: + type: string + default: '12.1' + + environment: + CUDA_VERSION: << parameters.cuda_version >> + # ------------------------------------------------------------------------------------- # Re-usable commands # ------------------------------------------------------------------------------------- @@ -101,6 +110,7 @@ jobs: gpu_tests: <<: *gpu + <<: *version_parameters working_directory: ~/fvcore From 577112deb5c7e55f37df9890cc74c2cfba4ee829 Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 19:05:26 +0200 Subject: [PATCH 07/13] isort --- fvcore/common/checkpoint.py | 1 - fvcore/nn/jit_analysis.py | 3 ++- linter.sh | 6 +++--- tests/bm_common.py | 3 ++- tests/bm_focal_loss.py | 3 ++- tests/test_activation_count.py | 3 ++- tests/test_checkpoint.py | 4 ++-- tests/test_common.py | 3 ++- tests/test_flop_count.py | 6 ++++-- tests/test_focal_loss.py | 3 ++- tests/test_giou_loss.py | 1 + tests/test_jit_model_analysis.py | 1 + tests/test_layers_squeeze_excitation.py | 1 + tests/test_param_count.py | 3 ++- tests/test_precise_bn.py | 3 ++- tests/test_print_model_statistics.py | 3 +-- tests/test_smooth_l1_loss.py | 1 + tests/test_transform.py | 1 + tests/test_transform_util.py | 1 + tests/test_weight_init.py | 1 + 20 files changed, 33 insertions(+), 18 deletions(-) diff --git a/fvcore/common/checkpoint.py b/fvcore/common/checkpoint.py index 99f1917..0effb71 100644 --- a/fvcore/common/checkpoint.py +++ b/fvcore/common/checkpoint.py @@ -291,7 +291,6 @@ def _load_model(self, checkpoint: Any) -> _IncompatibleKeys: shape_model = tuple(model_param.shape) shape_checkpoint = tuple(checkpoint_state_dict[k].shape) if shape_model != shape_checkpoint: - has_observer_base_classes = ( TORCH_VERSION >= (1, 8) and hasattr(quantization, "ObserverBase") diff --git a/fvcore/nn/jit_analysis.py b/fvcore/nn/jit_analysis.py index d2cf61f..c59f4b5 100644 --- a/fvcore/nn/jit_analysis.py +++ b/fvcore/nn/jit_analysis.py @@ -13,10 +13,11 @@ import numpy as np import torch import torch.nn as nn -from fvcore.common.checkpoint import _named_modules_with_dup from torch import Tensor from torch.jit import _get_trace_graph, TracerWarning +from fvcore.common.checkpoint import _named_modules_with_dup + from .jit_handles import Handle diff --git a/linter.sh b/linter.sh index 94fe194..cebc3a7 100755 --- a/linter.sh +++ b/linter.sh @@ -4,14 +4,14 @@ # Run this script at project root by "./linter.sh" before you commit. { - black --version | grep -E "22.3.0" > /dev/null + black --version | grep -E "23.3.0" > /dev/null } || { - echo "Linter requires 'black==22.3.0' !" + echo "Linter requires 'black==23.3.0' !" exit 1 } echo "Running isort..." -isort -y -sp . +isort --sp . . echo "Running black..." black . diff --git a/tests/bm_common.py b/tests/bm_common.py index faf559c..d3b5ffc 100644 --- a/tests/bm_common.py +++ b/tests/bm_common.py @@ -1,8 +1,9 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. -from fvcore.common.benchmark import benchmark from test_common import TestHistoryBuffer +from fvcore.common.benchmark import benchmark + def bm_history_buffer_update() -> None: kwargs_list = [ diff --git a/tests/bm_focal_loss.py b/tests/bm_focal_loss.py index 6544fc9..06afd57 100644 --- a/tests/bm_focal_loss.py +++ b/tests/bm_focal_loss.py @@ -1,9 +1,10 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. import torch -from fvcore.common.benchmark import benchmark from test_focal_loss import TestFocalLoss, TestFocalLossStar +from fvcore.common.benchmark import benchmark + def bm_focal_loss() -> None: if not torch.cuda.is_available(): diff --git a/tests/test_activation_count.py b/tests/test_activation_count.py index 0886906..1931114 100644 --- a/tests/test_activation_count.py +++ b/tests/test_activation_count.py @@ -8,9 +8,10 @@ import torch import torch.nn as nn +from numpy import prod + from fvcore.nn.activation_count import activation_count, ActivationCountAnalysis from fvcore.nn.jit_handles import Handle -from numpy import prod class SmallConvNet(nn.Module): diff --git a/tests/test_checkpoint.py b/tests/test_checkpoint.py index d79099e..34cd4b5 100644 --- a/tests/test_checkpoint.py +++ b/tests/test_checkpoint.py @@ -12,9 +12,10 @@ from unittest.mock import MagicMock import torch -from fvcore.common.checkpoint import Checkpointer, PeriodicCheckpointer from torch import nn +from fvcore.common.checkpoint import Checkpointer, PeriodicCheckpointer + TORCH_VERSION: Tuple[int, ...] = tuple(int(x) for x in torch.__version__.split(".")[:2]) if TORCH_VERSION >= (1, 11): @@ -125,7 +126,6 @@ def test_from_last_checkpoint_model(self) -> None: nn.DataParallel(self._create_model()), ), ]: - with TemporaryDirectory() as f: checkpointer = Checkpointer(trained_model, save_dir=f) checkpointer.save("checkpoint_file") diff --git a/tests/test_common.py b/tests/test_common.py index 3661f1d..a51dfda 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -6,11 +6,12 @@ import unittest import numpy as np +from yaml.constructor import ConstructorError + from fvcore.common.config import CfgNode from fvcore.common.history_buffer import HistoryBuffer from fvcore.common.registry import Registry from fvcore.common.timer import Timer -from yaml.constructor import ConstructorError class TestHistoryBuffer(unittest.TestCase): diff --git a/tests/test_flop_count.py b/tests/test_flop_count.py index ad593b9..ed7afd6 100644 --- a/tests/test_flop_count.py +++ b/tests/test_flop_count.py @@ -7,11 +7,12 @@ import torch import torch.nn as nn -from fvcore.nn.flop_count import _DEFAULT_SUPPORTED_OPS, flop_count, FlopCountAnalysis -from fvcore.nn.jit_handles import Handle from torch.autograd.function import Function from torch.nn import functional as F +from fvcore.nn.flop_count import _DEFAULT_SUPPORTED_OPS, flop_count, FlopCountAnalysis +from fvcore.nn.jit_handles import Handle + class _CustomOp(Function): @staticmethod @@ -189,6 +190,7 @@ def test_customized_ops(self) -> None: The second case checks when a new handle for a default operation is passed. The new handle should overwrite the default handle. """ + # New handle for a new operation. def dummy_sigmoid_flop_jit( inputs: typing.List[Any], outputs: typing.List[Any] diff --git a/tests/test_focal_loss.py b/tests/test_focal_loss.py index 435ef54..ab29ca6 100644 --- a/tests/test_focal_loss.py +++ b/tests/test_focal_loss.py @@ -5,13 +5,14 @@ import numpy as np import torch +from torch.nn import functional as F + from fvcore.nn import ( sigmoid_focal_loss, sigmoid_focal_loss_jit, sigmoid_focal_loss_star, sigmoid_focal_loss_star_jit, ) -from torch.nn import functional as F def logit(p: torch.Tensor) -> torch.Tensor: diff --git a/tests/test_giou_loss.py b/tests/test_giou_loss.py index 24ca0dc..3e76a3b 100644 --- a/tests/test_giou_loss.py +++ b/tests/test_giou_loss.py @@ -4,6 +4,7 @@ import numpy as np import torch + from fvcore.nn import giou_loss diff --git a/tests/test_jit_model_analysis.py b/tests/test_jit_model_analysis.py index 5f14818..077b292 100644 --- a/tests/test_jit_model_analysis.py +++ b/tests/test_jit_model_analysis.py @@ -10,6 +10,7 @@ import torch import torch.nn as nn + from fvcore.nn.flop_count import FlopCountAnalysis from fvcore.nn.jit_analysis import JitModelAnalysis from fvcore.nn.jit_handles import addmm_flop_jit, conv_flop_jit, Handle, linear_flop_jit diff --git a/tests/test_layers_squeeze_excitation.py b/tests/test_layers_squeeze_excitation.py index db090c9..209f27d 100644 --- a/tests/test_layers_squeeze_excitation.py +++ b/tests/test_layers_squeeze_excitation.py @@ -4,6 +4,7 @@ from typing import Iterable import torch + from fvcore.nn.squeeze_excitation import ( ChannelSpatialSqueezeExcitation, SpatialSqueezeExcitation, diff --git a/tests/test_param_count.py b/tests/test_param_count.py index 7f4464d..6e3d0c1 100644 --- a/tests/test_param_count.py +++ b/tests/test_param_count.py @@ -3,9 +3,10 @@ import unittest -from fvcore.nn.parameter_count import parameter_count, parameter_count_table from torch import nn +from fvcore.nn.parameter_count import parameter_count, parameter_count_table + class NetWithReuse(nn.Module): def __init__(self, reuse: bool = False) -> None: diff --git a/tests/test_precise_bn.py b/tests/test_precise_bn.py index e150b4c..41a1ad3 100644 --- a/tests/test_precise_bn.py +++ b/tests/test_precise_bn.py @@ -7,9 +7,10 @@ import numpy as np import torch -from fvcore.nn import update_bn_stats from torch import nn +from fvcore.nn import update_bn_stats + class TestPreciseBN(unittest.TestCase): def setUp(self) -> None: diff --git a/tests/test_print_model_statistics.py b/tests/test_print_model_statistics.py index 9a5ea59..7a7eecc 100644 --- a/tests/test_print_model_statistics.py +++ b/tests/test_print_model_statistics.py @@ -5,6 +5,7 @@ import torch import torch.nn as nn + from fvcore.nn import ActivationCountAnalysis, FlopCountAnalysis from fvcore.nn.print_model_statistics import ( _fill_missing_statistics, @@ -331,7 +332,6 @@ def test_model_stats_str(self) -> None: # ")" def test_model_stats_table(self) -> None: - stat_columns = ["stat1", "stat2", "stat3"] table = _model_stats_table(string_statistics, stat_columns=stat_columns) @@ -376,7 +376,6 @@ def test_model_stats_table(self) -> None: # "| a2.b1 | 0 | 100 | 40 |" def test_flop_count_table(self) -> None: - model = TestNet() inputs = (torch.randn((1, 10)),) diff --git a/tests/test_smooth_l1_loss.py b/tests/test_smooth_l1_loss.py index f6e1bfc..d59b8c2 100644 --- a/tests/test_smooth_l1_loss.py +++ b/tests/test_smooth_l1_loss.py @@ -4,6 +4,7 @@ import numpy as np import torch + from fvcore.nn import smooth_l1_loss diff --git a/tests/test_transform.py b/tests/test_transform.py index 9612b1a..ab9681d 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -6,6 +6,7 @@ import numpy as np import torch + from fvcore.transforms import transform as T from fvcore.transforms.transform_util import to_float_tensor, to_numpy diff --git a/tests/test_transform_util.py b/tests/test_transform_util.py index 5189681..b87d9f3 100644 --- a/tests/test_transform_util.py +++ b/tests/test_transform_util.py @@ -3,6 +3,7 @@ import unittest import numpy as np + from fvcore.transforms.transform_util import to_float_tensor, to_numpy diff --git a/tests/test_weight_init.py b/tests/test_weight_init.py index ba1164b..17b4b49 100644 --- a/tests/test_weight_init.py +++ b/tests/test_weight_init.py @@ -6,6 +6,7 @@ import torch import torch.nn as nn + from fvcore.nn.weight_init import c2_msra_fill, c2_xavier_fill From d9f2a4f510f178eaf7d5264a58578e60b8506a24 Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 19:07:41 +0200 Subject: [PATCH 08/13] isort --- fvcore/common/checkpoint.py | 41 ++---- fvcore/common/config.py | 24 ++-- fvcore/common/file_io.py | 4 +- fvcore/common/param_scheduler.py | 28 +--- fvcore/common/registry.py | 12 +- fvcore/nn/distributed.py | 12 +- fvcore/nn/focal_loss.py | 4 +- fvcore/nn/jit_analysis.py | 18 +-- fvcore/nn/jit_handles.py | 8 +- fvcore/nn/parameter_count.py | 4 +- fvcore/nn/precise_bn.py | 33 ++--- fvcore/nn/print_model_statistics.py | 24 +--- fvcore/nn/squeeze_excitation.py | 20 +-- fvcore/transforms/transform.py | 29 ++-- fvcore/transforms/transform_util.py | 12 +- io_tests/test_file_io.py | 4 +- linter.sh | 2 +- setup.py | 4 +- tests/bm_focal_loss.py | 4 +- tests/bm_main.py | 4 +- .../test_scheduler_composite.py | 12 +- .../test_scheduler_constant.py | 3 +- .../test_scheduler_exponential.py | 4 +- .../param_scheduler/test_scheduler_linear.py | 4 +- .../test_scheduler_multi_step.py | 3 +- tests/param_scheduler/test_scheduler_step.py | 3 +- .../test_scheduler_step_with_fixed_gamma.py | 3 +- tests/test_activation_count.py | 4 +- tests/test_checkpoint.py | 32 ++--- tests/test_common.py | 15 +- tests/test_flop_count.py | 50 ++----- tests/test_focal_loss.py | 132 +++++------------- tests/test_jit_model_analysis.py | 23 +-- tests/test_layers_squeeze_excitation.py | 4 +- tests/test_param_count.py | 4 +- tests/test_precise_bn.py | 10 +- tests/test_print_model_statistics.py | 8 +- tests/test_transform.py | 112 ++++----------- tests/test_weight_init.py | 8 +- 39 files changed, 188 insertions(+), 537 deletions(-) diff --git a/fvcore/common/checkpoint.py b/fvcore/common/checkpoint.py index 0effb71..f21cd8a 100644 --- a/fvcore/common/checkpoint.py +++ b/fvcore/common/checkpoint.py @@ -96,9 +96,7 @@ def add_checkpointable(self, key: str, checkpointable: Any) -> None: if key in self.checkpointables: raise KeyError(f"Key {key} already used in the Checkpointer") if not hasattr(checkpointable, "state_dict"): - raise TypeError( - "add_checkpointable needs an object with 'state_dict()' method." - ) + raise TypeError("add_checkpointable needs an object with 'state_dict()' method.") self.checkpointables[key] = checkpointable def save(self, name: str, **kwargs: Any) -> None: @@ -126,9 +124,7 @@ def save(self, name: str, **kwargs: Any) -> None: torch.save(data, cast(IO[bytes], f)) self.tag_last_checkpoint(basename) - def load( - self, path: str, checkpointables: Optional[List[str]] = None - ) -> Dict[str, Any]: + def load(self, path: str, checkpointables: Optional[List[str]] = None) -> Dict[str, Any]: """ Load from the given checkpoint. @@ -151,9 +147,7 @@ def load( # path may not be a local file, but _load_file is responsible to handle it. checkpoint = self._load_file(path) incompatible = self._load_model(checkpoint) - if ( - incompatible is not None - ): # handle some existing subclasses that returns None + if incompatible is not None: # handle some existing subclasses that returns None self._log_incompatible_keys(incompatible) for key in self.checkpointables if checkpointables is None else checkpointables: @@ -199,8 +193,7 @@ def get_all_checkpoint_files(self) -> List[str]: all_model_checkpoints = [ os.path.join(self.save_dir, file) for file in self.path_manager.ls(self.save_dir) - if self.path_manager.isfile(os.path.join(self.save_dir, file)) - and file.endswith(".pth") + if self.path_manager.isfile(os.path.join(self.save_dir, file)) and file.endswith(".pth") ] return all_model_checkpoints @@ -342,15 +335,11 @@ def _log_incompatible_keys(self, incompatible: _IncompatibleKeys) -> None: ) ) if incompatible.missing_keys: - missing_keys = _filter_reused_missing_keys( - self.model, incompatible.missing_keys - ) + missing_keys = _filter_reused_missing_keys(self.model, incompatible.missing_keys) if missing_keys: self.logger.warning(get_missing_parameters_message(missing_keys)) if incompatible.unexpected_keys: - self.logger.warning( - get_unexpected_parameters_message(incompatible.unexpected_keys) - ) + self.logger.warning(get_unexpected_parameters_message(incompatible.unexpected_keys)) def _convert_ndarray_to_tensor(self, state_dict: Dict[str, Any]) -> None: """ @@ -365,9 +354,7 @@ def _convert_ndarray_to_tensor(self, state_dict: Dict[str, Any]) -> None: for k in list(state_dict.keys()): v = state_dict[k] if not isinstance(v, np.ndarray) and not isinstance(v, torch.Tensor): - raise ValueError( - "Unsupported type found in checkpoint! {}: {}".format(k, type(v)) - ) + raise ValueError("Unsupported type found in checkpoint! {}: {}".format(k, type(v))) if not isinstance(v, torch.Tensor): state_dict[k] = torch.from_numpy(v) @@ -432,9 +419,9 @@ def step(self, iteration: int, **kwargs: Any) -> None: self.recent_checkpoints.append(self.checkpointer.get_checkpoint_file()) if len(self.recent_checkpoints) > self.max_to_keep: file_to_delete = self.recent_checkpoints.pop(0) - if self.path_manager.exists( - file_to_delete - ) and not file_to_delete.endswith(f"{self.file_prefix}_final.pth"): + if self.path_manager.exists(file_to_delete) and not file_to_delete.endswith( + f"{self.file_prefix}_final.pth" + ): self.path_manager.rm(file_to_delete) if self.max_iter is not None: @@ -501,9 +488,7 @@ def get_unexpected_parameters_message(keys: List[str]) -> str: """ groups = _group_checkpoint_keys(keys) msg = "The checkpoint state_dict contains keys that are not used by the model:\n" - msg += "\n".join( - " " + colored(k + _group_to_str(v), "magenta") for k, v in groups.items() - ) + msg += "\n".join(" " + colored(k + _group_to_str(v), "magenta") for k, v in groups.items()) return msg @@ -578,9 +563,7 @@ def _group_to_str(group: List[str]) -> str: return ".{" + ", ".join(sorted(group)) + "}" -def _named_modules_with_dup( - model: nn.Module, prefix: str = "" -) -> Iterable[Tuple[str, nn.Module]]: +def _named_modules_with_dup(model: nn.Module, prefix: str = "") -> Iterable[Tuple[str, nn.Module]]: """ The same as `model.named_modules()`, except that it includes duplicated modules that have more than one name. diff --git a/fvcore/common/config.py b/fvcore/common/config.py index 3882b09..96f70dc 100644 --- a/fvcore/common/config.py +++ b/fvcore/common/config.py @@ -40,9 +40,7 @@ def _open_cfg(cls, filename: str) -> Union[IO[str], IO[bytes]]: return g_pathmgr.open(filename, "r") @classmethod - def load_yaml_with_base( - cls, filename: str, allow_unsafe: bool = False - ) -> Dict[str, Any]: + def load_yaml_with_base(cls, filename: str, allow_unsafe: bool = False) -> Dict[str, Any]: """ Just like `yaml.load(open(filename))`, but inherit attributes from its `_BASE_`. @@ -65,9 +63,7 @@ def load_yaml_with_base( logger = logging.getLogger(__name__) logger.warning( "Loading config {} with yaml.unsafe_load. Your machine may " - "be at risk if the file contains malicious content.".format( - filename - ) + "be at risk if the file contains malicious content.".format(filename) ) f.close() with cls._open_cfg(filename) as f: @@ -77,9 +73,7 @@ def merge_a_into_b(a: Dict[str, Any], b: Dict[str, Any]) -> None: # merge dict a into dict b. values in a will overwrite b. for k, v in a.items(): if isinstance(v, dict) and k in b: - assert isinstance( - b[k], dict - ), "Cannot inherit key '{}' from base!".format(k) + assert isinstance(b[k], dict), "Cannot inherit key '{}' from base!".format(k) merge_a_into_b(v, b[k]) else: b[k] = v @@ -126,9 +120,9 @@ def merge_from_other_cfg(self, cfg_other: "CfgNode") -> Callable[[], None]: Args: cfg_other (CfgNode): configs to merge from. """ - assert ( - BASE_KEY not in cfg_other - ), "The reserved key '{}' can only be used in files!".format(BASE_KEY) + assert BASE_KEY not in cfg_other, "The reserved key '{}' can only be used in files!".format( + BASE_KEY + ) return super().merge_from_other_cfg(cfg_other) def merge_from_list(self, cfg_list: List[str]) -> Callable[[], None]: @@ -137,9 +131,9 @@ def merge_from_list(self, cfg_list: List[str]) -> Callable[[], None]: cfg_list (list): list of configs to merge from. """ keys = set(cfg_list[0::2]) - assert ( - BASE_KEY not in keys - ), "The reserved key '{}' can only be used in files!".format(BASE_KEY) + assert BASE_KEY not in keys, "The reserved key '{}' can only be used in files!".format( + BASE_KEY + ) return super().merge_from_list(cfg_list) def __setattr__(self, name: str, val: Any) -> None: # pyre-ignore diff --git a/fvcore/common/file_io.py b/fvcore/common/file_io.py index 31250e1..fdaee04 100644 --- a/fvcore/common/file_io.py +++ b/fvcore/common/file_io.py @@ -32,9 +32,7 @@ def get_cache_dir(cache_dir: Optional[str] = None) -> str: 2) otherwise ~/.torch/fvcore_cache """ if cache_dir is None: - cache_dir = os.path.expanduser( - os.getenv("FVCORE_CACHE", "~/.torch/fvcore_cache") - ) + cache_dir = os.path.expanduser(os.getenv("FVCORE_CACHE", "~/.torch/fvcore_cache")) try: PathManager.mkdirs(cache_dir) assert os.access(cache_dir, os.W_OK) diff --git a/fvcore/common/param_scheduler.py b/fvcore/common/param_scheduler.py index f95350b..08cf6b0 100644 --- a/fvcore/common/param_scheduler.py +++ b/fvcore/common/param_scheduler.py @@ -57,9 +57,7 @@ def __init__(self, value: float) -> None: def __call__(self, where: float) -> float: if where >= 1.0: - raise RuntimeError( - f"where in ParamScheduler must be in [0, 1]: got {where}" - ) + raise RuntimeError(f"where in ParamScheduler must be in [0, 1]: got {where}") return self._value @@ -207,9 +205,7 @@ def __init__( if num_updates is None: num_updates, milestones = milestones[-1], milestones[:-1] if num_updates < len(values): - raise ValueError( - "Total num_updates must be greater than length of param schedule" - ) + raise ValueError("Total num_updates must be greater than length of param schedule") self._param_schedule = values self._num_updates = num_updates @@ -233,9 +229,7 @@ def __init__( def __call__(self, where: float) -> float: if where > 1.0: - raise RuntimeError( - f"where in ParamScheduler must be in [0, 1]: got {where}" - ) + raise RuntimeError(f"where in ParamScheduler must be in [0, 1]: got {where}") epoch_num = int((where + self.WHERE_EPSILON) * self._num_updates) return self._param_schedule[bisect.bisect_right(self._milestones, epoch_num)] @@ -293,9 +287,7 @@ def __init__( if num_updates <= 0: raise ValueError("Number of updates must be larger than 0") if not (isinstance(values, Sequence) and len(values) > 0): - raise ValueError( - "Step scheduler requires a list of at least one param value" - ) + raise ValueError("Step scheduler requires a list of at least one param value") self._param_schedule = values def __call__(self, where: float) -> float: @@ -341,9 +333,7 @@ def __init__( for _ in range(num_decays): values.append(values[-1] * gamma) - self._step_param_scheduler = StepParamScheduler( - num_updates=num_updates, values=values - ) + self._step_param_scheduler = StepParamScheduler(num_updates=num_updates, values=values) def __call__(self, where: float) -> float: return self._step_param_scheduler(where) @@ -389,9 +379,7 @@ def __init__( if len(schedulers) != len(lengths): raise ValueError("Schedulers and lengths must be same length") if len(schedulers) == 0: - raise ValueError( - "There must be at least one scheduler in the composite scheduler" - ) + raise ValueError("There must be at least one scheduler in the composite scheduler") if abs(sum(lengths) - 1.0) >= 1e-3: raise ValueError("The sum of all values in lengths must be 1") if sum(lengths) != 1.0: @@ -408,9 +396,7 @@ def __call__(self, where: float) -> float: # Find scheduler corresponding to where i = 0 running_total = self._lengths[i] - while (where + self.WHERE_EPSILON) > running_total and i < len( - self._schedulers - ) - 1: + while (where + self.WHERE_EPSILON) > running_total and i < len(self._schedulers) - 1: i += 1 running_total += self._lengths[i] scheduler = self._schedulers[i] diff --git a/fvcore/common/registry.py b/fvcore/common/registry.py index a0ae0f1..6d318d0 100644 --- a/fvcore/common/registry.py +++ b/fvcore/common/registry.py @@ -42,9 +42,7 @@ def __init__(self, name: str) -> None: def _do_register(self, name: str, obj: Any) -> None: assert ( name not in self._obj_map - ), "An object named '{}' was already registered in '{}' registry!".format( - name, self._name - ) + ), "An object named '{}' was already registered in '{}' registry!".format(name, self._name) self._obj_map[name] = obj def register(self, obj: Any = None) -> Any: @@ -68,9 +66,7 @@ def deco(func_or_class: Any) -> Any: def get(self, name: str) -> Any: ret = self._obj_map.get(name) if ret is None: - raise KeyError( - "No object named '{}' found in '{}' registry!".format(name, self._name) - ) + raise KeyError("No object named '{}' found in '{}' registry!".format(name, self._name)) return ret def __contains__(self, name: str) -> bool: @@ -78,9 +74,7 @@ def __contains__(self, name: str) -> bool: def __repr__(self) -> str: table_headers = ["Names", "Objects"] - table = tabulate( - self._obj_map.items(), headers=table_headers, tablefmt="fancy_grid" - ) + table = tabulate(self._obj_map.items(), headers=table_headers, tablefmt="fancy_grid") return "Registry of {}:\n".format(self._name) + table def __iter__(self) -> Iterator[Tuple[str, Any]]: diff --git a/fvcore/nn/distributed.py b/fvcore/nn/distributed.py index 4852d07..26b190f 100644 --- a/fvcore/nn/distributed.py +++ b/fvcore/nn/distributed.py @@ -27,11 +27,7 @@ def differentiable_all_reduce(input: torch.Tensor) -> torch.Tensor: """ Differentiable counterpart of `dist.all_reduce`. """ - if ( - not dist.is_available() - or not dist.is_initialized() - or dist.get_world_size() == 1 - ): + if not dist.is_available() or not dist.is_initialized() or dist.get_world_size() == 1: return input return _AllReduce.apply(input) @@ -54,10 +50,6 @@ def differentiable_all_gather(input: torch.Tensor) -> List[torch.Tensor]: """ Differentiable counterpart of `dist.all_gather`. """ - if ( - not dist.is_available() - or not dist.is_initialized() - or dist.get_world_size() == 1 - ): + if not dist.is_available() or not dist.is_initialized() or dist.get_world_size() == 1: return [input] return list(_AllGather.apply(input)) diff --git a/fvcore/nn/focal_loss.py b/fvcore/nn/focal_loss.py index b60250f..f86e955 100644 --- a/fvcore/nn/focal_loss.py +++ b/fvcore/nn/focal_loss.py @@ -94,6 +94,4 @@ def sigmoid_focal_loss_star( return loss -sigmoid_focal_loss_star_jit: "torch.jit.ScriptModule" = torch.jit.script( - sigmoid_focal_loss_star -) +sigmoid_focal_loss_star_jit: "torch.jit.ScriptModule" = torch.jit.script(sigmoid_focal_loss_star) diff --git a/fvcore/nn/jit_analysis.py b/fvcore/nn/jit_analysis.py index c59f4b5..989bd40 100644 --- a/fvcore/nn/jit_analysis.py +++ b/fvcore/nn/jit_analysis.py @@ -161,9 +161,7 @@ def register_hooks(mod: nn.Module, name: str) -> None: hook_handles.append(posthook) # Unwrap DDP, but correct the scope names for the root module. - if isinstance( - module, (nn.parallel.distributed.DistributedDataParallel, nn.DataParallel) - ): + if isinstance(module, (nn.parallel.distributed.DistributedDataParallel, nn.DataParallel)): # Since DataParallel just wraps the model, add an extra set of hooks # to the model it wraps to account for the wrapper. Then trace it. root_name = aliases[module] @@ -310,8 +308,7 @@ def unsupported_ops(self, module_name: str = "") -> typing.Counter[str]: """ if self._stats is None: raise RuntimeError( - "Analysis results should be computed " - "before calling unsupported_ops()" + "Analysis results should be computed " "before calling unsupported_ops()" ) module_name = self.canonical_module_name(module_name) return self._stats.unsupported_ops[module_name] # pyre-fixme @@ -354,9 +351,7 @@ def set_op_handle(self, *args, **kwargs: Optional[Handle]) -> "JitModelAnalysis" """ self._stats = None if len(args) % 2 != 0: - raise TypeError( - "set_op_handle should be called with pairs of names and handles!" - ) + raise TypeError("set_op_handle should be called with pairs of names and handles!") for name, handle in zip(args[::2], args[1::2]): kwargs[name] = handle for name, handle in kwargs.items(): @@ -393,8 +388,7 @@ def canonical_module_name(self, name: str) -> str: return self._aliases[name] else: raise KeyError( - "Requested module name is not among " - "the descendants of the analyzed model." + "Requested module name is not among " "the descendants of the analyzed model." ) def copy( @@ -497,9 +491,7 @@ def _warn_unsupported_ops(self, ops: typing.Counter[str]) -> None: return logger = logging.getLogger(__name__) for op, freq in ops.items(): - logger.warning( - "Unsupported operator {} encountered {} time(s)".format(op, freq) - ) + logger.warning("Unsupported operator {} encountered {} time(s)".format(op, freq)) def _warn_uncalled_mods(self, uncalled_mods: Set[str]) -> None: if not self._enable_warn_uncalled_mods: diff --git a/fvcore/nn/jit_handles.py b/fvcore/nn/jit_handles.py index 747205c..796f4cf 100644 --- a/fvcore/nn/jit_handles.py +++ b/fvcore/nn/jit_handles.py @@ -62,9 +62,7 @@ def generic_activation_jit(op_name: Optional[str] = None) -> Handle: Callable: An activation handle for the given operation. """ - def _generic_activation_jit( - i: Any, outputs: List[Any] - ) -> Union[typing.Counter[str], Number]: + def _generic_activation_jit(i: Any, outputs: List[Any]) -> Union[typing.Counter[str], Number]: """ This is a generic jit handle that counts the number of activations for any operation given the output shape. @@ -166,9 +164,7 @@ def conv_flop_jit(inputs: List[Any], outputs: List[Any]) -> typing.Counter[str]: transposed = inputs[6].toIValue() # use a custom name instead of "_convolution" - return Counter( - {"conv": conv_flop_count(x_shape, w_shape, out_shape, transposed=transposed)} - ) + return Counter({"conv": conv_flop_count(x_shape, w_shape, out_shape, transposed=transposed)}) def einsum_flop_jit(inputs: List[Any], outputs: List[Any]) -> Number: diff --git a/fvcore/nn/parameter_count.py b/fvcore/nn/parameter_count.py index b5a3193..c638350 100644 --- a/fvcore/nn/parameter_count.py +++ b/fvcore/nn/parameter_count.py @@ -113,8 +113,6 @@ def fill(lvl: int, prefix: str) -> None: old_ws = tabulate.PRESERVE_WHITESPACE tabulate.PRESERVE_WHITESPACE = True - tab = tabulate.tabulate( - table, headers=["name", "#elements or shape"], tablefmt="pipe" - ) + tab = tabulate.tabulate(table, headers=["name", "#elements or shape"], tablefmt="pipe") tabulate.PRESERVE_WHITESPACE = old_ws return tab diff --git a/fvcore/nn/precise_bn.py b/fvcore/nn/precise_bn.py index 012fcc5..b745543 100644 --- a/fvcore/nn/precise_bn.py +++ b/fvcore/nn/precise_bn.py @@ -43,9 +43,7 @@ def __init__(self, mean_buffer: torch.Tensor, var_buffer: torch.Tensor) -> None: self.pop_var: torch.Tensor = torch.zeros_like(var_buffer) self.ind = 0 - def update( - self, batch_mean: torch.Tensor, batch_var: torch.Tensor, batch_size: int - ) -> None: + def update(self, batch_mean: torch.Tensor, batch_var: torch.Tensor, batch_size: int) -> None: self.ind += 1 self.pop_mean += (batch_mean - self.pop_mean) / self.ind self.pop_var += (batch_var - self.pop_var) / self.ind @@ -70,17 +68,11 @@ def __init__(self, mean_buffer: torch.Tensor, var_buffer: torch.Tensor) -> None: self.pop_square_mean: torch.Tensor = torch.zeros_like(var_buffer) self.tot = 0 - def update( - self, batch_mean: torch.Tensor, batch_var: torch.Tensor, batch_size: int - ) -> None: + def update(self, batch_mean: torch.Tensor, batch_var: torch.Tensor, batch_size: int) -> None: self.tot += batch_size - batch_square_mean = batch_mean.square() + batch_var * ( - (batch_size - 1) / batch_size - ) + batch_square_mean = batch_mean.square() + batch_var * ((batch_size - 1) / batch_size) self.pop_mean += (batch_mean - self.pop_mean) * (batch_size / self.tot) - self.pop_square_mean += (batch_square_mean - self.pop_square_mean) * ( - batch_size / self.tot - ) + self.pop_square_mean += (batch_square_mean - self.pop_square_mean) * (batch_size / self.tot) @property def pop_var(self) -> torch.Tensor: @@ -145,22 +137,15 @@ def get_bn_batch_size_hook( module not in batch_size_per_bn_layer ), "Some BN layers are reused. This is not supported and probably not desired." x = input[0] - assert isinstance( - x, torch.Tensor - ), f"BN layer should take tensor as input. Got {input}" + assert isinstance(x, torch.Tensor), f"BN layer should take tensor as input. Got {input}" # consider spatial dimensions as batch as well batch_size = x.numel() // x.shape[1] batch_size_per_bn_layer[module] = batch_size return (x,) - hooks_to_remove = [ - bn.register_forward_pre_hook(get_bn_batch_size_hook) for bn in bn_layers - ] + hooks_to_remove = [bn.register_forward_pre_hook(get_bn_batch_size_hook) for bn in bn_layers] - estimators = [ - _PopulationVarianceEstimator(bn.running_mean, bn.running_var) - for bn in bn_layers - ] + estimators = [_PopulationVarianceEstimator(bn.running_mean, bn.running_var) for bn in bn_layers] ind = -1 for inputs in tqdm.tqdm( @@ -205,7 +190,5 @@ def get_bn_modules(model: nn.Module) -> List[nn.Module]: list[nn.Module]: all BN modules in the model. """ # Finds all the bn layers. - bn_layers = [ - m for m in model.modules() if m.training and isinstance(m, BN_MODULE_TYPES) - ] + bn_layers = [m for m in model.modules() if m.training and isinstance(m, BN_MODULE_TYPES)] return bn_layers diff --git a/fvcore/nn/print_model_statistics.py b/fvcore/nn/print_model_statistics.py index 5c45d28..10d1bbc 100644 --- a/fvcore/nn/print_model_statistics.py +++ b/fvcore/nn/print_model_statistics.py @@ -70,15 +70,11 @@ def _pretty_statistics( """ out_stats = {} for mod, stats in statistics.items(): - out_stats[mod] = { - s: _format_size(val, sig_figs, hide_zero) for s, val in stats.items() - } + out_stats[mod] = {s: _format_size(val, sig_figs, hide_zero) for s, val in stats.items()} return out_stats -def _group_by_module( - statistics: Dict[str, Dict[str, Any]] -) -> Dict[str, Dict[str, Any]]: +def _group_by_module(statistics: Dict[str, Dict[str, Any]]) -> Dict[str, Dict[str, Any]]: """ Converts statistics organized first by statistic type and then by module to statistics organized first by module and then by statistic type. @@ -407,9 +403,7 @@ def flop_count_str( stats = _pretty_statistics(stats, sig_figs=2) stats = _indicate_uncalled_modules(stats, "#flops", flops.uncalled_modules()) if activations is not None: - stats = _indicate_uncalled_modules( - stats, "#acts", activations.uncalled_modules() - ) + stats = _indicate_uncalled_modules(stats, "#acts", activations.uncalled_modules()) model_string = "" if all_uncalled: @@ -425,9 +419,7 @@ def flop_count_str( ### Table Printing ### -def _get_single_child( - name: str, statistics: Dict[str, Dict[str, str]] -) -> Optional[str]: +def _get_single_child(name: str, statistics: Dict[str, Dict[str, str]]) -> Optional[str]: """ If the given module has only a single child in statistics, return it. Otherwise, return None. @@ -444,9 +436,7 @@ def _get_single_child( return child -def _try_combine( - stats1: Dict[str, str], stats2: Dict[str, str] -) -> Optional[Dict[str, str]]: +def _try_combine(stats1: Dict[str, str], stats2: Dict[str, str]) -> Optional[Dict[str, str]]: """ Try combine two statistics dict to display in one row. If they conflict, returns None. @@ -462,9 +452,7 @@ def _try_combine( return ret -def _fastforward( - name: str, statistics: Dict[str, Dict[str, str]] -) -> Tuple[str, Dict[str, str]]: +def _fastforward(name: str, statistics: Dict[str, Dict[str, str]]) -> Tuple[str, Dict[str, str]]: """ If the given module has only a single child and matches statistics with that child, merge statistics and their names into one row. diff --git a/fvcore/nn/squeeze_excitation.py b/fvcore/nn/squeeze_excitation.py index 42227d4..c7d4e9a 100644 --- a/fvcore/nn/squeeze_excitation.py +++ b/fvcore/nn/squeeze_excitation.py @@ -43,19 +43,11 @@ def __init__( activation = nn.ReLU() if is_3d: - conv1 = nn.Conv3d( - num_channels, num_channels_reduced, kernel_size=1, bias=True - ) - conv2 = nn.Conv3d( - num_channels_reduced, num_channels, kernel_size=1, bias=True - ) + conv1 = nn.Conv3d(num_channels, num_channels_reduced, kernel_size=1, bias=True) + conv2 = nn.Conv3d(num_channels_reduced, num_channels, kernel_size=1, bias=True) else: - conv1 = nn.Conv2d( - num_channels, num_channels_reduced, kernel_size=1, bias=True - ) - conv2 = nn.Conv2d( - num_channels_reduced, num_channels, kernel_size=1, bias=True - ) + conv1 = nn.Conv2d(num_channels, num_channels_reduced, kernel_size=1, bias=True) + conv2 = nn.Conv2d(num_channels_reduced, num_channels, kernel_size=1, bias=True) self.is_3d = is_3d self.block = nn.Sequential( @@ -168,8 +160,6 @@ def forward(self, input_tensor: torch.Tensor) -> torch.Tensor: For 3d X, shape = (batch_size, num_channels, T, H, W) output tensor """ - output_tensor = torch.max( - self.channel(input_tensor), self.spatial(input_tensor) - ) + output_tensor = torch.max(self.channel(input_tensor), self.spatial(input_tensor)) return output_tensor diff --git a/fvcore/transforms/transform.py b/fvcore/transforms/transform.py index f20560c..51820c7 100644 --- a/fvcore/transforms/transform.py +++ b/fvcore/transforms/transform.py @@ -189,9 +189,7 @@ def wrapper(decorated_func): assert callable( func - ), "You can only register a callable to a Transform. Got {} instead.".format( - func - ) + ), "You can only register a callable to a Transform. Got {} instead.".format(func) argspec = inspect.getfullargspec(func) assert len(argspec.args) == 2, ( "You can only register a function that takes two positional " @@ -224,14 +222,11 @@ def __repr__(self): argstr = [] for name, param in sig.parameters.items(): assert ( - param.kind != param.VAR_POSITIONAL - and param.kind != param.VAR_KEYWORD + param.kind != param.VAR_POSITIONAL and param.kind != param.VAR_KEYWORD ), "The default __repr__ doesn't support *args or **kwargs" assert hasattr(self, name), ( "Attribute {} not found! " - "Default __repr__ only works if attributes match the constructor.".format( - name - ) + "Default __repr__ only works if attributes match the constructor.".format(name) ) attr = getattr(self, name) default = param.default @@ -528,9 +523,9 @@ def apply_image(self, img: np.ndarray, interp: str = None) -> np.ndarray: h, w = img.shape[:2] else: raise ("Unsupported input with shape of {}".format(img.shape)) - assert ( - self.h == h and self.w == w - ), "Input size mismatch h w {}:{} -> {}:{}".format(self.h, self.w, h, w) + assert self.h == h and self.w == w, "Input size mismatch h w {}:{} -> {}:{}".format( + self.h, self.w, h, w + ) interp_method = interp if interp is not None else self.interp # Option of align_corners is only supported for linear, bilinear, # and bicubic. @@ -704,9 +699,7 @@ def apply_polygons(self, polygons: list) -> list: import shapely.geometry as geometry # Create a window that will be used to crop - crop_box = geometry.box( - self.x0, self.y0, self.x0 + self.w, self.y0 + self.h - ).buffer(0.0) + crop_box = geometry.box(self.x0, self.y0, self.x0 + self.w, self.y0 + self.h).buffer(0.0) cropped_polygons = [] @@ -741,9 +734,7 @@ def inverse(self) -> Transform: ), "orig_w, orig_h are required for CropTransform to be invertible!" pad_x1 = self.orig_w - self.x0 - self.w pad_y1 = self.orig_h - self.y0 - self.h - return PadTransform( - self.x0, self.y0, pad_x1, pad_y1, orig_w=self.w, orig_h=self.h - ) + return PadTransform(self.x0, self.y0, pad_x1, pad_y1, orig_w=self.w, orig_h=self.h) class PadTransform(Transform): @@ -805,9 +796,7 @@ def inverse(self) -> Transform: ), "orig_w, orig_h are required for PadTransform to be invertible!" neww = self.orig_w + self.x0 + self.x1 newh = self.orig_h + self.y0 + self.y1 - return CropTransform( - self.x0, self.y0, self.orig_w, self.orig_h, orig_w=neww, orig_h=newh - ) + return CropTransform(self.x0, self.y0, self.orig_w, self.orig_h, orig_w=neww, orig_h=newh) class BlendTransform(Transform): diff --git a/fvcore/transforms/transform_util.py b/fvcore/transforms/transform_util.py index 74a6bfc..9377db8 100644 --- a/fvcore/transforms/transform_util.py +++ b/fvcore/transforms/transform_util.py @@ -38,15 +38,11 @@ def to_float_tensor(numpy_array: np.ndarray) -> torch.Tensor: # NxHxWxC -> NxCxHxW float_tensor = float_tensor.permute(0, 3, 1, 2) else: - raise NotImplementedError( - "Unknow numpy_array dimension of {}".format(float_tensor.shape) - ) + raise NotImplementedError("Unknow numpy_array dimension of {}".format(float_tensor.shape)) return float_tensor -def to_numpy( - float_tensor: torch.Tensor, target_shape: list, target_dtype: np.dtype -) -> np.ndarray: +def to_numpy(float_tensor: torch.Tensor, target_shape: list, target_dtype: np.dtype) -> np.ndarray: """ Convert float tensor with dimension of NxCxHxW back to numpy array. Args: @@ -74,9 +70,7 @@ def to_numpy( # NxCxHxW -> NxHxWxC float_tensor = float_tensor.permute(0, 2, 3, 1) else: - raise NotImplementedError( - "Unknow target shape dimension of {}".format(target_shape) - ) + raise NotImplementedError("Unknow target shape dimension of {}".format(target_shape)) if target_dtype == np.uint8: # Need to specifically call round here, notice in pytroch the round # is half to even. diff --git a/io_tests/test_file_io.py b/io_tests/test_file_io.py index 9f47674..9263281 100644 --- a/io_tests/test_file_io.py +++ b/io_tests/test_file_io.py @@ -201,9 +201,7 @@ def test_open_writes(self) -> None: def test_bad_args(self) -> None: with self.assertRaises(NotImplementedError): - PathManager.copy( - self._remote_uri, self._remote_uri, foo="foo" # type: ignore - ) + PathManager.copy(self._remote_uri, self._remote_uri, foo="foo") # type: ignore with self.assertRaises(NotImplementedError): PathManager.exists(self._remote_uri, foo="foo") # type: ignore with self.assertRaises(ValueError): diff --git a/linter.sh b/linter.sh index cebc3a7..7d658f4 100755 --- a/linter.sh +++ b/linter.sh @@ -14,7 +14,7 @@ echo "Running isort..." isort --sp . . echo "Running black..." -black . +black -l 100 . echo "Running flake8..." if [ -x "$(command -v flake8)" ]; then diff --git a/setup.py b/setup.py index 7a84a43..e946e1c 100755 --- a/setup.py +++ b/setup.py @@ -8,9 +8,7 @@ def get_version(): - init_py_path = path.join( - path.abspath(path.dirname(__file__)), "fvcore", "__init__.py" - ) + init_py_path = path.join(path.abspath(path.dirname(__file__)), "fvcore", "__init__.py") init_py = open(init_py_path, "r").readlines() version_line = [l.strip() for l in init_py if l.startswith("__version__")][0] version = version_line.split("=")[-1].strip().strip("'\"") diff --git a/tests/bm_focal_loss.py b/tests/bm_focal_loss.py index 06afd57..8dc3a52 100644 --- a/tests/bm_focal_loss.py +++ b/tests/bm_focal_loss.py @@ -19,9 +19,7 @@ def bm_focal_loss() -> None: {"N": 10000}, {"N": 10000, "alpha": 0}, ] - benchmark( - TestFocalLoss.focal_loss_with_init, "Focal_loss", kwargs_list, warmup_iters=1 - ) + benchmark(TestFocalLoss.focal_loss_with_init, "Focal_loss", kwargs_list, warmup_iters=1) benchmark( TestFocalLoss.focal_loss_jit_with_init, "Focal_loss_JIT", diff --git a/tests/bm_main.py b/tests/bm_main.py index 8ff46aa..0c4d166 100755 --- a/tests/bm_main.py +++ b/tests/bm_main.py @@ -15,9 +15,7 @@ # Get all the benchmark files (starting with "bm_"). bm_files = glob.glob(join(dirname(__file__), "bm_*.py")) # pyre-ignore module_names = [ - basename(f)[:-3] - for f in bm_files - if isfile(f) and not f.endswith("bm_main.py") + basename(f)[:-3] for f in bm_files if isfile(f) and not f.endswith("bm_main.py") ] for module_name in module_names: diff --git a/tests/param_scheduler/test_scheduler_composite.py b/tests/param_scheduler/test_scheduler_composite.py index 730f61a..7bbefcf 100644 --- a/tests/param_scheduler/test_scheduler_composite.py +++ b/tests/param_scheduler/test_scheduler_composite.py @@ -95,8 +95,7 @@ def test_long_scheduler(self): scheduler = CompositeParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) - for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) ] expected_schedule = [0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.3, 0.4, 0.4, 0.4] @@ -106,8 +105,7 @@ def test_scheduler_lengths_within_epsilon_of_one(self): config = self._get_lengths_sum_less_one_config() scheduler = CompositeParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) - for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) ] expected_schedule = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2] self.assertEqual(schedule, expected_schedule) @@ -171,8 +169,7 @@ def test_linear_scheduler_no_gaps(self): # Check rescaled scheduler = CompositeParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) - for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) ] expected_schedule = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] self.assertEqual(expected_schedule, schedule) @@ -183,8 +180,7 @@ def test_linear_scheduler_no_gaps(self): scheduler = CompositeParamScheduler(**config) linear_scheduler = config["schedulers"][0] schedule = [ - scheduler(epoch_num / self._num_updates) - for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) ] expected_schedule = [ linear_scheduler(epoch_num / self._num_updates) diff --git a/tests/param_scheduler/test_scheduler_constant.py b/tests/param_scheduler/test_scheduler_constant.py index 5a63bb1..3d25bd8 100644 --- a/tests/param_scheduler/test_scheduler_constant.py +++ b/tests/param_scheduler/test_scheduler_constant.py @@ -11,8 +11,7 @@ class TestConstantScheduler(unittest.TestCase): def test_scheduler(self): scheduler = ConstantParamScheduler(0.1) schedule = [ - scheduler(epoch_num / self._num_epochs) - for epoch_num in range(self._num_epochs) + scheduler(epoch_num / self._num_epochs) for epoch_num in range(self._num_epochs) ] expected_schedule = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] diff --git a/tests/param_scheduler/test_scheduler_exponential.py b/tests/param_scheduler/test_scheduler_exponential.py index 4c94b97..08efefa 100644 --- a/tests/param_scheduler/test_scheduler_exponential.py +++ b/tests/param_scheduler/test_scheduler_exponential.py @@ -22,8 +22,6 @@ def test_scheduler(self): round(scheduler(epoch_num / self._num_epochs), 4) for epoch_num in range(self._num_epochs) ] - expected_schedule = [ - config["start_value"] - ] + self._get_valid_intermediate_values() + expected_schedule = [config["start_value"]] + self._get_valid_intermediate_values() self.assertEqual(schedule, expected_schedule) diff --git a/tests/param_scheduler/test_scheduler_linear.py b/tests/param_scheduler/test_scheduler_linear.py index 2eb8e41..547b237 100644 --- a/tests/param_scheduler/test_scheduler_linear.py +++ b/tests/param_scheduler/test_scheduler_linear.py @@ -35,7 +35,5 @@ def test_scheduler(self): round(scheduler(epoch_num / self._num_epochs), 4) for epoch_num in range(self._num_epochs) ] - expected_schedule = [config["start_value"]] + list( - reversed(self._get_valid_intermediate()) - ) + expected_schedule = [config["start_value"]] + list(reversed(self._get_valid_intermediate())) self.assertEqual(schedule, expected_schedule) diff --git a/tests/param_scheduler/test_scheduler_multi_step.py b/tests/param_scheduler/test_scheduler_multi_step.py index c3462da..349f579 100644 --- a/tests/param_scheduler/test_scheduler_multi_step.py +++ b/tests/param_scheduler/test_scheduler_multi_step.py @@ -62,8 +62,7 @@ def test_invalid_config(self): def _test_config_scheduler(self, config, expected_schedule): scheduler = MultiStepParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) - for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) ] self.assertEqual(schedule, expected_schedule) diff --git a/tests/param_scheduler/test_scheduler_step.py b/tests/param_scheduler/test_scheduler_step.py index 979c9f2..19aa388 100644 --- a/tests/param_scheduler/test_scheduler_step.py +++ b/tests/param_scheduler/test_scheduler_step.py @@ -38,8 +38,7 @@ def test_scheduler(self): scheduler = StepParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) - for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) ] expected_schedule = [ 0.1, diff --git a/tests/param_scheduler/test_scheduler_step_with_fixed_gamma.py b/tests/param_scheduler/test_scheduler_step_with_fixed_gamma.py index d22c56c..cca4f70 100644 --- a/tests/param_scheduler/test_scheduler_step_with_fixed_gamma.py +++ b/tests/param_scheduler/test_scheduler_step_with_fixed_gamma.py @@ -48,8 +48,7 @@ def test_scheduler(self): scheduler = StepWithFixedGammaParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) - for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) ] expected_schedule = [ 1, diff --git a/tests/test_activation_count.py b/tests/test_activation_count.py index 1931114..01699ea 100644 --- a/tests/test_activation_count.py +++ b/tests/test_activation_count.py @@ -96,9 +96,7 @@ def test_linear(self) -> None: gt_count = batch_size * output_dim gt_dict = defaultdict(float) gt_dict[self.lin_op] = gt_count / 1e6 - self.assertEquals( - gt_dict, ac_dict, "FC layer failed to pass the activation count test." - ) + self.assertEquals(gt_dict, ac_dict, "FC layer failed to pass the activation count test.") def test_supported_ops(self) -> None: """ diff --git a/tests/test_checkpoint.py b/tests/test_checkpoint.py index 34cd4b5..3a47571 100644 --- a/tests/test_checkpoint.py +++ b/tests/test_checkpoint.py @@ -139,9 +139,7 @@ def test_from_last_checkpoint_model(self) -> None: ) fresh_checkpointer.load(fresh_checkpointer.get_checkpoint_file()) - for trained_p, loaded_p in zip( - trained_model.parameters(), fresh_model.parameters() - ): + for trained_p, loaded_p in zip(trained_model.parameters(), fresh_model.parameters()): # different tensor references self.assertFalse(id(trained_p) == id(loaded_p)) # same content @@ -161,9 +159,7 @@ def test_from_name_file_model(self) -> None: ), ]: with TemporaryDirectory() as f: - checkpointer = Checkpointer( - trained_model, save_dir=f, save_to_disk=True - ) + checkpointer = Checkpointer(trained_model, save_dir=f, save_to_disk=True) checkpointer.save("checkpoint_file") # on different folders. @@ -173,9 +169,7 @@ def test_from_name_file_model(self) -> None: self.assertEqual(fresh_checkpointer.get_checkpoint_file(), "") fresh_checkpointer.load(os.path.join(f, "checkpoint_file.pth")) - for trained_p, loaded_p in zip( - trained_model.parameters(), fresh_model.parameters() - ): + for trained_p, loaded_p in zip(trained_model.parameters(), fresh_model.parameters()): # different tensor references. self.assertFalse(id(trained_p) == id(loaded_p)) # same content. @@ -193,9 +187,7 @@ class CheckpointableObj: """ def __init__(self): - self.state = { - self.random_handle(): self.random_handle() for i in range(10) - } + self.state = {self.random_handle(): self.random_handle() for i in range(10)} def random_handle(self, str_len=100) -> str: """ @@ -241,9 +233,7 @@ def load_state_dict(self, state) -> None: fresh_checkpointer.get_checkpoint_file(), os.path.join(f, "checkpoint_file.pth"), ) - checkpoint = fresh_checkpointer.load( - fresh_checkpointer.get_checkpoint_file() - ) + checkpoint = fresh_checkpointer.load(fresh_checkpointer.get_checkpoint_file()) state_dict = checkpointables.state_dict() for key, _ in state_dict.items(): self.assertTrue(checkpoint["checkpointables"].get(key) is not None) @@ -271,9 +261,7 @@ def __init__(self, has_y: bool) -> None: ) logger.info.assert_not_called() - @unittest.skipIf( # pyre-fixme[56] - not hasattr(nn, "LazyLinear"), "LazyModule not supported" - ) + @unittest.skipIf(not hasattr(nn, "LazyLinear"), "LazyModule not supported") # pyre-fixme[56] def test_load_lazy_module(self) -> None: def _get_model() -> nn.Sequential: return nn.Sequential(nn.LazyLinear(10)) @@ -313,9 +301,7 @@ def test_periodic_checkpointer(self) -> None: nn.DataParallel(self._create_model()), ]: with TemporaryDirectory() as f: - checkpointer = Checkpointer( - trained_model, save_dir=f, save_to_disk=True - ) + checkpointer = Checkpointer(trained_model, save_dir=f, save_to_disk=True) periodic_checkpointer = PeriodicCheckpointer(checkpointer, _period, 99) for iteration in range(_max_iter): periodic_checkpointer.step(iteration) @@ -337,9 +323,7 @@ def test_periodic_checkpointer_max_to_keep(self) -> None: nn.DataParallel(self._create_model()), ]: with TemporaryDirectory() as f: - checkpointer = Checkpointer( - trained_model, save_dir=f, save_to_disk=True - ) + checkpointer = Checkpointer(trained_model, save_dir=f, save_to_disk=True) periodic_checkpointer = PeriodicCheckpointer( checkpointer, _period, 99, max_to_keep=_max_to_keep ) diff --git a/tests/test_common.py b/tests/test_common.py index a51dfda..7e1ea48 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -51,9 +51,7 @@ def test_buffer(self) -> None: for _ in range(num_iters): gt_len = 1000 buffer_len = np.random.randint(1, gt_len) - create_buffer = TestHistoryBuffer.create_buffer_with_init( - gt_len, buffer_len - ) + create_buffer = TestHistoryBuffer.create_buffer_with_init(gt_len, buffer_len) buf, gt = create_buffer() # pyre-ignore values, iterations = zip(*buf.values()) @@ -199,9 +197,7 @@ def test_setattr(self) -> None: cfg.COMPUTED_1 = "computed1" with self.assertRaises(KeyError) as err: cfg.COMPUTED_1 = "update_computed1" - self.assertTrue( - "Computed attributed 'COMPUTED_1' already exists" in str(err.exception) - ) + self.assertTrue("Computed attributed 'COMPUTED_1' already exists" in str(err.exception)) # Resetting the same value should be safe: cfg.COMPUTED_1 = "computed1" @@ -230,11 +226,8 @@ class Object1: with self.assertRaises(KeyError) as err: OBJECT_REGISTRY.get("Object2") self.assertTrue( - "No object named 'Object2' found in 'OBJECT' registry!" - in str(err.exception) + "No object named 'Object2' found in 'OBJECT' registry!" in str(err.exception) ) items = list(OBJECT_REGISTRY) - self.assertListEqual( - items, [("Object1", Object1)], "Registry iterable contains valid item" - ) + self.assertListEqual(items, [("Object1", Object1)], "Registry iterable contains valid item") diff --git a/tests/test_flop_count.py b/tests/test_flop_count.py index ed7afd6..6ef9a1c 100644 --- a/tests/test_flop_count.py +++ b/tests/test_flop_count.py @@ -231,9 +231,7 @@ def addmm_dummy_flop_jit( flop_dict[self.lin_op] = 400000 return flop_dict - custom_ops2: Dict[str, Handle] = { - "aten::{}".format(self.lin_op): addmm_dummy_flop_jit - } + custom_ops2: Dict[str, Handle] = {"aten::{}".format(self.lin_op): addmm_dummy_flop_jit} flop_dict2, _ = flop_count(customNet, (x,), supported_ops=custom_ops2) flop = 400000 / 1e9 self.assertEqual( @@ -255,9 +253,7 @@ def test_nn(self) -> None: gt_flop = batch_size * input_dim * output_dim / 1e9 gt_dict = defaultdict(float) gt_dict[self.lin_op] = gt_flop - self.assertDictEqual( - flop_dict, gt_dict, "nn.Linear failed to pass the flop count test." - ) + self.assertDictEqual(flop_dict, gt_dict, "nn.Linear failed to pass the flop count test.") def test_skip_ops(self) -> None: """ @@ -350,9 +346,7 @@ def _test_conv( elif conv_dim == 2: x = torch.randn(batch_size, input_dim, spatial_dim, spatial_dim) else: - x = torch.randn( - batch_size, input_dim, spatial_dim, spatial_dim, spatial_dim - ) + x = torch.randn(batch_size, input_dim, spatial_dim, spatial_dim, spatial_dim) flop_dict, _ = flop_count(convNet, (x,)) if transpose: @@ -721,9 +715,7 @@ def test_batchnorm(self) -> None: gt_flop = batch_size * input_dim / 1e9 gt_dict = defaultdict(float) gt_dict["batch_norm"] = gt_flop - self.assertDictEqual( - flop_dict, gt_dict, "BatchNorm1d failed to pass the flop count test." - ) + self.assertDictEqual(flop_dict, gt_dict, "BatchNorm1d failed to pass the flop count test.") # Test for BatchNorm2d. batch_size = 10 @@ -736,9 +728,7 @@ def test_batchnorm(self) -> None: gt_flop = 4 * batch_size * input_dim * spatial_dim_x * spatial_dim_y / 1e9 gt_dict = defaultdict(float) gt_dict["batch_norm"] = gt_flop - self.assertDictEqual( - flop_dict, gt_dict, "BatchNorm2d failed to pass the flop count test." - ) + self.assertDictEqual(flop_dict, gt_dict, "BatchNorm2d failed to pass the flop count test.") # Test for BatchNorm3d. batch_size = 10 @@ -747,24 +737,12 @@ def test_batchnorm(self) -> None: spatial_dim_y = 5 spatial_dim_z = 5 batch_3d = nn.BatchNorm3d(input_dim, affine=False) - x = torch.randn( - batch_size, input_dim, spatial_dim_x, spatial_dim_y, spatial_dim_z - ) + x = torch.randn(batch_size, input_dim, spatial_dim_x, spatial_dim_y, spatial_dim_z) flop_dict, _ = flop_count(batch_3d, (x,)) - gt_flop = ( - 4 - * batch_size - * input_dim - * spatial_dim_x - * spatial_dim_y - * spatial_dim_z - / 1e9 - ) + gt_flop = 4 * batch_size * input_dim * spatial_dim_x * spatial_dim_y * spatial_dim_z / 1e9 gt_dict = defaultdict(float) gt_dict["batch_norm"] = gt_flop - self.assertDictEqual( - flop_dict, gt_dict, "BatchNorm3d failed to pass the flop count test." - ) + self.assertDictEqual(flop_dict, gt_dict, "BatchNorm3d failed to pass the flop count test.") def test_threeNet(self) -> None: """ @@ -890,14 +868,10 @@ def test_group_norm(self): counter = _DEFAULT_SUPPORTED_OPS[op_name] vec = torch.rand(2) - nodes = self._count_function( - F.group_norm, (torch.rand(2, 2, 2, 2), 2, vec, vec), op_name - ) + nodes = self._count_function(F.group_norm, (torch.rand(2, 2, 2, 2), 2, vec, vec), op_name) self.assertEqual(counter(*nodes), 80) - nodes = self._count_function( - F.group_norm, (torch.rand(2, 2, 2, 2), 2, None, None), op_name - ) + nodes = self._count_function(F.group_norm, (torch.rand(2, 2, 2, 2), 2, None, None), op_name) self.assertEqual(counter(*nodes), 64) def test_upsample(self): @@ -921,9 +895,7 @@ def test_complicated_einsum(self): self.assertEqual(counter(*nodes), 72.0) def test_torch_mm(self): - for op_name, func in zip( - ["aten::mm", "aten::matmul"], [torch.mm, torch.matmul] - ): + for op_name, func in zip(["aten::mm", "aten::matmul"], [torch.mm, torch.matmul]): counter = _DEFAULT_SUPPORTED_OPS[op_name] nodes = self._count_function( diff --git a/tests/test_focal_loss.py b/tests/test_focal_loss.py index ab29ca6..3b69529 100644 --- a/tests/test_focal_loss.py +++ b/tests/test_focal_loss.py @@ -28,21 +28,15 @@ def test_focal_loss_equals_ce_loss(self) -> None: """ No weighting of easy/hard (gamma = 0) or positive/negative (alpha = 0). """ - inputs = logit( - torch.tensor([[[0.95], [0.90], [0.98], [0.99]]], dtype=torch.float32) - ) + inputs = logit(torch.tensor([[[0.95], [0.90], [0.98], [0.99]]], dtype=torch.float32)) targets = torch.tensor([[[1], [1], [1], [1]]], dtype=torch.float32) inputs_fl = inputs.clone().requires_grad_() targets_fl = targets.clone() inputs_ce = inputs.clone().requires_grad_() targets_ce = targets.clone() - focal_loss = sigmoid_focal_loss( - inputs_fl, targets_fl, gamma=0, alpha=-1, reduction="mean" - ) - ce_loss = F.binary_cross_entropy_with_logits( - inputs_ce, targets_ce, reduction="mean" - ) + focal_loss = sigmoid_focal_loss(inputs_fl, targets_fl, gamma=0, alpha=-1, reduction="mean") + ce_loss = F.binary_cross_entropy_with_logits(inputs_ce, targets_ce, reduction="mean") self.assertEqual(ce_loss, focal_loss.data) focal_loss.backward() @@ -69,9 +63,7 @@ def test_easy_ex_focal_loss_weighted_less_than_ce_loss(self) -> None: """ With gamma = 2, alpha = 0.5 loss of easy examples is downweighted. """ - inputs = logit( - torch.tensor([[[0.95], [0.90], [0.6], [0.3]]], dtype=torch.float64) - ) + inputs = logit(torch.tensor([[[0.95], [0.90], [0.6], [0.3]]], dtype=torch.float64)) targets = torch.tensor([[[1], [1], [1], [1]]], dtype=torch.float64) focal_loss = sigmoid_focal_loss(inputs, targets, gamma=2, alpha=0.5) ce_loss = F.binary_cross_entropy_with_logits(inputs, targets, reduction="none") @@ -95,17 +87,11 @@ def test_negatives_ignored_focal_loss(self) -> None: """ With alpha = 1 negative examples have focal loss of 0. """ - inputs = logit( - torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) - ) + inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) - focal_loss = ( - sigmoid_focal_loss(inputs, targets, gamma=2, alpha=1).squeeze().numpy() - ) + focal_loss = sigmoid_focal_loss(inputs, targets, gamma=2, alpha=1).squeeze().numpy() ce_loss = ( - F.binary_cross_entropy_with_logits(inputs, targets, reduction="none") - .squeeze() - .numpy() + F.binary_cross_entropy_with_logits(inputs, targets, reduction="none").squeeze().numpy() ) targets = targets.squeeze().numpy() self.assertTrue(np.all(ce_loss[targets == 0] > 0)) @@ -115,17 +101,11 @@ def test_positives_ignored_focal_loss(self) -> None: """ With alpha = 0 postive examples have focal loss of 0. """ - inputs = logit( - torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) - ) + inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) - focal_loss = ( - sigmoid_focal_loss(inputs, targets, gamma=2, alpha=0).squeeze().numpy() - ) + focal_loss = sigmoid_focal_loss(inputs, targets, gamma=2, alpha=0).squeeze().numpy() ce_loss = ( - F.binary_cross_entropy_with_logits(inputs, targets, reduction="none") - .squeeze() - .numpy() + F.binary_cross_entropy_with_logits(inputs, targets, reduction="none").squeeze().numpy() ) targets = targets.squeeze().numpy() self.assertTrue(np.all(ce_loss[targets == 1] > 0)) @@ -142,9 +122,7 @@ def test_mean_focal_loss_equals_ce_loss(self) -> None: ) ) targets = torch.tensor([[1, 0], [1, 0], [1, 1], [0, 1]], dtype=torch.float32) - focal_loss = sigmoid_focal_loss( - inputs, targets, gamma=0, alpha=-1, reduction="mean" - ) + focal_loss = sigmoid_focal_loss(inputs, targets, gamma=0, alpha=-1, reduction="mean") ce_loss = F.binary_cross_entropy_with_logits(inputs, targets, reduction="mean") self.assertEqual(ce_loss, focal_loss) @@ -152,13 +130,9 @@ def test_sum_focal_loss_equals_ce_loss(self) -> None: """ Sum of focal loss across all examples matches ce loss. """ - inputs = logit( - torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) - ) + inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) - focal_loss = sigmoid_focal_loss( - inputs, targets, gamma=0, alpha=-1, reduction="sum" - ) + focal_loss = sigmoid_focal_loss(inputs, targets, gamma=0, alpha=-1, reduction="sum") ce_loss = F.binary_cross_entropy_with_logits(inputs, targets, reduction="sum") self.assertEqual(ce_loss, focal_loss) @@ -183,9 +157,7 @@ def test_focal_loss_equals_ce_loss_multi_class(self) -> None: [[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]], dtype=torch.float32, ) - focal_loss = sigmoid_focal_loss( - inputs, targets, gamma=0, alpha=-1, reduction="mean" - ) + focal_loss = sigmoid_focal_loss(inputs, targets, gamma=0, alpha=-1, reduction="mean") ce_loss = F.binary_cross_entropy_with_logits(inputs, targets, reduction="mean") self.assertEqual(ce_loss, focal_loss) @@ -201,44 +173,32 @@ def test_focal_loss_equals_ce_loss_jit(self) -> None: inputs = logit(torch.rand(N)).to(device) targets = torch.randint(0, 2, (N,)).float().to(device) focal_loss = sigmoid_focal_loss_jit(inputs, targets, gamma=0, alpha=-1) - ce_loss = F.binary_cross_entropy_with_logits( - inputs.cpu(), targets.cpu(), reduction="none" - ) + ce_loss = F.binary_cross_entropy_with_logits(inputs.cpu(), targets.cpu(), reduction="none") self.assertTrue(np.allclose(ce_loss, focal_loss.cpu())) @staticmethod def focal_loss_with_init(N: int, alpha: float = -1) -> typing.Callable[[], None]: device = torch.device("cuda:0") inputs: torch.Tensor = logit(torch.rand(N)).to(device).requires_grad_() - targets: torch.Tensor = ( - torch.randint(0, 2, (N,)).float().to(device).requires_grad_() - ) + targets: torch.Tensor = torch.randint(0, 2, (N,)).float().to(device).requires_grad_() torch.cuda.synchronize() def run_focal_loss() -> None: - fl = sigmoid_focal_loss( - inputs, targets, gamma=0, alpha=alpha, reduction="mean" - ) + fl = sigmoid_focal_loss(inputs, targets, gamma=0, alpha=alpha, reduction="mean") fl.backward() torch.cuda.synchronize() return run_focal_loss @staticmethod - def focal_loss_jit_with_init( - N: int, alpha: float = -1 - ) -> typing.Callable[[], None]: + def focal_loss_jit_with_init(N: int, alpha: float = -1) -> typing.Callable[[], None]: device = torch.device("cuda:0") inputs: torch.Tensor = logit(torch.rand(N)).to(device).requires_grad_() - targets: torch.Tensor = ( - torch.randint(0, 2, (N,)).float().to(device).requires_grad_() - ) + targets: torch.Tensor = torch.randint(0, 2, (N,)).float().to(device).requires_grad_() torch.cuda.synchronize() def run_focal_loss_jit() -> None: - fl = sigmoid_focal_loss_jit( - inputs, targets, gamma=0, alpha=alpha, reduction="mean" - ) + fl = sigmoid_focal_loss_jit(inputs, targets, gamma=0, alpha=alpha, reduction="mean") fl.backward() torch.cuda.synchronize() @@ -254,9 +214,7 @@ def test_focal_loss_star_equals_ce_loss(self) -> None: """ No weighting of easy/hard (gamma = 1) or positive/negative (alpha = -1). """ - inputs = logit( - torch.tensor([[[0.95], [0.90], [0.98], [0.99]]], dtype=torch.float32) - ) + inputs = logit(torch.tensor([[[0.95], [0.90], [0.98], [0.99]]], dtype=torch.float32)) targets = torch.tensor([[[1], [1], [1], [1]]], dtype=torch.float32) inputs_fl = inputs.clone().requires_grad_() targets_fl = targets.clone() @@ -266,9 +224,7 @@ def test_focal_loss_star_equals_ce_loss(self) -> None: focal_loss_star = sigmoid_focal_loss_star( inputs_fl, targets_fl, gamma=1, alpha=-1, reduction="mean" ) - ce_loss = F.binary_cross_entropy_with_logits( - inputs_ce, targets_ce, reduction="mean" - ) + ce_loss = F.binary_cross_entropy_with_logits(inputs_ce, targets_ce, reduction="mean") self.assertEqual(ce_loss, focal_loss_star.data) focal_loss_star.backward() @@ -316,17 +272,13 @@ def test_negatives_ignored_focal_loss_star(self) -> None: """ With alpha = 1 negative examples have focal loss of 0. """ - inputs = logit( - torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) - ) + inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) focal_loss_star = ( sigmoid_focal_loss_star(inputs, targets, gamma=3, alpha=1).squeeze().numpy() ) ce_loss = ( - F.binary_cross_entropy_with_logits(inputs, targets, reduction="none") - .squeeze() - .numpy() + F.binary_cross_entropy_with_logits(inputs, targets, reduction="none").squeeze().numpy() ) targets = targets.squeeze().numpy() self.assertTrue(np.all(ce_loss[targets == 0] > 0)) @@ -336,17 +288,13 @@ def test_positives_ignored_focal_loss_star(self) -> None: """ With alpha = 0 postive examples have focal loss of 0. """ - inputs = logit( - torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) - ) + inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) focal_loss_star = ( sigmoid_focal_loss_star(inputs, targets, gamma=3, alpha=0).squeeze().numpy() ) ce_loss = ( - F.binary_cross_entropy_with_logits(inputs, targets, reduction="none") - .squeeze() - .numpy() + F.binary_cross_entropy_with_logits(inputs, targets, reduction="none").squeeze().numpy() ) targets = targets.squeeze().numpy() self.assertTrue(np.all(ce_loss[targets == 1] > 0)) @@ -373,9 +321,7 @@ def test_sum_focal_loss_star_equals_ce_loss(self) -> None: """ Sum of focal loss across all examples matches ce loss. """ - inputs = logit( - torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) - ) + inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) focal_loss_star = sigmoid_focal_loss_star( inputs, targets, gamma=1, alpha=-1, reduction="sum" @@ -422,40 +368,28 @@ def test_focal_loss_star_equals_ce_loss_jit(self) -> None: inputs = logit(torch.rand(N)).to(device) targets = torch.randint(0, 2, (N,)).float().to(device) focal_loss_star = sigmoid_focal_loss_star_jit(inputs, targets, gamma=1) - ce_loss = F.binary_cross_entropy_with_logits( - inputs.cpu(), targets.cpu(), reduction="none" - ) + ce_loss = F.binary_cross_entropy_with_logits(inputs.cpu(), targets.cpu(), reduction="none") self.assertTrue(np.allclose(ce_loss, focal_loss_star.cpu())) @staticmethod - def focal_loss_star_with_init( - N: int, alpha: float = -1 - ) -> typing.Callable[[], None]: + def focal_loss_star_with_init(N: int, alpha: float = -1) -> typing.Callable[[], None]: device = torch.device("cuda:0") inputs: torch.Tensor = logit(torch.rand(N)).to(device).requires_grad_() - targets: torch.Tensor = ( - torch.randint(0, 2, (N,)).float().to(device).requires_grad_() - ) + targets: torch.Tensor = torch.randint(0, 2, (N,)).float().to(device).requires_grad_() torch.cuda.synchronize() def run_focal_loss_star() -> None: - fl = sigmoid_focal_loss_star( - inputs, targets, gamma=1, alpha=alpha, reduction="mean" - ) + fl = sigmoid_focal_loss_star(inputs, targets, gamma=1, alpha=alpha, reduction="mean") fl.backward() torch.cuda.synchronize() return run_focal_loss_star @staticmethod - def focal_loss_star_jit_with_init( - N: int, alpha: float = -1 - ) -> typing.Callable[[], None]: + def focal_loss_star_jit_with_init(N: int, alpha: float = -1) -> typing.Callable[[], None]: device = torch.device("cuda:0") inputs: torch.Tensor = logit(torch.rand(N)).to(device).requires_grad_() - targets: torch.Tensor = ( - torch.randint(0, 2, (N,)).float().to(device).requires_grad_() - ) + targets: torch.Tensor = torch.randint(0, 2, (N,)).float().to(device).requires_grad_() torch.cuda.synchronize() def run_focal_loss_star_jit() -> None: diff --git a/tests/test_jit_model_analysis.py b/tests/test_jit_model_analysis.py index 077b292..489c786 100644 --- a/tests/test_jit_model_analysis.py +++ b/tests/test_jit_model_analysis.py @@ -505,12 +505,8 @@ def test_shared_module(self) -> None: # Test getting canonical name self.assertEqual(analyzer.canonical_module_name("multiname2"), "multiname1") self.assertEqual(analyzer.canonical_module_name("multiname1"), "multiname1") - self.assertEqual( - analyzer.canonical_module_name("submod2.submod"), "submod1.submod" - ) - self.assertEqual( - analyzer.canonical_module_name("submod1.submod"), "submod1.submod" - ) + self.assertEqual(analyzer.canonical_module_name("submod2.submod"), "submod1.submod") + self.assertEqual(analyzer.canonical_module_name("submod1.submod"), "submod1.submod") # Tests no uncalled modules self.assertEqual(analyzer.uncalled_modules(), set()) @@ -541,8 +537,7 @@ def test_data_parallel(self) -> None: # Find flops for wrapper flops = { - "module" + ("." if name else "") + name: flop - for name, flop in model.flops.items() + "module" + ("." if name else "") + name: flop for name, flop in model.flops.items() } flops[""] = model.flops[""] name_to_module = { @@ -629,9 +624,7 @@ def test_changing_handles(self) -> None: "aten::linear": linear_flop_jit, } - analyzer = JitModelAnalysis(model=model, inputs=inputs).set_op_handle( - **op_handles - ) + analyzer = JitModelAnalysis(model=model, inputs=inputs).set_op_handle(**op_handles) analyzer.unsupported_ops_warnings(enabled=False) # Request a result once to cache flop counts @@ -644,18 +637,14 @@ def test_changing_handles(self) -> None: # Overwrite an op handle def make_dummy_op(name: str, output: int) -> Handle: - def dummy_ops_handle( - inputs: List[Any], outputs: List[Any] - ) -> typing.Counter[str]: + def dummy_ops_handle(inputs: List[Any], outputs: List[Any]) -> typing.Counter[str]: return Counter({name: output}) return dummy_ops_handle dummy_name = "dummy_op" dummy_out = 1000 - analyzer.set_op_handle( - "aten::{}".format(self.lin_op), make_dummy_op(dummy_name, dummy_out) - ) + analyzer.set_op_handle("aten::{}".format(self.lin_op), make_dummy_op(dummy_name, dummy_out)) dummy_flops = {} for name, counts in model.flops.items(): diff --git a/tests/test_layers_squeeze_excitation.py b/tests/test_layers_squeeze_excitation.py index 209f27d..2e9f58d 100644 --- a/tests/test_layers_squeeze_excitation.py +++ b/tests/test_layers_squeeze_excitation.py @@ -108,9 +108,7 @@ def _get_inputs2d(num_channels: int = 8) -> Iterable[torch.Tensor]: yield torch.rand(shape) @staticmethod - def _get_inputs( - num_channels: int = 8, is_3d: bool = False - ) -> Iterable[torch.Tensor]: + def _get_inputs(num_channels: int = 8, is_3d: bool = False) -> Iterable[torch.Tensor]: """ Provide different tensors as test cases. diff --git a/tests/test_param_count.py b/tests/test_param_count.py index 6e3d0c1..44f26e2 100644 --- a/tests/test_param_count.py +++ b/tests/test_param_count.py @@ -41,6 +41,4 @@ def test_param_with_same_prefix(self) -> None: net = NetWithDupPrefix() table = parameter_count_table(net) c = ["conv111.weight" in line for line in table.split("\n")] - self.assertEqual( - sum(c), 1 - ) # it only appears once, despite being a prefix of conv1 + self.assertEqual(sum(c), 1) # it only appears once, despite being a prefix of conv1 diff --git a/tests/test_precise_bn.py b/tests/test_precise_bn.py index 41a1ad3..2ed8b95 100644 --- a/tests/test_precise_bn.py +++ b/tests/test_precise_bn.py @@ -27,11 +27,7 @@ def compute_bn_stats( tensors (list): list of randomly initialized tensors. dims (list): list of dimensions to compute the mean and variance. """ - mean = ( - torch.stack([tensor.mean(dim=dims) for tensor in tensors]) - .mean(dim=0) - .numpy() - ) + mean = torch.stack([tensor.mean(dim=dims) for tensor in tensors]).mean(dim=0).numpy() mean_of_batch_var = ( torch.stack([tensor.var(dim=dims, unbiased=True) for tensor in tensors]) .mean(dim=0) @@ -52,9 +48,7 @@ def test_precise_bn(self) -> None: model = bn(input_dim[1]) model.train() tensors = [torch.randn(input_dim) for _ in range(NB)] - mean, mean_of_batch_var, var = TestPreciseBN.compute_bn_stats( - tensors, stats_dim - ) + mean, mean_of_batch_var, var = TestPreciseBN.compute_bn_stats(tensors, stats_dim) old_weight = model.weight.detach().numpy() diff --git a/tests/test_print_model_statistics.py b/tests/test_print_model_statistics.py index 7a7eecc..b0ffc99 100644 --- a/tests/test_print_model_statistics.py +++ b/tests/test_print_model_statistics.py @@ -356,9 +356,7 @@ def test_model_stats_table(self) -> None: # "| a2.b1.c2 | 0 | | |" # Test changing max depth - table = _model_stats_table( - string_statistics, stat_columns=stat_columns, max_depth=2 - ) + table = _model_stats_table(string_statistics, stat_columns=stat_columns, max_depth=2) self.assertTrue("a1.b1.c1.d1" in table) # Skipping wrappers reaches deeper self.assertTrue(" a2.b1 " in table) # Get to depth 2 @@ -440,9 +438,7 @@ def test_flop_count_str(self) -> None: model = TestNet() inputs = (torch.randn((1, 10)),) - model_str = flop_count_str( - FlopCountAnalysis(model, inputs).ancestor_mode("caller") - ) + model_str = flop_count_str(FlopCountAnalysis(model, inputs).ancestor_mode("caller")) self.assertTrue("N/A indicates a possibly missing statistic" in model_str) self.assertTrue("#params: 0.11K, #flops: 100" in model_str) diff --git a/tests/test_transform.py b/tests/test_transform.py index ab9681d..76b0d02 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -199,24 +199,16 @@ def ScaleTransform_img_gt(imgs, *args) -> Tuple[Any, Any]: float_tensor = to_float_tensor(imgs) if interp == "nearest": if float_tensor.dim() == 3: - float_tensor = torch._C._nn.upsample_nearest1d( - float_tensor, (new_h, new_w) - ) + float_tensor = torch._C._nn.upsample_nearest1d(float_tensor, (new_h, new_w)) elif float_tensor.dim() == 4: - float_tensor = torch._C._nn.upsample_nearest2d( - float_tensor, (new_h, new_w) - ) + float_tensor = torch._C._nn.upsample_nearest2d(float_tensor, (new_h, new_w)) elif float_tensor.dim() == 5: - float_tensor = torch._C._nn.upsample_nearest3d( - float_tensor, (new_h, new_w) - ) + float_tensor = torch._C._nn.upsample_nearest3d(float_tensor, (new_h, new_w)) else: return None, None elif interp == "bilinear": if float_tensor.dim() == 4: - float_tensor = torch._C._nn.upsample_bilinear2d( - float_tensor, (new_h, new_w), False - ) + float_tensor = torch._C._nn.upsample_bilinear2d(float_tensor, (new_h, new_w), False) else: return None, None numpy_tensor = to_numpy(float_tensor, imgs.shape, imgs.dtype) @@ -647,16 +639,12 @@ def test_blend_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) @staticmethod @@ -683,9 +671,7 @@ def test_vflip_coords_transforms(self): _trans_name = "VFlipTransform" params = ((20,), (30,)) - for coords, param in itertools.product( - TestTransforms._coords_provider(), params - ): + for coords, param in itertools.product(TestTransforms._coords_provider(), params): gt_transformer = getattr(self, "{}_coords_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -696,16 +682,12 @@ def test_vflip_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) @staticmethod @@ -732,9 +714,7 @@ def test_hflip_coords_transforms(self): _trans_name = "HFlipTransform" params = ((20,), (30,)) - for coords, param in itertools.product( - TestTransforms._coords_provider(), params - ): + for coords, param in itertools.product(TestTransforms._coords_provider(), params): gt_transformer = getattr(self, "{}_coords_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -745,16 +725,12 @@ def test_hflip_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) coords_inversed = transformer.inverse().apply_coords(result) @@ -797,9 +773,7 @@ def test_crop_coords_transforms(self): (3, 3, 6, 6, 10, 11), (6, 6, 6, 6, 10, 11), ) - for coords, param in itertools.product( - TestTransforms._coords_provider(), params - ): + for coords, param in itertools.product(TestTransforms._coords_provider(), params): gt_transformer = getattr(self, "{}_coords_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -810,16 +784,12 @@ def test_crop_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) coords_inversed = transformer.inverse().apply_coords(result) @@ -862,9 +832,7 @@ def test_scale_coords_transforms(self): (10, 20, 10, 5), ) - for coords, param in itertools.product( - TestTransforms._coords_provider(), params - ): + for coords, param in itertools.product(TestTransforms._coords_provider(), params): gt_transformer = getattr(self, "{}_coords_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -875,16 +843,12 @@ def test_scale_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) coords_inversed = transformer.inverse().apply_coords(result) @@ -932,16 +896,12 @@ def test_blend_seg_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) self.assertTrue( np.allclose(result, seg_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) @staticmethod @@ -982,9 +942,7 @@ def test_scale_seg_transforms(self): (10, 20, 10, 5), ) - for seg, param in itertools.product( - TestTransforms._seg_provider(h=10, w=20), params - ): + for seg, param in itertools.product(TestTransforms._seg_provider(h=10, w=20), params): gt_transformer = getattr(self, "{}_seg_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -996,17 +954,13 @@ def test_scale_seg_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) if seg_gt is not None: self.assertTrue( np.allclose(result, seg_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) # Testing failure cases. @@ -1019,9 +973,7 @@ def test_scale_seg_transforms(self): (0, 0, 0, -1), (20, 10, 0, -1), ) - for seg, param in itertools.product( - TestTransforms._seg_provider(w=10, h=20), params - ): + for seg, param in itertools.product(TestTransforms._seg_provider(w=10, h=20), params): gt_transformer = getattr(self, "{}_seg_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) with self.assertRaises((RuntimeError, AssertionError)): @@ -1049,9 +1001,7 @@ def test_no_op_coords_transforms(self): _trans_name = "NoOpTransform" params = () - for coords, param in itertools.product( - TestTransforms._coords_provider(), params - ): + for coords, param in itertools.product(TestTransforms._coords_provider(), params): gt_transformer = getattr(self, "{}_coords_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -1062,16 +1012,12 @@ def test_no_op_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format( - _trans_name, param, result.shape - ), + "params {} given input with shape {}".format(_trans_name, param, result.shape), ) def test_transformlist_flatten(self): @@ -1089,6 +1035,4 @@ def test_print_transform(self): self.assertEqual(str(t), f"TransformList[NoOpTransform(), {t0}]") t = T.BlendTransform(np.zeros((100, 100, 100)), 1.0, 1.0) - self.assertEqual( - str(t), "BlendTransform(src_image=..., src_weight=1.0, dst_weight=1.0)" - ) + self.assertEqual(str(t), "BlendTransform(src_image=..., src_weight=1.0, dst_weight=1.0)") diff --git a/tests/test_weight_init.py b/tests/test_weight_init.py index 17b4b49..b30c08a 100644 --- a/tests/test_weight_init.py +++ b/tests/test_weight_init.py @@ -40,9 +40,7 @@ def weight_and_bias_dist_match( # number of elements would not give us a standard deviation that close # enough to the expected distribution. So the default rtol of 1e-8 will # break some test cases. Therefore a larger rtol is used. - weight_dist_match = torch.allclose( - target_std, torch.std(weight), rtol=1e-2, atol=0 - ) + weight_dist_match = torch.allclose(target_std, torch.std(weight), rtol=1e-2, atol=0) bias_dist_match = torch.nonzero(bias).nelement() == 0 return weight_dist_match and bias_dist_match @@ -112,9 +110,7 @@ def test_linear_weight_init(self) -> None: channel_out_dims = [256, 512, 1024, 2048] for layer in [nn.Linear]: - for c_in_dim, c_out_dim in itertools.product( - channel_in_dims, channel_out_dims - ): + for c_in_dim, c_out_dim in itertools.product(channel_in_dims, channel_out_dims): p = {"in_features": c_in_dim, "out_features": c_out_dim} # pyre-fixme[6]: For 1st argument expected `bool` but got `int`. model = layer(**p) From 5c564ca26713d1a410f2c71f341c0aa0db156305 Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 19:08:48 +0200 Subject: [PATCH 09/13] isort --- .github/workflows/workflow.yml | 2 +- fvcore/common/checkpoint.py | 41 ++++-- fvcore/common/config.py | 24 ++-- fvcore/common/file_io.py | 4 +- fvcore/common/param_scheduler.py | 28 +++- fvcore/common/registry.py | 12 +- fvcore/nn/distributed.py | 12 +- fvcore/nn/focal_loss.py | 4 +- fvcore/nn/jit_analysis.py | 18 ++- fvcore/nn/jit_handles.py | 8 +- fvcore/nn/parameter_count.py | 4 +- fvcore/nn/precise_bn.py | 33 +++-- fvcore/nn/print_model_statistics.py | 24 +++- fvcore/nn/squeeze_excitation.py | 20 ++- fvcore/transforms/transform.py | 29 ++-- fvcore/transforms/transform_util.py | 12 +- linter.sh | 2 +- setup.py | 4 +- tests/bm_focal_loss.py | 4 +- tests/bm_main.py | 4 +- .../test_scheduler_composite.py | 12 +- .../test_scheduler_constant.py | 3 +- .../test_scheduler_exponential.py | 4 +- .../param_scheduler/test_scheduler_linear.py | 4 +- .../test_scheduler_multi_step.py | 3 +- tests/param_scheduler/test_scheduler_step.py | 3 +- .../test_scheduler_step_with_fixed_gamma.py | 3 +- tests/test_activation_count.py | 4 +- tests/test_checkpoint.py | 32 +++-- tests/test_common.py | 15 +- tests/test_flop_count.py | 50 +++++-- tests/test_focal_loss.py | 132 +++++++++++++----- tests/test_jit_model_analysis.py | 23 ++- tests/test_layers_squeeze_excitation.py | 4 +- tests/test_param_count.py | 4 +- tests/test_precise_bn.py | 10 +- tests/test_print_model_statistics.py | 8 +- tests/test_transform.py | 112 +++++++++++---- tests/test_weight_init.py | 8 +- 39 files changed, 535 insertions(+), 188 deletions(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index a084fc2..88c989b 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -27,6 +27,6 @@ jobs: echo "Running isort" isort -c --sp . . echo "Running black" - black -l 100 --check . + black --check . echo "Running flake8" flake8 . diff --git a/fvcore/common/checkpoint.py b/fvcore/common/checkpoint.py index f21cd8a..0effb71 100644 --- a/fvcore/common/checkpoint.py +++ b/fvcore/common/checkpoint.py @@ -96,7 +96,9 @@ def add_checkpointable(self, key: str, checkpointable: Any) -> None: if key in self.checkpointables: raise KeyError(f"Key {key} already used in the Checkpointer") if not hasattr(checkpointable, "state_dict"): - raise TypeError("add_checkpointable needs an object with 'state_dict()' method.") + raise TypeError( + "add_checkpointable needs an object with 'state_dict()' method." + ) self.checkpointables[key] = checkpointable def save(self, name: str, **kwargs: Any) -> None: @@ -124,7 +126,9 @@ def save(self, name: str, **kwargs: Any) -> None: torch.save(data, cast(IO[bytes], f)) self.tag_last_checkpoint(basename) - def load(self, path: str, checkpointables: Optional[List[str]] = None) -> Dict[str, Any]: + def load( + self, path: str, checkpointables: Optional[List[str]] = None + ) -> Dict[str, Any]: """ Load from the given checkpoint. @@ -147,7 +151,9 @@ def load(self, path: str, checkpointables: Optional[List[str]] = None) -> Dict[s # path may not be a local file, but _load_file is responsible to handle it. checkpoint = self._load_file(path) incompatible = self._load_model(checkpoint) - if incompatible is not None: # handle some existing subclasses that returns None + if ( + incompatible is not None + ): # handle some existing subclasses that returns None self._log_incompatible_keys(incompatible) for key in self.checkpointables if checkpointables is None else checkpointables: @@ -193,7 +199,8 @@ def get_all_checkpoint_files(self) -> List[str]: all_model_checkpoints = [ os.path.join(self.save_dir, file) for file in self.path_manager.ls(self.save_dir) - if self.path_manager.isfile(os.path.join(self.save_dir, file)) and file.endswith(".pth") + if self.path_manager.isfile(os.path.join(self.save_dir, file)) + and file.endswith(".pth") ] return all_model_checkpoints @@ -335,11 +342,15 @@ def _log_incompatible_keys(self, incompatible: _IncompatibleKeys) -> None: ) ) if incompatible.missing_keys: - missing_keys = _filter_reused_missing_keys(self.model, incompatible.missing_keys) + missing_keys = _filter_reused_missing_keys( + self.model, incompatible.missing_keys + ) if missing_keys: self.logger.warning(get_missing_parameters_message(missing_keys)) if incompatible.unexpected_keys: - self.logger.warning(get_unexpected_parameters_message(incompatible.unexpected_keys)) + self.logger.warning( + get_unexpected_parameters_message(incompatible.unexpected_keys) + ) def _convert_ndarray_to_tensor(self, state_dict: Dict[str, Any]) -> None: """ @@ -354,7 +365,9 @@ def _convert_ndarray_to_tensor(self, state_dict: Dict[str, Any]) -> None: for k in list(state_dict.keys()): v = state_dict[k] if not isinstance(v, np.ndarray) and not isinstance(v, torch.Tensor): - raise ValueError("Unsupported type found in checkpoint! {}: {}".format(k, type(v))) + raise ValueError( + "Unsupported type found in checkpoint! {}: {}".format(k, type(v)) + ) if not isinstance(v, torch.Tensor): state_dict[k] = torch.from_numpy(v) @@ -419,9 +432,9 @@ def step(self, iteration: int, **kwargs: Any) -> None: self.recent_checkpoints.append(self.checkpointer.get_checkpoint_file()) if len(self.recent_checkpoints) > self.max_to_keep: file_to_delete = self.recent_checkpoints.pop(0) - if self.path_manager.exists(file_to_delete) and not file_to_delete.endswith( - f"{self.file_prefix}_final.pth" - ): + if self.path_manager.exists( + file_to_delete + ) and not file_to_delete.endswith(f"{self.file_prefix}_final.pth"): self.path_manager.rm(file_to_delete) if self.max_iter is not None: @@ -488,7 +501,9 @@ def get_unexpected_parameters_message(keys: List[str]) -> str: """ groups = _group_checkpoint_keys(keys) msg = "The checkpoint state_dict contains keys that are not used by the model:\n" - msg += "\n".join(" " + colored(k + _group_to_str(v), "magenta") for k, v in groups.items()) + msg += "\n".join( + " " + colored(k + _group_to_str(v), "magenta") for k, v in groups.items() + ) return msg @@ -563,7 +578,9 @@ def _group_to_str(group: List[str]) -> str: return ".{" + ", ".join(sorted(group)) + "}" -def _named_modules_with_dup(model: nn.Module, prefix: str = "") -> Iterable[Tuple[str, nn.Module]]: +def _named_modules_with_dup( + model: nn.Module, prefix: str = "" +) -> Iterable[Tuple[str, nn.Module]]: """ The same as `model.named_modules()`, except that it includes duplicated modules that have more than one name. diff --git a/fvcore/common/config.py b/fvcore/common/config.py index 96f70dc..3882b09 100644 --- a/fvcore/common/config.py +++ b/fvcore/common/config.py @@ -40,7 +40,9 @@ def _open_cfg(cls, filename: str) -> Union[IO[str], IO[bytes]]: return g_pathmgr.open(filename, "r") @classmethod - def load_yaml_with_base(cls, filename: str, allow_unsafe: bool = False) -> Dict[str, Any]: + def load_yaml_with_base( + cls, filename: str, allow_unsafe: bool = False + ) -> Dict[str, Any]: """ Just like `yaml.load(open(filename))`, but inherit attributes from its `_BASE_`. @@ -63,7 +65,9 @@ def load_yaml_with_base(cls, filename: str, allow_unsafe: bool = False) -> Dict[ logger = logging.getLogger(__name__) logger.warning( "Loading config {} with yaml.unsafe_load. Your machine may " - "be at risk if the file contains malicious content.".format(filename) + "be at risk if the file contains malicious content.".format( + filename + ) ) f.close() with cls._open_cfg(filename) as f: @@ -73,7 +77,9 @@ def merge_a_into_b(a: Dict[str, Any], b: Dict[str, Any]) -> None: # merge dict a into dict b. values in a will overwrite b. for k, v in a.items(): if isinstance(v, dict) and k in b: - assert isinstance(b[k], dict), "Cannot inherit key '{}' from base!".format(k) + assert isinstance( + b[k], dict + ), "Cannot inherit key '{}' from base!".format(k) merge_a_into_b(v, b[k]) else: b[k] = v @@ -120,9 +126,9 @@ def merge_from_other_cfg(self, cfg_other: "CfgNode") -> Callable[[], None]: Args: cfg_other (CfgNode): configs to merge from. """ - assert BASE_KEY not in cfg_other, "The reserved key '{}' can only be used in files!".format( - BASE_KEY - ) + assert ( + BASE_KEY not in cfg_other + ), "The reserved key '{}' can only be used in files!".format(BASE_KEY) return super().merge_from_other_cfg(cfg_other) def merge_from_list(self, cfg_list: List[str]) -> Callable[[], None]: @@ -131,9 +137,9 @@ def merge_from_list(self, cfg_list: List[str]) -> Callable[[], None]: cfg_list (list): list of configs to merge from. """ keys = set(cfg_list[0::2]) - assert BASE_KEY not in keys, "The reserved key '{}' can only be used in files!".format( - BASE_KEY - ) + assert ( + BASE_KEY not in keys + ), "The reserved key '{}' can only be used in files!".format(BASE_KEY) return super().merge_from_list(cfg_list) def __setattr__(self, name: str, val: Any) -> None: # pyre-ignore diff --git a/fvcore/common/file_io.py b/fvcore/common/file_io.py index fdaee04..31250e1 100644 --- a/fvcore/common/file_io.py +++ b/fvcore/common/file_io.py @@ -32,7 +32,9 @@ def get_cache_dir(cache_dir: Optional[str] = None) -> str: 2) otherwise ~/.torch/fvcore_cache """ if cache_dir is None: - cache_dir = os.path.expanduser(os.getenv("FVCORE_CACHE", "~/.torch/fvcore_cache")) + cache_dir = os.path.expanduser( + os.getenv("FVCORE_CACHE", "~/.torch/fvcore_cache") + ) try: PathManager.mkdirs(cache_dir) assert os.access(cache_dir, os.W_OK) diff --git a/fvcore/common/param_scheduler.py b/fvcore/common/param_scheduler.py index 08cf6b0..f95350b 100644 --- a/fvcore/common/param_scheduler.py +++ b/fvcore/common/param_scheduler.py @@ -57,7 +57,9 @@ def __init__(self, value: float) -> None: def __call__(self, where: float) -> float: if where >= 1.0: - raise RuntimeError(f"where in ParamScheduler must be in [0, 1]: got {where}") + raise RuntimeError( + f"where in ParamScheduler must be in [0, 1]: got {where}" + ) return self._value @@ -205,7 +207,9 @@ def __init__( if num_updates is None: num_updates, milestones = milestones[-1], milestones[:-1] if num_updates < len(values): - raise ValueError("Total num_updates must be greater than length of param schedule") + raise ValueError( + "Total num_updates must be greater than length of param schedule" + ) self._param_schedule = values self._num_updates = num_updates @@ -229,7 +233,9 @@ def __init__( def __call__(self, where: float) -> float: if where > 1.0: - raise RuntimeError(f"where in ParamScheduler must be in [0, 1]: got {where}") + raise RuntimeError( + f"where in ParamScheduler must be in [0, 1]: got {where}" + ) epoch_num = int((where + self.WHERE_EPSILON) * self._num_updates) return self._param_schedule[bisect.bisect_right(self._milestones, epoch_num)] @@ -287,7 +293,9 @@ def __init__( if num_updates <= 0: raise ValueError("Number of updates must be larger than 0") if not (isinstance(values, Sequence) and len(values) > 0): - raise ValueError("Step scheduler requires a list of at least one param value") + raise ValueError( + "Step scheduler requires a list of at least one param value" + ) self._param_schedule = values def __call__(self, where: float) -> float: @@ -333,7 +341,9 @@ def __init__( for _ in range(num_decays): values.append(values[-1] * gamma) - self._step_param_scheduler = StepParamScheduler(num_updates=num_updates, values=values) + self._step_param_scheduler = StepParamScheduler( + num_updates=num_updates, values=values + ) def __call__(self, where: float) -> float: return self._step_param_scheduler(where) @@ -379,7 +389,9 @@ def __init__( if len(schedulers) != len(lengths): raise ValueError("Schedulers and lengths must be same length") if len(schedulers) == 0: - raise ValueError("There must be at least one scheduler in the composite scheduler") + raise ValueError( + "There must be at least one scheduler in the composite scheduler" + ) if abs(sum(lengths) - 1.0) >= 1e-3: raise ValueError("The sum of all values in lengths must be 1") if sum(lengths) != 1.0: @@ -396,7 +408,9 @@ def __call__(self, where: float) -> float: # Find scheduler corresponding to where i = 0 running_total = self._lengths[i] - while (where + self.WHERE_EPSILON) > running_total and i < len(self._schedulers) - 1: + while (where + self.WHERE_EPSILON) > running_total and i < len( + self._schedulers + ) - 1: i += 1 running_total += self._lengths[i] scheduler = self._schedulers[i] diff --git a/fvcore/common/registry.py b/fvcore/common/registry.py index 6d318d0..a0ae0f1 100644 --- a/fvcore/common/registry.py +++ b/fvcore/common/registry.py @@ -42,7 +42,9 @@ def __init__(self, name: str) -> None: def _do_register(self, name: str, obj: Any) -> None: assert ( name not in self._obj_map - ), "An object named '{}' was already registered in '{}' registry!".format(name, self._name) + ), "An object named '{}' was already registered in '{}' registry!".format( + name, self._name + ) self._obj_map[name] = obj def register(self, obj: Any = None) -> Any: @@ -66,7 +68,9 @@ def deco(func_or_class: Any) -> Any: def get(self, name: str) -> Any: ret = self._obj_map.get(name) if ret is None: - raise KeyError("No object named '{}' found in '{}' registry!".format(name, self._name)) + raise KeyError( + "No object named '{}' found in '{}' registry!".format(name, self._name) + ) return ret def __contains__(self, name: str) -> bool: @@ -74,7 +78,9 @@ def __contains__(self, name: str) -> bool: def __repr__(self) -> str: table_headers = ["Names", "Objects"] - table = tabulate(self._obj_map.items(), headers=table_headers, tablefmt="fancy_grid") + table = tabulate( + self._obj_map.items(), headers=table_headers, tablefmt="fancy_grid" + ) return "Registry of {}:\n".format(self._name) + table def __iter__(self) -> Iterator[Tuple[str, Any]]: diff --git a/fvcore/nn/distributed.py b/fvcore/nn/distributed.py index 26b190f..4852d07 100644 --- a/fvcore/nn/distributed.py +++ b/fvcore/nn/distributed.py @@ -27,7 +27,11 @@ def differentiable_all_reduce(input: torch.Tensor) -> torch.Tensor: """ Differentiable counterpart of `dist.all_reduce`. """ - if not dist.is_available() or not dist.is_initialized() or dist.get_world_size() == 1: + if ( + not dist.is_available() + or not dist.is_initialized() + or dist.get_world_size() == 1 + ): return input return _AllReduce.apply(input) @@ -50,6 +54,10 @@ def differentiable_all_gather(input: torch.Tensor) -> List[torch.Tensor]: """ Differentiable counterpart of `dist.all_gather`. """ - if not dist.is_available() or not dist.is_initialized() or dist.get_world_size() == 1: + if ( + not dist.is_available() + or not dist.is_initialized() + or dist.get_world_size() == 1 + ): return [input] return list(_AllGather.apply(input)) diff --git a/fvcore/nn/focal_loss.py b/fvcore/nn/focal_loss.py index f86e955..b60250f 100644 --- a/fvcore/nn/focal_loss.py +++ b/fvcore/nn/focal_loss.py @@ -94,4 +94,6 @@ def sigmoid_focal_loss_star( return loss -sigmoid_focal_loss_star_jit: "torch.jit.ScriptModule" = torch.jit.script(sigmoid_focal_loss_star) +sigmoid_focal_loss_star_jit: "torch.jit.ScriptModule" = torch.jit.script( + sigmoid_focal_loss_star +) diff --git a/fvcore/nn/jit_analysis.py b/fvcore/nn/jit_analysis.py index 989bd40..c59f4b5 100644 --- a/fvcore/nn/jit_analysis.py +++ b/fvcore/nn/jit_analysis.py @@ -161,7 +161,9 @@ def register_hooks(mod: nn.Module, name: str) -> None: hook_handles.append(posthook) # Unwrap DDP, but correct the scope names for the root module. - if isinstance(module, (nn.parallel.distributed.DistributedDataParallel, nn.DataParallel)): + if isinstance( + module, (nn.parallel.distributed.DistributedDataParallel, nn.DataParallel) + ): # Since DataParallel just wraps the model, add an extra set of hooks # to the model it wraps to account for the wrapper. Then trace it. root_name = aliases[module] @@ -308,7 +310,8 @@ def unsupported_ops(self, module_name: str = "") -> typing.Counter[str]: """ if self._stats is None: raise RuntimeError( - "Analysis results should be computed " "before calling unsupported_ops()" + "Analysis results should be computed " + "before calling unsupported_ops()" ) module_name = self.canonical_module_name(module_name) return self._stats.unsupported_ops[module_name] # pyre-fixme @@ -351,7 +354,9 @@ def set_op_handle(self, *args, **kwargs: Optional[Handle]) -> "JitModelAnalysis" """ self._stats = None if len(args) % 2 != 0: - raise TypeError("set_op_handle should be called with pairs of names and handles!") + raise TypeError( + "set_op_handle should be called with pairs of names and handles!" + ) for name, handle in zip(args[::2], args[1::2]): kwargs[name] = handle for name, handle in kwargs.items(): @@ -388,7 +393,8 @@ def canonical_module_name(self, name: str) -> str: return self._aliases[name] else: raise KeyError( - "Requested module name is not among " "the descendants of the analyzed model." + "Requested module name is not among " + "the descendants of the analyzed model." ) def copy( @@ -491,7 +497,9 @@ def _warn_unsupported_ops(self, ops: typing.Counter[str]) -> None: return logger = logging.getLogger(__name__) for op, freq in ops.items(): - logger.warning("Unsupported operator {} encountered {} time(s)".format(op, freq)) + logger.warning( + "Unsupported operator {} encountered {} time(s)".format(op, freq) + ) def _warn_uncalled_mods(self, uncalled_mods: Set[str]) -> None: if not self._enable_warn_uncalled_mods: diff --git a/fvcore/nn/jit_handles.py b/fvcore/nn/jit_handles.py index 796f4cf..747205c 100644 --- a/fvcore/nn/jit_handles.py +++ b/fvcore/nn/jit_handles.py @@ -62,7 +62,9 @@ def generic_activation_jit(op_name: Optional[str] = None) -> Handle: Callable: An activation handle for the given operation. """ - def _generic_activation_jit(i: Any, outputs: List[Any]) -> Union[typing.Counter[str], Number]: + def _generic_activation_jit( + i: Any, outputs: List[Any] + ) -> Union[typing.Counter[str], Number]: """ This is a generic jit handle that counts the number of activations for any operation given the output shape. @@ -164,7 +166,9 @@ def conv_flop_jit(inputs: List[Any], outputs: List[Any]) -> typing.Counter[str]: transposed = inputs[6].toIValue() # use a custom name instead of "_convolution" - return Counter({"conv": conv_flop_count(x_shape, w_shape, out_shape, transposed=transposed)}) + return Counter( + {"conv": conv_flop_count(x_shape, w_shape, out_shape, transposed=transposed)} + ) def einsum_flop_jit(inputs: List[Any], outputs: List[Any]) -> Number: diff --git a/fvcore/nn/parameter_count.py b/fvcore/nn/parameter_count.py index c638350..b5a3193 100644 --- a/fvcore/nn/parameter_count.py +++ b/fvcore/nn/parameter_count.py @@ -113,6 +113,8 @@ def fill(lvl: int, prefix: str) -> None: old_ws = tabulate.PRESERVE_WHITESPACE tabulate.PRESERVE_WHITESPACE = True - tab = tabulate.tabulate(table, headers=["name", "#elements or shape"], tablefmt="pipe") + tab = tabulate.tabulate( + table, headers=["name", "#elements or shape"], tablefmt="pipe" + ) tabulate.PRESERVE_WHITESPACE = old_ws return tab diff --git a/fvcore/nn/precise_bn.py b/fvcore/nn/precise_bn.py index b745543..012fcc5 100644 --- a/fvcore/nn/precise_bn.py +++ b/fvcore/nn/precise_bn.py @@ -43,7 +43,9 @@ def __init__(self, mean_buffer: torch.Tensor, var_buffer: torch.Tensor) -> None: self.pop_var: torch.Tensor = torch.zeros_like(var_buffer) self.ind = 0 - def update(self, batch_mean: torch.Tensor, batch_var: torch.Tensor, batch_size: int) -> None: + def update( + self, batch_mean: torch.Tensor, batch_var: torch.Tensor, batch_size: int + ) -> None: self.ind += 1 self.pop_mean += (batch_mean - self.pop_mean) / self.ind self.pop_var += (batch_var - self.pop_var) / self.ind @@ -68,11 +70,17 @@ def __init__(self, mean_buffer: torch.Tensor, var_buffer: torch.Tensor) -> None: self.pop_square_mean: torch.Tensor = torch.zeros_like(var_buffer) self.tot = 0 - def update(self, batch_mean: torch.Tensor, batch_var: torch.Tensor, batch_size: int) -> None: + def update( + self, batch_mean: torch.Tensor, batch_var: torch.Tensor, batch_size: int + ) -> None: self.tot += batch_size - batch_square_mean = batch_mean.square() + batch_var * ((batch_size - 1) / batch_size) + batch_square_mean = batch_mean.square() + batch_var * ( + (batch_size - 1) / batch_size + ) self.pop_mean += (batch_mean - self.pop_mean) * (batch_size / self.tot) - self.pop_square_mean += (batch_square_mean - self.pop_square_mean) * (batch_size / self.tot) + self.pop_square_mean += (batch_square_mean - self.pop_square_mean) * ( + batch_size / self.tot + ) @property def pop_var(self) -> torch.Tensor: @@ -137,15 +145,22 @@ def get_bn_batch_size_hook( module not in batch_size_per_bn_layer ), "Some BN layers are reused. This is not supported and probably not desired." x = input[0] - assert isinstance(x, torch.Tensor), f"BN layer should take tensor as input. Got {input}" + assert isinstance( + x, torch.Tensor + ), f"BN layer should take tensor as input. Got {input}" # consider spatial dimensions as batch as well batch_size = x.numel() // x.shape[1] batch_size_per_bn_layer[module] = batch_size return (x,) - hooks_to_remove = [bn.register_forward_pre_hook(get_bn_batch_size_hook) for bn in bn_layers] + hooks_to_remove = [ + bn.register_forward_pre_hook(get_bn_batch_size_hook) for bn in bn_layers + ] - estimators = [_PopulationVarianceEstimator(bn.running_mean, bn.running_var) for bn in bn_layers] + estimators = [ + _PopulationVarianceEstimator(bn.running_mean, bn.running_var) + for bn in bn_layers + ] ind = -1 for inputs in tqdm.tqdm( @@ -190,5 +205,7 @@ def get_bn_modules(model: nn.Module) -> List[nn.Module]: list[nn.Module]: all BN modules in the model. """ # Finds all the bn layers. - bn_layers = [m for m in model.modules() if m.training and isinstance(m, BN_MODULE_TYPES)] + bn_layers = [ + m for m in model.modules() if m.training and isinstance(m, BN_MODULE_TYPES) + ] return bn_layers diff --git a/fvcore/nn/print_model_statistics.py b/fvcore/nn/print_model_statistics.py index 10d1bbc..5c45d28 100644 --- a/fvcore/nn/print_model_statistics.py +++ b/fvcore/nn/print_model_statistics.py @@ -70,11 +70,15 @@ def _pretty_statistics( """ out_stats = {} for mod, stats in statistics.items(): - out_stats[mod] = {s: _format_size(val, sig_figs, hide_zero) for s, val in stats.items()} + out_stats[mod] = { + s: _format_size(val, sig_figs, hide_zero) for s, val in stats.items() + } return out_stats -def _group_by_module(statistics: Dict[str, Dict[str, Any]]) -> Dict[str, Dict[str, Any]]: +def _group_by_module( + statistics: Dict[str, Dict[str, Any]] +) -> Dict[str, Dict[str, Any]]: """ Converts statistics organized first by statistic type and then by module to statistics organized first by module and then by statistic type. @@ -403,7 +407,9 @@ def flop_count_str( stats = _pretty_statistics(stats, sig_figs=2) stats = _indicate_uncalled_modules(stats, "#flops", flops.uncalled_modules()) if activations is not None: - stats = _indicate_uncalled_modules(stats, "#acts", activations.uncalled_modules()) + stats = _indicate_uncalled_modules( + stats, "#acts", activations.uncalled_modules() + ) model_string = "" if all_uncalled: @@ -419,7 +425,9 @@ def flop_count_str( ### Table Printing ### -def _get_single_child(name: str, statistics: Dict[str, Dict[str, str]]) -> Optional[str]: +def _get_single_child( + name: str, statistics: Dict[str, Dict[str, str]] +) -> Optional[str]: """ If the given module has only a single child in statistics, return it. Otherwise, return None. @@ -436,7 +444,9 @@ def _get_single_child(name: str, statistics: Dict[str, Dict[str, str]]) -> Optio return child -def _try_combine(stats1: Dict[str, str], stats2: Dict[str, str]) -> Optional[Dict[str, str]]: +def _try_combine( + stats1: Dict[str, str], stats2: Dict[str, str] +) -> Optional[Dict[str, str]]: """ Try combine two statistics dict to display in one row. If they conflict, returns None. @@ -452,7 +462,9 @@ def _try_combine(stats1: Dict[str, str], stats2: Dict[str, str]) -> Optional[Dic return ret -def _fastforward(name: str, statistics: Dict[str, Dict[str, str]]) -> Tuple[str, Dict[str, str]]: +def _fastforward( + name: str, statistics: Dict[str, Dict[str, str]] +) -> Tuple[str, Dict[str, str]]: """ If the given module has only a single child and matches statistics with that child, merge statistics and their names into one row. diff --git a/fvcore/nn/squeeze_excitation.py b/fvcore/nn/squeeze_excitation.py index c7d4e9a..42227d4 100644 --- a/fvcore/nn/squeeze_excitation.py +++ b/fvcore/nn/squeeze_excitation.py @@ -43,11 +43,19 @@ def __init__( activation = nn.ReLU() if is_3d: - conv1 = nn.Conv3d(num_channels, num_channels_reduced, kernel_size=1, bias=True) - conv2 = nn.Conv3d(num_channels_reduced, num_channels, kernel_size=1, bias=True) + conv1 = nn.Conv3d( + num_channels, num_channels_reduced, kernel_size=1, bias=True + ) + conv2 = nn.Conv3d( + num_channels_reduced, num_channels, kernel_size=1, bias=True + ) else: - conv1 = nn.Conv2d(num_channels, num_channels_reduced, kernel_size=1, bias=True) - conv2 = nn.Conv2d(num_channels_reduced, num_channels, kernel_size=1, bias=True) + conv1 = nn.Conv2d( + num_channels, num_channels_reduced, kernel_size=1, bias=True + ) + conv2 = nn.Conv2d( + num_channels_reduced, num_channels, kernel_size=1, bias=True + ) self.is_3d = is_3d self.block = nn.Sequential( @@ -160,6 +168,8 @@ def forward(self, input_tensor: torch.Tensor) -> torch.Tensor: For 3d X, shape = (batch_size, num_channels, T, H, W) output tensor """ - output_tensor = torch.max(self.channel(input_tensor), self.spatial(input_tensor)) + output_tensor = torch.max( + self.channel(input_tensor), self.spatial(input_tensor) + ) return output_tensor diff --git a/fvcore/transforms/transform.py b/fvcore/transforms/transform.py index 51820c7..f20560c 100644 --- a/fvcore/transforms/transform.py +++ b/fvcore/transforms/transform.py @@ -189,7 +189,9 @@ def wrapper(decorated_func): assert callable( func - ), "You can only register a callable to a Transform. Got {} instead.".format(func) + ), "You can only register a callable to a Transform. Got {} instead.".format( + func + ) argspec = inspect.getfullargspec(func) assert len(argspec.args) == 2, ( "You can only register a function that takes two positional " @@ -222,11 +224,14 @@ def __repr__(self): argstr = [] for name, param in sig.parameters.items(): assert ( - param.kind != param.VAR_POSITIONAL and param.kind != param.VAR_KEYWORD + param.kind != param.VAR_POSITIONAL + and param.kind != param.VAR_KEYWORD ), "The default __repr__ doesn't support *args or **kwargs" assert hasattr(self, name), ( "Attribute {} not found! " - "Default __repr__ only works if attributes match the constructor.".format(name) + "Default __repr__ only works if attributes match the constructor.".format( + name + ) ) attr = getattr(self, name) default = param.default @@ -523,9 +528,9 @@ def apply_image(self, img: np.ndarray, interp: str = None) -> np.ndarray: h, w = img.shape[:2] else: raise ("Unsupported input with shape of {}".format(img.shape)) - assert self.h == h and self.w == w, "Input size mismatch h w {}:{} -> {}:{}".format( - self.h, self.w, h, w - ) + assert ( + self.h == h and self.w == w + ), "Input size mismatch h w {}:{} -> {}:{}".format(self.h, self.w, h, w) interp_method = interp if interp is not None else self.interp # Option of align_corners is only supported for linear, bilinear, # and bicubic. @@ -699,7 +704,9 @@ def apply_polygons(self, polygons: list) -> list: import shapely.geometry as geometry # Create a window that will be used to crop - crop_box = geometry.box(self.x0, self.y0, self.x0 + self.w, self.y0 + self.h).buffer(0.0) + crop_box = geometry.box( + self.x0, self.y0, self.x0 + self.w, self.y0 + self.h + ).buffer(0.0) cropped_polygons = [] @@ -734,7 +741,9 @@ def inverse(self) -> Transform: ), "orig_w, orig_h are required for CropTransform to be invertible!" pad_x1 = self.orig_w - self.x0 - self.w pad_y1 = self.orig_h - self.y0 - self.h - return PadTransform(self.x0, self.y0, pad_x1, pad_y1, orig_w=self.w, orig_h=self.h) + return PadTransform( + self.x0, self.y0, pad_x1, pad_y1, orig_w=self.w, orig_h=self.h + ) class PadTransform(Transform): @@ -796,7 +805,9 @@ def inverse(self) -> Transform: ), "orig_w, orig_h are required for PadTransform to be invertible!" neww = self.orig_w + self.x0 + self.x1 newh = self.orig_h + self.y0 + self.y1 - return CropTransform(self.x0, self.y0, self.orig_w, self.orig_h, orig_w=neww, orig_h=newh) + return CropTransform( + self.x0, self.y0, self.orig_w, self.orig_h, orig_w=neww, orig_h=newh + ) class BlendTransform(Transform): diff --git a/fvcore/transforms/transform_util.py b/fvcore/transforms/transform_util.py index 9377db8..74a6bfc 100644 --- a/fvcore/transforms/transform_util.py +++ b/fvcore/transforms/transform_util.py @@ -38,11 +38,15 @@ def to_float_tensor(numpy_array: np.ndarray) -> torch.Tensor: # NxHxWxC -> NxCxHxW float_tensor = float_tensor.permute(0, 3, 1, 2) else: - raise NotImplementedError("Unknow numpy_array dimension of {}".format(float_tensor.shape)) + raise NotImplementedError( + "Unknow numpy_array dimension of {}".format(float_tensor.shape) + ) return float_tensor -def to_numpy(float_tensor: torch.Tensor, target_shape: list, target_dtype: np.dtype) -> np.ndarray: +def to_numpy( + float_tensor: torch.Tensor, target_shape: list, target_dtype: np.dtype +) -> np.ndarray: """ Convert float tensor with dimension of NxCxHxW back to numpy array. Args: @@ -70,7 +74,9 @@ def to_numpy(float_tensor: torch.Tensor, target_shape: list, target_dtype: np.dt # NxCxHxW -> NxHxWxC float_tensor = float_tensor.permute(0, 2, 3, 1) else: - raise NotImplementedError("Unknow target shape dimension of {}".format(target_shape)) + raise NotImplementedError( + "Unknow target shape dimension of {}".format(target_shape) + ) if target_dtype == np.uint8: # Need to specifically call round here, notice in pytroch the round # is half to even. diff --git a/linter.sh b/linter.sh index 7d658f4..cebc3a7 100755 --- a/linter.sh +++ b/linter.sh @@ -14,7 +14,7 @@ echo "Running isort..." isort --sp . . echo "Running black..." -black -l 100 . +black . echo "Running flake8..." if [ -x "$(command -v flake8)" ]; then diff --git a/setup.py b/setup.py index e946e1c..7a84a43 100755 --- a/setup.py +++ b/setup.py @@ -8,7 +8,9 @@ def get_version(): - init_py_path = path.join(path.abspath(path.dirname(__file__)), "fvcore", "__init__.py") + init_py_path = path.join( + path.abspath(path.dirname(__file__)), "fvcore", "__init__.py" + ) init_py = open(init_py_path, "r").readlines() version_line = [l.strip() for l in init_py if l.startswith("__version__")][0] version = version_line.split("=")[-1].strip().strip("'\"") diff --git a/tests/bm_focal_loss.py b/tests/bm_focal_loss.py index 8dc3a52..06afd57 100644 --- a/tests/bm_focal_loss.py +++ b/tests/bm_focal_loss.py @@ -19,7 +19,9 @@ def bm_focal_loss() -> None: {"N": 10000}, {"N": 10000, "alpha": 0}, ] - benchmark(TestFocalLoss.focal_loss_with_init, "Focal_loss", kwargs_list, warmup_iters=1) + benchmark( + TestFocalLoss.focal_loss_with_init, "Focal_loss", kwargs_list, warmup_iters=1 + ) benchmark( TestFocalLoss.focal_loss_jit_with_init, "Focal_loss_JIT", diff --git a/tests/bm_main.py b/tests/bm_main.py index 0c4d166..8ff46aa 100755 --- a/tests/bm_main.py +++ b/tests/bm_main.py @@ -15,7 +15,9 @@ # Get all the benchmark files (starting with "bm_"). bm_files = glob.glob(join(dirname(__file__), "bm_*.py")) # pyre-ignore module_names = [ - basename(f)[:-3] for f in bm_files if isfile(f) and not f.endswith("bm_main.py") + basename(f)[:-3] + for f in bm_files + if isfile(f) and not f.endswith("bm_main.py") ] for module_name in module_names: diff --git a/tests/param_scheduler/test_scheduler_composite.py b/tests/param_scheduler/test_scheduler_composite.py index 7bbefcf..730f61a 100644 --- a/tests/param_scheduler/test_scheduler_composite.py +++ b/tests/param_scheduler/test_scheduler_composite.py @@ -95,7 +95,8 @@ def test_long_scheduler(self): scheduler = CompositeParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) + for epoch_num in range(self._num_updates) ] expected_schedule = [0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.3, 0.4, 0.4, 0.4] @@ -105,7 +106,8 @@ def test_scheduler_lengths_within_epsilon_of_one(self): config = self._get_lengths_sum_less_one_config() scheduler = CompositeParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) + for epoch_num in range(self._num_updates) ] expected_schedule = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2] self.assertEqual(schedule, expected_schedule) @@ -169,7 +171,8 @@ def test_linear_scheduler_no_gaps(self): # Check rescaled scheduler = CompositeParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) + for epoch_num in range(self._num_updates) ] expected_schedule = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] self.assertEqual(expected_schedule, schedule) @@ -180,7 +183,8 @@ def test_linear_scheduler_no_gaps(self): scheduler = CompositeParamScheduler(**config) linear_scheduler = config["schedulers"][0] schedule = [ - scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) + for epoch_num in range(self._num_updates) ] expected_schedule = [ linear_scheduler(epoch_num / self._num_updates) diff --git a/tests/param_scheduler/test_scheduler_constant.py b/tests/param_scheduler/test_scheduler_constant.py index 3d25bd8..5a63bb1 100644 --- a/tests/param_scheduler/test_scheduler_constant.py +++ b/tests/param_scheduler/test_scheduler_constant.py @@ -11,7 +11,8 @@ class TestConstantScheduler(unittest.TestCase): def test_scheduler(self): scheduler = ConstantParamScheduler(0.1) schedule = [ - scheduler(epoch_num / self._num_epochs) for epoch_num in range(self._num_epochs) + scheduler(epoch_num / self._num_epochs) + for epoch_num in range(self._num_epochs) ] expected_schedule = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] diff --git a/tests/param_scheduler/test_scheduler_exponential.py b/tests/param_scheduler/test_scheduler_exponential.py index 08efefa..4c94b97 100644 --- a/tests/param_scheduler/test_scheduler_exponential.py +++ b/tests/param_scheduler/test_scheduler_exponential.py @@ -22,6 +22,8 @@ def test_scheduler(self): round(scheduler(epoch_num / self._num_epochs), 4) for epoch_num in range(self._num_epochs) ] - expected_schedule = [config["start_value"]] + self._get_valid_intermediate_values() + expected_schedule = [ + config["start_value"] + ] + self._get_valid_intermediate_values() self.assertEqual(schedule, expected_schedule) diff --git a/tests/param_scheduler/test_scheduler_linear.py b/tests/param_scheduler/test_scheduler_linear.py index 547b237..2eb8e41 100644 --- a/tests/param_scheduler/test_scheduler_linear.py +++ b/tests/param_scheduler/test_scheduler_linear.py @@ -35,5 +35,7 @@ def test_scheduler(self): round(scheduler(epoch_num / self._num_epochs), 4) for epoch_num in range(self._num_epochs) ] - expected_schedule = [config["start_value"]] + list(reversed(self._get_valid_intermediate())) + expected_schedule = [config["start_value"]] + list( + reversed(self._get_valid_intermediate()) + ) self.assertEqual(schedule, expected_schedule) diff --git a/tests/param_scheduler/test_scheduler_multi_step.py b/tests/param_scheduler/test_scheduler_multi_step.py index 349f579..c3462da 100644 --- a/tests/param_scheduler/test_scheduler_multi_step.py +++ b/tests/param_scheduler/test_scheduler_multi_step.py @@ -62,7 +62,8 @@ def test_invalid_config(self): def _test_config_scheduler(self, config, expected_schedule): scheduler = MultiStepParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) + for epoch_num in range(self._num_updates) ] self.assertEqual(schedule, expected_schedule) diff --git a/tests/param_scheduler/test_scheduler_step.py b/tests/param_scheduler/test_scheduler_step.py index 19aa388..979c9f2 100644 --- a/tests/param_scheduler/test_scheduler_step.py +++ b/tests/param_scheduler/test_scheduler_step.py @@ -38,7 +38,8 @@ def test_scheduler(self): scheduler = StepParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) + for epoch_num in range(self._num_updates) ] expected_schedule = [ 0.1, diff --git a/tests/param_scheduler/test_scheduler_step_with_fixed_gamma.py b/tests/param_scheduler/test_scheduler_step_with_fixed_gamma.py index cca4f70..d22c56c 100644 --- a/tests/param_scheduler/test_scheduler_step_with_fixed_gamma.py +++ b/tests/param_scheduler/test_scheduler_step_with_fixed_gamma.py @@ -48,7 +48,8 @@ def test_scheduler(self): scheduler = StepWithFixedGammaParamScheduler(**config) schedule = [ - scheduler(epoch_num / self._num_updates) for epoch_num in range(self._num_updates) + scheduler(epoch_num / self._num_updates) + for epoch_num in range(self._num_updates) ] expected_schedule = [ 1, diff --git a/tests/test_activation_count.py b/tests/test_activation_count.py index 01699ea..1931114 100644 --- a/tests/test_activation_count.py +++ b/tests/test_activation_count.py @@ -96,7 +96,9 @@ def test_linear(self) -> None: gt_count = batch_size * output_dim gt_dict = defaultdict(float) gt_dict[self.lin_op] = gt_count / 1e6 - self.assertEquals(gt_dict, ac_dict, "FC layer failed to pass the activation count test.") + self.assertEquals( + gt_dict, ac_dict, "FC layer failed to pass the activation count test." + ) def test_supported_ops(self) -> None: """ diff --git a/tests/test_checkpoint.py b/tests/test_checkpoint.py index 3a47571..ed9d771 100644 --- a/tests/test_checkpoint.py +++ b/tests/test_checkpoint.py @@ -139,7 +139,9 @@ def test_from_last_checkpoint_model(self) -> None: ) fresh_checkpointer.load(fresh_checkpointer.get_checkpoint_file()) - for trained_p, loaded_p in zip(trained_model.parameters(), fresh_model.parameters()): + for trained_p, loaded_p in zip( + trained_model.parameters(), fresh_model.parameters() + ): # different tensor references self.assertFalse(id(trained_p) == id(loaded_p)) # same content @@ -159,7 +161,9 @@ def test_from_name_file_model(self) -> None: ), ]: with TemporaryDirectory() as f: - checkpointer = Checkpointer(trained_model, save_dir=f, save_to_disk=True) + checkpointer = Checkpointer( + trained_model, save_dir=f, save_to_disk=True + ) checkpointer.save("checkpoint_file") # on different folders. @@ -169,7 +173,9 @@ def test_from_name_file_model(self) -> None: self.assertEqual(fresh_checkpointer.get_checkpoint_file(), "") fresh_checkpointer.load(os.path.join(f, "checkpoint_file.pth")) - for trained_p, loaded_p in zip(trained_model.parameters(), fresh_model.parameters()): + for trained_p, loaded_p in zip( + trained_model.parameters(), fresh_model.parameters() + ): # different tensor references. self.assertFalse(id(trained_p) == id(loaded_p)) # same content. @@ -187,7 +193,9 @@ class CheckpointableObj: """ def __init__(self): - self.state = {self.random_handle(): self.random_handle() for i in range(10)} + self.state = { + self.random_handle(): self.random_handle() for i in range(10) + } def random_handle(self, str_len=100) -> str: """ @@ -233,7 +241,9 @@ def load_state_dict(self, state) -> None: fresh_checkpointer.get_checkpoint_file(), os.path.join(f, "checkpoint_file.pth"), ) - checkpoint = fresh_checkpointer.load(fresh_checkpointer.get_checkpoint_file()) + checkpoint = fresh_checkpointer.load( + fresh_checkpointer.get_checkpoint_file() + ) state_dict = checkpointables.state_dict() for key, _ in state_dict.items(): self.assertTrue(checkpoint["checkpointables"].get(key) is not None) @@ -261,7 +271,9 @@ def __init__(self, has_y: bool) -> None: ) logger.info.assert_not_called() - @unittest.skipIf(not hasattr(nn, "LazyLinear"), "LazyModule not supported") # pyre-fixme[56] + @unittest.skipIf( + not hasattr(nn, "LazyLinear"), "LazyModule not supported" + ) # pyre-fixme[56] def test_load_lazy_module(self) -> None: def _get_model() -> nn.Sequential: return nn.Sequential(nn.LazyLinear(10)) @@ -301,7 +313,9 @@ def test_periodic_checkpointer(self) -> None: nn.DataParallel(self._create_model()), ]: with TemporaryDirectory() as f: - checkpointer = Checkpointer(trained_model, save_dir=f, save_to_disk=True) + checkpointer = Checkpointer( + trained_model, save_dir=f, save_to_disk=True + ) periodic_checkpointer = PeriodicCheckpointer(checkpointer, _period, 99) for iteration in range(_max_iter): periodic_checkpointer.step(iteration) @@ -323,7 +337,9 @@ def test_periodic_checkpointer_max_to_keep(self) -> None: nn.DataParallel(self._create_model()), ]: with TemporaryDirectory() as f: - checkpointer = Checkpointer(trained_model, save_dir=f, save_to_disk=True) + checkpointer = Checkpointer( + trained_model, save_dir=f, save_to_disk=True + ) periodic_checkpointer = PeriodicCheckpointer( checkpointer, _period, 99, max_to_keep=_max_to_keep ) diff --git a/tests/test_common.py b/tests/test_common.py index 7e1ea48..a51dfda 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -51,7 +51,9 @@ def test_buffer(self) -> None: for _ in range(num_iters): gt_len = 1000 buffer_len = np.random.randint(1, gt_len) - create_buffer = TestHistoryBuffer.create_buffer_with_init(gt_len, buffer_len) + create_buffer = TestHistoryBuffer.create_buffer_with_init( + gt_len, buffer_len + ) buf, gt = create_buffer() # pyre-ignore values, iterations = zip(*buf.values()) @@ -197,7 +199,9 @@ def test_setattr(self) -> None: cfg.COMPUTED_1 = "computed1" with self.assertRaises(KeyError) as err: cfg.COMPUTED_1 = "update_computed1" - self.assertTrue("Computed attributed 'COMPUTED_1' already exists" in str(err.exception)) + self.assertTrue( + "Computed attributed 'COMPUTED_1' already exists" in str(err.exception) + ) # Resetting the same value should be safe: cfg.COMPUTED_1 = "computed1" @@ -226,8 +230,11 @@ class Object1: with self.assertRaises(KeyError) as err: OBJECT_REGISTRY.get("Object2") self.assertTrue( - "No object named 'Object2' found in 'OBJECT' registry!" in str(err.exception) + "No object named 'Object2' found in 'OBJECT' registry!" + in str(err.exception) ) items = list(OBJECT_REGISTRY) - self.assertListEqual(items, [("Object1", Object1)], "Registry iterable contains valid item") + self.assertListEqual( + items, [("Object1", Object1)], "Registry iterable contains valid item" + ) diff --git a/tests/test_flop_count.py b/tests/test_flop_count.py index 6ef9a1c..ed7afd6 100644 --- a/tests/test_flop_count.py +++ b/tests/test_flop_count.py @@ -231,7 +231,9 @@ def addmm_dummy_flop_jit( flop_dict[self.lin_op] = 400000 return flop_dict - custom_ops2: Dict[str, Handle] = {"aten::{}".format(self.lin_op): addmm_dummy_flop_jit} + custom_ops2: Dict[str, Handle] = { + "aten::{}".format(self.lin_op): addmm_dummy_flop_jit + } flop_dict2, _ = flop_count(customNet, (x,), supported_ops=custom_ops2) flop = 400000 / 1e9 self.assertEqual( @@ -253,7 +255,9 @@ def test_nn(self) -> None: gt_flop = batch_size * input_dim * output_dim / 1e9 gt_dict = defaultdict(float) gt_dict[self.lin_op] = gt_flop - self.assertDictEqual(flop_dict, gt_dict, "nn.Linear failed to pass the flop count test.") + self.assertDictEqual( + flop_dict, gt_dict, "nn.Linear failed to pass the flop count test." + ) def test_skip_ops(self) -> None: """ @@ -346,7 +350,9 @@ def _test_conv( elif conv_dim == 2: x = torch.randn(batch_size, input_dim, spatial_dim, spatial_dim) else: - x = torch.randn(batch_size, input_dim, spatial_dim, spatial_dim, spatial_dim) + x = torch.randn( + batch_size, input_dim, spatial_dim, spatial_dim, spatial_dim + ) flop_dict, _ = flop_count(convNet, (x,)) if transpose: @@ -715,7 +721,9 @@ def test_batchnorm(self) -> None: gt_flop = batch_size * input_dim / 1e9 gt_dict = defaultdict(float) gt_dict["batch_norm"] = gt_flop - self.assertDictEqual(flop_dict, gt_dict, "BatchNorm1d failed to pass the flop count test.") + self.assertDictEqual( + flop_dict, gt_dict, "BatchNorm1d failed to pass the flop count test." + ) # Test for BatchNorm2d. batch_size = 10 @@ -728,7 +736,9 @@ def test_batchnorm(self) -> None: gt_flop = 4 * batch_size * input_dim * spatial_dim_x * spatial_dim_y / 1e9 gt_dict = defaultdict(float) gt_dict["batch_norm"] = gt_flop - self.assertDictEqual(flop_dict, gt_dict, "BatchNorm2d failed to pass the flop count test.") + self.assertDictEqual( + flop_dict, gt_dict, "BatchNorm2d failed to pass the flop count test." + ) # Test for BatchNorm3d. batch_size = 10 @@ -737,12 +747,24 @@ def test_batchnorm(self) -> None: spatial_dim_y = 5 spatial_dim_z = 5 batch_3d = nn.BatchNorm3d(input_dim, affine=False) - x = torch.randn(batch_size, input_dim, spatial_dim_x, spatial_dim_y, spatial_dim_z) + x = torch.randn( + batch_size, input_dim, spatial_dim_x, spatial_dim_y, spatial_dim_z + ) flop_dict, _ = flop_count(batch_3d, (x,)) - gt_flop = 4 * batch_size * input_dim * spatial_dim_x * spatial_dim_y * spatial_dim_z / 1e9 + gt_flop = ( + 4 + * batch_size + * input_dim + * spatial_dim_x + * spatial_dim_y + * spatial_dim_z + / 1e9 + ) gt_dict = defaultdict(float) gt_dict["batch_norm"] = gt_flop - self.assertDictEqual(flop_dict, gt_dict, "BatchNorm3d failed to pass the flop count test.") + self.assertDictEqual( + flop_dict, gt_dict, "BatchNorm3d failed to pass the flop count test." + ) def test_threeNet(self) -> None: """ @@ -868,10 +890,14 @@ def test_group_norm(self): counter = _DEFAULT_SUPPORTED_OPS[op_name] vec = torch.rand(2) - nodes = self._count_function(F.group_norm, (torch.rand(2, 2, 2, 2), 2, vec, vec), op_name) + nodes = self._count_function( + F.group_norm, (torch.rand(2, 2, 2, 2), 2, vec, vec), op_name + ) self.assertEqual(counter(*nodes), 80) - nodes = self._count_function(F.group_norm, (torch.rand(2, 2, 2, 2), 2, None, None), op_name) + nodes = self._count_function( + F.group_norm, (torch.rand(2, 2, 2, 2), 2, None, None), op_name + ) self.assertEqual(counter(*nodes), 64) def test_upsample(self): @@ -895,7 +921,9 @@ def test_complicated_einsum(self): self.assertEqual(counter(*nodes), 72.0) def test_torch_mm(self): - for op_name, func in zip(["aten::mm", "aten::matmul"], [torch.mm, torch.matmul]): + for op_name, func in zip( + ["aten::mm", "aten::matmul"], [torch.mm, torch.matmul] + ): counter = _DEFAULT_SUPPORTED_OPS[op_name] nodes = self._count_function( diff --git a/tests/test_focal_loss.py b/tests/test_focal_loss.py index 3b69529..ab29ca6 100644 --- a/tests/test_focal_loss.py +++ b/tests/test_focal_loss.py @@ -28,15 +28,21 @@ def test_focal_loss_equals_ce_loss(self) -> None: """ No weighting of easy/hard (gamma = 0) or positive/negative (alpha = 0). """ - inputs = logit(torch.tensor([[[0.95], [0.90], [0.98], [0.99]]], dtype=torch.float32)) + inputs = logit( + torch.tensor([[[0.95], [0.90], [0.98], [0.99]]], dtype=torch.float32) + ) targets = torch.tensor([[[1], [1], [1], [1]]], dtype=torch.float32) inputs_fl = inputs.clone().requires_grad_() targets_fl = targets.clone() inputs_ce = inputs.clone().requires_grad_() targets_ce = targets.clone() - focal_loss = sigmoid_focal_loss(inputs_fl, targets_fl, gamma=0, alpha=-1, reduction="mean") - ce_loss = F.binary_cross_entropy_with_logits(inputs_ce, targets_ce, reduction="mean") + focal_loss = sigmoid_focal_loss( + inputs_fl, targets_fl, gamma=0, alpha=-1, reduction="mean" + ) + ce_loss = F.binary_cross_entropy_with_logits( + inputs_ce, targets_ce, reduction="mean" + ) self.assertEqual(ce_loss, focal_loss.data) focal_loss.backward() @@ -63,7 +69,9 @@ def test_easy_ex_focal_loss_weighted_less_than_ce_loss(self) -> None: """ With gamma = 2, alpha = 0.5 loss of easy examples is downweighted. """ - inputs = logit(torch.tensor([[[0.95], [0.90], [0.6], [0.3]]], dtype=torch.float64)) + inputs = logit( + torch.tensor([[[0.95], [0.90], [0.6], [0.3]]], dtype=torch.float64) + ) targets = torch.tensor([[[1], [1], [1], [1]]], dtype=torch.float64) focal_loss = sigmoid_focal_loss(inputs, targets, gamma=2, alpha=0.5) ce_loss = F.binary_cross_entropy_with_logits(inputs, targets, reduction="none") @@ -87,11 +95,17 @@ def test_negatives_ignored_focal_loss(self) -> None: """ With alpha = 1 negative examples have focal loss of 0. """ - inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) + inputs = logit( + torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) + ) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) - focal_loss = sigmoid_focal_loss(inputs, targets, gamma=2, alpha=1).squeeze().numpy() + focal_loss = ( + sigmoid_focal_loss(inputs, targets, gamma=2, alpha=1).squeeze().numpy() + ) ce_loss = ( - F.binary_cross_entropy_with_logits(inputs, targets, reduction="none").squeeze().numpy() + F.binary_cross_entropy_with_logits(inputs, targets, reduction="none") + .squeeze() + .numpy() ) targets = targets.squeeze().numpy() self.assertTrue(np.all(ce_loss[targets == 0] > 0)) @@ -101,11 +115,17 @@ def test_positives_ignored_focal_loss(self) -> None: """ With alpha = 0 postive examples have focal loss of 0. """ - inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) + inputs = logit( + torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) + ) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) - focal_loss = sigmoid_focal_loss(inputs, targets, gamma=2, alpha=0).squeeze().numpy() + focal_loss = ( + sigmoid_focal_loss(inputs, targets, gamma=2, alpha=0).squeeze().numpy() + ) ce_loss = ( - F.binary_cross_entropy_with_logits(inputs, targets, reduction="none").squeeze().numpy() + F.binary_cross_entropy_with_logits(inputs, targets, reduction="none") + .squeeze() + .numpy() ) targets = targets.squeeze().numpy() self.assertTrue(np.all(ce_loss[targets == 1] > 0)) @@ -122,7 +142,9 @@ def test_mean_focal_loss_equals_ce_loss(self) -> None: ) ) targets = torch.tensor([[1, 0], [1, 0], [1, 1], [0, 1]], dtype=torch.float32) - focal_loss = sigmoid_focal_loss(inputs, targets, gamma=0, alpha=-1, reduction="mean") + focal_loss = sigmoid_focal_loss( + inputs, targets, gamma=0, alpha=-1, reduction="mean" + ) ce_loss = F.binary_cross_entropy_with_logits(inputs, targets, reduction="mean") self.assertEqual(ce_loss, focal_loss) @@ -130,9 +152,13 @@ def test_sum_focal_loss_equals_ce_loss(self) -> None: """ Sum of focal loss across all examples matches ce loss. """ - inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) + inputs = logit( + torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) + ) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) - focal_loss = sigmoid_focal_loss(inputs, targets, gamma=0, alpha=-1, reduction="sum") + focal_loss = sigmoid_focal_loss( + inputs, targets, gamma=0, alpha=-1, reduction="sum" + ) ce_loss = F.binary_cross_entropy_with_logits(inputs, targets, reduction="sum") self.assertEqual(ce_loss, focal_loss) @@ -157,7 +183,9 @@ def test_focal_loss_equals_ce_loss_multi_class(self) -> None: [[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]], dtype=torch.float32, ) - focal_loss = sigmoid_focal_loss(inputs, targets, gamma=0, alpha=-1, reduction="mean") + focal_loss = sigmoid_focal_loss( + inputs, targets, gamma=0, alpha=-1, reduction="mean" + ) ce_loss = F.binary_cross_entropy_with_logits(inputs, targets, reduction="mean") self.assertEqual(ce_loss, focal_loss) @@ -173,32 +201,44 @@ def test_focal_loss_equals_ce_loss_jit(self) -> None: inputs = logit(torch.rand(N)).to(device) targets = torch.randint(0, 2, (N,)).float().to(device) focal_loss = sigmoid_focal_loss_jit(inputs, targets, gamma=0, alpha=-1) - ce_loss = F.binary_cross_entropy_with_logits(inputs.cpu(), targets.cpu(), reduction="none") + ce_loss = F.binary_cross_entropy_with_logits( + inputs.cpu(), targets.cpu(), reduction="none" + ) self.assertTrue(np.allclose(ce_loss, focal_loss.cpu())) @staticmethod def focal_loss_with_init(N: int, alpha: float = -1) -> typing.Callable[[], None]: device = torch.device("cuda:0") inputs: torch.Tensor = logit(torch.rand(N)).to(device).requires_grad_() - targets: torch.Tensor = torch.randint(0, 2, (N,)).float().to(device).requires_grad_() + targets: torch.Tensor = ( + torch.randint(0, 2, (N,)).float().to(device).requires_grad_() + ) torch.cuda.synchronize() def run_focal_loss() -> None: - fl = sigmoid_focal_loss(inputs, targets, gamma=0, alpha=alpha, reduction="mean") + fl = sigmoid_focal_loss( + inputs, targets, gamma=0, alpha=alpha, reduction="mean" + ) fl.backward() torch.cuda.synchronize() return run_focal_loss @staticmethod - def focal_loss_jit_with_init(N: int, alpha: float = -1) -> typing.Callable[[], None]: + def focal_loss_jit_with_init( + N: int, alpha: float = -1 + ) -> typing.Callable[[], None]: device = torch.device("cuda:0") inputs: torch.Tensor = logit(torch.rand(N)).to(device).requires_grad_() - targets: torch.Tensor = torch.randint(0, 2, (N,)).float().to(device).requires_grad_() + targets: torch.Tensor = ( + torch.randint(0, 2, (N,)).float().to(device).requires_grad_() + ) torch.cuda.synchronize() def run_focal_loss_jit() -> None: - fl = sigmoid_focal_loss_jit(inputs, targets, gamma=0, alpha=alpha, reduction="mean") + fl = sigmoid_focal_loss_jit( + inputs, targets, gamma=0, alpha=alpha, reduction="mean" + ) fl.backward() torch.cuda.synchronize() @@ -214,7 +254,9 @@ def test_focal_loss_star_equals_ce_loss(self) -> None: """ No weighting of easy/hard (gamma = 1) or positive/negative (alpha = -1). """ - inputs = logit(torch.tensor([[[0.95], [0.90], [0.98], [0.99]]], dtype=torch.float32)) + inputs = logit( + torch.tensor([[[0.95], [0.90], [0.98], [0.99]]], dtype=torch.float32) + ) targets = torch.tensor([[[1], [1], [1], [1]]], dtype=torch.float32) inputs_fl = inputs.clone().requires_grad_() targets_fl = targets.clone() @@ -224,7 +266,9 @@ def test_focal_loss_star_equals_ce_loss(self) -> None: focal_loss_star = sigmoid_focal_loss_star( inputs_fl, targets_fl, gamma=1, alpha=-1, reduction="mean" ) - ce_loss = F.binary_cross_entropy_with_logits(inputs_ce, targets_ce, reduction="mean") + ce_loss = F.binary_cross_entropy_with_logits( + inputs_ce, targets_ce, reduction="mean" + ) self.assertEqual(ce_loss, focal_loss_star.data) focal_loss_star.backward() @@ -272,13 +316,17 @@ def test_negatives_ignored_focal_loss_star(self) -> None: """ With alpha = 1 negative examples have focal loss of 0. """ - inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) + inputs = logit( + torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) + ) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) focal_loss_star = ( sigmoid_focal_loss_star(inputs, targets, gamma=3, alpha=1).squeeze().numpy() ) ce_loss = ( - F.binary_cross_entropy_with_logits(inputs, targets, reduction="none").squeeze().numpy() + F.binary_cross_entropy_with_logits(inputs, targets, reduction="none") + .squeeze() + .numpy() ) targets = targets.squeeze().numpy() self.assertTrue(np.all(ce_loss[targets == 0] > 0)) @@ -288,13 +336,17 @@ def test_positives_ignored_focal_loss_star(self) -> None: """ With alpha = 0 postive examples have focal loss of 0. """ - inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) + inputs = logit( + torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) + ) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) focal_loss_star = ( sigmoid_focal_loss_star(inputs, targets, gamma=3, alpha=0).squeeze().numpy() ) ce_loss = ( - F.binary_cross_entropy_with_logits(inputs, targets, reduction="none").squeeze().numpy() + F.binary_cross_entropy_with_logits(inputs, targets, reduction="none") + .squeeze() + .numpy() ) targets = targets.squeeze().numpy() self.assertTrue(np.all(ce_loss[targets == 1] > 0)) @@ -321,7 +373,9 @@ def test_sum_focal_loss_star_equals_ce_loss(self) -> None: """ Sum of focal loss across all examples matches ce loss. """ - inputs = logit(torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32)) + inputs = logit( + torch.tensor([[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32) + ) targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32) focal_loss_star = sigmoid_focal_loss_star( inputs, targets, gamma=1, alpha=-1, reduction="sum" @@ -368,28 +422,40 @@ def test_focal_loss_star_equals_ce_loss_jit(self) -> None: inputs = logit(torch.rand(N)).to(device) targets = torch.randint(0, 2, (N,)).float().to(device) focal_loss_star = sigmoid_focal_loss_star_jit(inputs, targets, gamma=1) - ce_loss = F.binary_cross_entropy_with_logits(inputs.cpu(), targets.cpu(), reduction="none") + ce_loss = F.binary_cross_entropy_with_logits( + inputs.cpu(), targets.cpu(), reduction="none" + ) self.assertTrue(np.allclose(ce_loss, focal_loss_star.cpu())) @staticmethod - def focal_loss_star_with_init(N: int, alpha: float = -1) -> typing.Callable[[], None]: + def focal_loss_star_with_init( + N: int, alpha: float = -1 + ) -> typing.Callable[[], None]: device = torch.device("cuda:0") inputs: torch.Tensor = logit(torch.rand(N)).to(device).requires_grad_() - targets: torch.Tensor = torch.randint(0, 2, (N,)).float().to(device).requires_grad_() + targets: torch.Tensor = ( + torch.randint(0, 2, (N,)).float().to(device).requires_grad_() + ) torch.cuda.synchronize() def run_focal_loss_star() -> None: - fl = sigmoid_focal_loss_star(inputs, targets, gamma=1, alpha=alpha, reduction="mean") + fl = sigmoid_focal_loss_star( + inputs, targets, gamma=1, alpha=alpha, reduction="mean" + ) fl.backward() torch.cuda.synchronize() return run_focal_loss_star @staticmethod - def focal_loss_star_jit_with_init(N: int, alpha: float = -1) -> typing.Callable[[], None]: + def focal_loss_star_jit_with_init( + N: int, alpha: float = -1 + ) -> typing.Callable[[], None]: device = torch.device("cuda:0") inputs: torch.Tensor = logit(torch.rand(N)).to(device).requires_grad_() - targets: torch.Tensor = torch.randint(0, 2, (N,)).float().to(device).requires_grad_() + targets: torch.Tensor = ( + torch.randint(0, 2, (N,)).float().to(device).requires_grad_() + ) torch.cuda.synchronize() def run_focal_loss_star_jit() -> None: diff --git a/tests/test_jit_model_analysis.py b/tests/test_jit_model_analysis.py index 489c786..077b292 100644 --- a/tests/test_jit_model_analysis.py +++ b/tests/test_jit_model_analysis.py @@ -505,8 +505,12 @@ def test_shared_module(self) -> None: # Test getting canonical name self.assertEqual(analyzer.canonical_module_name("multiname2"), "multiname1") self.assertEqual(analyzer.canonical_module_name("multiname1"), "multiname1") - self.assertEqual(analyzer.canonical_module_name("submod2.submod"), "submod1.submod") - self.assertEqual(analyzer.canonical_module_name("submod1.submod"), "submod1.submod") + self.assertEqual( + analyzer.canonical_module_name("submod2.submod"), "submod1.submod" + ) + self.assertEqual( + analyzer.canonical_module_name("submod1.submod"), "submod1.submod" + ) # Tests no uncalled modules self.assertEqual(analyzer.uncalled_modules(), set()) @@ -537,7 +541,8 @@ def test_data_parallel(self) -> None: # Find flops for wrapper flops = { - "module" + ("." if name else "") + name: flop for name, flop in model.flops.items() + "module" + ("." if name else "") + name: flop + for name, flop in model.flops.items() } flops[""] = model.flops[""] name_to_module = { @@ -624,7 +629,9 @@ def test_changing_handles(self) -> None: "aten::linear": linear_flop_jit, } - analyzer = JitModelAnalysis(model=model, inputs=inputs).set_op_handle(**op_handles) + analyzer = JitModelAnalysis(model=model, inputs=inputs).set_op_handle( + **op_handles + ) analyzer.unsupported_ops_warnings(enabled=False) # Request a result once to cache flop counts @@ -637,14 +644,18 @@ def test_changing_handles(self) -> None: # Overwrite an op handle def make_dummy_op(name: str, output: int) -> Handle: - def dummy_ops_handle(inputs: List[Any], outputs: List[Any]) -> typing.Counter[str]: + def dummy_ops_handle( + inputs: List[Any], outputs: List[Any] + ) -> typing.Counter[str]: return Counter({name: output}) return dummy_ops_handle dummy_name = "dummy_op" dummy_out = 1000 - analyzer.set_op_handle("aten::{}".format(self.lin_op), make_dummy_op(dummy_name, dummy_out)) + analyzer.set_op_handle( + "aten::{}".format(self.lin_op), make_dummy_op(dummy_name, dummy_out) + ) dummy_flops = {} for name, counts in model.flops.items(): diff --git a/tests/test_layers_squeeze_excitation.py b/tests/test_layers_squeeze_excitation.py index 2e9f58d..209f27d 100644 --- a/tests/test_layers_squeeze_excitation.py +++ b/tests/test_layers_squeeze_excitation.py @@ -108,7 +108,9 @@ def _get_inputs2d(num_channels: int = 8) -> Iterable[torch.Tensor]: yield torch.rand(shape) @staticmethod - def _get_inputs(num_channels: int = 8, is_3d: bool = False) -> Iterable[torch.Tensor]: + def _get_inputs( + num_channels: int = 8, is_3d: bool = False + ) -> Iterable[torch.Tensor]: """ Provide different tensors as test cases. diff --git a/tests/test_param_count.py b/tests/test_param_count.py index 44f26e2..6e3d0c1 100644 --- a/tests/test_param_count.py +++ b/tests/test_param_count.py @@ -41,4 +41,6 @@ def test_param_with_same_prefix(self) -> None: net = NetWithDupPrefix() table = parameter_count_table(net) c = ["conv111.weight" in line for line in table.split("\n")] - self.assertEqual(sum(c), 1) # it only appears once, despite being a prefix of conv1 + self.assertEqual( + sum(c), 1 + ) # it only appears once, despite being a prefix of conv1 diff --git a/tests/test_precise_bn.py b/tests/test_precise_bn.py index 2ed8b95..41a1ad3 100644 --- a/tests/test_precise_bn.py +++ b/tests/test_precise_bn.py @@ -27,7 +27,11 @@ def compute_bn_stats( tensors (list): list of randomly initialized tensors. dims (list): list of dimensions to compute the mean and variance. """ - mean = torch.stack([tensor.mean(dim=dims) for tensor in tensors]).mean(dim=0).numpy() + mean = ( + torch.stack([tensor.mean(dim=dims) for tensor in tensors]) + .mean(dim=0) + .numpy() + ) mean_of_batch_var = ( torch.stack([tensor.var(dim=dims, unbiased=True) for tensor in tensors]) .mean(dim=0) @@ -48,7 +52,9 @@ def test_precise_bn(self) -> None: model = bn(input_dim[1]) model.train() tensors = [torch.randn(input_dim) for _ in range(NB)] - mean, mean_of_batch_var, var = TestPreciseBN.compute_bn_stats(tensors, stats_dim) + mean, mean_of_batch_var, var = TestPreciseBN.compute_bn_stats( + tensors, stats_dim + ) old_weight = model.weight.detach().numpy() diff --git a/tests/test_print_model_statistics.py b/tests/test_print_model_statistics.py index b0ffc99..7a7eecc 100644 --- a/tests/test_print_model_statistics.py +++ b/tests/test_print_model_statistics.py @@ -356,7 +356,9 @@ def test_model_stats_table(self) -> None: # "| a2.b1.c2 | 0 | | |" # Test changing max depth - table = _model_stats_table(string_statistics, stat_columns=stat_columns, max_depth=2) + table = _model_stats_table( + string_statistics, stat_columns=stat_columns, max_depth=2 + ) self.assertTrue("a1.b1.c1.d1" in table) # Skipping wrappers reaches deeper self.assertTrue(" a2.b1 " in table) # Get to depth 2 @@ -438,7 +440,9 @@ def test_flop_count_str(self) -> None: model = TestNet() inputs = (torch.randn((1, 10)),) - model_str = flop_count_str(FlopCountAnalysis(model, inputs).ancestor_mode("caller")) + model_str = flop_count_str( + FlopCountAnalysis(model, inputs).ancestor_mode("caller") + ) self.assertTrue("N/A indicates a possibly missing statistic" in model_str) self.assertTrue("#params: 0.11K, #flops: 100" in model_str) diff --git a/tests/test_transform.py b/tests/test_transform.py index 76b0d02..ab9681d 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -199,16 +199,24 @@ def ScaleTransform_img_gt(imgs, *args) -> Tuple[Any, Any]: float_tensor = to_float_tensor(imgs) if interp == "nearest": if float_tensor.dim() == 3: - float_tensor = torch._C._nn.upsample_nearest1d(float_tensor, (new_h, new_w)) + float_tensor = torch._C._nn.upsample_nearest1d( + float_tensor, (new_h, new_w) + ) elif float_tensor.dim() == 4: - float_tensor = torch._C._nn.upsample_nearest2d(float_tensor, (new_h, new_w)) + float_tensor = torch._C._nn.upsample_nearest2d( + float_tensor, (new_h, new_w) + ) elif float_tensor.dim() == 5: - float_tensor = torch._C._nn.upsample_nearest3d(float_tensor, (new_h, new_w)) + float_tensor = torch._C._nn.upsample_nearest3d( + float_tensor, (new_h, new_w) + ) else: return None, None elif interp == "bilinear": if float_tensor.dim() == 4: - float_tensor = torch._C._nn.upsample_bilinear2d(float_tensor, (new_h, new_w), False) + float_tensor = torch._C._nn.upsample_bilinear2d( + float_tensor, (new_h, new_w), False + ) else: return None, None numpy_tensor = to_numpy(float_tensor, imgs.shape, imgs.dtype) @@ -639,12 +647,16 @@ def test_blend_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) @staticmethod @@ -671,7 +683,9 @@ def test_vflip_coords_transforms(self): _trans_name = "VFlipTransform" params = ((20,), (30,)) - for coords, param in itertools.product(TestTransforms._coords_provider(), params): + for coords, param in itertools.product( + TestTransforms._coords_provider(), params + ): gt_transformer = getattr(self, "{}_coords_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -682,12 +696,16 @@ def test_vflip_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) @staticmethod @@ -714,7 +732,9 @@ def test_hflip_coords_transforms(self): _trans_name = "HFlipTransform" params = ((20,), (30,)) - for coords, param in itertools.product(TestTransforms._coords_provider(), params): + for coords, param in itertools.product( + TestTransforms._coords_provider(), params + ): gt_transformer = getattr(self, "{}_coords_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -725,12 +745,16 @@ def test_hflip_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) coords_inversed = transformer.inverse().apply_coords(result) @@ -773,7 +797,9 @@ def test_crop_coords_transforms(self): (3, 3, 6, 6, 10, 11), (6, 6, 6, 6, 10, 11), ) - for coords, param in itertools.product(TestTransforms._coords_provider(), params): + for coords, param in itertools.product( + TestTransforms._coords_provider(), params + ): gt_transformer = getattr(self, "{}_coords_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -784,12 +810,16 @@ def test_crop_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) coords_inversed = transformer.inverse().apply_coords(result) @@ -832,7 +862,9 @@ def test_scale_coords_transforms(self): (10, 20, 10, 5), ) - for coords, param in itertools.product(TestTransforms._coords_provider(), params): + for coords, param in itertools.product( + TestTransforms._coords_provider(), params + ): gt_transformer = getattr(self, "{}_coords_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -843,12 +875,16 @@ def test_scale_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) coords_inversed = transformer.inverse().apply_coords(result) @@ -896,12 +932,16 @@ def test_blend_seg_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) self.assertTrue( np.allclose(result, seg_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) @staticmethod @@ -942,7 +982,9 @@ def test_scale_seg_transforms(self): (10, 20, 10, 5), ) - for seg, param in itertools.product(TestTransforms._seg_provider(h=10, w=20), params): + for seg, param in itertools.product( + TestTransforms._seg_provider(h=10, w=20), params + ): gt_transformer = getattr(self, "{}_seg_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -954,13 +996,17 @@ def test_scale_seg_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) if seg_gt is not None: self.assertTrue( np.allclose(result, seg_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) # Testing failure cases. @@ -973,7 +1019,9 @@ def test_scale_seg_transforms(self): (0, 0, 0, -1), (20, 10, 0, -1), ) - for seg, param in itertools.product(TestTransforms._seg_provider(w=10, h=20), params): + for seg, param in itertools.product( + TestTransforms._seg_provider(w=10, h=20), params + ): gt_transformer = getattr(self, "{}_seg_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) with self.assertRaises((RuntimeError, AssertionError)): @@ -1001,7 +1049,9 @@ def test_no_op_coords_transforms(self): _trans_name = "NoOpTransform" params = () - for coords, param in itertools.product(TestTransforms._coords_provider(), params): + for coords, param in itertools.product( + TestTransforms._coords_provider(), params + ): gt_transformer = getattr(self, "{}_coords_gt".format(_trans_name)) transformer = getattr(T, _trans_name)(*param) @@ -1012,12 +1062,16 @@ def test_no_op_coords_transforms(self): shape_gt, result.shape, "transform {} failed to pass the shape check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) self.assertTrue( np.allclose(result, coords_gt), "transform {} failed to pass the value check with" - "params {} given input with shape {}".format(_trans_name, param, result.shape), + "params {} given input with shape {}".format( + _trans_name, param, result.shape + ), ) def test_transformlist_flatten(self): @@ -1035,4 +1089,6 @@ def test_print_transform(self): self.assertEqual(str(t), f"TransformList[NoOpTransform(), {t0}]") t = T.BlendTransform(np.zeros((100, 100, 100)), 1.0, 1.0) - self.assertEqual(str(t), "BlendTransform(src_image=..., src_weight=1.0, dst_weight=1.0)") + self.assertEqual( + str(t), "BlendTransform(src_image=..., src_weight=1.0, dst_weight=1.0)" + ) diff --git a/tests/test_weight_init.py b/tests/test_weight_init.py index b30c08a..17b4b49 100644 --- a/tests/test_weight_init.py +++ b/tests/test_weight_init.py @@ -40,7 +40,9 @@ def weight_and_bias_dist_match( # number of elements would not give us a standard deviation that close # enough to the expected distribution. So the default rtol of 1e-8 will # break some test cases. Therefore a larger rtol is used. - weight_dist_match = torch.allclose(target_std, torch.std(weight), rtol=1e-2, atol=0) + weight_dist_match = torch.allclose( + target_std, torch.std(weight), rtol=1e-2, atol=0 + ) bias_dist_match = torch.nonzero(bias).nelement() == 0 return weight_dist_match and bias_dist_match @@ -110,7 +112,9 @@ def test_linear_weight_init(self) -> None: channel_out_dims = [256, 512, 1024, 2048] for layer in [nn.Linear]: - for c_in_dim, c_out_dim in itertools.product(channel_in_dims, channel_out_dims): + for c_in_dim, c_out_dim in itertools.product( + channel_in_dims, channel_out_dims + ): p = {"in_features": c_in_dim, "out_features": c_out_dim} # pyre-fixme[6]: For 1st argument expected `bool` but got `int`. model = layer(**p) From 118295d947d99afd7ced113ec5e55fd7291cafaf Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 20:15:02 +0200 Subject: [PATCH 10/13] . --- .circleci/config.yml | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 95cf4f2..ddb728c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,7 +9,7 @@ version: 2.1 # ------------------------------------------------------------------------------------- cpu: &cpu docker: - - image: cimg/python:3.11.4 + - image: circleci/python:3.7 auth: username: $DOCKERHUB_USERNAME password: $DOCKERHUB_TOKEN @@ -17,19 +17,10 @@ cpu: &cpu gpu: &gpu machine: - image: linux-cuda-12:2023.05.1 + image: ubuntu-2004-cuda-11.4:202110-01 docker_layer_caching: true resource_class: gpu.nvidia.small -version_parameters: &version_parameters - parameters: - cuda_version: - type: string - default: '12.1' - - environment: - CUDA_VERSION: << parameters.cuda_version >> - # ------------------------------------------------------------------------------------- # Re-usable commands # ------------------------------------------------------------------------------------- @@ -67,11 +58,6 @@ run_unittests: &run_unittests python -m unittest discover -v -s tests python -m unittest discover -v -s io_tests -select_cuda: &select_cuda - - run: - name: Select CUDA - command: | - sudo update-alternatives --set cuda /usr/local/cuda-<< parameters.cuda_version >> # ------------------------------------------------------------------------------------- # Jobs to run # ------------------------------------------------------------------------------------- @@ -88,14 +74,14 @@ jobs: # Cache the venv directory that contains dependencies - restore_cache: keys: - - cache-key-{{ .Branch }}-ID-20230617 + - cache-key-{{ .Branch }}-ID-20200130 - <<: *install_dep - save_cache: paths: - ~/venv - key: cache-key-{{ .Branch }}-ID-20230617 + key: cache-key-{{ .Branch }}-ID-20200130 - <<: *install_fvcore @@ -110,13 +96,11 @@ jobs: gpu_tests: <<: *gpu - <<: *version_parameters working_directory: ~/fvcore steps: - checkout - - <<: *select_cuda - run: name: Install nvidia-docker working_directory: ~/ @@ -150,7 +134,7 @@ jobs: upload_wheel: docker: - - image: cimg/python:3.11.4 + - image: circleci/python:3.7 auth: username: $DOCKERHUB_USERNAME password: $DOCKERHUB_TOKEN @@ -200,7 +184,6 @@ workflows: context: - DOCKERHUB_TOKEN - gpu_tests: - cuda_version: '12.1' context: - DOCKERHUB_TOKEN @@ -232,4 +215,4 @@ workflows: filters: branches: only: - - main + - main \ No newline at end of file From f0354e68606bcd547388c6801a8a01253daf83f8 Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 20:19:24 +0200 Subject: [PATCH 11/13] . --- .circleci/config.yml | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ddb728c..8a96d0c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,6 @@ -# Python CircleCI 2.0 configuration file +# Python CircleCI 2.1 configuration file # -# Check https://circleci.com/docs/2.0/language-python/ for more details +# Check https://circleci.com/docs/2.1/language-python/ for more details # version: 2.1 @@ -9,7 +9,7 @@ version: 2.1 # ------------------------------------------------------------------------------------- cpu: &cpu docker: - - image: circleci/python:3.7 + - image: cimg/python:3.11.4 auth: username: $DOCKERHUB_USERNAME password: $DOCKERHUB_TOKEN @@ -17,10 +17,18 @@ cpu: &cpu gpu: &gpu machine: - image: ubuntu-2004-cuda-11.4:202110-01 + image: linux-cuda-12:2023.05.1 docker_layer_caching: true resource_class: gpu.nvidia.small +version_parameters: &version_parameters + parameters: + cuda_version: + type: string + default: '12.1' + environment: + CUDA_VERSION: << parameters.cuda_version >> + # ------------------------------------------------------------------------------------- # Re-usable commands # ------------------------------------------------------------------------------------- @@ -58,6 +66,11 @@ run_unittests: &run_unittests python -m unittest discover -v -s tests python -m unittest discover -v -s io_tests +select_cuda: &select_cuda + - run: + name: Select CUDA + command: | + sudo update-alternatives --set cuda /usr/local/cuda-<< parameters.cuda_version >> # ------------------------------------------------------------------------------------- # Jobs to run # ------------------------------------------------------------------------------------- @@ -74,14 +87,14 @@ jobs: # Cache the venv directory that contains dependencies - restore_cache: keys: - - cache-key-{{ .Branch }}-ID-20200130 + - cache-key-{{ .Branch }}-ID-20230617 - <<: *install_dep - save_cache: paths: - ~/venv - key: cache-key-{{ .Branch }}-ID-20200130 + key: cache-key-{{ .Branch }}-ID-20230617 - <<: *install_fvcore @@ -96,11 +109,13 @@ jobs: gpu_tests: <<: *gpu + <<: *version_parameters working_directory: ~/fvcore steps: - checkout + - <<: *select_cuda - run: name: Install nvidia-docker working_directory: ~/ @@ -134,7 +149,7 @@ jobs: upload_wheel: docker: - - image: circleci/python:3.7 + - image: cimg/python:3.11.4 auth: username: $DOCKERHUB_USERNAME password: $DOCKERHUB_TOKEN @@ -184,6 +199,7 @@ workflows: context: - DOCKERHUB_TOKEN - gpu_tests: + cuda_version: '12.1' context: - DOCKERHUB_TOKEN @@ -215,4 +231,4 @@ workflows: filters: branches: only: - - main \ No newline at end of file + - main From a93a1cbf3591907a4485baf150df375de8c4a9bd Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 20:44:35 +0200 Subject: [PATCH 12/13] upgrade python version by security --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 7a84a43..37a6072 100755 --- a/setup.py +++ b/setup.py @@ -41,7 +41,7 @@ def get_version(): url="https://github.com/facebookresearch/fvcore", description="Collection of common code shared among different research " "projects in FAIR computer vision team", - python_requires=">=3.6", + python_requires=">=3.8", install_requires=[ "numpy", "yacs>=0.1.6", @@ -51,7 +51,7 @@ def get_version(): "Pillow", "tabulate", "iopath>=0.1.7", - "dataclasses; python_version<'3.7'", + "dataclasses; python_version<'3.12'", ], extras_require={"all": ["shapely"]}, packages=find_packages(exclude=("tests",)), From 6c696c5876bf31a82fb94a6a5bb00e5a0b694bb9 Mon Sep 17 00:00:00 2001 From: johnnynunez Date: Fri, 16 Jun 2023 20:46:17 +0200 Subject: [PATCH 13/13] upgrade python version by security --- README.md | 2 +- packaging/build_all_conda.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bc4e199..68bb1ac 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Besides some basic utilities, fvcore includes the following features: ## Install: -fvcore requires pytorch and python >= 3.6. +fvcore requires pytorch and python >= 3.8. Use one of the following ways to install: diff --git a/packaging/build_all_conda.sh b/packaging/build_all_conda.sh index 4b11125..7d9dd37 100644 --- a/packaging/build_all_conda.sh +++ b/packaging/build_all_conda.sh @@ -2,14 +2,14 @@ # Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. set -ex -for PV in 3.6 3.7 3.8 +for PV in 3.8 3.9 3.10 3.11 do PYTHON_VERSION=$PV bash packaging/build_conda.sh done ls -Rl packaging -for version in 36 37 38 +for version in 38 39 310 311 do (cd packaging/out && conda convert -p win-64 linux-64/fvcore-*-py$version.tar.bz2) (cd packaging/out && conda convert -p osx-64 linux-64/fvcore-*-py$version.tar.bz2)