Using Network-Slimming to prune classifier.
Learning Efficient Convolutional Networks Through Network Slimming (ICCV 2017)
timestamp | description | related file |
---|---|---|
2020-07-16 | debug vgg_prune.py, add p_conv's bias parameters copy | vgg_prune.py |
2020-07-19 | upload vgg_sensitity.ipynb (analyze each layer's sensitivity for prune) | vgg_sensitity.ipynb |
2020-07-19 | upload vgg_l1-norm_ns_random.ipynb (analyze each layer's sensitivity for l1-norm algorithm, network slimming algorithm and random prune algorithm) | vgg_l1-norm_ns_random.ipynb |
- pytorch v1.5.1
- torchvision v0.6.1
- terminaltables v3.1.0
- tensorboardX v2.0
- tqdm v4.46.1
- torchsummary v1.5.1
- ResNet(18, 36, 50, 101, 152)
- VGG(11, 13, 16, 19)
- CIFAR10
Of course, it is easy to extend this code to other classification datasets.
-
VGG
- vgg_prune.py
There is no dependency between VGG's Conv, so all Convs can be pruned.
- vgg_prune.py
-
ResNet
- resnet_prune.py(prune = 0):
It can only prune the first Conv's filters in every BasicBlock or First two Conv's filters in every Bottleneck.
When dealing with Sparse-regularization(sp), prune shoud set to 0, that is "--prune 0" - resnet_slim_prune.py(prune = 1):
It can prune all Conv's filters.
When multiple Convs depend on each other (these Convs need to have the same number of filters), we can only prune the filters that each Conv thinks can be prune. That is, when seeking the pruning mask, you need to find the union of '1' (or we can also say the intersection of '0'), where '1' indicates reservation and '0' indicates pruning.
When dealing with Sparse-regularization(sp), prune shoud set to 1, that is "--prune 1"
- resnet_prune.py(prune = 0):
Next time, I will take more models into account when pruning.
To prune ResNet Convenience, I have change the function to create ResNet model.
I define a cfg and use it to create ResNet pruned model.
cfg is a 2D integer list:
- row index means the block idx in ResNet
- collum index means the Conv layer idx in the block (the first Conv, BasicBlock or Bottleneck)
- each element value is the number of Conv's output chananel (or we can say the Conv's filter number)
When prune is complete, I generate a cfg file to save the model's architecture by using 'torch.save()' function.
training from scratch to get the baseline of Acc, this step will get the baseline's weights.
python train.py --model-name [eg. ResNet18] \
-ckpt-dir [the directory to save checkpoint] \
-log [the directory to save tensorboard output] \
--lr [learning rate] --epochs [epochs]
training with Sparse-regularization from baseline's weights, this step will get the weights which with sparse gamma.
python train.py --model-name [eg. ResNet18] \
-ckpt [the file path of baseline's checkpoint] \
-ckpt-dir [the directory to save checkpoint] \
-log [the directory to save tensorboard output] \
--lr [learning rate] \
--epochs [epochs] \
-sr \
--s 0.001 \
--prune 0
param | description |
---|---|
sr | the switch to open sparse-regularization |
s | sparsity factor(in paper, it is lambda) |
prune | sparse mode, used to control which BN layer's gamma need to be sparse and only works under ResNet(VGG does not need to set this parameter) |
prune the filters with small corresponding gamma.
python resnet_prune.py --model-name [eg. ResNet18] \
-ckpt [the file path of sp's checkpoint] \
-saved-dir [the directory to save pruned model's cfg and weights] \
-percent [the prune ratio]
After prune, it will create pruned cfg and weights that inherit the some weights of the original model.
percent = (the filters pruned) / (the filters that can be pruned), "the filters that can be pruned" means all filters in a layer which idx is in prune_idx.
finetune pruned model to recover the Acc.
python train.py --model-name [eg. ResNet18] \
--cfg [the config file of pruned model] \
-ckpt [the file path of pruned_model's weights] \
-ckpt-dir [the directory to save finetune model's cfg and weights] \
-log [the directory to save tensorboard output] \
--lr [learning rate] \
--epochs [epochs]
train pruned model from scratch.
python train.py --model-name [eg. ResNet18] \
--cfg [the config file of pruned model] \
-ckpt [the file path of pruned_model's weights] \
-ckpt-dir [the directory to save finetune model's cfg and weights] \
-log [the directory to save tensorboard output] \
--lr [learning rate] \
--epochs [epochs] \
--from-scratch
I also write a shell script to run baseline -> sp -> prune -> finetune
sh run_resnet18_prune.sh