Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Add DCFF #295

Merged
merged 53 commits into from
Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
4ef83de
add ChannelGroup (#250)
LKJacky Sep 14, 2022
159500f
Add BaseChannelMutator and refactor Autoslim (#289)
LKJacky Sep 20, 2022
49c524b
tmpsave
Sep 20, 2022
762544d
migrate ut
Sep 20, 2022
8ad6ef0
tmpsave2
Sep 20, 2022
4fc4a0e
add loss collector
spynccat Sep 21, 2022
ce2578e
refactor slimmable and add l1-norm (#291)
LKJacky Sep 22, 2022
f23e185
update config
spynccat Sep 23, 2022
6368117
Merge branch 'pruning' into dcff_pruning
spynccat Sep 23, 2022
cf84c1b
fix md & pytorch support <1.9.0 in batchnorm init
spynccat Sep 23, 2022
2488025
Clean old codes. (#296)
LKJacky Sep 23, 2022
80da3df
fix ci
spynccat Sep 26, 2022
8f2ef5c
ci fix py3.6.x & add mmpose
spynccat Sep 26, 2022
2dab5d8
ci fix py3.6.9 in utils/index_dict.py
spynccat Sep 26, 2022
e66e23d
fix mmpose
spynccat Sep 26, 2022
214b007
minimum_version_cpu=3.7
spynccat Sep 27, 2022
54bae0c
fix ci 3.7.13
spynccat Sep 27, 2022
64cb49f
Merge branch 'pruning' into dcff_pruning
spynccat Sep 27, 2022
505700d
fix pruning &meta ci
spynccat Sep 27, 2022
6dc3517
support python3.6.9
spynccat Sep 28, 2022
d878c6c
fix py3.6 import caused by circular import patch in py3.7
spynccat Sep 28, 2022
ca38384
fix py3.6.9
spynccat Sep 28, 2022
784c62a
Add channel-flow (#301)
LKJacky Sep 29, 2022
8fc9295
Merge branch 'pruning' into dcff_pruning
spynccat Sep 29, 2022
79725cc
support >=3.7
spynccat Sep 29, 2022
b464e93
support py3.6.9
spynccat Sep 29, 2022
d137b67
Rename: ChannelGroup -> ChannelUnit (#302)
LKJacky Sep 30, 2022
d9d07de
Merge branch 'pruning' into dcff_pruning
spynccat Oct 8, 2022
52997e4
update new channel config format
spynccat Oct 8, 2022
94cfdf3
update pruning refactor
spynccat Oct 10, 2022
9d98e1d
update merged pruning
spynccat Oct 11, 2022
96292fc
Merge branch 'dev-1.x' into dcff_pruning
spynccat Oct 11, 2022
a9f5d99
update commit
spynccat Oct 17, 2022
a8a903c
fix dynamic_conv_mixin
spynccat Oct 17, 2022
584e671
update comments: readme&dynamic_conv_mixins.py
spynccat Oct 20, 2022
0581fd4
update readme
spynccat Oct 20, 2022
1bc4e2e
move kl softmax channel pooling to op by comments
spynccat Oct 21, 2022
47e8e37
fix comments: fix redundant & split README.md
spynccat Oct 27, 2022
8a0ec1e
Merge branch 'dev-1.x' into dcff_pruning
spynccat Nov 2, 2022
d2f8c86
dcff in ItePruneAlgorithm
spynccat Nov 4, 2022
c24fa31
partial dynamic params for fuseconv
spynccat Nov 9, 2022
d870dd9
add step_freq & prune_time check
spynccat Nov 10, 2022
c464766
update comments
spynccat Nov 11, 2022
4a9cc66
update comments
spynccat Nov 11, 2022
88fee8a
update comments
spynccat Nov 15, 2022
e388cdc
Merge branch 'dev-1.x' into dcff_pruning
spynccat Nov 15, 2022
55526b1
fix ut
spynccat Nov 15, 2022
6e63d9e
fix gpu ut & revise step_freq in ItePruneAlgorithm
spynccat Nov 16, 2022
e387082
update readme
spynccat Nov 16, 2022
779cc18
revise ItePruneAlgorithm
spynccat Nov 18, 2022
33ade2c
fix docs
spynccat Nov 22, 2022
beb86ee
fix dynamic_conv attr
spynccat Nov 22, 2022
a8a3023
fix ci
spynccat Nov 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .circleci/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ jobs:
pip install git+https://github.com/open-mmlab/mmclassification.git@dev-1.x
pip install git+https://github.com/open-mmlab/mmdetection.git@dev-3.x
pip install git+https://github.com/open-mmlab/mmsegmentation.git@dev-1.x
python -m pip install git+ssh://git@github.com/open-mmlab/mmpose.git@dev-1.x
pip install -r requirements.txt
- run:
name: Build and install
Expand Down Expand Up @@ -163,7 +164,7 @@ workflows:
torchvision: 0.13.1
python: 3.9.0
requires:
- minimum_version_cpu
- lint
- hold:
type: approval
requires:
Expand Down
82 changes: 82 additions & 0 deletions configs/pruning/mmcls/dcff/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Training Compact CNNs for Image Classification using Dynamic-coded Filter Fusion
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This README should be split and paced in mmcls/mmdet/mmseg/mmpose, respectively.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. For convenience the empirical statistics are not split.


## Abstract

The mainstream approach for filter pruning is usually either to force a hard-coded importance estimation upon a computation-heavy pretrained model to select “important” filters, or to impose a hyperparameter-sensitive sparse constraint on the loss objective to regularize the network training. In this paper, we present a novel filter pruning method, dubbed dynamic-coded filter fusion (DCFF), to derive compact CNNs in a computationeconomical and regularization-free manner for efficient image classification. Each filter in our DCFF is firstly given an intersimilarity distribution with a temperature parameter as a filter proxy, on top of which, a fresh Kullback-Leibler divergence based dynamic-coded criterion is proposed to evaluate the filter importance. In contrast to simply keeping high-score filters in other methods, we propose the concept of filter fusion, i.e., the weighted averages using the assigned proxies, as our preserved filters. We obtain a one-hot inter-similarity distribution as the temperature parameter approaches infinity. Thus, the relative importance of each filter can vary along with the training of the compact CNN, leading to dynamically changeable fused filters without both the dependency on the pretrained model and the introduction of sparse constraints. Extensive experiments on classification benchmarks demonstrate the superiority of our DCFF over the compared counterparts. For example, our DCFF derives a compact VGGNet-16 with only 72.77M FLOPs and 1.06M parameters while reaching top-1 accuracy of 93.47% on CIFAR-10. A compact ResNet-50 is obtained with 63.8% FLOPs and 58.6% parameter reductions, retaining 75.60% top1 accuracy on ILSVRC-2012.

![pipeline](https://user-images.githubusercontent.com/31244134/189286581-722853ba-c6d7-4a39-b902-37995b444c71.jpg)

## Results and models
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The readME should add necessary notes on how to generate resnet_cls.json, resnet_det.json, and so on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with channel_unit_cfg generation using tools/get_channel_unit.py


### 1. Classification

| Dataset | Backbone | Params(M) | FLOPs(M) | lr_type | Top-1 (%) | Top-5 (%) | CPrate | Config | Download |
| :------: | :----------: | :-------: | :------: | :-----: | :-------: | :-------: | :---------------------------------------------: | :--------------------------------------------------: | :--------------------------: |
| ImageNet | DCFFResNet50 | 15.16 | 2260 | step | 73.96 | 91.66 | \[0.0\]+\[0.35,0.4,0.1\]\*10+\[0.3,0.3,0.1\]\*6 | [config](../../mmcls/dcff/dcff_resnet_8xb32_in1k.py) | [model](<>) \| \[log\] (\<>) |

### 2. Detection

| Dataset | Method | Backbone | Style | Lr schd | Params(M) | FLOPs(M) | bbox AP | CPrate | Config | Download |
| :-----: | :---------: | :----------: | :-----: | :-----: | :-------: | :------: | :-----: | :---------------------------------------------: | :---------------------------------------------------------------: | :--------------------------: |
| COCO | Faster_RCNN | DCFFResNet50 | pytorch | step | 33.31 | 168320 | 35.8 | \[0.0\]+\[0.35,0.4,0.1\]\*10+\[0.3,0.3,0.1\]\*6 | [config](../../mmdet/dcff/dcff_faster_rcnn_resnet50_8xb4_coco.py) | [model](<>) \| \[log\] (\<>) |

### 3. Segmentation

| Dataset | Method | Backbone | crop size | Lr schd | Params(M) | FLOPs(M) | mIoU | CPrate | Config | Download |
| :--------: | :-------: | :-------------: | :-------: | :-----: | :-------: | :------: | :---: | :-----------------------------------------------------------------: | :-------------------------------------------------------------------: | :--------------------------: |
| Cityscapes | PointRend | DCFFResNetV1c50 | 512x1024 | 160k | 18.43 | 74410 | 76.75 | \[0.0, 0.0, 0.0\] + \[0.35, 0.4, 0.1\] * 10 + \[0.3, 0.3, 0.1\] * 6 | [config](../../mmseg/dcff/dcff_pointrend_resnet50_8xb2_cityscapes.py) | [model](<>) \| \[log\] (\<>) |

### 4. Pose

| Dataset | Method | Backbone | crop size | total epochs | Params(M) | FLOPs(M) | AP | CPrate | Config | Download |
| :-----: | :-------------: | :----------: | :-------: | :----------: | :-------: | :------: | :--: | :--------------------------------------------------------: | :---------------------------------------------------------------: | :--------------------------: |
| COCO | TopDown HeatMap | DCFFResNet50 | 256x192 | 300 | 26.95 | 4290 | 68.3 | \[0.0\] + \[0.2, 0.2, 0.1\] * 10 + \[0.15, 0.15, 0.1\] * 6 | [config](../../mmpose/dcff/dcff_topdown_heatmap_resnet50_coco.py) | [model](<>) \| \[log\] (\<>) |

## Citation

```latex
@article{lin2021training,
title={Training Compact CNNs for Image Classification using Dynamic-coded Filter Fusion},
author={Lin, Mingbao and Ji, Rongrong and Chen, Bohong and Chao, Fei and Liu, Jianzhuang and Zeng, Wei and Tian, Yonghong and Tian, Qi},
journal={arXiv preprint arXiv:2107.06916},
year={2021}
}
```

## Getting Started

### Generate channel_config file

Generate `resnet_cls.json` with `tools/get_channel_units.py`.

```bash
python tools/get_channel_units.py
configs/pruning/mmcls/dcff/dcff_resnet50_8xb32_in1k.py \
-c -i --output-path=configs/pruning/mmcls/dcff/resnet_cls.json
```

Then set layers' pruning rates `target_pruning_ratio` by `resnet_cls.json`.

### Train DCFF

#### Classification

##### ImageNet

```bash
sh tools/slurm_train.sh $PARTITION $JOB_NAME \
configs/pruning/mmcls/dcff/dcff_resnet50_8xb32_in1k.py \
$WORK_DIR
```

### Test DCFF

#### Classification

##### ImageNet

```bash
sh tools/slurm_test.sh $PARTITION $JOB_NAME \
configs/pruning/mmcls/dcff/dcff_compact_resnet50_8xb32_in1k.py \
$WORK_DIR
```
5 changes: 5 additions & 0 deletions configs/pruning/mmcls/dcff/dcff_compact_resnet_8xb32_in1k.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
_base_ = ['dcff_resnet_8xb32_in1k.py']

# model settings
model = _base_.model
model['is_deployed'] = True
81 changes: 81 additions & 0 deletions configs/pruning/mmcls/dcff/dcff_resnet_8xb32_in1k.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
_base_ = [
'mmcls::_base_/datasets/imagenet_bs32.py',
'mmcls::_base_/schedules/imagenet_bs256.py',
'mmcls::_base_/default_runtime.py'
]

stage_ratio_1 = 0.65
stage_ratio_2 = 0.6
stage_ratio_3 = 0.9
stage_ratio_4 = 0.7

# the config template of target_pruning_ratio can be got by
# python ./tools/get_channel_units.py {config_file} --choice
target_pruning_ratio = {
'backbone.layer1.0.conv1_(0, 64)_64': stage_ratio_1,
'backbone.layer1.0.conv2_(0, 64)_64': stage_ratio_2,
'backbone.layer1.0.conv3_(0, 256)_256': stage_ratio_3,
'backbone.layer1.1.conv1_(0, 64)_64': stage_ratio_1,
'backbone.layer1.1.conv2_(0, 64)_64': stage_ratio_2,
'backbone.layer1.2.conv1_(0, 64)_64': stage_ratio_1,
'backbone.layer1.2.conv2_(0, 64)_64': stage_ratio_2,
# block 1 [0.65, 0.6] downsample=[0.9]
'backbone.layer2.0.conv1_(0, 128)_128': stage_ratio_1,
'backbone.layer2.0.conv2_(0, 128)_128': stage_ratio_2,
'backbone.layer2.0.conv3_(0, 512)_512': stage_ratio_3,
'backbone.layer2.1.conv1_(0, 128)_128': stage_ratio_1,
'backbone.layer2.1.conv2_(0, 128)_128': stage_ratio_2,
'backbone.layer2.2.conv1_(0, 128)_128': stage_ratio_1,
'backbone.layer2.2.conv2_(0, 128)_128': stage_ratio_2,
'backbone.layer2.3.conv1_(0, 128)_128': stage_ratio_1,
'backbone.layer2.3.conv2_(0, 128)_128': stage_ratio_2,
# block 2 [0.65, 0.6] downsample=[0.9]
'backbone.layer3.0.conv1_(0, 256)_256': stage_ratio_1,
'backbone.layer3.0.conv2_(0, 256)_256': stage_ratio_2,
'backbone.layer3.0.conv3_(0, 1024)_1024': stage_ratio_3,
'backbone.layer3.1.conv1_(0, 256)_256': stage_ratio_1,
'backbone.layer3.1.conv2_(0, 256)_256': stage_ratio_2,
'backbone.layer3.2.conv1_(0, 256)_256': stage_ratio_1,
'backbone.layer3.2.conv2_(0, 256)_256': stage_ratio_2,
'backbone.layer3.3.conv1_(0, 256)_256': stage_ratio_4,
'backbone.layer3.3.conv2_(0, 256)_256': stage_ratio_4,
'backbone.layer3.4.conv1_(0, 256)_256': stage_ratio_4,
'backbone.layer3.4.conv2_(0, 256)_256': stage_ratio_4,
'backbone.layer3.5.conv1_(0, 256)_256': stage_ratio_4,
'backbone.layer3.5.conv2_(0, 256)_256': stage_ratio_4,
# block 3 [0.65, 0.6]*2+[0.7, 0.7]*2 downsample=[0.9]
'backbone.layer4.0.conv1_(0, 512)_512': stage_ratio_4,
'backbone.layer4.0.conv2_(0, 512)_512': stage_ratio_4,
'backbone.layer4.0.conv3_(0, 2048)_2048': stage_ratio_3,
'backbone.layer4.1.conv1_(0, 512)_512': stage_ratio_4,
'backbone.layer4.1.conv2_(0, 512)_512': stage_ratio_4,
'backbone.layer4.2.conv1_(0, 512)_512': stage_ratio_4,
'backbone.layer4.2.conv2_(0, 512)_512': stage_ratio_4
# block 4 [0.7, 0.7] downsample=[0.9]
}

optim_wrapper = dict(
optimizer=dict(type='SGD', lr=0.1, momentum=0.9, weight_decay=0.0001))
param_scheduler = dict(
type='MultiStepLR', by_epoch=True, milestones=[30, 60, 90], gamma=0.1)
train_cfg = dict(by_epoch=True, max_epochs=120, val_interval=1)

data_preprocessor = {'type': 'mmcls.ClsDataPreprocessor'}

# model settings
model = dict(
_scope_='mmrazor',
type='DCFF',
architecture=dict(
cfg_path='mmcls::resnet/resnet50_8xb32_in1k.py', pretrained=False),
mutator_cfg=dict(
type='DCFFChannelMutator',
channel_unit_cfg=dict(
type='DCFFChannelUnit', default_args=dict(choice_mode='ratio')),
parse_cfg=dict(
type='BackwardTracer',
loss_calculator=dict(type='ImageClassifierPseudoLoss'))),
target_pruning_ratio=target_pruning_ratio,
step_freq=1,
linear_schedule=False,
is_deployed=False)
Loading