From b7b520881fcaa4e159435cfad07424badde7f6ed Mon Sep 17 00:00:00 2001 From: mzr1996 Date: Wed, 14 Apr 2021 21:22:37 +0800 Subject: [PATCH] Update CONTRIBUTING.md according to mmcv (#210) * Update CONTRIBUTING.md according to mmcv * Docstring formatting by docformatter * Update openmmlab website. --- .github/CONTRIBUTING.md | 65 +++++++++++++++---- .pre-commit-config.yaml | 30 +++++++-- README.md | 2 +- mmcls/core/evaluation/eval_metrics.py | 6 +- mmcls/core/evaluation/mean_ap.py | 4 +- .../evaluation/multilabel_eval_metrics.py | 4 +- mmcls/datasets/cifar.py | 3 +- mmcls/datasets/mnist.py | 15 +++-- mmcls/datasets/multi_label.py | 3 +- mmcls/datasets/pipelines/auto_augment.py | 13 ++-- mmcls/datasets/pipelines/formating.py | 3 +- mmcls/datasets/pipelines/transforms.py | 6 +- mmcls/datasets/voc.py | 5 +- mmcls/models/backbones/base_backbone.py | 12 ++-- mmcls/models/backbones/mobilenet_v2.py | 2 +- mmcls/models/backbones/mobilenet_v3.py | 2 +- mmcls/models/backbones/regnet.py | 2 +- mmcls/models/backbones/resnet.py | 12 ++-- mmcls/models/backbones/shufflenet_v1.py | 2 +- mmcls/models/backbones/shufflenet_v2.py | 2 +- mmcls/models/classifiers/base.py | 17 ++--- mmcls/models/classifiers/image.py | 3 +- mmcls/models/heads/base_head.py | 4 +- mmcls/models/heads/multi_label_head.py | 1 - mmcls/models/heads/multi_label_linear_head.py | 1 - mmcls/models/losses/accuracy.py | 6 +- mmcls/models/losses/asymmetric_loss.py | 9 ++- mmcls/models/losses/cross_entropy_loss.py | 2 +- mmcls/models/losses/focal_loss.py | 6 +- mmcls/models/losses/label_smooth_loss.py | 14 ++-- mmcls/models/losses/utils.py | 4 +- mmcls/models/necks/gap.py | 7 +- mmcls/models/utils/inverted_residual.py | 3 +- mmcls/models/utils/mixup.py | 2 +- mmcls/version.py | 1 + tests/test_backbones/test_resnet.py | 2 +- tests/test_backbones/test_seresnet.py | 2 +- tests/test_backbones/test_vgg.py | 2 +- tools/convert_models/vgg_to_mmcls.py | 3 +- 39 files changed, 163 insertions(+), 119 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a8428ec6..6f8399b8 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributing to MMClassification +# Contributing to OpenMMLab All kinds of contributions are welcome, including but not limited to the following. @@ -7,24 +7,63 @@ All kinds of contributions are welcome, including but not limited to the followi ## Workflow -1. Fork and pull the latest mmclassification -2. Checkout a new branch with a meaningful name (do not use master branch for PRs) -3. Commit your changes -4. Create a PR +1. fork and pull the latest OpenMMLab repository (mmclassification) +3. checkout a new branch (do not use master branch for PRs) +4. commit your changes +5. create a PR -Note - -- If you plan to add some new features that involve large changes, it is encouraged to open an issue for discussion first. -- If you are the author of some papers and would like to include your method to mmclassification, - -please contact Lei Yang (jerryyanglei@gmail). We will much appreciate your contribution. +Note: If you plan to add some new features that involve large changes, it is encouraged to open an issue for discussion first. ## Code style ### Python We adopt [PEP8](https://www.python.org/dev/peps/pep-0008/) as the preferred code style. -We use [flake8](http://flake8.pycqa.org/en/latest/) as the linter and [yapf](https://github.com/google/yapf) as the formatter. -Please upgrade to the latest yapf (>=0.27.0) and refer to the [configuration](.style.yapf). + +We use the following tools for linting and formatting: + +- [flake8](http://flake8.pycqa.org/en/latest/): A wrapper around some linter tools. +- [yapf](https://github.com/google/yapf): A formatter for Python files. +- [isort](https://github.com/timothycrosley/isort): A Python utility to sort imports. +- [markdownlint](https://github.com/markdownlint/markdownlint): A linter to check markdown files and flag style issues. +- [docformatter](https://github.com/myint/docformatter): A formatter to format docstring. + +Style configurations of yapf and isort can be found in [setup.cfg](./setup.cfg). + +We use [pre-commit hook](https://pre-commit.com/) that checks and formats for `flake8`, `yapf`, `isort`, `trailing whitespaces`, `markdown files`, +fixes `end-of-files`, `double-quoted-strings`, `python-encoding-pragma`, `mixed-line-ending`, sorts `requirments.txt` automatically on every commit. +The config for a pre-commit hook is stored in [.pre-commit-config](./.pre-commit-config.yaml). + +After you clone the repository, you will need to install initialize pre-commit hook. + +```shell +pip install -U pre-commit +``` + +From the repository folder + +```shell +pre-commit install +``` + +Try the following steps to install ruby when you encounter an issue on installing markdownlint + +```shell +# install rvm +curl -L https://get.rvm.io | bash -s -- --autolibs=read-fail +[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" +rvm autolibs disable + +# install ruby +rvm install 2.7.1 +``` + +Or refer to [this repo](https://github.com/innerlee/setup) and take [`zzruby.sh`](https://github.com/innerlee/setup/blob/master/zzruby.sh) according its instruction. + +After this on every commit check code linters and formatter will be enforced. >Before you create a PR, make sure that your code lints and is formatted by yapf. + +### C++ and CUDA + +We follow the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html). diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f4afe367..efa84b8c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,32 +1,50 @@ +exclude: ^tests/data/ repos: - repo: https://gitlab.com/pycqa/flake8.git - rev: 3.8.0 + rev: 3.8.3 hooks: - id: flake8 - repo: https://github.com/asottile/seed-isort-config - rev: v2.1.0 + rev: v2.2.0 hooks: - id: seed-isort-config - repo: https://github.com/timothycrosley/isort rev: 4.3.21 hooks: - - id: isort + - id: isort - repo: https://github.com/pre-commit/mirrors-yapf - rev: v0.29.0 + rev: v0.30.0 hooks: - id: yapf - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.5.0 + rev: v3.1.0 hooks: - id: trailing-whitespace - id: check-yaml - id: end-of-file-fixer - id: requirements-txt-fixer - id: double-quote-string-fixer + - id: check-merge-conflict - id: fix-encoding-pragma args: ["--remove"] + - id: mixed-line-ending + args: ["--fix=lf"] - repo: https://github.com/jumanjihouse/pre-commit-hooks rev: 2.1.4 hooks: - id: markdownlint - args: ["-r", "~MD002,~MD013,~MD024,~MD029,~MD033,~MD034,~MD036"] + args: ["-r", "~MD002,~MD013,~MD029,~MD033,~MD034", + "-t", "allow_different_nesting"] + - repo: https://github.com/myint/docformatter + rev: v1.3.1 + hooks: + - id: docformatter + args: ["--in-place", "--wrap-descriptions", "79"] + # - repo: local + # hooks: + # - id: clang-format + # name: clang-format + # description: Format files with ClangFormat + # entry: clang-format -style=google -i + # language: system + # files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|cuh|proto)$ diff --git a/README.md b/README.md index 67e71f41..82e51da7 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## Introduction MMClassification is an open source image classification toolbox based on PyTorch. It is -a part of the [OpenMMLab](https://open-mmlab.github.io/) project. +a part of the [OpenMMLab](https://openmmlab.com/) project. Documentation: https://mmclassification.readthedocs.io/en/latest/ diff --git a/mmcls/core/evaluation/eval_metrics.py b/mmcls/core/evaluation/eval_metrics.py index 93112b0c..64e4b953 100644 --- a/mmcls/core/evaluation/eval_metrics.py +++ b/mmcls/core/evaluation/eval_metrics.py @@ -38,7 +38,7 @@ def calculate_confusion_matrix(pred, target): def precision_recall_f1(pred, target, average_mode='macro', thrs=None): """Calculate precision, recall and f1 score according to the prediction and - target. + target. Args: pred (torch.Tensor | np.array): The model prediction with shape (N, C). @@ -204,8 +204,8 @@ def f1_score(pred, target, average_mode='macro', thrs=None): def support(pred, target, average_mode='macro'): - """Calculate the total number of occurrences of each label according to - the prediction and target. + """Calculate the total number of occurrences of each label according to the + prediction and target. Args: pred (torch.Tensor | np.array): The model prediction with shape (N, C). diff --git a/mmcls/core/evaluation/mean_ap.py b/mmcls/core/evaluation/mean_ap.py index 44331cab..2255ce22 100644 --- a/mmcls/core/evaluation/mean_ap.py +++ b/mmcls/core/evaluation/mean_ap.py @@ -3,7 +3,7 @@ import torch def average_precision(pred, target): - """ Calculate the average precision for a single class + """Calculate the average precision for a single class. AP summarizes a precision-recall curve as the weighted mean of maximum precisions obtained for any r'>r, where r is the recall: @@ -43,7 +43,7 @@ def average_precision(pred, target): def mAP(pred, target): - """ Calculate the mean average precision with respect of classes + """Calculate the mean average precision with respect of classes. Args: pred (torch.Tensor | np.ndarray): The model prediction with shape diff --git a/mmcls/core/evaluation/multilabel_eval_metrics.py b/mmcls/core/evaluation/multilabel_eval_metrics.py index c8663a16..e8fcfc11 100644 --- a/mmcls/core/evaluation/multilabel_eval_metrics.py +++ b/mmcls/core/evaluation/multilabel_eval_metrics.py @@ -6,8 +6,8 @@ import torch def average_performance(pred, target, thr=None, k=None): """Calculate CP, CR, CF1, OP, OR, OF1, where C stands for per-class - average, O stands for overall average, P stands for precision, R - stands for recall and F1 stands for F1-score + average, O stands for overall average, P stands for precision, R stands for + recall and F1 stands for F1-score. Args: pred (torch.Tensor | np.ndarray): The model prediction with shape diff --git a/mmcls/datasets/cifar.py b/mmcls/datasets/cifar.py index 27a5d747..a2c22d1e 100644 --- a/mmcls/datasets/cifar.py +++ b/mmcls/datasets/cifar.py @@ -102,8 +102,7 @@ class CIFAR10(BaseDataset): @DATASETS.register_module() class CIFAR100(CIFAR10): - """`CIFAR100 `_ Dataset. - """ + """`CIFAR100 `_ Dataset.""" base_folder = 'cifar-100-python' url = 'https://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz' diff --git a/mmcls/datasets/mnist.py b/mmcls/datasets/mnist.py index fadc2f71..0bd41725 100644 --- a/mmcls/datasets/mnist.py +++ b/mmcls/datasets/mnist.py @@ -84,8 +84,7 @@ class MNIST(BaseDataset): @DATASETS.register_module() class FashionMNIST(MNIST): """`Fashion-MNIST `_ - Dataset. - """ + Dataset.""" resource_prefix = 'http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/' # noqa: E501 resources = { @@ -110,8 +109,9 @@ def get_int(b): def open_maybe_compressed_file(path): """Return a file object that possibly decompresses 'path' on the fly. - Decompression occurs when argument `path` is a string - and ends with '.gz' or '.xz'. + + Decompression occurs when argument `path` is a string and ends with '.gz' + or '.xz'. """ if not isinstance(path, str): return path @@ -125,9 +125,10 @@ def open_maybe_compressed_file(path): def read_sn3_pascalvincent_tensor(path, strict=True): - """Read a SN3 file in "Pascal Vincent" format - (Lush file 'libidx/idx-io.lsh'). - Argument may be a filename, compressed filename, or file object. + """Read a SN3 file in "Pascal Vincent" format (Lush file 'libidx/idx- + io.lsh'). + + Argument may be a filename, compressed filename, or file object. """ # typemap if not hasattr(read_sn3_pascalvincent_tensor, 'typemap'): diff --git a/mmcls/datasets/multi_label.py b/mmcls/datasets/multi_label.py index 8889de1b..68076a66 100644 --- a/mmcls/datasets/multi_label.py +++ b/mmcls/datasets/multi_label.py @@ -7,8 +7,7 @@ from .base_dataset import BaseDataset class MultiLabelDataset(BaseDataset): - """ Multi-label Dataset. - """ + """Multi-label Dataset.""" def get_cat_ids(self, idx): """Get category ids by index. diff --git a/mmcls/datasets/pipelines/auto_augment.py b/mmcls/datasets/pipelines/auto_augment.py index e4b48c89..b1892f08 100644 --- a/mmcls/datasets/pipelines/auto_augment.py +++ b/mmcls/datasets/pipelines/auto_augment.py @@ -15,9 +15,10 @@ def random_negative(value, random_negative_prob): @PIPELINES.register_module() class AutoAugment(object): - """Auto augmentation. - This data augmentation is proposed in `AutoAugment: Learning Augmentation - Policies from Data `_. + """Auto augmentation. This data augmentation is proposed in `AutoAugment: + Learning Augmentation Policies from Data. + + `_. Args: policies (list[list[dict]]): The policies of auto augmentation. Each @@ -53,9 +54,9 @@ class AutoAugment(object): @PIPELINES.register_module() class RandAugment(object): - """Random augmentation. - This data augmentation is proposed in `RandAugment: Practical automated - data augmentation with a reduced search space + """Random augmentation. This data augmentation is proposed in `RandAugment: + Practical automated data augmentation with a reduced search space. + `_. Args: diff --git a/mmcls/datasets/pipelines/formating.py b/mmcls/datasets/pipelines/formating.py index f8d785a2..be41d8f5 100644 --- a/mmcls/datasets/pipelines/formating.py +++ b/mmcls/datasets/pipelines/formating.py @@ -106,8 +106,7 @@ class ToNumpy(object): @PIPELINES.register_module() class Collect(object): - """ - Collect data from the loader relevant to the specific task. + """Collect data from the loader relevant to the specific task. This is usually the last stage of the data loader pipeline. Typically keys is set to some subset of "img" and "gt_label". diff --git a/mmcls/datasets/pipelines/transforms.py b/mmcls/datasets/pipelines/transforms.py index 99113316..f69eae23 100644 --- a/mmcls/datasets/pipelines/transforms.py +++ b/mmcls/datasets/pipelines/transforms.py @@ -272,7 +272,6 @@ class RandomGrayscale(object): - If input image is 1 channel: grayscale version is 1 channel. - If input image is 3 channel: grayscale version is 3 channel with r == g == b. - """ def __init__(self, gray_prob=0.1): @@ -661,6 +660,7 @@ class Albu(object): def albu_builder(self, cfg): """Import a module from albumentations. + It inherits some of :func:`build_from_cfg` logic. Args: cfg (dict): Config dict. It should at least contain the key "type". @@ -692,7 +692,9 @@ class Albu(object): @staticmethod def mapper(d, keymap): - """Dictionary mapper. Renames keys according to keymap provided. + """Dictionary mapper. + + Renames keys according to keymap provided. Args: d (dict): old dict keymap (dict): {'old_key':'new_key'} diff --git a/mmcls/datasets/voc.py b/mmcls/datasets/voc.py index 84d2dd04..7eeb552d 100644 --- a/mmcls/datasets/voc.py +++ b/mmcls/datasets/voc.py @@ -10,8 +10,7 @@ from .multi_label import MultiLabelDataset @DATASETS.register_module() class VOC(MultiLabelDataset): - """`Pascal VOC `_ Dataset. - """ + """`Pascal VOC `_ Dataset.""" CLASSES = ('aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', @@ -26,7 +25,7 @@ class VOC(MultiLabelDataset): raise ValueError('Cannot infer dataset year from img_prefix.') def load_annotations(self): - """Load annotations + """Load annotations. Returns: list[dict]: Annotation info from XML file. diff --git a/mmcls/models/backbones/base_backbone.py b/mmcls/models/backbones/base_backbone.py index 1e163862..f1d21382 100644 --- a/mmcls/models/backbones/base_backbone.py +++ b/mmcls/models/backbones/base_backbone.py @@ -8,17 +8,15 @@ from mmcv.runner import load_checkpoint class BaseBackbone(nn.Module, metaclass=ABCMeta): """Base backbone. - This class defines the basic functions of a backbone. - Any backbone that inherits this class should at least - define its own `forward` function. - + This class defines the basic functions of a backbone. Any backbone that + inherits this class should at least define its own `forward` function. """ def __init__(self): super(BaseBackbone, self).__init__() def init_weights(self, pretrained=None): - """Init backbone weights + """Init backbone weights. Args: pretrained (str | None): If pretrained is a string, then it @@ -38,7 +36,7 @@ class BaseBackbone(nn.Module, metaclass=ABCMeta): @abstractmethod def forward(self, x): - """Forward computation + """Forward computation. Args: x (tensor | tuple[tensor]): x could be a Torch.tensor or a tuple of @@ -47,7 +45,7 @@ class BaseBackbone(nn.Module, metaclass=ABCMeta): pass def train(self, mode=True): - """Set module status before forward computation + """Set module status before forward computation. Args: mode (bool): Whether it is train_mode or test_mode diff --git a/mmcls/models/backbones/mobilenet_v2.py b/mmcls/models/backbones/mobilenet_v2.py index 7c36d2c4..64433d2f 100644 --- a/mmcls/models/backbones/mobilenet_v2.py +++ b/mmcls/models/backbones/mobilenet_v2.py @@ -199,7 +199,7 @@ class MobileNetV2(BaseBackbone): self.layers.append('conv2') def make_layer(self, out_channels, num_blocks, stride, expand_ratio): - """ Stack InvertedResidual blocks to build a layer for MobileNetV2. + """Stack InvertedResidual blocks to build a layer for MobileNetV2. Args: out_channels (int): out_channels of block. diff --git a/mmcls/models/backbones/mobilenet_v3.py b/mmcls/models/backbones/mobilenet_v3.py index dbbc8579..ee6693f4 100644 --- a/mmcls/models/backbones/mobilenet_v3.py +++ b/mmcls/models/backbones/mobilenet_v3.py @@ -12,7 +12,7 @@ from .base_backbone import BaseBackbone @BACKBONES.register_module() class MobileNetv3(BaseBackbone): - """ MobileNetv3 backbone + """MobileNetv3 backbone. Args: arch (str): Architechture of mobilnetv3, from {small, big}. diff --git a/mmcls/models/backbones/regnet.py b/mmcls/models/backbones/regnet.py index b780d182..93f773fc 100644 --- a/mmcls/models/backbones/regnet.py +++ b/mmcls/models/backbones/regnet.py @@ -273,7 +273,7 @@ class RegNet(ResNet): return widths, groups def get_stages_from_blocks(self, widths): - """Gets widths/stage_blocks of network at each stage + """Gets widths/stage_blocks of network at each stage. Args: widths (list[int]): Width in each stage. diff --git a/mmcls/models/backbones/resnet.py b/mmcls/models/backbones/resnet.py index 1f83887b..4d031de0 100644 --- a/mmcls/models/backbones/resnet.py +++ b/mmcls/models/backbones/resnet.py @@ -634,13 +634,13 @@ class ResNet(BaseBackbone): @BACKBONES.register_module() class ResNetV1d(ResNet): - """ResNetV1d variant described in - `Bag of Tricks `_. + """ResNetV1d variant described in `Bag of Tricks. - Compared with default ResNet(ResNetV1b), ResNetV1d replaces the 7x7 conv - in the input stem with three 3x3 convs. And in the downsampling block, - a 2x2 avg_pool with stride 2 is added before conv, whose stride is - changed to 1. + `_. + + Compared with default ResNet(ResNetV1b), ResNetV1d replaces the 7x7 conv in + the input stem with three 3x3 convs. And in the downsampling block, a 2x2 + avg_pool with stride 2 is added before conv, whose stride is changed to 1. """ def __init__(self, **kwargs): diff --git a/mmcls/models/backbones/shufflenet_v1.py b/mmcls/models/backbones/shufflenet_v1.py index a3a8d30f..e5d5f43c 100644 --- a/mmcls/models/backbones/shufflenet_v1.py +++ b/mmcls/models/backbones/shufflenet_v1.py @@ -271,7 +271,7 @@ class ShuffleNetV1(BaseBackbone): f'{type(pretrained)}') def make_layer(self, out_channels, num_blocks, first_block=False): - """ Stack ShuffleUnit blocks to make a layer. + """Stack ShuffleUnit blocks to make a layer. Args: out_channels (int): out_channels of the block. diff --git a/mmcls/models/backbones/shufflenet_v2.py b/mmcls/models/backbones/shufflenet_v2.py index 2f4f1043..2a498eef 100644 --- a/mmcls/models/backbones/shufflenet_v2.py +++ b/mmcls/models/backbones/shufflenet_v2.py @@ -222,7 +222,7 @@ class ShuffleNetV2(BaseBackbone): act_cfg=act_cfg)) def _make_layer(self, out_channels, num_blocks): - """ Stack blocks to make a layer. + """Stack blocks to make a layer. Args: out_channels (int): out_channels of the block. diff --git a/mmcls/models/classifiers/base.py b/mmcls/models/classifiers/base.py index d4d72bdf..fa0e1c3e 100644 --- a/mmcls/models/classifiers/base.py +++ b/mmcls/models/classifiers/base.py @@ -20,7 +20,7 @@ except ImportError: class BaseClassifier(nn.Module, metaclass=ABCMeta): - """Base class for classifiers""" + """Base class for classifiers.""" def __init__(self): super(BaseClassifier, self).__init__() @@ -81,13 +81,14 @@ class BaseClassifier(nn.Module, metaclass=ABCMeta): @auto_fp16(apply_to=('img', )) def forward(self, img, return_loss=True, **kwargs): - """ - Calls either forward_train or forward_test depending on whether - return_loss=True. Note this setting will change the expected inputs. - When `return_loss=True`, img and img_meta are single-nested (i.e. - Tensor and List[dict]), and when `resturn_loss=False`, img and img_meta - should be double nested (i.e. List[Tensor], List[List[dict]]), with - the outer list indicating test time augmentations. + """Calls either forward_train or forward_test depending on whether + return_loss=True. + + Note this setting will change the expected inputs. When + `return_loss=True`, img and img_meta are single-nested (i.e. Tensor and + List[dict]), and when `resturn_loss=False`, img and img_meta should be + double nested (i.e. List[Tensor], List[List[dict]]), with the outer + list indicating test time augmentations. """ if return_loss: return self.forward_train(img, **kwargs) diff --git a/mmcls/models/classifiers/image.py b/mmcls/models/classifiers/image.py index fee4dd61..e70d88d0 100644 --- a/mmcls/models/classifiers/image.py +++ b/mmcls/models/classifiers/image.py @@ -44,8 +44,7 @@ class ImageClassifier(BaseClassifier): self.head.init_weights() def extract_feat(self, img): - """Directly extract features from the backbone + neck - """ + """Directly extract features from the backbone + neck.""" x = self.backbone(img) if self.with_neck: x = self.neck(x) diff --git a/mmcls/models/heads/base_head.py b/mmcls/models/heads/base_head.py index b66d2f10..053390ee 100644 --- a/mmcls/models/heads/base_head.py +++ b/mmcls/models/heads/base_head.py @@ -4,9 +4,7 @@ import torch.nn as nn class BaseHead(nn.Module, metaclass=ABCMeta): - """Base head. - - """ + """Base head.""" def __init__(self): super(BaseHead, self).__init__() diff --git a/mmcls/models/heads/multi_label_head.py b/mmcls/models/heads/multi_label_head.py index e3109638..e5ea4fe9 100644 --- a/mmcls/models/heads/multi_label_head.py +++ b/mmcls/models/heads/multi_label_head.py @@ -11,7 +11,6 @@ class MultiLabelClsHead(BaseHead): Args: loss (dict): Config of classification loss. - """ def __init__(self, diff --git a/mmcls/models/heads/multi_label_linear_head.py b/mmcls/models/heads/multi_label_linear_head.py index b2507d0e..0922542f 100644 --- a/mmcls/models/heads/multi_label_linear_head.py +++ b/mmcls/models/heads/multi_label_linear_head.py @@ -15,7 +15,6 @@ class MultiLabelLinearClsHead(MultiLabelClsHead): num_classes (int): Number of categories. in_channels (int): Number of channels in the input feature map. loss (dict): Config of classification loss. - """ def __init__(self, diff --git a/mmcls/models/losses/accuracy.py b/mmcls/models/losses/accuracy.py index d46c05ab..4ce2b07c 100644 --- a/mmcls/models/losses/accuracy.py +++ b/mmcls/models/losses/accuracy.py @@ -69,7 +69,7 @@ def accuracy_torch(pred, target, topk=1, thrs=None): def accuracy(pred, target, topk=1, thrs=None): - """Calculate accuracy according to the prediction and target + """Calculate accuracy according to the prediction and target. Args: pred (torch.Tensor | np.array): The model prediction. @@ -112,7 +112,7 @@ def accuracy(pred, target, topk=1, thrs=None): class Accuracy(nn.Module): def __init__(self, topk=(1, )): - """Module to calculate the accuracy + """Module to calculate the accuracy. Args: topk (tuple): The criterion used to calculate the @@ -122,7 +122,7 @@ class Accuracy(nn.Module): self.topk = topk def forward(self, pred, target): - """Forward function to calculate accuracy + """Forward function to calculate accuracy. Args: pred (torch.Tensor): Prediction of models. diff --git a/mmcls/models/losses/asymmetric_loss.py b/mmcls/models/losses/asymmetric_loss.py index 09ec46dc..5b15f167 100644 --- a/mmcls/models/losses/asymmetric_loss.py +++ b/mmcls/models/losses/asymmetric_loss.py @@ -13,7 +13,7 @@ def asymmetric_loss(pred, clip=0.05, reduction='mean', avg_factor=None): - """asymmetric loss + """asymmetric loss. Please refer to the `paper `_ for details. @@ -63,7 +63,7 @@ def asymmetric_loss(pred, @LOSSES.register_module() class AsymmetricLoss(nn.Module): - """asymmetric loss + """asymmetric loss. Args: gamma_pos (float): positive focusing parameter. @@ -74,7 +74,7 @@ class AsymmetricLoss(nn.Module): reduction (str): The method used to reduce the loss into a scalar. loss_weight (float): Weight of loss. Defaults to 1.0. - """ + """ def __init__(self, gamma_pos=0.0, @@ -95,8 +95,7 @@ class AsymmetricLoss(nn.Module): weight=None, avg_factor=None, reduction_override=None): - """asymmetric loss - """ + """asymmetric loss.""" assert reduction_override in (None, 'none', 'mean', 'sum') reduction = ( reduction_override if reduction_override else self.reduction) diff --git a/mmcls/models/losses/cross_entropy_loss.py b/mmcls/models/losses/cross_entropy_loss.py index b003c77e..05859521 100644 --- a/mmcls/models/losses/cross_entropy_loss.py +++ b/mmcls/models/losses/cross_entropy_loss.py @@ -103,7 +103,7 @@ def binary_cross_entropy(pred, @LOSSES.register_module() class CrossEntropyLoss(nn.Module): - """Cross entropy loss + """Cross entropy loss. Args: use_sigmoid (bool): Whether the prediction uses sigmoid diff --git a/mmcls/models/losses/focal_loss.py b/mmcls/models/losses/focal_loss.py index 93d82997..f8b61653 100644 --- a/mmcls/models/losses/focal_loss.py +++ b/mmcls/models/losses/focal_loss.py @@ -12,7 +12,7 @@ def sigmoid_focal_loss(pred, alpha=0.25, reduction='mean', avg_factor=None): - """Sigmoid focal loss + """Sigmoid focal loss. Args: pred (torch.Tensor): The prediction with shape (N, *). @@ -52,7 +52,7 @@ def sigmoid_focal_loss(pred, @LOSSES.register_module() class FocalLoss(nn.Module): - """Focal loss + """Focal loss. Args: gamma (float): Focusing parameter in focal loss. @@ -82,7 +82,7 @@ class FocalLoss(nn.Module): weight=None, avg_factor=None, reduction_override=None): - """Sigmoid focal loss + """Sigmoid focal loss. Args: pred (torch.Tensor): The prediction with shape (N, *). diff --git a/mmcls/models/losses/label_smooth_loss.py b/mmcls/models/losses/label_smooth_loss.py index 6d6bdcf4..299f6795 100644 --- a/mmcls/models/losses/label_smooth_loss.py +++ b/mmcls/models/losses/label_smooth_loss.py @@ -38,10 +38,8 @@ class LabelSmoothLoss(CrossEntropyLoss): self._eps = np.finfo(np.float32).eps def generate_one_hot_like_label(self, label): - """ - This function takes one-hot or index label vectors and computes - one-hot like label vectors (float) - """ + """This function takes one-hot or index label vectors and computes one- + hot like label vectors (float)""" label_shape_list = list(label.size()) # check if targets are inputted as class integers if len(label_shape_list) == 1 or (len(label_shape_list) == 2 @@ -50,11 +48,9 @@ class LabelSmoothLoss(CrossEntropyLoss): return label.float() def smooth_label(self, one_hot_like_label): - """ - This function takes one-hot like target vectors and - computes smoothed target vectors (normalized) - according to the loss's smoothing parameter - """ + """This function takes one-hot like target vectors and computes + smoothed target vectors (normalized) according to the loss's smoothing + parameter.""" assert self.num_classes > 0 one_hot_like_label /= self._eps + one_hot_like_label.sum( dim=1, keepdim=True) diff --git a/mmcls/models/losses/utils.py b/mmcls/models/losses/utils.py index e5d4c47f..e7303443 100644 --- a/mmcls/models/losses/utils.py +++ b/mmcls/models/losses/utils.py @@ -100,8 +100,8 @@ def weighted_loss(loss_func): def convert_to_one_hot(targets: torch.Tensor, classes) -> torch.Tensor: - """This function converts target class indices to one-hot vectors, - given the number of classes. + """This function converts target class indices to one-hot vectors, given + the number of classes. Args: targets (Tensor): The ground truth label of the prediction diff --git a/mmcls/models/necks/gap.py b/mmcls/models/necks/gap.py index 016a5971..e9b7a95f 100644 --- a/mmcls/models/necks/gap.py +++ b/mmcls/models/necks/gap.py @@ -8,10 +8,9 @@ from ..builder import NECKS class GlobalAveragePooling(nn.Module): """Global Average Pooling neck. - Note that we use `view` to remove extra channel after pooling. - We do not use `squeeze` as it will also remove the batch dimension - when the tensor has a batch dimension of size 1, which can lead to - unexpected errors. + Note that we use `view` to remove extra channel after pooling. We do not + use `squeeze` as it will also remove the batch dimension when the tensor + has a batch dimension of size 1, which can lead to unexpected errors. """ def __init__(self): diff --git a/mmcls/models/utils/inverted_residual.py b/mmcls/models/utils/inverted_residual.py index 261d929e..e7cc6810 100644 --- a/mmcls/models/utils/inverted_residual.py +++ b/mmcls/models/utils/inverted_residual.py @@ -6,7 +6,7 @@ from .se_layer import SELayer class InvertedResidual(nn.Module): - """Inverted Residual Block + """Inverted Residual Block. Args: in_channels (int): The input channels of this Module. @@ -31,7 +31,6 @@ class InvertedResidual(nn.Module): Returns: Tensor: The output tensor. - """ def __init__(self, diff --git a/mmcls/models/utils/mixup.py b/mmcls/models/utils/mixup.py index 2a42bef9..8d46d6ee 100644 --- a/mmcls/models/utils/mixup.py +++ b/mmcls/models/utils/mixup.py @@ -6,7 +6,7 @@ from torch.distributions.beta import Beta class BaseMixupLayer(object, metaclass=ABCMeta): - """Base class for MixupLayer""" + """Base class for MixupLayer.""" def __init__(self): super(BaseMixupLayer, self).__init__() diff --git a/mmcls/version.py b/mmcls/version.py index 03a4cc7c..684c14b8 100644 --- a/mmcls/version.py +++ b/mmcls/version.py @@ -5,6 +5,7 @@ __version__ = '0.10.0' def parse_version_info(version_str): """Parse a version string into a tuple. + Args: version_str (str): The version string. Returns: diff --git a/tests/test_backbones/test_resnet.py b/tests/test_backbones/test_resnet.py index b39da03a..0912a12d 100644 --- a/tests/test_backbones/test_resnet.py +++ b/tests/test_backbones/test_resnet.py @@ -371,7 +371,7 @@ def test_bottleneck_reslayer(): def test_resnet(): - """Test resnet backbone""" + """Test resnet backbone.""" with pytest.raises(KeyError): # ResNet depth should be in [18, 34, 50, 101, 152] ResNet(20) diff --git a/tests/test_backbones/test_seresnet.py b/tests/test_backbones/test_seresnet.py index cb60e602..c2550447 100644 --- a/tests/test_backbones/test_seresnet.py +++ b/tests/test_backbones/test_seresnet.py @@ -120,7 +120,7 @@ def test_res_layer(): def test_seresnet(): - """Test resnet backbone""" + """Test resnet backbone.""" with pytest.raises(KeyError): # SEResNet depth should be in [50, 101, 152] SEResNet(20) diff --git a/tests/test_backbones/test_vgg.py b/tests/test_backbones/test_vgg.py index fc184214..7696833e 100644 --- a/tests/test_backbones/test_vgg.py +++ b/tests/test_backbones/test_vgg.py @@ -15,7 +15,7 @@ def check_norm_state(modules, train_state): def test_vgg(): - """Test VGG backbone""" + """Test VGG backbone.""" with pytest.raises(KeyError): # VGG depth should be in [11, 13, 16, 19] VGG(18) diff --git a/tools/convert_models/vgg_to_mmcls.py b/tools/convert_models/vgg_to_mmcls.py index db93059b..f1937c48 100644 --- a/tools/convert_models/vgg_to_mmcls.py +++ b/tools/convert_models/vgg_to_mmcls.py @@ -56,8 +56,7 @@ def get_layer_maps(layer_num, with_bn): def convert(src, dst, layer_num, with_bn=False): - """Convert keys in torchvision pretrained VGG models to mmcls - style.""" + """Convert keys in torchvision pretrained VGG models to mmcls style.""" # load pytorch model assert os.path.isfile(src), f'no checkpoint found at {src}'