From 4ca182dbb87ea52c5117354193f8099a1db74fc9 Mon Sep 17 00:00:00 2001 From: KaiyangZhou Date: Sun, 24 Mar 2019 15:52:39 +0000 Subject: [PATCH] add model public keys --- README.rst | 38 ++++++++++++- docs/user_guide.rst | 24 +++++++++ torchreid/models/__init__.py | 7 +++ torchreid/models/densenet.py | 57 +++++++++++++++++++- torchreid/models/hacnn.py | 3 ++ torchreid/models/inceptionresnetv2.py | 3 ++ torchreid/models/inceptionv4.py | 3 ++ torchreid/models/mlfn.py | 5 +- torchreid/models/mobilenetv2.py | 4 ++ torchreid/models/mudeep.py | 3 ++ torchreid/models/nasnet.py | 3 ++ torchreid/models/pcb.py | 4 ++ torchreid/models/resnet.py | 77 ++++++++++++++++++++++++++- torchreid/models/resnetmid.py | 3 ++ torchreid/models/resnext.py | 4 ++ torchreid/models/senet.py | 9 ++++ torchreid/models/shufflenet.py | 3 ++ torchreid/models/squeezenet.py | 5 ++ torchreid/models/xception.py | 3 ++ 19 files changed, 254 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 8590725..c6433cb 100755 --- a/README.rst +++ b/README.rst @@ -19,11 +19,23 @@ It features: Installation --------------- +1. Install PyTorch and torchvision following the `official instructions `_. +2. Install Cython. +3. Clone ``deep-person-reid`` to your preferred directory. + .. code-block:: bash $ git clone https://github.com/KaiyangZhou/deep-person-reid.git + +4. Install ``torchreid`` via + +.. code-block:: bash + $ cd deep-person-reid/ - $ python setup.py install # or python3 setup.py install + $ python setup.py install # or python3 + $ # If you wanna modify the source code without + $ # the need to re-build it, you can do + $ # python setup.py develop News @@ -102,6 +114,30 @@ Get started: 30 seconds to Torchreid ) +A unified interface +----------------------- +In "deep-person-reid/scripts/", we provide a unified interface including a default parser file ``default_parser.py`` and the main script ``main.py``. For example, to train an image reid model on Market1501 using softmax, you can do + +.. code-block:: python + + python main.py \ + --root path/to/reid-data \ + --app image \ + --loss softmax \ + --label-smooth \ + -s market1501 \ + -a resnet50 \ + --optim adam \ + --lr 0.0003 \ + --max-epoch 60 \ + --stepsize 20 40 \ + --batch-size 32 \ + --save-dir log/resnet50-market-softmax \ + --gpu-devices 0 + +Please refer to ``default_parser.py`` and ``main.py`` for more details. + + Datasets -------- diff --git a/docs/user_guide.rst b/docs/user_guide.rst index 73f16a3..a5b5432 100644 --- a/docs/user_guide.rst +++ b/docs/user_guide.rst @@ -5,6 +5,30 @@ How-to :local: +Find model keys +----------------- +Keys are listed under the *Public keys* section within each model class in :ref:`torchreid_models`. + + +Show available models +---------------------- + +.. code-block:: python + + import torchreid + torchreid.models.show_avai_models() + + +Change the training sampler +----------------------------- +The default ``train_sampler`` is "RandomSampler". You can give the specific sampler name as input to ``train_sampler``, e.g. ``train_sampler='RandomIdentitySampler'`` for triplet loss. + + +Choose an optimizer/lr_scheduler +---------------------------------- +Please refer to the source code of ``build_optimizer``/``build_lr_scheduler`` in :ref:`torchreid_optim` for details. + + Resume training ---------------- Suppose the checkpoint is saved in "log/resnet50/model.pth.tar-30", you can do diff --git a/torchreid/models/__init__.py b/torchreid/models/__init__.py index 2cc94e7..bffb319 100644 --- a/torchreid/models/__init__.py +++ b/torchreid/models/__init__.py @@ -24,7 +24,11 @@ from .mlfn import * __model_factory = { # image classification models + 'resnet18': resnet18, + 'resnet34': resnet34, 'resnet50': resnet50, + 'resnet101': resnet101, + 'resnet152': resnet152, 'resnet50_fc512': resnet50_fc512, 'resnext50_32x4d': resnext50_32x4d, 'resnext50_32x4d_fc512': resnext50_32x4d_fc512, @@ -34,6 +38,9 @@ __model_factory = { 'se_resnext50_32x4d': se_resnext50_32x4d, 'se_resnext101_32x4d': se_resnext101_32x4d, 'densenet121': densenet121, + 'densenet169': densenet169, + 'densenet201': densenet201, + 'densenet161': densenet161, 'densenet121_fc512': densenet121_fc512, 'inceptionresnetv2': inceptionresnetv2, 'inceptionv4': inceptionv4, diff --git a/torchreid/models/densenet.py b/torchreid/models/densenet.py index 892eed0..e58495d 100644 --- a/torchreid/models/densenet.py +++ b/torchreid/models/densenet.py @@ -1,7 +1,7 @@ from __future__ import absolute_import from __future__ import division -__all__ = ['densenet121', 'densenet121_fc512'] +__all__ = ['densenet121', 'densenet169', 'densenet201', 'densenet161', 'densenet121_fc512'] from collections import OrderedDict import math @@ -65,6 +65,13 @@ class DenseNet(nn.Module): Reference: Huang et al. Densely Connected Convolutional Networks. CVPR 2017. + + Public keys: + - ``densenet121``: DenseNet121. + - ``densenet169``: DenseNet169. + - ``densenet201``: DenseNet201. + - ``densenet161``: DenseNet161. + - ``densenet121_fc512``: DenseNet121 + FC. """ def __init__(self, num_classes, loss, growth_rate=32, block_config=(6, 12, 24, 16), num_init_features=64, bn_size=4, drop_rate=0, fc_dims=None, dropout_p=None, **kwargs): @@ -223,6 +230,54 @@ def densenet121(num_classes, loss='softmax', pretrained=True, **kwargs): return model +def densenet169(num_classes, loss='softmax', pretrained=True, **kwargs): + model = DenseNet( + num_classes=num_classes, + loss=loss, + num_init_features=64, + growth_rate=32, + block_config=(6, 12, 32, 32), + fc_dims=None, + dropout_p=None, + **kwargs + ) + if pretrained: + init_pretrained_weights(model, model_urls['densenet169']) + return model + + +def densenet201(num_classes, loss='softmax', pretrained=True, **kwargs): + model = DenseNet( + num_classes=num_classes, + loss=loss, + num_init_features=64, + growth_rate=32, + block_config=(6, 12, 48, 32), + fc_dims=None, + dropout_p=None, + **kwargs + ) + if pretrained: + init_pretrained_weights(model, model_urls['densenet201']) + return model + + +def densenet161(num_classes, loss='softmax', pretrained=True, **kwargs): + model = DenseNet( + num_classes=num_classes, + loss=loss, + num_init_features=96, + growth_rate=48, + block_config=(6, 12, 36, 24), + fc_dims=None, + dropout_p=None, + **kwargs + ) + if pretrained: + init_pretrained_weights(model, model_urls['densenet161']) + return model + + def densenet121_fc512(num_classes, loss='softmax', pretrained=True, **kwargs): model = DenseNet( num_classes=num_classes, diff --git a/torchreid/models/hacnn.py b/torchreid/models/hacnn.py index f3a9cb2..fec5675 100644 --- a/torchreid/models/hacnn.py +++ b/torchreid/models/hacnn.py @@ -190,6 +190,9 @@ class HACNN(nn.Module): Reference: Li et al. Harmonious Attention Network for Person Re-identification. CVPR 2018. + + Public keys: + - ``hacnn``: HACNN. """ # Args: diff --git a/torchreid/models/inceptionresnetv2.py b/torchreid/models/inceptionresnetv2.py index 6fb7836..874fc2a 100644 --- a/torchreid/models/inceptionresnetv2.py +++ b/torchreid/models/inceptionresnetv2.py @@ -279,6 +279,9 @@ class InceptionResNetV2(nn.Module): Reference: Szegedy et al. Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning. AAAI 2017. + + Public keys: + - ``inceptionresnetv2``: Inception-ResNet-V2. """ def __init__(self, num_classes, loss='softmax', **kwargs): diff --git a/torchreid/models/inceptionv4.py b/torchreid/models/inceptionv4.py index c520a09..d577543 100644 --- a/torchreid/models/inceptionv4.py +++ b/torchreid/models/inceptionv4.py @@ -274,6 +274,9 @@ class InceptionV4(nn.Module): Reference: Szegedy et al. Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning. AAAI 2017. + + Public keys: + - ``inceptionv4``: InceptionV4. """ def __init__(self, num_classes, loss, **kwargs): diff --git a/torchreid/models/mlfn.py b/torchreid/models/mlfn.py index ae50a09..29d8dde 100644 --- a/torchreid/models/mlfn.py +++ b/torchreid/models/mlfn.py @@ -87,11 +87,14 @@ class MLFNBlock(nn.Module): class MLFN(nn.Module): - """Multi-Level Factorisation Nets. + """Multi-Level Factorisation Net. Reference: Chang et al. Multi-Level Factorisation Net for Person Re-Identification. CVPR 2018. + + Public keys: + - ``mlfn``: MLFN (Multi-Level Factorisation Net). """ def __init__(self, num_classes, loss='softmax', groups=32, channels=[64, 256, 512, 1024, 2048], embed_dim=1024, **kwargs): diff --git a/torchreid/models/mobilenetv2.py b/torchreid/models/mobilenetv2.py index a91e597..e4057c7 100644 --- a/torchreid/models/mobilenetv2.py +++ b/torchreid/models/mobilenetv2.py @@ -70,6 +70,10 @@ class MobileNetV2(nn.Module): Reference: Sandler et al. MobileNetV2: Inverted Residuals and Linear Bottlenecks. CVPR 2018. + + Public keys: + - ``mobilenetv2_1dot0``: MobileNetV2 x1.0. + - ``mobilenetv2_1dot4``: MobileNetV2 x1.4. """ def __init__(self, num_classes, width_mult=1, loss='softmax', fc_dims=None, dropout_p=None, **kwargs): diff --git a/torchreid/models/mudeep.py b/torchreid/models/mudeep.py index 42d3a85..0a0cacc 100644 --- a/torchreid/models/mudeep.py +++ b/torchreid/models/mudeep.py @@ -157,6 +157,9 @@ class MuDeep(nn.Module): Reference: Qian et al. Multi-scale Deep Learning Architectures for Person Re-identification. ICCV 2017. + + Public keys: + - ``mudeep``: Multiscale deep neural network. """ def __init__(self, num_classes, loss='softmax', **kwargs): diff --git a/torchreid/models/nasnet.py b/torchreid/models/nasnet.py index 45d4d96..a93c229 100644 --- a/torchreid/models/nasnet.py +++ b/torchreid/models/nasnet.py @@ -535,6 +535,9 @@ class NASNetAMobile(nn.Module): Reference: Zoph et al. Learning Transferable Architectures for Scalable Image Recognition. CVPR 2018. + + Public keys: + - ``nasnetamobile``: NASNet-A Mobile. """ def __init__(self, num_classes, loss, stem_filters=32, penultimate_filters=1056, filters_multiplier=2, **kwargs): diff --git a/torchreid/models/pcb.py b/torchreid/models/pcb.py index 81133c0..058a3f9 100644 --- a/torchreid/models/pcb.py +++ b/torchreid/models/pcb.py @@ -121,6 +121,10 @@ class PCB(nn.Module): Reference: Sun et al. Beyond Part Models: Person Retrieval with Refined Part Pooling (and A Strong Convolutional Baseline). ECCV 2018. + + Public keys: + - ``pcb_p4``: PCB with 4-part strips. + - ``pcb_p6``: PCB with 6-part strips. """ def __init__(self, num_classes, loss, block, layers, diff --git a/torchreid/models/resnet.py b/torchreid/models/resnet.py index bb9c237..edc844e 100644 --- a/torchreid/models/resnet.py +++ b/torchreid/models/resnet.py @@ -1,7 +1,7 @@ from __future__ import absolute_import from __future__ import division -__all__ = ['resnet50', 'resnet50_fc512'] +__all__ = ['resnet18', 'resnet34', 'resnet50', 'resnet101', 'resnet152', 'resnet50_fc512'] import torch from torch import nn @@ -101,6 +101,14 @@ class ResNet(nn.Module): Reference: He et al. Deep Residual Learning for Image Recognition. CVPR 2016. + + Public keys: + - ``resnet18``: ResNet18. + - ``resnet34``: ResNet34. + - ``resnet50``: ResNet50. + - ``resnet101``: ResNet101. + - ``resnet152``: ResNet152. + - ``resnet50_fc512``: ResNet50 + FC. """ def __init__(self, num_classes, loss, block, layers, @@ -246,6 +254,38 @@ resnet152: block=Bottleneck, layers=[3, 8, 36, 3] """ +def resnet18(num_classes, loss='softmax', pretrained=True, **kwargs): + model = ResNet( + num_classes=num_classes, + loss=loss, + block=BasicBlock, + layers=[2, 2, 2, 2], + last_stride=2, + fc_dims=None, + dropout_p=None, + **kwargs + ) + if pretrained: + init_pretrained_weights(model, model_urls['resnet18']) + return model + + +def resnet34(num_classes, loss='softmax', pretrained=True, **kwargs): + model = ResNet( + num_classes=num_classes, + loss=loss, + block=BasicBlock, + layers=[3, 4, 6, 3], + last_stride=2, + fc_dims=None, + dropout_p=None, + **kwargs + ) + if pretrained: + init_pretrained_weights(model, model_urls['resnet34']) + return model + + def resnet50(num_classes, loss='softmax', pretrained=True, **kwargs): model = ResNet( num_classes=num_classes, @@ -262,6 +302,41 @@ def resnet50(num_classes, loss='softmax', pretrained=True, **kwargs): return model +def resnet101(num_classes, loss='softmax', pretrained=True, **kwargs): + model = ResNet( + num_classes=num_classes, + loss=loss, + block=Bottleneck, + layers=[3, 4, 23, 3], + last_stride=2, + fc_dims=None, + dropout_p=None, + **kwargs + ) + if pretrained: + init_pretrained_weights(model, model_urls['resnet101']) + return model + + +def resnet152(num_classes, loss='softmax', pretrained=True, **kwargs): + model = ResNet( + num_classes=num_classes, + loss=loss, + block=Bottleneck, + layers=[3, 8, 36, 3], + last_stride=2, + fc_dims=None, + dropout_p=None, + **kwargs + ) + if pretrained: + init_pretrained_weights(model, model_urls['resnet152']) + return model + + +""" +resnet + fc +""" def resnet50_fc512(num_classes, loss='softmax', pretrained=True, **kwargs): model = ResNet( num_classes=num_classes, diff --git a/torchreid/models/resnetmid.py b/torchreid/models/resnetmid.py index 67c2f62..e86df17 100644 --- a/torchreid/models/resnetmid.py +++ b/torchreid/models/resnetmid.py @@ -102,6 +102,9 @@ class ResNetMid(nn.Module): Reference: Yu et al. The Devil is in the Middle: Exploiting Mid-level Representations for Cross-Domain Instance Matching. arXiv:1711.08106. + + Public keys: + - ``resnet50mid``: ResNet50 + mid-level feature fusion. """ def __init__(self, num_classes, loss, block, layers, diff --git a/torchreid/models/resnext.py b/torchreid/models/resnext.py index eb2f453..7af7220 100644 --- a/torchreid/models/resnext.py +++ b/torchreid/models/resnext.py @@ -63,6 +63,10 @@ class ResNeXt(nn.Module): Reference: Xie et al. Aggregated Residual Transformations for Deep Neural Networks. CVPR 2017. + + Public keys: + - ``resnext50_32x4d``: ResNeXt50 (groups=32, width=4). + - ``resnext50_32x4d_fc512`` ResNeXt50 (groups=32, width=4) + FC. """ def __init__(self, num_classes, loss, block, layers, diff --git a/torchreid/models/senet.py b/torchreid/models/senet.py index 4b0d846..e3537b9 100644 --- a/torchreid/models/senet.py +++ b/torchreid/models/senet.py @@ -220,6 +220,15 @@ class SENet(nn.Module): Reference: Hu et al. Squeeze-and-Excitation Networks. CVPR 2018. + + Public keys: + - ``senet154``: SENet154. + - ``se_resnet50``: ResNet50 + SE. + - ``se_resnet101``: ResNet101 + SE. + - ``se_resnet152``: ResNet152 + SE. + - ``se_resnext50_32x4d``: ResNeXt50 (groups=32, width=4) + SE. + - ``se_resnext101_32x4d``: ResNeXt101 (groups=32, width=4) + SE. + - ``se_resnet50_fc512``: (ResNet50 + SE) + FC. """ def __init__(self, num_classes, loss, block, layers, groups, reduction, dropout_p=0.2, diff --git a/torchreid/models/shufflenet.py b/torchreid/models/shufflenet.py index ccbf1d0..3cad0b2 100644 --- a/torchreid/models/shufflenet.py +++ b/torchreid/models/shufflenet.py @@ -82,6 +82,9 @@ class ShuffleNet(nn.Module): Reference: Zhang et al. ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices. CVPR 2018. + + Public keys: + - ``shufflenet``: ShuffleNet (groups=3). """ def __init__(self, num_classes, loss='softmax', num_groups=3, **kwargs): diff --git a/torchreid/models/squeezenet.py b/torchreid/models/squeezenet.py index 82732f8..88a08af 100644 --- a/torchreid/models/squeezenet.py +++ b/torchreid/models/squeezenet.py @@ -54,6 +54,11 @@ class SqueezeNet(nn.Module): Reference: Iandola et al. SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and< 0.5 MB model size. arXiv:1602.07360. + + Public keys: + - ``squeezenet1_0``: SqueezeNet (version=1.0). + - ``squeezenet1_1``: SqueezeNet (version=1.1). + - ``squeezenet1_0_fc512``: SqueezeNet (version=1.0) + FC. """ def __init__(self, num_classes, loss, version=1.0, fc_dims=None, dropout_p=None, **kwargs): diff --git a/torchreid/models/xception.py b/torchreid/models/xception.py index bfe9a11..9da4e5b 100644 --- a/torchreid/models/xception.py +++ b/torchreid/models/xception.py @@ -102,6 +102,9 @@ class Xception(nn.Module): Reference: Chollet. Xception: Deep Learning with Depthwise Separable Convolutions. CVPR 2017. + + Public keys: + - ``xception``: Xception. """ def __init__(self, num_classes, loss, fc_dims=None, dropout_p=None, **kwargs):