From 803254bb40526cadb9a087a90917e599c79d1e94 Mon Sep 17 00:00:00 2001 From: Ross Wightman Date: Mon, 24 Oct 2022 21:43:49 -0700 Subject: [PATCH 01/10] Fix spacing misalignment for fast norm path in LayerNorm modules --- timm/models/layers/norm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/timm/models/layers/norm.py b/timm/models/layers/norm.py index 42445a49..77d719ed 100644 --- a/timm/models/layers/norm.py +++ b/timm/models/layers/norm.py @@ -50,7 +50,7 @@ class LayerNorm(nn.LayerNorm): def forward(self, x: torch.Tensor) -> torch.Tensor: if self._fast_norm: - x = fast_layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps) + x = fast_layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps) else: x = F.layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps) return x @@ -65,7 +65,7 @@ class LayerNorm2d(nn.LayerNorm): def forward(self, x: torch.Tensor) -> torch.Tensor: x = x.permute(0, 2, 3, 1) if self._fast_norm: - x = fast_layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps) + x = fast_layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps) else: x = F.layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps) x = x.permute(0, 3, 1, 2) From 29baf32327cd1a1f7ae50d1b6b331b446698e883 Mon Sep 17 00:00:00 2001 From: hova88 <84240614@qq.com> Date: Fri, 28 Oct 2022 09:30:51 +0800 Subject: [PATCH 02/10] fix typo : miss back quote --- train.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/train.py b/train.py index e004881d..d106f3dc 100755 --- a/train.py +++ b/train.py @@ -145,7 +145,7 @@ group.add_argument('--grad-checkpointing', action='store_true', default=False, # Optimizer parameters group = parser.add_argument_group('Optimizer parameters') group.add_argument('--opt', default='sgd', type=str, metavar='OPTIMIZER', - help='Optimizer (default: "sgd"') + help='Optimizer (default: "sgd")') group.add_argument('--opt-eps', default=None, type=float, metavar='EPSILON', help='Optimizer Epsilon (default: None, use opt default)') group.add_argument('--opt-betas', default=None, type=float, nargs='+', metavar='BETA', @@ -210,7 +210,7 @@ group.add_argument('--warmup-prefix', action='store_true', default=False, group.add_argument('--cooldown-epochs', type=int, default=0, metavar='N', help='epochs to cooldown LR at min_lr, after cyclic schedule ends') group.add_argument('--patience-epochs', type=int, default=10, metavar='N', - help='patience epochs for Plateau LR scheduler (default: 10') + help='patience epochs for Plateau LR scheduler (default: 10)') group.add_argument('--decay-rate', '--dr', type=float, default=0.1, metavar='RATE', help='LR decay rate (default: 0.1)') From 9152b1047841ec159115d6e6c1cf56eedfb5b9c8 Mon Sep 17 00:00:00 2001 From: NPU-Franklin <1109797240@qq.com> Date: Sun, 30 Oct 2022 08:49:40 +0800 Subject: [PATCH 03/10] :pencil2: fix typo --- train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/train.py b/train.py index d106f3dc..dfbbc0b5 100755 --- a/train.py +++ b/train.py @@ -97,7 +97,7 @@ group.add_argument('--class-map', default='', type=str, metavar='FILENAME', # Model parameters group = parser.add_argument_group('Model parameters') group.add_argument('--model', default='resnet50', type=str, metavar='MODEL', - help='Name of model to train (default: "resnet50"') + help='Name of model to train (default: "resnet50")') group.add_argument('--pretrained', action='store_true', default=False, help='Start with pretrained version of specified network (if avail)') group.add_argument('--initial-checkpoint', default='', type=str, metavar='PATH', From ddd6361904136b7e709e70475db223a074b12fa9 Mon Sep 17 00:00:00 2001 From: klae01 <101966044+klae01@users.noreply.github.com> Date: Tue, 1 Nov 2022 16:55:05 +0900 Subject: [PATCH 04/10] Update train.py fix typo args.in_chanes --- train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/train.py b/train.py index d106f3dc..c4127fab 100755 --- a/train.py +++ b/train.py @@ -407,7 +407,7 @@ def main(): in_chans = 3 if args.in_chans is not None: - in_chans = args.in_chanes + in_chans = args.in_chans elif args.input_size is not None: in_chans = args.input_size[0] From 8ff45e41f7a6aba4d5fdadee7dc3b7f2733df045 Mon Sep 17 00:00:00 2001 From: Ross Wightman Date: Wed, 26 Oct 2022 22:32:32 -0700 Subject: [PATCH 05/10] Fix xdist dependency change --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d6474086..f85aff42 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,7 +30,7 @@ jobs: - name: Install testing dependencies run: | python -m pip install --upgrade pip - pip install pytest pytest-timeout pytest-xdist expecttest + pip install pytest pytest-timeout pytest-xdist pytest-forked expecttest - name: Install torch on mac if: startsWith(matrix.os, 'macOS') run: pip install --no-cache-dir torch==${{ matrix.torch }} torchvision==${{ matrix.torchvision }} From ae0a0db7de06fa994a5ca0cb790422837eba924e Mon Sep 17 00:00:00 2001 From: Wauplin Date: Tue, 15 Nov 2022 15:17:20 +0100 Subject: [PATCH 06/10] Create repo before cloning with Repository.clone_from --- timm/models/hub.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/timm/models/hub.py b/timm/models/hub.py index 8b63ff7e..938f10eb 100644 --- a/timm/models/hub.py +++ b/timm/models/hub.py @@ -130,25 +130,28 @@ def push_to_hf_hub( revision=None, model_config=None, ): + if isinstance(use_auth_token, str): + token = use_auth_token + else: + token = HfFolder.get_token() + if token is None: + raise ValueError( + "You must login to the Hugging Face hub on this computer by typing `huggingface-cli login` and " + "entering your credentials to use `use_auth_token=True`. Alternatively, you can pass your own " + "token as the `use_auth_token` argument." + ) + if repo_namespace_or_url: repo_owner, repo_name = repo_namespace_or_url.rstrip('/').split('/')[-2:] else: - if isinstance(use_auth_token, str): - token = use_auth_token - else: - token = HfFolder.get_token() - - if token is None: - raise ValueError( - "You must login to the Hugging Face hub on this computer by typing `transformers-cli login` and " - "entering your credentials to use `use_auth_token=True`. Alternatively, you can pass your own " - "token as the `use_auth_token` argument." - ) - repo_owner = HfApi().whoami(token)['name'] repo_name = Path(local_dir).name - repo_url = f'https://huggingface.co/{repo_owner}/{repo_name}' + repo_id = f'{repo_owner}/{repo_name}' + repo_url = f'https://huggingface.co/{repo_id}' + + # Create repo if doesn't exist yet + HfApi().create_repo(repo_id, token=use_auth_token, exist_ok=True) repo = Repository( local_dir, From 9b114754dbbf2fc327bd7835af91aa41af7348d3 Mon Sep 17 00:00:00 2001 From: Wauplin Date: Wed, 16 Nov 2022 12:03:34 +0100 Subject: [PATCH 07/10] refactor push_to_hub helper --- timm/models/hub.py | 92 ++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 49 deletions(-) diff --git a/timm/models/hub.py b/timm/models/hub.py index 938f10eb..4cf3e4e7 100644 --- a/timm/models/hub.py +++ b/timm/models/hub.py @@ -3,10 +3,12 @@ import logging import os from functools import partial from pathlib import Path -from typing import Union +from tempfile import TemporaryDirectory +from typing import Optional, Union import torch from torch.hub import HASH_REGEX, download_url_to_file, urlparse + try: from torch.hub import get_dir except ImportError: @@ -15,7 +17,10 @@ except ImportError: from timm import __version__ try: - from huggingface_hub import HfApi, HfFolder, Repository, hf_hub_download, hf_hub_url + from huggingface_hub import (create_repo, get_hf_file_metadata, + hf_hub_download, hf_hub_url, + repo_type_and_id_from_hf_id, upload_folder) + from huggingface_hub.utils import EntryNotFoundError hf_hub_download = partial(hf_hub_download, library_name="timm", library_version=__version__) _has_hf_hub = True except ImportError: @@ -121,56 +126,45 @@ def save_for_hf(model, save_directory, model_config=None): def push_to_hf_hub( model, - local_dir, - repo_namespace_or_url=None, - commit_message='Add model', - use_auth_token=True, - git_email=None, - git_user=None, - revision=None, - model_config=None, + repo_id: str, + commit_message: str ='Add model', + token: Optional[str] = None, + revision: Optional[str] = None, + private: bool = False, + create_pr: bool = False, + model_config: Optional[dict] = None, ): - if isinstance(use_auth_token, str): - token = use_auth_token - else: - token = HfFolder.get_token() - if token is None: - raise ValueError( - "You must login to the Hugging Face hub on this computer by typing `huggingface-cli login` and " - "entering your credentials to use `use_auth_token=True`. Alternatively, you can pass your own " - "token as the `use_auth_token` argument." - ) - - if repo_namespace_or_url: - repo_owner, repo_name = repo_namespace_or_url.rstrip('/').split('/')[-2:] - else: - repo_owner = HfApi().whoami(token)['name'] - repo_name = Path(local_dir).name - - repo_id = f'{repo_owner}/{repo_name}' - repo_url = f'https://huggingface.co/{repo_id}' - # Create repo if doesn't exist yet - HfApi().create_repo(repo_id, token=use_auth_token, exist_ok=True) - - repo = Repository( - local_dir, - clone_from=repo_url, - use_auth_token=use_auth_token, - git_user=git_user, - git_email=git_email, - revision=revision, - ) - - # Prepare a default model card that includes the necessary tags to enable inference. - readme_text = f'---\ntags:\n- image-classification\n- timm\nlibrary_tag: timm\n---\n# Model card for {repo_name}' - with repo.commit(commit_message): + repo_url = create_repo(repo_id, token=token, private=private, exist_ok=True) + + # Infer complete repo_id from repo_url + # Can be different from the input `repo_id` if repo_owner was implicit + _, repo_owner, repo_name = repo_type_and_id_from_hf_id(repo_url) + repo_id = f"{repo_owner}/{repo_name}" + + # Check if README file already exist in repo + try: + get_hf_file_metadata(hf_hub_url(repo_id=repo_id, filename="README.md", revision=revision)) + has_readme = True + except EntryNotFoundError: + has_readme = False + + # Dump model and push to Hub + with TemporaryDirectory() as tmpdir: # Save model weights and config. - save_for_hf(model, repo.local_dir, model_config=model_config) + save_for_hf(model, tmpdir, model_config=model_config) - # Save a model card if it doesn't exist. - readme_path = Path(repo.local_dir) / 'README.md' - if not readme_path.exists(): + # Add readme if does not exist + if not has_readme: + readme_path = Path(tmpdir) / "README.md" + readme_text = f'---\ntags:\n- image-classification\n- timm\nlibrary_tag: timm\n---\n# Model card for {repo_id}' readme_path.write_text(readme_text) - return repo.git_remote_url() + # Upload model and return + return upload_folder( + repo_id=repo_id, + folder_path=tmpdir, + revision=revision, + create_pr=create_pr, + commit_message=commit_message, + ) From bdc9fad63838e5e1b354b5c357521ceb9652fa75 Mon Sep 17 00:00:00 2001 From: hongxin xiang Date: Thu, 24 Nov 2022 14:37:44 +0800 Subject: [PATCH 08/10] Fix compatible BUG: QMNIST and ImageNet datasets do not exist in torchvision 0.10.1. --- timm/data/dataset_factory.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/timm/data/dataset_factory.py b/timm/data/dataset_factory.py index 3777a5aa..92529357 100644 --- a/timm/data/dataset_factory.py +++ b/timm/data/dataset_factory.py @@ -4,7 +4,7 @@ Hacked together by / Copyright 2021, Ross Wightman """ import os -from torchvision.datasets import CIFAR100, CIFAR10, MNIST, QMNIST, KMNIST, FashionMNIST, ImageNet, ImageFolder +from torchvision.datasets import CIFAR100, CIFAR10, MNIST, KMNIST, FashionMNIST, ImageFolder try: from torchvision.datasets import Places365 has_places365 = True @@ -15,6 +15,16 @@ try: has_inaturalist = True except ImportError: has_inaturalist = False +try: + from torchvision.datasets import QMNIST + has_qmnist = True +except ImportError: + has_qmnist = False +try: + from torchvision.datasets import ImageNet + has_imagenet = True +except ImportError: + has_imagenet = False from .dataset import IterableImageDataset, ImageDataset @@ -22,7 +32,6 @@ _TORCH_BASIC_DS = dict( cifar10=CIFAR10, cifar100=CIFAR100, mnist=MNIST, - qmist=QMNIST, kmnist=KMNIST, fashion_mnist=FashionMNIST, ) From 653bdc7105098763cb672e344f6d716021f9c627 Mon Sep 17 00:00:00 2001 From: hongxin xiang Date: Fri, 25 Nov 2022 09:52:52 +0800 Subject: [PATCH 09/10] Fix comment: https://github.com/rwightman/pytorch-image-models/pull/1564#issuecomment-1326743424 --- timm/data/dataset_factory.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/timm/data/dataset_factory.py b/timm/data/dataset_factory.py index 92529357..757c2e5d 100644 --- a/timm/data/dataset_factory.py +++ b/timm/data/dataset_factory.py @@ -131,7 +131,12 @@ def create_dataset( elif split in _EVAL_SYNONYM: split = 'val' ds = Places365(split=split, **torch_kwargs) + elif name == 'qmnist': + assert has_qmnist, 'Please update to a newer PyTorch and torchvision for QMNIST dataset.' + use_train = split in _TRAIN_SYNONYM + ds = QMNIST(train=use_train, **torch_kwargs) elif name == 'imagenet': + assert has_imagenet, 'Please update to a newer PyTorch and torchvision for ImageNet dataset.' if split in _EVAL_SYNONYM: split = 'val' ds = ImageNet(split=split, **torch_kwargs) From e8ddc6865c2c74871e6953e8d42873829768ba14 Mon Sep 17 00:00:00 2001 From: Ross Wightman Date: Sat, 26 Nov 2022 19:46:55 -0800 Subject: [PATCH 10/10] Update torch to 1.13 and python to 3.10 in test workflow (#1562) * Update torch and python version in test workflow * Python back to 3.9 for test workflow, see if that's the cause of macos failure.. * Try windows runner * Try Python 3.10 + macOS-12 in quest for working second target * Remove macOS from tests, not working anymore --- .github/workflows/tests.yml | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f85aff42..5690c88c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,10 +15,10 @@ jobs: name: Run tests on ${{ matrix.os }} with Python ${{ matrix.python }} strategy: matrix: - os: [ubuntu-latest, macOS-latest] - python: ['3.9'] - torch: ['1.10.0'] - torchvision: ['0.11.1'] + os: [ubuntu-latest] + python: ['3.10'] + torch: ['1.13.0'] + torchvision: ['0.14.0'] runs-on: ${{ matrix.os }} steps: @@ -34,6 +34,9 @@ jobs: - name: Install torch on mac if: startsWith(matrix.os, 'macOS') run: pip install --no-cache-dir torch==${{ matrix.torch }} torchvision==${{ matrix.torchvision }} + - name: Install torch on Windows + if: startsWith(matrix.os, 'windows') + run: pip install --no-cache-dir torch==${{ matrix.torch }} torchvision==${{ matrix.torchvision }} - name: Install torch on ubuntu if: startsWith(matrix.os, 'ubuntu') run: | @@ -42,11 +45,18 @@ jobs: sudo apt install -y google-perftools - name: Install requirements run: | - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - pip install --no-cache-dir git+https://github.com/mapillary/inplace_abn.git@v1.1.0 - - name: Run tests + pip install -r requirements.txt + pip install --no-cache-dir git+https://github.com/mapillary/inplace_abn.git + - name: Run tests on Windows + if: startsWith(matrix.os, 'windows') + env: + PYTHONDONTWRITEBYTECODE: 1 + run: | + pytest -vv tests + - name: Run tests on Linux / Mac + if: ${{ !startsWith(matrix.os, 'windows') }} env: LD_PRELOAD: /usr/lib/x86_64-linux-gnu/libtcmalloc.so.4 + PYTHONDONTWRITEBYTECODE: 1 run: | - export PYTHONDONTWRITEBYTECODE=1 - pytest -vv --forked --durations=0 ./tests + pytest -vv --forked --durations=0 tests