├── .gitignore ├── LICENSE ├── README.md ├── apps └── imagenet │ ├── mobilenetv1 │ └── conventional │ │ ├── mbv1_fix_quant_test.yml │ │ ├── mbv1_fix_quant_test_int_model.yml │ │ ├── mbv1_fix_quant_test_int_op_only_on_cpu.yml │ │ ├── mbv1_fix_quant_test_integize_on_gpu.yml │ │ ├── mbv1_fix_quant_train.yml │ │ ├── mbv1_floating_test.yml │ │ └── mbv1_floating_train.yml │ ├── mobilenetv2 │ └── conventional │ │ ├── mbv2_fix_quant_test.yml │ │ ├── mbv2_fix_quant_test_int_model.yml │ │ ├── mbv2_fix_quant_test_int_op_only_on_cpu.yml │ │ ├── mbv2_fix_quant_test_integize_on_gpu.yml │ │ ├── mbv2_fix_quant_train.yml │ │ ├── mbv2_floating_test.yml │ │ └── mbv2_floating_train.yml │ ├── resnet18 │ ├── conventional │ │ ├── res18_fix_quant_test.yml │ │ ├── res18_fix_quant_test_int_model.yml │ │ ├── res18_fix_quant_test_int_op_only.yml │ │ ├── res18_fix_quant_test_integize.yml │ │ ├── res18_fix_quant_train.yml │ │ ├── res18_floating_test.yml │ │ └── res18_floating_train.yml │ └── tiny_finetuning │ │ ├── res18_fix_quant_ptcv_pretrained_test.yml │ │ ├── res18_fix_quant_ptcv_pretrained_test_int_model.yml │ │ ├── res18_fix_quant_ptcv_pretrained_test_int_op_only_on_cpu.yml │ │ ├── res18_fix_quant_ptcv_pretrained_test_integize_on_gpu.yml │ │ └── res18_fix_quant_ptcv_pretrained_train.yml │ └── resnet50 │ └── tiny_finetuning │ ├── res50_fix_quant_nvidia_pretrained_test.yml │ ├── res50_fix_quant_nvidia_pretrained_test_int_model.yml │ ├── res50_fix_quant_nvidia_pretrained_test_int_op_only_on_cpu.yml │ ├── res50_fix_quant_nvidia_pretrained_test_integize_on_gpu.yml │ ├── res50_fix_quant_nvidia_pretrained_train.yml │ ├── res50_fix_quant_ptcv_pretrained_test.yml │ ├── res50_fix_quant_ptcv_pretrained_test_int_model.yml │ ├── res50_fix_quant_ptcv_pretrained_test_int_op_only_on_cpu.yml │ ├── res50_fix_quant_ptcv_pretrained_test_integize_on_gpu.yml │ └── res50_fix_quant_ptcv_pretrained_train.yml ├── distributed_run.sh ├── error_analysis ├── all_results_8bit_signed_False.txt ├── all_results_8bit_signed_True.txt ├── fixed_quant_analysis.py ├── fixed_quant_analysis_all_metrics.py ├── sigma_threshold_vs_fl_8bit_signed_False.pdf ├── sigma_threshold_vs_fl_8bit_signed_True.pdf ├── std_fix_quant_error_analysis_8bit_signed_False.pdf ├── std_fix_quant_error_analysis_8bit_signed_True.pdf ├── std_opt_fl_and_err_vs_sigma_8bit_signed_False.pdf ├── std_opt_fl_and_err_vs_sigma_8bit_signed_True.pdf ├── std_opt_sigma_vs_fl_8bit_signed_False.pdf └── std_opt_sigma_vs_fl_8bit_signed_True.pdf ├── fix_train.py ├── fraclen_visual ├── fraclen_visualizing_mbv2.py ├── fraclen_visualizing_res50.py ├── mbv2_fix_quant.out ├── mobilenetv2_8bit_fraclens.pdf ├── mobilenetv2_8bit_fraclens_wo_title.pdf ├── res50_fix_quant_nvidia_pretrained.out ├── res50_fix_quant_ptcv_pretrained.out ├── resnet50_nvidia_8bit_fraclens.pdf ├── resnet50_nvidia_8bit_fraclens_wo_title.pdf ├── resnet50_ptcv_8bit_fraclens.pdf └── resnet50_ptcv_8bit_fraclens_wo_title.pdf ├── imagenet_classes ├── images └── comparisons.png ├── models ├── fix_mobilenet_v1.py ├── fix_mobilenet_v2.py ├── fix_quant_ops.py └── fix_resnet.py ├── myutils ├── config.py ├── distributed.py ├── export.py └── meters.py ├── requirements.in ├── requirements.txt ├── run.sh └── weight_boxplot ├── mobilenetv2_pytorchcv_eff_weight.pdf ├── mobilenetv2_pytorchcv_eff_weight_wo_title.pdf ├── mobilenetv2_torchvision_eff_weight.pdf ├── mobilenetv2_torchvision_eff_weight_wo_title.pdf └── weight_boxplot.py /.gitignore: -------------------------------------------------------------------------------- 1 | cache 2 | data 3 | exp 4 | logs 5 | results 6 | .flake8 7 | *.bak 8 | *.pyc 9 | __pycache__ 10 | pretrained* 11 | .vscode 12 | apps_local 13 | .DS_Store* 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | For Snap Research F8Net software: 2 | Copyright (c) 2022 Snap Inc. 3 | 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 11 | 12 | --------------------------- LICENSE FOR AdaBits -------------------------------- 13 | The following software may be included in this product: AdaBits. This software is subject to the following license and notice: 14 | 15 | CC 4.0 Attribution-NonCommercial International https://creativecommons.org/licenses/by-nc/4.0/legalcode 16 | 17 | The software is for educational and academic research purposes only. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## F8Net
Fixed-Point 8-bit Only Multiplication for Network Quantization (ICLR 2022 Oral) 2 | 3 | [OpenReview](https://openreview.net/forum?id=_CfpJazzXT2) | [arXiv](https://arxiv.org/abs/2202.05239) | [PDF](https://arxiv.org/pdf/2202.05239.pdf) | [Model Zoo](#f8net-model-zoo) | [BibTex](#citation) 4 | 5 | 6 | 7 | 8 | 9 | PyTorch implementation of neural network quantization with fixed-point 8-bit only multiplication.
10 | >[F8Net: Fixed-Point 8-bit Only Multiplication for Network Quantization](https://openreview.net/forum?id=_CfpJazzXT2)
11 | >[Qing Jin](https://scholar.google.com/citations?user=X9iggBcAAAAJ&hl=zh-CN)1,2, [Jian Ren](https://alanspike.github.io/)1, [Richard Zhuang](https://www.linkedin.com/in/richard-zhuang-82ba504/)1, [Sumant Hanumante](https://www.linkedin.com/in/sumant-hanumante-3a698123/)1, [Zhengang Li](https://scholar.google.com/citations?user=hH1Oun0AAAAJ&hl=en)2, [Zhiyu Chen](https://vlsi.rice.edu/authors/zhiyu/)3, [Yanzhi Wang](https://coe.northeastern.edu/people/wang-yanzhi/)2, [Kaiyuan Yang](https://vlsi.rice.edu/authors/admin/)3, [Sergey Tulyakov](http://www.stulyakov.com/)1 12 | >1Snap Inc., 2Northeastern University, 3Rice University
13 | >ICLR 2022 Oral. 14 | 15 | 16 |
17 | 18 | Overview 19 | 20 | Neural network quantization implements efficient inference via reducing the weight and input precisions. Previous methods for quantization can be categorized as simulated quantization, integer-only quantization, and fixed-point quantization, with the former two involving high-precision multiplications with 32-bit floating-point or integer scaling. In contrast, fixed-point models can avoid such high-demanding requirements but demonstrates inferior performance to the other two methods. In this work, we study the problem of how to train such models. Specifically, we conduct statistical analysis on values for quantization and propose to determine the fixed-point format from data during training with some semi-empirical formula. Our method demonstrates that high-precision multiplication is not necessary for the quantized model to achieve comparable performance as their full-precision counterparts. 21 |
22 | 23 | 24 | ## Getting Started 25 | 26 |
27 | Requirements 28 | 29 | 1. Please check the [requirements](/requirements.txt) and download packages. 30 | 31 | 2. Prepare ImageNet-1k data following pytorch [example](https://github.com/pytorch/examples/tree/master/imagenet), and create a softlink to the ImageNet data path to data under current the code directory (`ln -s /path/to/imagenet data`). 32 | 33 |
34 | 35 |
Model Training
36 | 37 |
Conventional training
38 | 39 | * We train the model with the file [distributed_run.sh](/distributed_run.sh) and the command 40 | ``` 41 | bash distributed_run.sh /path/to/yml_file batch_size 42 | ``` 43 | * We set `batch_size=2048` for conventional training of floating-/fixed-point ResNet18 and MobileNet V1/V2. 44 | * Before training, please update the `dataset_dir` and `log_dir` arguments in the yaml files for training the floating-/fixed-point models. 45 | * To train the floating-point model, please use the yaml file `***_floating_train.yml` in the `conventional` subfolder under the corresponding folder of the model. 46 | * To train the fixed-point model, please first train the floating-point model as the initialization. Please use the yaml file `***_fix_quant_train.yml` in the `conventional` subfolder under the corresponding folder of the model. Please make sure the argument `fp_pretrained_file` directs to the correct path for the corresponding floating-point checkpoint. We also provide our pretrained floating-point models in the [Model Zoo](#f8net-model-zoo) below. 47 |
48 | 49 |
Tiny finetuning
50 | 51 | * We finetune the model with the file [run.sh](/run.sh) and the command 52 | ``` 53 | bash run.sh /path/to/yml_file batch_size 54 | ``` 55 | * We set `batch_size=128` and use one GPU for tiny-finetuning of fixed-point ResNet18/50. 56 | 57 | * Before fine-tuning, please update the `dataset_dir` and `log_dir` arguments in the yaml files for finetuning the fixed-point models. 58 | 59 | * To finetune the fixed-point model, please use the yaml file `***_fix_quant_***_pretrained_train.yml` in the `tiny_finetuning` subfolder under the corresponding folder of the model. For model pretrained with [`PytorchCV`](https://pypi.org/project/pytorchcv/) (Baseline of ResNet18 and Baseline#1 of ResNet50), the floating-point checkpoint will be downloaded automatically during code running. For the model pretrained by [`Nvidia`](https://catalog.ngc.nvidia.com/orgs/nvidia/models/resnet50_pyt_amp/files) (Baseline#2 of ResNet50), please download the checkpoint first and make sure the argument `nvidia_pretrained_file` directs to the correct path of this checkpoint. 60 | 61 |
62 | 63 |
64 | 65 |
66 | Model Testing 67 | 68 | * We test the model with the file [run.sh](/run.sh) and the command 69 | ``` 70 | bash run.sh /path/to/yml_file batch_size 71 | ``` 72 | * We set `batch_size=128` and use one GPU for model testing. 73 | 74 | * Before testing, please update the `dataset_dir` and `log_dir` arguments in the yaml files. Please update the argument `integize_file_path` and `int_op_only_file_path` arguments in the yaml files `***_fix_quant_test***_integize.yml` and `***_fix_quant_test***_int_op_only.yml`, respectively. Please also update other arguments like `nvidia_pretrained_file` if necessary (even if they are not used during testing). 75 | 76 | * We use the yaml file `***_floating_test.yml` for testing the floating-point model; `***_fix_quant***_test.yml` for testing the fixed-point model with the same setting as during training/tiny-finetuning; `***_fix_quant***_test_int_model.yml` for testing the fixed-point model on GPU with all quantized weights, bias and inputs implemented with integers (but with `float` dtype as GPU does not support integer operations) and use the original modules during training (e.g. with batch normalization layers); `***_fix_quant***_test_integize.yml` for testing the fixed-point model on GPU with all quantized weights, bias and inputs implemented with integers (but with `float` dtype as GPU does not support integer operations) and a new equivalent model with only convolution, pooling and fully-connected layers; `***_fix_quant***_test_int_op_only.yml` for testing the fixed-point model on CPU with all quantized weights, bias and inputs implemented with integers (with `int` dtype) and a new equivalent model with only convolution, pooling and fully-connected layers. Note that the accuracy from the four testing files can differ a little due to numerical error. 77 | 78 |
79 | 80 | 81 |
82 | Model Export 83 | 84 | * We export fixed-point model with integer weights, bias and inputs to run on GPU and CPU during model testing with `***_fix_quant_test_integize.yml` and `***_fix_quant_test_int_op_only.yml` files, respectively. 85 | 86 | * The exported onnx files are saved to the path given by the arguments `integize_file_path` and `int_op_only_file_path`. 87 | 88 |
89 | 90 | 91 | 92 | 93 | ## F8Net Model Zoo 94 | 95 | All checkpoints and onnx files are available at **[here](https://drive.google.com/drive/folders/1lYWPj9TB-c50lIxXlYWbCfpF5pSAP0fc?usp=sharing)**. 96 | 97 | **Conventional** 98 | 99 | | Model | Type | Top-1 Acc.a | Checkpoint | 100 | | :--- | :---: | :---: | :---: | 101 | | ResNet18 | FP
8-bit | 70.3
71.0 | [`Res18_32`](https://drive.google.com/file/d/1BxRPKr7SRQmrRdJt1oUrRxzjas65ItQN/view?usp=sharing)
[`Res18_8`](https://drive.google.com/file/d/1U93c7QLHs0Ww_93yY1msbRsghZTGaruG/view?usp=sharing) | 102 | | MobileNet-V1 | FP
8-bit | 72.4
72.8 | [`MBV1_32`](https://drive.google.com/file/d/14zeH0HLUS8UN7RKDyKWMHPKzXKa6mesp/view?usp=sharing)
[`MBV1_8`](https://drive.google.com/file/d/1Q89sIqR2HrCcEOOcLrKl8emcippkT6p3/view?usp=sharing) | 103 | | MobileNet-V2b | FP
8-bit | 72.7
72.6 | [`MBV2b_32`](https://drive.google.com/file/d/1OYz0CkLLQ2JV-X666HxiBVFAbJ3ojWIw/view?usp=sharing)
[`MBV2b_8`](https://drive.google.com/file/d/1YbDKgxHBFrBLhsZ4GJoL5R4sm5L8BT0p/view?usp=sharing) | 104 | 105 | **Tiny Finetuning** 106 | 107 | | Model | Type | Top-1 Acc.a | Checkpoint | 108 | | :--- | :---: | :---: | :---: | 109 | | ResNet18 | FP
8-bit | 73.1
72.3 | `Res18_32p`
[`Res18_8p`](https://drive.google.com/file/d/1L2vziGb5_OCjlA-cAoUk-54jA9BA-spN/view?usp=sharing) | 110 | | ResNet50b (BL#1) | FP
8-bit | 77.6
77.6 | `Res50b_32p`
[`Res50b_8p`](https://drive.google.com/file/d/1YHe7MB4JpG75uo8GMpCxwsVHvAJflXF0/view?usp=sharing) | 111 | | ResNet50b (BL#2) | FP
8-bit | 78.5
78.1 | [`Res50b_32n`](https://catalog.ngc.nvidia.com/orgs/nvidia/models/resnet50_pyt_amp/files)
[`Res50b_8n`](https://drive.google.com/file/d/1WU_ccesykRVKp9ntEDn_mieYTW-wAkkN/view?usp=sharing) | 112 | 113 | a The accuracies are obtained from the inference step during training. Test accuracy for the final exported model might have some small accuracy difference due to numerical error. 114 | 115 | 116 | ## Technical Details 117 | 118 | The main techniques for neural network quantization with 8-bit fixed-point multiplication includes the following: 119 | * Quantized methods/modules including determining fixed-point formats from statistics or by grid-search, fusing convolution and batch normalization layers, and reformulating PACT with fixed-point quantization are implemented in [`models/fix_quant_ops`](/models/fix_quant_ops.py). 120 | * Clipping-level sharing and private fractional length for residual blocks are implemented in the ResNet ([`models/fix_resnet`](/models/fix_resnet.py)) and MobileNet V2 ([`models/fix_mobilenet_v2`](/models/fix_mobilenet_v2.py)). 121 | 122 | 123 | ## Acknowledgement 124 | This repo is based on [AdaBits](https://github.com/deJQK/AdaBits). 125 | 126 | 127 | ## Citation 128 | If our code or models help your work, please cite our paper: 129 | ```bibtex 130 | @inproceedings{ 131 | jin2022fnet, 132 | title={F8Net: Fixed-Point 8-bit Only Multiplication for Network Quantization}, 133 | author={Qing Jin and Jian Ren and Richard Zhuang and Sumant Hanumante and Zhengang Li and Zhiyu Chen and Yanzhi Wang and Kaiyuan Yang and Sergey Tulyakov}, 134 | booktitle={International Conference on Learning Representations}, 135 | year={2022}, 136 | url={https://openreview.net/forum?id=_CfpJazzXT2} 137 | } 138 | ``` 139 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv1/conventional/mbv1_fix_quant_test.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | weight_format: [8, 7] 57 | input_format: [8, 6] 58 | 59 | # 60 | format_type: per_layer #[~, per_model, per_layer, per_channel] 61 | 62 | # 63 | format_from_metric: True 64 | momentum_for_metric: 0.1 65 | metric: std 66 | 67 | # 68 | weight_decay_scheme: all 69 | 70 | # =========================== Override Settings =========================== 71 | quant_bias: False 72 | quant_avgpool: False 73 | pool_fusing: False 74 | int_infer: False #True ## For int model 75 | integize: False #True ## For gpu inference 76 | int_op_only: False ## For cpu inference 77 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit 78 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit 79 | 80 | test_only: True 81 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit/checkpoints/best_model.pt 82 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv1 83 | model: models.fix_mobilenet_v1 84 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv1/conventional/mbv1_fix_quant_test_int_model.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | weight_format: [8, 7] 57 | input_format: [8, 6] 58 | 59 | # 60 | format_type: per_layer #[~, per_model, per_layer, per_channel] 61 | 62 | # 63 | format_from_metric: True 64 | momentum_for_metric: 0.1 65 | metric: std 66 | 67 | # 68 | weight_decay_scheme: all 69 | 70 | # =========================== Override Settings =========================== 71 | quant_bias: True 72 | quant_avgpool: True 73 | pool_fusing: True 74 | int_infer: True ## For int model 75 | integize: False #True ## For gpu inference 76 | int_op_only: False ## For cpu inference 77 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit 78 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit 79 | 80 | test_only: True 81 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit/checkpoints/best_model.pt 82 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv1 83 | model: models.fix_mobilenet_v1 84 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv1/conventional/mbv1_fix_quant_test_int_op_only_on_cpu.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | weight_format: [8, 7] 57 | input_format: [8, 6] 58 | 59 | # 60 | format_type: per_layer #[~, per_model, per_layer, per_channel] 61 | 62 | # 63 | format_from_metric: True 64 | momentum_for_metric: 0.1 65 | metric: std 66 | 67 | # 68 | weight_decay_scheme: all 69 | 70 | # =========================== Override Settings =========================== 71 | quant_bias: True 72 | quant_avgpool: True 73 | pool_fusing: True 74 | int_infer: True ## For int model 75 | integize: False #True ## For gpu inference 76 | int_op_only: True #False ## For cpu inference 77 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit 78 | int_op_only_file_path: /path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit 79 | 80 | test_only: True 81 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit/checkpoints/best_model.pt 82 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv1 83 | model: models.fix_mobilenet_v1 84 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv1/conventional/mbv1_fix_quant_test_integize_on_gpu.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | weight_format: [8, 7] 57 | input_format: [8, 6] 58 | 59 | # 60 | format_type: per_layer #[~, per_model, per_layer, per_channel] 61 | 62 | # 63 | format_from_metric: True 64 | momentum_for_metric: 0.1 65 | metric: std 66 | 67 | # 68 | weight_decay_scheme: all 69 | 70 | # =========================== Override Settings =========================== 71 | quant_bias: True 72 | quant_avgpool: True 73 | pool_fusing: True 74 | int_infer: True 75 | integize: True ## For gpu inference 76 | int_op_only: False ## For cpu inference 77 | integize_file_path: /path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit 78 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit 79 | 80 | test_only: True 81 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/MobileNetV1/8bit/checkpoints/best_model.pt 82 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv1 83 | model: models.fix_mobilenet_v1 84 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv1/conventional/mbv1_fix_quant_train.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: True 42 | distributed_all_reduce: True 43 | use_diff_seed: True 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | weight_format: [8, 7] 57 | input_format: [8, 6] 58 | 59 | # 60 | format_type: per_layer #[~, per_model, per_layer, per_channel] 61 | 62 | # 63 | format_from_metric: True 64 | momentum_for_metric: 0.1 65 | metric: std 66 | 67 | # 68 | weight_decay_scheme: all 69 | 70 | # =========================== Override Settings =========================== 71 | fp_pretrained_file: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv1/fp32/checkpoints/best_model.pt 72 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv1 73 | model: models.fix_mobilenet_v1 74 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv1/conventional/mbv1_floating_test.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | floating_model: True 57 | 58 | # 59 | weight_format: [8, 7] 60 | input_format: [8, 6] 61 | 62 | # 63 | format_type: ~ #[~, per_layer, per_channel] 64 | 65 | # 66 | weight_decay_scheme: all 67 | 68 | # =========================== Override Settings =========================== 69 | test_only: True 70 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/MobileNetV1/fp32/checkpoints/best_model.pt 71 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv1 72 | model: models.fix_mobilenet_v1 73 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv1/conventional/mbv1_floating_train.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: True 42 | distributed_all_reduce: True 43 | use_diff_seed: True 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | floating_model: True 57 | 58 | # 59 | weight_format: [8, 7] 60 | input_format: [8, 6] 61 | 62 | # 63 | format_type: ~ #[~, per_layer, per_channel] 64 | 65 | # 66 | weight_decay_scheme: all 67 | 68 | # =========================== Override Settings =========================== 69 | #fp_pretrained_file: /path/to/best_model.pt 70 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv1 71 | model: models.fix_mobilenet_v1 72 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv2/conventional/mbv2_fix_quant_test.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.1 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | weight_format: [8, 7] 57 | input_format: [8, 6] 58 | 59 | # 60 | format_type: per_layer #[~, per_model, per_layer, per_channel] 61 | 62 | # 63 | format_from_metric: True 64 | momentum_for_metric: 0.1 65 | metric: std 66 | 67 | # 68 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 69 | 70 | # 71 | input_fraclen_sharing: False 72 | 73 | # =========================== Override Settings =========================== 74 | quant_bias: False 75 | quant_avgpool: False 76 | pool_fusing: False 77 | int_infer: False #True ## For int model 78 | integize: False #True ## For gpu inference 79 | int_op_only: False ## For cpu inference 80 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit 81 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit 82 | 83 | test_only: True 84 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit/checkpoints/best_model.pt 85 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv2 86 | model: models.fix_mobilenet_v2 87 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv2/conventional/mbv2_fix_quant_test_int_model.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.1 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | weight_format: [8, 7] 57 | input_format: [8, 6] 58 | 59 | # 60 | format_type: per_layer #[~, per_model, per_layer, per_channel] 61 | 62 | # 63 | format_from_metric: True 64 | momentum_for_metric: 0.1 65 | metric: std 66 | 67 | # 68 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 69 | 70 | # 71 | input_fraclen_sharing: False 72 | 73 | # =========================== Override Settings =========================== 74 | quant_bias: True 75 | quant_avgpool: True 76 | pool_fusing: True 77 | int_infer: True ## For int model 78 | integize: False #True ## For gpu inference 79 | int_op_only: False ## For cpu inference 80 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit 81 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit 82 | 83 | test_only: True 84 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit/checkpoints/best_model.pt 85 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv2 86 | model: models.fix_mobilenet_v2 87 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv2/conventional/mbv2_fix_quant_test_int_op_only_on_cpu.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.1 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | weight_format: [8, 7] 57 | input_format: [8, 6] 58 | 59 | # 60 | format_type: per_layer #[~, per_model, per_layer, per_channel] 61 | 62 | # 63 | format_from_metric: True 64 | momentum_for_metric: 0.1 65 | metric: std 66 | 67 | # 68 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 69 | 70 | # 71 | input_fraclen_sharing: False 72 | 73 | # =========================== Override Settings =========================== 74 | quant_bias: True 75 | quant_avgpool: True 76 | pool_fusing: True 77 | int_infer: True ## For int model 78 | integize: False #True ## For gpu inference 79 | int_op_only: True #False ## For cpu inference 80 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit 81 | int_op_only_file_path: /path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit 82 | 83 | test_only: True 84 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit/checkpoints/best_model.pt 85 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv2 86 | model: models.fix_mobilenet_v2 87 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv2/conventional/mbv2_fix_quant_test_integize_on_gpu.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.1 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | weight_format: [8, 7] 57 | input_format: [8, 6] 58 | 59 | # 60 | format_type: per_layer #[~, per_model, per_layer, per_channel] 61 | 62 | # 63 | format_from_metric: True 64 | momentum_for_metric: 0.1 65 | metric: std 66 | 67 | # 68 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 69 | 70 | # 71 | input_fraclen_sharing: False 72 | 73 | # =========================== Override Settings =========================== 74 | quant_bias: True 75 | quant_avgpool: True 76 | pool_fusing: True 77 | int_infer: True ## For int model 78 | integize: True ## For gpu inference 79 | int_op_only: False ## For cpu inference 80 | integize_file_path: /path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit 81 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit 82 | 83 | test_only: True 84 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/MobileNetV2/8bit/checkpoints/best_model.pt 85 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv2 86 | model: models.fix_mobilenet_v2 87 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv2/conventional/mbv2_fix_quant_train.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.1 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: True 42 | distributed_all_reduce: True 43 | use_diff_seed: True 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | weight_format: [8, 7] 57 | input_format: [8, 6] 58 | 59 | # 60 | format_type: per_layer #[~, per_model, per_layer, per_channel] 61 | 62 | # 63 | format_from_metric: True 64 | momentum_for_metric: 0.1 65 | metric: std 66 | 67 | # 68 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 69 | 70 | # 71 | input_fraclen_sharing: False 72 | 73 | # =========================== Override Settings =========================== 74 | fp_pretrained_file: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv2/fp32/checkpoints/best_model.pt 75 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv2 76 | model: models.fix_mobilenet_v2 77 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv2/conventional/mbv2_floating_test.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.1 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | floating_model: True 57 | 58 | # 59 | weight_format: [8, 7] 60 | input_format: [8, 6] 61 | 62 | # 63 | format_type: ~ #[~, per_layer, per_channel] 64 | 65 | # 66 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 67 | 68 | # 69 | input_fraclen_sharing: True 70 | 71 | # =========================== Override Settings =========================== 72 | test_only: True 73 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/MobileNetV2/fp32/checkpoints/best_model.pt 74 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv2 75 | model: models.fix_mobilenet_v2 76 | -------------------------------------------------------------------------------- /apps/imagenet/mobilenetv2/conventional/mbv2_floating_train.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.1 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: True 42 | distributed_all_reduce: True 43 | use_diff_seed: True 44 | 45 | # 46 | width_divisor: 8 47 | min_width: 1 48 | 49 | # 50 | rescale_forward: True 51 | rescale_forward_conv: False 52 | #normalize: False 53 | rescale_type: constant #[stddev, constant] 54 | 55 | # 56 | floating_model: True 57 | 58 | # 59 | weight_format: [8, 7] 60 | input_format: [8, 6] 61 | 62 | # 63 | format_type: ~ #[~, per_layer, per_channel] 64 | 65 | # 66 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 67 | 68 | # 69 | input_fraclen_sharing: True 70 | 71 | # =========================== Override Settings =========================== 72 | #fp_pretrained_file: /path/to/best_model.pt 73 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/mobilenetv2 74 | model: models.fix_mobilenet_v2 75 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/conventional/res18_fix_quant_test.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | #normalize: False 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | # 64 | weight_decay_scheme: all 65 | 66 | # 67 | no_clipping: False 68 | input_fraclen_sharing: False 69 | 70 | # =========================== Override Settings =========================== 71 | quant_bias: False 72 | quant_avgpool: False 73 | pool_fusing: False 74 | int_infer: False #True ## For int model 75 | integize: False #True ## For gpu inference 76 | int_op_only: False ## For cpu inference 77 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit 78 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit 79 | 80 | test_only: True 81 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit/checkpoints/best_model.pt 82 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 83 | model: models.fix_resnet 84 | depth: 18 85 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/conventional/res18_fix_quant_test_int_model.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | #normalize: False 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | # 64 | weight_decay_scheme: all 65 | 66 | # 67 | no_clipping: False 68 | input_fraclen_sharing: False 69 | 70 | # =========================== Override Settings =========================== 71 | quant_bias: True 72 | quant_avgpool: True 73 | pool_fusing: True 74 | quant_maxpool: True 75 | int_infer: True ## For int model 76 | integize: False ## For gpu inference 77 | int_op_only: False ## For cpu inference 78 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit 79 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit 80 | 81 | test_only: True 82 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit/checkpoints/best_model.pt 83 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 84 | model: models.fix_resnet 85 | depth: 18 86 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/conventional/res18_fix_quant_test_int_op_only.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | #normalize: False 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | # 64 | weight_decay_scheme: all 65 | 66 | # 67 | no_clipping: False 68 | input_fraclen_sharing: False 69 | 70 | # =========================== Override Settings =========================== 71 | quant_bias: True 72 | quant_avgpool: True 73 | pool_fusing: True 74 | quant_maxpool: False #True 75 | int_infer: True ## For int model 76 | integize: False ## For gpu inference 77 | int_op_only: True ## For cpu inference 78 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit 79 | int_op_only_file_path: /path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit 80 | 81 | test_only: True 82 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit/checkpoints/best_model.pt 83 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 84 | model: models.fix_resnet 85 | depth: 18 86 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/conventional/res18_fix_quant_test_integize.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | #normalize: False 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | # 64 | weight_decay_scheme: all 65 | 66 | # 67 | no_clipping: False 68 | input_fraclen_sharing: False 69 | 70 | # =========================== Override Settings =========================== 71 | quant_bias: True 72 | quant_avgpool: True 73 | pool_fusing: True 74 | quant_maxpool: False #True 75 | int_infer: True ## For int model 76 | integize: True ## For gpu inference 77 | int_op_only: False ## For cpu inference 78 | integize_file_path: /path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit 79 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit 80 | 81 | test_only: True 82 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/ResNet18/8bit/checkpoints/best_model.pt 83 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 84 | model: models.fix_resnet 85 | depth: 18 86 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/conventional/res18_fix_quant_train.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.1 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: True 42 | distributed_all_reduce: True 43 | use_diff_seed: True 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | #normalize: False 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | # 64 | weight_decay_scheme: all 65 | 66 | # 67 | input_fraclen_sharing: False 68 | 69 | # =========================== Override Settings =========================== 70 | fp_pretrained_file: /path/to/checkpoints/F8Net/results/imagenet/resnet18/fp32/checkpoints/best_model.pt 71 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 72 | model: models.fix_resnet 73 | depth: 18 74 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/conventional/res18_floating_test.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | #normalize: False 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | floating_model: True 53 | 54 | # 55 | weight_format: [8, 7] 56 | input_format: [8, 6] 57 | 58 | # 59 | format_type: ~ #[~, per_layer, per_channel] 60 | 61 | # 62 | weight_decay_scheme: all 63 | 64 | # 65 | input_fraclen_sharing: True 66 | 67 | # =========================== Override Settings =========================== 68 | test_only: True 69 | pretrained_file: /path/to/pretrained_models/ImageNet/conventional/ResNet18/fp32/checkpoints/best_model.pt 70 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 71 | model: models.fix_resnet 72 | depth: 18 73 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/conventional/res18_floating_train.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 150 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.00004 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.05 26 | lr_scheduler: cos_annealing_iter 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: True 42 | distributed_all_reduce: True 43 | use_diff_seed: True 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | #normalize: False 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | floating_model: True 53 | 54 | # 55 | weight_format: [8, 7] 56 | input_format: [8, 6] 57 | 58 | # 59 | format_type: ~ #[~, per_layer, per_channel] 60 | 61 | # 62 | weight_decay_scheme: all 63 | 64 | # 65 | input_fraclen_sharing: True 66 | 67 | # =========================== Override Settings =========================== 68 | #fp_pretrained_file: /path/to/best_model.pt 69 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 70 | model: models.fix_resnet 71 | depth: 18 72 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/tiny_finetuning/res18_fix_quant_ptcv_pretrained_test.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 100 64 | ptcv_pretrained: True 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | # =========================== Override Settings =========================== 75 | quant_bias: False 76 | quant_avgpool: False 77 | pool_fusing: False 78 | quant_maxpool: False 79 | int_infer: False ## For int model 80 | integize: False #True ## For gpu inference 81 | int_op_only: False ## For cpu inference 82 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit 83 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit 84 | print_each_iter: True 85 | 86 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 87 | test_only: True 88 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 89 | model: models.fix_resnet 90 | depth: 18 91 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/tiny_finetuning/res18_fix_quant_ptcv_pretrained_test_int_model.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 100 64 | ptcv_pretrained: True 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | # =========================== Override Settings =========================== 75 | quant_bias: True 76 | quant_avgpool: True 77 | pool_fusing: True 78 | quant_maxpool: True 79 | int_infer: True ## For int model 80 | integize: False #True ## For gpu inference 81 | int_op_only: False ## For cpu inference 82 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit 83 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit 84 | print_each_iter: True 85 | 86 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 87 | test_only: True 88 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 89 | model: models.fix_resnet 90 | depth: 18 91 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/tiny_finetuning/res18_fix_quant_ptcv_pretrained_test_int_op_only_on_cpu.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 100 64 | ptcv_pretrained: True 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | # =========================== Override Settings =========================== 75 | quant_bias: True 76 | quant_avgpool: True 77 | pool_fusing: True 78 | quant_maxpool: False #True ## Onnx does not support unfold used in MaxPool 79 | int_infer: True ## For int model 80 | integize: False #True ## For gpu inference 81 | int_op_only: True #False ## For cpu inference 82 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit 83 | int_op_only_file_path: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit 84 | print_each_iter: True 85 | 86 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 87 | test_only: True 88 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 89 | model: models.fix_resnet 90 | depth: 18 91 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/tiny_finetuning/res18_fix_quant_ptcv_pretrained_test_integize_on_gpu.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 100 64 | ptcv_pretrained: True 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | # =========================== Override Settings =========================== 75 | quant_bias: True 76 | quant_avgpool: True 77 | pool_fusing: True 78 | quant_maxpool: False #True ## Onnx does not support unfold used in MaxPool 79 | int_infer: True ## For int model 80 | integize: True ## For gpu inference 81 | int_op_only: False ## For cpu inference 82 | integize_file_path: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit 83 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit 84 | print_each_iter: True 85 | 86 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet18/ptcv_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 87 | test_only: True 88 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 89 | model: models.fix_resnet 90 | depth: 18 91 | -------------------------------------------------------------------------------- /apps/imagenet/resnet18/tiny_finetuning/res18_fix_quant_ptcv_pretrained_train.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.0 26 | lr_scheduler: constant 27 | 28 | # pretrain, resume, test_only 29 | pretrained_dir: '' 30 | pretrained_file: '' 31 | resume: '' 32 | test_only: False 33 | 34 | # 35 | random_seed: 1995 36 | model: '' 37 | reset_parameters: True 38 | 39 | # 40 | distributed: False 41 | distributed_all_reduce: False 42 | use_diff_seed: False 43 | 44 | # 45 | rescale_forward: True 46 | rescale_forward_conv: False 47 | normalize: True 48 | rescale_type: constant #[stddev, constant] 49 | 50 | # 51 | weight_format: [8, 7] 52 | input_format: [8, 6] 53 | 54 | # 55 | format_type: per_layer #[~, per_model, per_layer, per_channel] 56 | 57 | # 58 | format_from_metric: False 59 | momentum_for_metric: 0.1 60 | metric: std 61 | 62 | finetune_iters: 100 63 | ptcv_pretrained: True 64 | 65 | no_clipping: True 66 | input_fraclen_sharing: False 67 | 68 | format_grid_search: True 69 | 70 | # 71 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 72 | 73 | # =========================== Override Settings =========================== 74 | quant_avgpool: False 75 | pool_fusing: False 76 | 77 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet18 78 | model: models.fix_resnet 79 | depth: 18 80 | -------------------------------------------------------------------------------- /apps/imagenet/resnet50/tiny_finetuning/res50_fix_quant_nvidia_pretrained_test.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: False 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 500 64 | ptcv_pretrained: False 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | nvidia_pretrained: True 75 | nvidia_pretrained_file: '/path/to/nvidia_model/nvidia_resnet50_200821.pth.tar' 76 | 77 | # =========================== Override Settings =========================== 78 | quant_bias: False 79 | quant_avgpool: True 80 | pool_fusing: True 81 | quant_maxpool: False 82 | int_infer: False #True ## For int model 83 | integize: False #True ## For gpu inference 84 | int_op_only: False ## For cpu inference 85 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit 86 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit 87 | print_each_iter: True 88 | 89 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 90 | test_only: True 91 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet50 92 | model: models.fix_resnet 93 | depth: 50 94 | -------------------------------------------------------------------------------- /apps/imagenet/resnet50/tiny_finetuning/res50_fix_quant_nvidia_pretrained_test_int_model.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: False 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 500 64 | ptcv_pretrained: False 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | nvidia_pretrained: True 75 | nvidia_pretrained_file: '/path/to/nvidia_model/nvidia_resnet50_200821.pth.tar' 76 | 77 | # =========================== Override Settings =========================== 78 | quant_bias: True 79 | quant_avgpool: True 80 | pool_fusing: True 81 | quant_maxpool: True 82 | int_infer: True ## For int model 83 | integize: False #True ## For gpu inference 84 | int_op_only: False ## For cpu inference 85 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit 86 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit 87 | print_each_iter: True 88 | 89 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 90 | test_only: True 91 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet50 92 | model: models.fix_resnet 93 | depth: 50 94 | -------------------------------------------------------------------------------- /apps/imagenet/resnet50/tiny_finetuning/res50_fix_quant_nvidia_pretrained_test_int_op_only_on_cpu.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: False 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 500 64 | ptcv_pretrained: False 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | nvidia_pretrained: True 75 | nvidia_pretrained_file: '/path/to/nvidia_model/nvidia_resnet50_200821.pth.tar' 76 | 77 | # =========================== Override Settings =========================== 78 | quant_bias: True 79 | quant_avgpool: True 80 | pool_fusing: True 81 | quant_maxpool: False #True ## Onnx does not support unfold used in MaxPool 82 | int_infer: True ## For int model 83 | integize: False #True ## For gpu inference 84 | int_op_only: True #False ## For cpu inference 85 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit 86 | int_op_only_file_path: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit 87 | print_each_iter: True 88 | 89 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 90 | test_only: True 91 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet50 92 | model: models.fix_resnet 93 | depth: 50 94 | -------------------------------------------------------------------------------- /apps/imagenet/resnet50/tiny_finetuning/res50_fix_quant_nvidia_pretrained_test_integize_on_gpu.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: False 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 500 64 | ptcv_pretrained: False 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | nvidia_pretrained: True 75 | nvidia_pretrained_file: '/path/to/nvidia_model/nvidia_resnet50_200821.pth.tar' 76 | 77 | # =========================== Override Settings =========================== 78 | quant_bias: True 79 | quant_avgpool: True 80 | pool_fusing: True 81 | quant_maxpool: False #True ## Onnx does not support unfold used in MaxPool 82 | int_infer: True ## For int model 83 | integize: True ## For gpu inference 84 | int_op_only: False ## For cpu inference 85 | integize_file_path: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit 86 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit 87 | print_each_iter: True 88 | 89 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/nvidia_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 90 | test_only: True 91 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet50 92 | model: models.fix_resnet 93 | depth: 50 94 | -------------------------------------------------------------------------------- /apps/imagenet/resnet50/tiny_finetuning/res50_fix_quant_nvidia_pretrained_train.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.0001 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: False 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 500 64 | ptcv_pretrained: False 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | nvidia_pretrained: True 75 | nvidia_pretrained_file: '/path/to/nvidia_model/nvidia_resnet50_200821.pth.tar' 76 | 77 | # =========================== Override Settings =========================== 78 | quant_avgpool: True #False 79 | pool_fusing: True #False 80 | 81 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet50 82 | model: models.fix_resnet 83 | depth: 50 84 | -------------------------------------------------------------------------------- /apps/imagenet/resnet50/tiny_finetuning/res50_fix_quant_ptcv_pretrained_test.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 500 64 | ptcv_pretrained: True 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | # =========================== Override Settings =========================== 75 | quant_bias: False 76 | quant_avgpool: True 77 | pool_fusing: True 78 | quant_maxpool: False 79 | int_infer: False #True ## For int model 80 | integize: False #True ## For gpu inference 81 | int_op_only: False ## For cpu inference 82 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit 83 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit 84 | print_each_iter: True 85 | 86 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 87 | test_only: True 88 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet50 89 | model: models.fix_resnet 90 | depth: 50 91 | -------------------------------------------------------------------------------- /apps/imagenet/resnet50/tiny_finetuning/res50_fix_quant_ptcv_pretrained_test_int_model.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 500 64 | ptcv_pretrained: True 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | # =========================== Override Settings =========================== 75 | quant_bias: True 76 | quant_avgpool: True 77 | pool_fusing: True 78 | quant_maxpool: True 79 | int_infer: True ## For int model 80 | integize: False #True ## For gpu inference 81 | int_op_only: False ## For cpu inference 82 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit 83 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit 84 | print_each_iter: True 85 | 86 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 87 | test_only: True 88 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet50 89 | model: models.fix_resnet 90 | depth: 50 91 | -------------------------------------------------------------------------------- /apps/imagenet/resnet50/tiny_finetuning/res50_fix_quant_ptcv_pretrained_test_int_op_only_on_cpu.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 500 64 | ptcv_pretrained: True 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | # =========================== Override Settings =========================== 75 | quant_bias: True 76 | quant_avgpool: True 77 | pool_fusing: True 78 | quant_maxpool: False #True ## Onnx does not support unfold used in MaxPool 79 | int_infer: True ## For int model 80 | integize: False #True ## For gpu inference 81 | int_op_only: True #False ## For cpu inference 82 | integize_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit 83 | int_op_only_file_path: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit 84 | print_each_iter: True 85 | 86 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 87 | test_only: True 88 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet50 89 | model: models.fix_resnet 90 | depth: 50 91 | -------------------------------------------------------------------------------- /apps/imagenet/resnet50/tiny_finetuning/res50_fix_quant_ptcv_pretrained_test_integize_on_gpu.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0 26 | lr_scheduler: constant 27 | 28 | 29 | # pretrain, resume, test_only 30 | pretrained_dir: '' 31 | pretrained_file: '' 32 | resume: '' 33 | test_only: False 34 | 35 | # 36 | random_seed: 1995 37 | model: '' 38 | reset_parameters: True 39 | 40 | # 41 | distributed: False 42 | distributed_all_reduce: False 43 | use_diff_seed: False 44 | 45 | # 46 | rescale_forward: True 47 | rescale_forward_conv: False 48 | normalize: True 49 | rescale_type: constant #[stddev, constant] 50 | 51 | # 52 | weight_format: [8, 7] 53 | input_format: [8, 6] 54 | 55 | # 56 | format_type: per_layer #[~, per_model, per_layer, per_channel] 57 | 58 | # 59 | format_from_metric: True 60 | momentum_for_metric: 0.1 61 | metric: std 62 | 63 | finetune_iters: 500 64 | ptcv_pretrained: True 65 | 66 | no_clipping: True 67 | input_fraclen_sharing: False 68 | 69 | format_grid_search: True 70 | 71 | # 72 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 73 | 74 | # =========================== Override Settings =========================== 75 | quant_bias: True 76 | quant_avgpool: True 77 | pool_fusing: True 78 | quant_maxpool: False #True ## Onnx does not support unfold used in MaxPool 79 | int_infer: True ## For int model 80 | integize: True ## For gpu inference 81 | int_op_only: False ## For cpu inference 82 | integize_file_path: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit 83 | int_op_only_file_path: '' #/path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit 84 | print_each_iter: True 85 | 86 | pretrained_file: /path/to/pretrained_models/ImageNet/tiny_finetuning/ResNet50/ptcv_pretrained/8bit/checkpoints/quant_avgpool_True_pool_fusing_True/best_model.pt 87 | test_only: True 88 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet50 89 | model: models.fix_resnet 90 | depth: 50 91 | -------------------------------------------------------------------------------- /apps/imagenet/resnet50/tiny_finetuning/res50_fix_quant_ptcv_pretrained_train.yml: -------------------------------------------------------------------------------- 1 | # =========================== Basic Settings =========================== 2 | # machine info 3 | num_gpus_per_job: 8 # number of gpus each job need 4 | 5 | # data 6 | dataset: imagenet1k 7 | data_transforms: imagenet1k 8 | data_loader: imagenet1k 9 | dataset_dir: data 10 | data_loader_workers: 5 11 | 12 | # info 13 | num_classes: 1000 14 | image_size: 224 15 | topk: [1, 5] 16 | num_epochs: 1 17 | 18 | # optimizer 19 | optimizer: sgd 20 | momentum: 0.9 21 | weight_decay: 0.0001 22 | nesterov: True 23 | 24 | # lr 25 | lr: 0.0001 26 | lr_scheduler: constant 27 | 28 | # pretrain, resume, test_only 29 | pretrained_dir: '' 30 | pretrained_file: '' 31 | resume: '' 32 | test_only: False 33 | 34 | # 35 | random_seed: 1995 36 | model: '' 37 | reset_parameters: True 38 | 39 | # 40 | distributed: False 41 | distributed_all_reduce: False 42 | use_diff_seed: False 43 | 44 | # 45 | rescale_forward: True 46 | rescale_forward_conv: False 47 | normalize: True 48 | rescale_type: constant #[stddev, constant] 49 | 50 | # 51 | weight_format: [8, 7] 52 | input_format: [8, 6] 53 | 54 | # 55 | format_type: per_layer #[~, per_model, per_layer, per_channel] 56 | 57 | # 58 | format_from_metric: False 59 | momentum_for_metric: 0.1 60 | metric: std 61 | 62 | finetune_iters: 500 63 | ptcv_pretrained: True 64 | 65 | no_clipping: True 66 | input_fraclen_sharing: False 67 | 68 | format_grid_search: True 69 | 70 | # 71 | weight_decay_scheme: no_depthwise_no_bn #[all, only_no_depthwise, only_no_bn, no_depthwise_no_bn] 72 | 73 | # =========================== Override Settings =========================== 74 | quant_avgpool: True 75 | pool_fusing: True 76 | 77 | log_dir: /path/to/checkpoints/F8Net/results/imagenet/resnet50 78 | model: models.fix_resnet 79 | depth: 50 80 | -------------------------------------------------------------------------------- /distributed_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cfg=$1 3 | bs=${2:-256} 4 | num_gpus=${3:-8} 5 | num_proc_per_nodes=$(( num_gpus < 8 ? num_gpus : 8 )) 6 | echo "Total batch size: " $bs 7 | echo "No. of processes per node: " $num_proc_per_nodes 8 | if [ ! -f $cfg ]; then 9 | echo "Config not found!" 10 | fi 11 | 12 | RANK=0 python3 -W ignore -m torch.distributed.launch --nproc_per_node=$num_proc_per_nodes fix_train.py app:$cfg bs:$bs 13 | -------------------------------------------------------------------------------- /error_analysis/fixed_quant_analysis.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from matplotlib.patches import Ellipse, FancyArrowPatch 4 | 5 | import torch 6 | 7 | 8 | def fix_quant(input, wl=8, fl=0, signed=True): 9 | assert wl >= 0 10 | assert fl >= 0 11 | if signed: 12 | assert fl <= wl - 1 13 | else: 14 | assert fl <= wl 15 | assert type(wl) == int 16 | assert type(fl) == int 17 | res = input * (2**fl) 18 | res.round_() 19 | if signed: 20 | bound = 2**(wl - 1) - 1 21 | res.clamp_(max=bound, min=-bound) 22 | else: 23 | bound = 2**wl - 1 24 | res.clamp_(max=bound, min=0) 25 | res.div_(2**fl) 26 | return res 27 | 28 | 29 | def main(): 30 | fl_cmap = { 31 | 0: [0.2, 0.2, 0.2], 32 | 1: [155 / 255, 221 / 255, 239 / 255], 33 | 2: [255 / 255, 102 / 255, 153 / 255], 34 | 3: [189 / 255, 146 / 255, 222 / 255], 35 | 4: [75 / 255, 148 / 255, 255 / 255], 36 | 5: [199 / 255, 225 / 255, 181 / 255], 37 | 6: [241 / 255, 245 / 255, 161 / 255], 38 | 7: [255 / 255, 133 / 255, 133 / 255], 39 | 8: [40 / 255, 240 / 255, 128 / 255] 40 | } 41 | 42 | wl = 8 43 | N = 10000 44 | signed = True 45 | normalize = True 46 | 47 | fig_size = (6, 4) 48 | axes_label_size = 16 49 | text_size = 12 50 | equation_text_size = 20 51 | title_size = 16 52 | legend_size = 8 53 | font_weight = 'normal' 54 | 55 | sigma_list = np.logspace(-3, 3, 1000) 56 | title_dict = {0: 'Unsigned (Rectified Gaussian)', 1: 'Signed (Gaussian)'} 57 | for wl in [8]: 58 | for signed in [True, False]: 59 | fl_list = list(range(wl + 1 - int(signed))) 60 | w_quant_err_sigma = [] 61 | opt_fl = [] 62 | opt_err = [] 63 | for sigma in sigma_list: 64 | w_quant_err_fl = [] 65 | w_rand = torch.randn(N) * sigma 66 | if not signed: 67 | w_rand = torch.relu(w_rand) 68 | for fl in fl_list: 69 | w_quant = fix_quant(w_rand, wl, fl, signed) 70 | error = np.mean((w_rand - w_quant).cpu().numpy()**2)**0.5 71 | if normalize: 72 | error = error / sigma 73 | w_quant_err_fl.append(error) 74 | err_min_idx = np.argmin(w_quant_err_fl) 75 | opt_fl.append(fl_list[err_min_idx]) 76 | opt_err.append(w_quant_err_fl[err_min_idx]) 77 | w_quant_err_sigma.append(w_quant_err_fl) 78 | w_quant_err_sigma = np.array(w_quant_err_sigma) 79 | 80 | ## replace the first zeros by the max 81 | opt_fl = np.array(opt_fl) 82 | idx_last_max = np.nonzero(opt_fl == max(fl_list))[0][-1] 83 | mask_to_change = opt_fl[:idx_last_max] == 0 84 | opt_fl[:idx_last_max][mask_to_change] = max(fl_list) 85 | 86 | ## sigma 87 | opt_sigma = [] 88 | fig = plt.figure(figsize=fig_size) 89 | for idx, fl in enumerate(fl_list): 90 | plt.semilogx(sigma_list, 91 | w_quant_err_sigma[:, idx], 92 | label=f'FL={fl}', 93 | c=fl_cmap[fl], 94 | lw=2) 95 | local_min = np.argmin(w_quant_err_sigma[:, idx]) 96 | opt_sigma.append(sigma_list[local_min]) 97 | plt.scatter(sigma_list[local_min], 98 | w_quant_err_sigma[local_min, idx], 99 | color=fl_cmap[fl], 100 | marker='*', 101 | s=60) 102 | plt.gca().annotate('Overflow', 103 | fontsize=text_size, 104 | fontweight=font_weight, 105 | xy=(0.55, 0.87), 106 | xycoords='figure fraction', 107 | xytext=(0.65, 0.86), 108 | textcoords='figure fraction', 109 | arrowprops=dict(arrowstyle="<-", 110 | connectionstyle="arc3")) 111 | plt.gca().annotate('Underflow', 112 | fontsize=text_size, 113 | fontweight=font_weight, 114 | xy=(0.55, 0.87), 115 | xycoords='figure fraction', 116 | xytext=(0.32, 0.86), 117 | textcoords='figure fraction', 118 | arrowprops=dict(arrowstyle="<-", 119 | connectionstyle="arc3")) 120 | plt.legend(ncol=1, 121 | loc='lower right', 122 | prop={ 123 | 'size': legend_size, 124 | 'weight': font_weight 125 | }) 126 | plt.xlabel(r'$\sigma$', 127 | fontsize=axes_label_size, 128 | fontweight=font_weight) 129 | plt.ylabel('Relative Error', 130 | fontsize=axes_label_size, 131 | fontweight=font_weight) 132 | plt.ylim(top=plt.ylim()[1] * 1.02) 133 | plt.setp(plt.gca().get_xticklabels(), 134 | fontsize=axes_label_size, 135 | fontweight=font_weight) 136 | plt.setp(plt.gca().get_yticklabels(), 137 | fontsize=axes_label_size, 138 | fontweight=font_weight) 139 | title = title_dict[int(signed)].split(' ') 140 | title.insert(1, f'{wl}-bit') 141 | title = ' '.join(title) 142 | plt.title(title, fontsize=title_size) 143 | plt.subplots_adjust(bottom=0.15, top=0.9, left=0.15, right=0.95) 144 | plt.savefig( 145 | f'./std_fix_quant_error_analysis_{wl}bit_signed_{signed}.pdf', 146 | dpi=800) 147 | 148 | fig = plt.figure(figsize=fig_size) 149 | plt.semilogy(fl_list, 150 | opt_sigma, 151 | color='b', 152 | lw=2, 153 | ls='--', 154 | marker='o', 155 | markersize=8) 156 | plt.xlabel('Fractional Length (FL)', 157 | fontsize=axes_label_size, 158 | fontweight=font_weight) 159 | plt.ylabel('Optimal ' + r'$\sigma$', 160 | fontsize=axes_label_size, 161 | fontweight=font_weight) 162 | plt.setp(plt.gca().get_xticklabels(), 163 | fontsize=axes_label_size, 164 | fontweight=font_weight) 165 | plt.setp(plt.gca().get_yticklabels(), 166 | fontsize=axes_label_size, 167 | fontweight=font_weight) 168 | title = title_dict[int(signed)].split(' ') 169 | title.insert(1, f'{wl}-bit') 170 | title = ' '.join(title) 171 | plt.title(title, fontsize=title_size, fontweight=font_weight) 172 | plt.subplots_adjust(bottom=0.15, top=0.9, left=0.15, right=0.95) 173 | plt.savefig(f'./std_opt_sigma_vs_fl_{wl}bit_signed_{signed}.pdf', 174 | dpi=800) 175 | 176 | ax1_color = 'b' 177 | ax2_color = 'r' 178 | fig, ax1 = plt.subplots(figsize=fig_size) 179 | lns1 = ax1.semilogx(sigma_list, 180 | opt_fl, 181 | color=ax1_color, 182 | lw=2, 183 | ls='-', 184 | label='Opt. Frac. Len.') 185 | if signed: 186 | ell1_x = 0.84 187 | else: 188 | ell1_x = 0.88 189 | ellipse1 = Ellipse(xy=(ell1_x, 0.5), 190 | width=0.04, 191 | height=0.12, 192 | edgecolor=ax1_color, 193 | fc='None', 194 | lw=2, 195 | transform=plt.gca().transAxes) 196 | arrow_connectionstyle = "arc3,rad=.2" 197 | arrow_style = "Simple, tail_width=0.5, head_width=4, head_length=8" 198 | arr1 = FancyArrowPatch((ell1_x, 0.5 - 0.058), 199 | (ell1_x + 0.04 * 2.5, 0.5 - 0.06 * 1.8), 200 | connectionstyle=arrow_connectionstyle, 201 | arrowstyle=arrow_style, 202 | color=ax1_color, 203 | transform=plt.gca().transAxes) 204 | ax1.set_xlabel(r'$\sigma$', 205 | fontsize=axes_label_size, 206 | fontweight=font_weight) 207 | ax1.set_ylabel('Opt. Frac. Len. (' + r'$\mathrm{FL}^*$' + ')', 208 | fontsize=axes_label_size, 209 | fontweight=font_weight) 210 | ax1.yaxis.label.set_color(ax1_color) 211 | ax1.tick_params(axis='y', labelcolor=ax1_color) 212 | plt.setp(ax1.get_xticklabels(), 213 | fontsize=axes_label_size, 214 | fontweight=font_weight) 215 | plt.setp(ax1.get_yticklabels(), 216 | fontsize=axes_label_size, 217 | fontweight=font_weight) 218 | 219 | ax2 = ax1.twinx() 220 | lns2 = ax2.semilogx(sigma_list, 221 | opt_err, 222 | color=ax2_color, 223 | lw=2, 224 | ls='-', 225 | label='Min. Rel. Err.') 226 | if signed: 227 | ell2_x = 0.3 228 | else: 229 | ell2_x = 0.3 230 | ellipse2 = Ellipse(xy=(ell2_x, 0.93), 231 | width=0.04, 232 | height=0.12, 233 | edgecolor=ax2_color, 234 | fc='None', 235 | lw=2, 236 | transform=plt.gca().transAxes) 237 | arrow_connectionstyle = "arc3,rad=-.2" 238 | arrow_style = "Simple, tail_width=0.5, head_width=4, head_length=8" 239 | arr2 = FancyArrowPatch((ell2_x, 0.93 - 0.058), 240 | (ell2_x - 0.04 * 2.5, 0.93 - 0.06 * 1.8), 241 | connectionstyle=arrow_connectionstyle, 242 | arrowstyle=arrow_style, 243 | color=ax2_color, 244 | transform=plt.gca().transAxes) 245 | ax2.set_ylabel('Minimum Relative Error', 246 | fontsize=axes_label_size, 247 | fontweight=font_weight) 248 | ax2.yaxis.label.set_color(ax2_color) 249 | ax2.tick_params(axis='y', labelcolor=ax2_color) 250 | plt.setp(ax2.get_xticklabels(), 251 | fontsize=axes_label_size, 252 | fontweight=font_weight) 253 | plt.setp(ax2.get_yticklabels(), 254 | fontsize=axes_label_size, 255 | fontweight=font_weight) 256 | leg = lns1 + lns2 257 | labs = [l.get_label() for l in leg] 258 | ax1.legend(leg, 259 | labs, 260 | ncol=2, 261 | loc='upper center', 262 | prop={'size': axes_label_size * 0.75}, 263 | bbox_to_anchor=(0.5, -0.25)) 264 | title = title_dict[int(signed)].split(' ') 265 | title.insert(1, f'{wl}-bit') 266 | title = ' '.join(title) 267 | plt.title(title, fontsize=title_size, fontweight=font_weight) 268 | plt.subplots_adjust(bottom=0.27, top=0.9, left=0.1, right=0.87) 269 | plt.savefig( 270 | f'./std_opt_fl_and_err_vs_sigma_{wl}bit_signed_{signed}.pdf', 271 | dpi=800) 272 | 273 | all_result = np.stack( 274 | [np.array(sigma_list), 275 | np.array(opt_err), 276 | np.array(opt_fl)], 277 | axis=1) 278 | np.savetxt( 279 | f'./all_results_{wl}bit_signed_{signed}.txt', 280 | all_result, 281 | header=f'signed={signed}\nsigma\tmae\trms\topt err\t opt fl') 282 | 283 | ## threshold plot 284 | fl_list = np.array(fl_list) 285 | sigma_th_list = [] 286 | for fl in fl_list[1:]: 287 | threshold_idx = np.nonzero(opt_fl == fl - 1)[0][0] 288 | sigma_th_list.append(sigma_list[threshold_idx]) 289 | ## sigma 290 | plt.figure(figsize=fig_size) 291 | plt.scatter(fl_list[1:], 292 | sigma_th_list, 293 | color='b', 294 | marker='o', 295 | s=24, 296 | label='Empirical') 297 | coeff = 2**np.mean(np.array(fl_list[1:]) + np.log2(sigma_th_list)) 298 | coeff = np.around(coeff, 2) 299 | plt.plot(fl_list[1:], 300 | coeff / 2**fl_list[1:], 301 | color='r', 302 | lw=2, 303 | ls='--', 304 | label='Linear Fitting') 305 | plt.text(0.2, 306 | 0.3, 307 | r'$\sigma=$'.format(coeff, 'fl'), 308 | transform=plt.gca().transAxes, 309 | fontsize=equation_text_size, 310 | fontweight=font_weight) 311 | plt.text(0.31, 312 | 0.3, 313 | r'$\frac{{{}}}{{2^\mathrm{{{}}}}}$'.format(coeff, 'FL'), 314 | transform=plt.gca().transAxes, 315 | fontsize=equation_text_size * 1.2, 316 | fontweight=font_weight) 317 | plt.gca().set_yscale('log') 318 | plt.legend(ncol=2, 319 | loc='upper center', 320 | bbox_to_anchor=(0.5, -0.25), 321 | prop={ 322 | 'weight': font_weight, 323 | 'size': legend_size * 1.5 324 | }) 325 | plt.xlabel('Fractional Length (FL)', 326 | fontsize=axes_label_size, 327 | fontweight=font_weight) 328 | plt.ylabel('Threshold ' + r'$\sigma$', 329 | fontsize=axes_label_size, 330 | fontweight=font_weight) 331 | plt.setp(plt.gca().get_xticklabels(), 332 | fontsize=axes_label_size, 333 | fontweight=font_weight) 334 | plt.setp(plt.gca().get_yticklabels(), 335 | fontsize=axes_label_size, 336 | fontweight=font_weight) 337 | title = title_dict[int(signed)].split(' ') 338 | title.insert(1, f'{wl}-bit') 339 | title = ' '.join(title) 340 | plt.title(title, fontsize=title_size, fontweight=font_weight) 341 | plt.subplots_adjust(bottom=0.27, top=0.9, left=0.15, right=0.95) 342 | plt.savefig(f'./sigma_threshold_vs_fl_{wl}bit_signed_{signed}.pdf', 343 | dpi=800) 344 | 345 | 346 | if __name__ == '__main__': 347 | main() 348 | -------------------------------------------------------------------------------- /error_analysis/sigma_threshold_vs_fl_8bit_signed_False.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/error_analysis/sigma_threshold_vs_fl_8bit_signed_False.pdf -------------------------------------------------------------------------------- /error_analysis/sigma_threshold_vs_fl_8bit_signed_True.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/error_analysis/sigma_threshold_vs_fl_8bit_signed_True.pdf -------------------------------------------------------------------------------- /error_analysis/std_fix_quant_error_analysis_8bit_signed_False.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/error_analysis/std_fix_quant_error_analysis_8bit_signed_False.pdf -------------------------------------------------------------------------------- /error_analysis/std_fix_quant_error_analysis_8bit_signed_True.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/error_analysis/std_fix_quant_error_analysis_8bit_signed_True.pdf -------------------------------------------------------------------------------- /error_analysis/std_opt_fl_and_err_vs_sigma_8bit_signed_False.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/error_analysis/std_opt_fl_and_err_vs_sigma_8bit_signed_False.pdf -------------------------------------------------------------------------------- /error_analysis/std_opt_fl_and_err_vs_sigma_8bit_signed_True.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/error_analysis/std_opt_fl_and_err_vs_sigma_8bit_signed_True.pdf -------------------------------------------------------------------------------- /error_analysis/std_opt_sigma_vs_fl_8bit_signed_False.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/error_analysis/std_opt_sigma_vs_fl_8bit_signed_False.pdf -------------------------------------------------------------------------------- /error_analysis/std_opt_sigma_vs_fl_8bit_signed_True.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/error_analysis/std_opt_sigma_vs_fl_8bit_signed_True.pdf -------------------------------------------------------------------------------- /fraclen_visual/fraclen_visualizing_mbv2.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | import matplotlib 5 | matplotlib.use('Agg') 6 | 7 | matplotlib.rcParams['pdf.fonttype'] = 42 8 | matplotlib.rcParams['ps.fonttype'] = 42 9 | 10 | import matplotlib.pyplot as plt 11 | import matplotlib.patches as patches 12 | 13 | import torch 14 | 15 | 16 | def main(): 17 | work_dir = './' 18 | log_file_name = 'mbv2_fix_quant.out' 19 | 20 | depthwise_layer = [ 21 | 'stage_0_layer_0.body.0', 'stage_1_layer_0.body.1', 22 | 'stage_1_layer_1.body.1', 'stage_2_layer_0.body.1', 23 | 'stage_2_layer_1.body.1', 'stage_2_layer_2.body.1', 24 | 'stage_3_layer_0.body.1', 'stage_3_layer_1.body.1', 25 | 'stage_3_layer_2.body.1', 'stage_3_layer_3.body.1', 26 | 'stage_4_layer_0.body.1', 'stage_4_layer_1.body.1', 27 | 'stage_4_layer_2.body.1', 'stage_5_layer_0.body.1', 28 | 'stage_5_layer_1.body.1', 'stage_5_layer_2.body.1', 29 | 'stage_6_layer_0.body.1' 30 | ] 31 | 32 | layer_fraclen_dict = {} 33 | with open(os.path.join(work_dir, log_file_name), 'r') as f: 34 | lines = f.read().splitlines() 35 | lines = [l for l in lines if 'fraclen' in l or 'name' in l] 36 | lines = [ 37 | l for l in lines 38 | if 'setting' not in l and 'model' not in l and 'log' not in l 39 | ] 40 | lines = [l[:-1] for l in lines] 41 | assert len(lines) % 3 == 0 42 | for idx in range(len(lines) // 3): 43 | assert 'layer name' in lines[idx * 3] 44 | assert 'input_fraclen' in lines[idx * 3 + 1] 45 | assert 'weight_fraclen' in lines[idx * 3 + 2] 46 | layer_name = lines[idx * 3][12:] 47 | if layer_name in depthwise_layer: 48 | depthwise = True 49 | else: 50 | depthwise = False 51 | if 'shortcut' in layer_name: 52 | shortcut = True 53 | else: 54 | shortcut = False 55 | if 'classifier' in layer_name: 56 | fc = True 57 | else: 58 | fc = False 59 | if 'body.0' in layer_name and 'stage_0' not in layer_name: 60 | double_side = True 61 | elif 'tail' in layer_name: 62 | double_side = True 63 | else: 64 | double_side = False 65 | input_fraclen = int( 66 | torch.round(eval('torch.' + lines[idx * 3 + 1][15:])).item()) 67 | weight_fraclen = int(np.around(eval(lines[idx * 3 + 2][16:]))) 68 | layer_fraclen_dict[layer_name] = (weight_fraclen, input_fraclen, 69 | depthwise, shortcut, fc, double_side) 70 | 71 | cm = {'b': [80 / 255, 156 / 255, 1.0], 'm': [250 / 255, 0, 101 / 255]} 72 | model_name = {'mobilenetv2': 'MobileNet V2'} 73 | delta = {'mobilenetv2': 6} 74 | bit_cmap = { 75 | 0: [1.0, 1.0, 1.0], 76 | 1: [155 / 255, 221 / 255, 239 / 255], 77 | 2: [255 / 255, 102 / 255, 153 / 255], 78 | 3: [189 / 255, 146 / 255, 222 / 255], 79 | 4: [75 / 255, 148 / 255, 255 / 255], 80 | 5: [199 / 255, 225 / 255, 181 / 255], 81 | 6: [241 / 255, 245 / 255, 161 / 255], 82 | 7: [255 / 255, 133 / 255, 133 / 255], 83 | 8: [40 / 255, 240 / 255, 128 / 255] 84 | } 85 | fig_size = (6, 4) 86 | axes_label_size = 16 87 | text_size = 12 88 | title_size = 16 89 | legend_size = 8 90 | font_weight = 'normal' 91 | for model in ['mobilenetv2']: 92 | if model in ['mobilenetv2']: 93 | barwidth = 1 94 | patch_width = 2 95 | arrow_extension = 3 96 | else: 97 | barwidth = 1 98 | if shortcut: 99 | patch_width = 1 100 | else: 101 | patch_width = .75 102 | arrow_extension = .75 103 | 104 | weight_fraclen_list = [v[0] for v in layer_fraclen_dict.values()] 105 | input_fraclen_list = [-v[1] for v in layer_fraclen_dict.values()] 106 | ## The first layer does not quantize input 107 | input_fraclen_list[0] = -8 108 | depthwise_list = [v[2] for v in layer_fraclen_dict.values()] 109 | fc_list = [v[4] for v in layer_fraclen_dict.values()] 110 | double_side_list = [v[5] for v in layer_fraclen_dict.values()] 111 | plt.figure(figsize=fig_size) 112 | plt.gca().spines['top'].set_visible(False) 113 | plt.gca().spines['bottom'].set_visible(False) 114 | plt.gca().spines['left'].set_visible(False) 115 | plt.gca().spines['right'].set_visible(False) 116 | plt.gca().tick_params(axis='both', which='both', length=0) 117 | ids = np.arange(len(weight_fraclen_list)) 118 | alpha = 0.5 119 | if model in ['mobilenetv2']: 120 | color_w = [ 121 | cm['b'] + [alpha] if depthwise_list[idx] else cm['b'] 122 | for idx in ids 123 | ] 124 | color_a = [ 125 | cm['m'] + [alpha] if depthwise_list[idx] else cm['m'] 126 | for idx in ids 127 | ] 128 | else: 129 | color_w = [cm['b'] for idx in ids] 130 | color_a = [cm['m'] for idx in ids] 131 | plt.bar(ids * barwidth, 132 | weight_fraclen_list, 133 | bottom=0.01, 134 | width=barwidth * 0.8, 135 | color=color_w, 136 | edgecolor='k', 137 | linewidth=0.3) 138 | plt.bar(ids * barwidth, 139 | input_fraclen_list, 140 | bottom=-0.01, 141 | width=barwidth * 0.8, 142 | color=color_a, 143 | edgecolor='k', 144 | linewidth=0.3) 145 | plt.plot(np.arange(-barwidth / 2, 146 | barwidth * len(ids) + barwidth / 2, barwidth), 147 | np.ones(len(ids) + 1) * 2, 148 | ls='--', 149 | lw=0.5, 150 | c='k') 151 | plt.plot(np.arange(-barwidth / 2, 152 | barwidth * len(ids) + barwidth / 2, barwidth), 153 | np.ones(len(ids) + 1) * 4, 154 | ls='--', 155 | lw=0.5, 156 | c='k') 157 | plt.plot(np.arange(-barwidth / 2, 158 | barwidth * len(ids) + barwidth / 2, barwidth), 159 | np.ones(len(ids) + 1) * 6, 160 | ls='--', 161 | lw=0.5, 162 | c='k') 163 | plt.plot(np.arange(-barwidth / 2, 164 | barwidth * len(ids) + barwidth / 2, barwidth), 165 | np.ones(len(ids) + 1) * 8, 166 | ls='--', 167 | lw=0.5, 168 | c='k') 169 | plt.plot(np.arange(-barwidth / 2, 170 | barwidth * len(ids) + barwidth / 2, barwidth), 171 | -np.ones(len(ids) + 1) * 8, 172 | ls='--', 173 | lw=0.5, 174 | c='k') 175 | plt.plot(np.arange(-barwidth / 2, 176 | barwidth * len(ids) + barwidth / 2, barwidth), 177 | -np.ones(len(ids) + 1) * 6, 178 | ls='--', 179 | lw=0.5, 180 | c='k') 181 | plt.plot(np.arange(-barwidth / 2, 182 | barwidth * len(ids) + barwidth / 2, barwidth), 183 | -np.ones(len(ids) + 1) * 4, 184 | ls='--', 185 | lw=0.5, 186 | c='k') 187 | plt.plot(np.arange(-barwidth / 2, 188 | barwidth * len(ids) + barwidth / 2, barwidth), 189 | -np.ones(len(ids) + 1) * 2, 190 | ls='--', 191 | lw=0.5, 192 | c='k') 193 | plt.arrow(-barwidth / 2, 194 | 0, 195 | barwidth * len(ids) + barwidth / 2 + 196 | barwidth * arrow_extension, 197 | 0, 198 | ls='-', 199 | color='k', 200 | width=.005, 201 | head_width=0.15, 202 | head_length=0.1 * arrow_extension) 203 | rect_w_pw = patches.Rectangle((barwidth * len(ids) / 2 * 0, -10), 204 | 1.2 * patch_width, 205 | 1.2, 206 | linewidth=.5, 207 | edgecolor='k', 208 | facecolor=cm['b']) 209 | rect_w_dw = patches.Rectangle((barwidth * len(ids) / 2 * 0, -12), 210 | 1.2 * patch_width, 211 | 1.2, 212 | linewidth=.5, 213 | edgecolor='k', 214 | facecolor=cm['b'] + [alpha]) 215 | rect_a_pw = patches.Rectangle((barwidth * len(ids) / 2 * 1.1, -10), 216 | 1.2 * patch_width, 217 | 1.2, 218 | linewidth=.5, 219 | edgecolor='k', 220 | facecolor=cm['m']) 221 | rect_a_dw = patches.Rectangle((barwidth * len(ids) / 2 * 1.1, -12), 222 | 1.2 * patch_width, 223 | 1.2, 224 | linewidth=.5, 225 | edgecolor='k', 226 | facecolor=cm['m'] + [alpha]) 227 | plt.gca().add_patch(rect_w_pw) 228 | plt.gca().add_patch(rect_a_pw) 229 | if model in ['mobilenetv2']: 230 | plt.gca().add_patch(rect_w_dw) 231 | plt.gca().add_patch(rect_a_dw) 232 | if model in ['mobilenetv2']: 233 | plt.text(barwidth * len(ids) / 2 * 0 + patch_width * 1.6, 234 | -9.65, 235 | '#Weight FL (pointwise)', 236 | fontsize=text_size) 237 | plt.text(barwidth * len(ids) / 2 * 1.1 + patch_width * 1.6, 238 | -9.65, 239 | '#Activation FL (pointwise)', 240 | fontsize=text_size) 241 | plt.text(barwidth * len(ids) / 2 * 0 + patch_width * 1.6, 242 | -11.65, 243 | '#Weight FL (depthwise)', 244 | fontsize=text_size) 245 | plt.text(barwidth * len(ids) / 2 * 1.1 + patch_width * 1.6, 246 | -11.65, 247 | '#Activation FL (depthwise)', 248 | fontsize=text_size) 249 | plt.xticks([]) 250 | plt.yticks(np.arange(-8, 9, 2), np.abs(np.arange(-8, 9, 2))) 251 | plt.xlabel('Layer', fontsize=axes_label_size) 252 | plt.ylabel('Fractional Length', fontsize=axes_label_size) 253 | plt.setp(plt.gca().get_xticklabels(), 254 | fontsize=axes_label_size, 255 | fontweight=font_weight) 256 | plt.setp(plt.gca().get_yticklabels(), 257 | fontsize=axes_label_size, 258 | fontweight=font_weight) 259 | plt.gca().xaxis.set_label_coords(1.0, 0.56) 260 | plt.gca().yaxis.set_label_coords(-0.05, 0.58) 261 | plt.xlim(-0.6, barwidth * len(ids) + 1.2 * barwidth * arrow_extension) 262 | plt.ylim(-12, 8.5) 263 | plt.savefig(f'./{model}_8bit_fraclens_wo_title.pdf', 264 | dpi=300, 265 | bbox_inches='tight') 266 | plt.title(f'Fractional Length vs Layer (8-bit {model_name[model]})', 267 | fontsize=title_size) 268 | plt.savefig(f'./{model}_8bit_fraclens.pdf', 269 | dpi=300, 270 | bbox_inches='tight') 271 | 272 | 273 | if __name__ == '__main__': 274 | main() 275 | -------------------------------------------------------------------------------- /fraclen_visual/fraclen_visualizing_res50.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | import matplotlib 5 | matplotlib.use('Agg') 6 | 7 | matplotlib.rcParams['pdf.fonttype'] = 42 8 | matplotlib.rcParams['ps.fonttype'] = 42 9 | 10 | import matplotlib.pyplot as plt 11 | import matplotlib.patches as patches 12 | 13 | import torch 14 | 15 | 16 | def main(): 17 | work_dir = './' 18 | log_file_name_dict = { 19 | 'ptcv': 20 | 'res50_fix_quant_ptcv_pretrained.out', 21 | 'nvidia': 22 | 'res50_fix_quant_nvidia_pretrained.out' 23 | } 24 | for pretrained_method in log_file_name_dict.keys(): 25 | print(f'pretrained with {pretrained_method}') 26 | log_file_name = log_file_name_dict[pretrained_method] 27 | 28 | depthwise_layer = [] 29 | 30 | layer_fraclen_dict = {} 31 | with open(os.path.join(work_dir, log_file_name), 'r') as f: 32 | lines = f.read().splitlines() 33 | lines = [ 34 | l for l in lines 35 | if 'fraclen' in l or l.startswith('layer name') 36 | ] 37 | lines = [ 38 | l for l in lines 39 | if 'setting' not in l and 'model' not in l and 'log' not in l 40 | ] 41 | lines = [l[:-1] for l in lines] 42 | assert len(lines) % 3 == 0 43 | for idx in range(len(lines) // 3): 44 | assert 'layer name' in lines[idx * 3] 45 | assert 'input_fraclen' in lines[idx * 3 + 1] 46 | assert 'weight_fraclen' in lines[idx * 3 + 2] 47 | layer_name = lines[idx * 3][12:] 48 | if 'shortcut' in layer_name: 49 | shortcut = True 50 | else: 51 | shortcut = False 52 | if 'classifier' in layer_name: 53 | fc = True 54 | else: 55 | fc = False 56 | input_fraclen = int( 57 | torch.round(eval('torch.' + lines[idx * 3 + 1][15:])).item()) 58 | weight_fraclen = int(np.around(eval(lines[idx * 3 + 2][16:]))) 59 | layer_fraclen_dict[layer_name] = (weight_fraclen, input_fraclen, 60 | shortcut, fc) 61 | 62 | cm = {'b': [80 / 255, 156 / 255, 1.0], 'm': [250 / 255, 0, 101 / 255]} 63 | model_name = {'resnet50': 'ResNet50'} 64 | bit_cmap = { 65 | 0: [1.0, 1.0, 1.0], 66 | 1: [155 / 255, 221 / 255, 239 / 255], 67 | 2: [255 / 255, 102 / 255, 153 / 255], 68 | 3: [189 / 255, 146 / 255, 222 / 255], 69 | 4: [75 / 255, 148 / 255, 255 / 255], 70 | 5: [199 / 255, 225 / 255, 181 / 255], 71 | 6: [241 / 255, 245 / 255, 161 / 255], 72 | 7: [255 / 255, 133 / 255, 133 / 255], 73 | 8: [40 / 255, 240 / 255, 128 / 255] 74 | } 75 | fig_size = (6, 4) 76 | axes_label_size = 16 77 | text_size = 12 78 | title_size = 16 79 | legend_size = 8 80 | font_weight = 'normal' 81 | for model in ['resnet50']: 82 | barwidth = 1 83 | patch_width = 1.0 84 | arrow_extension = 2.0 85 | 86 | weight_fraclen_list = [v[0] for v in layer_fraclen_dict.values()] 87 | input_fraclen_list = [-v[1] for v in layer_fraclen_dict.values()] 88 | ## The first layer does not quantize input 89 | input_fraclen_list[0] = -8 90 | fc_list = [v[3] for v in layer_fraclen_dict.values()] 91 | plt.figure(figsize=fig_size) 92 | plt.gca().spines['top'].set_visible(False) 93 | plt.gca().spines['bottom'].set_visible(False) 94 | plt.gca().spines['left'].set_visible(False) 95 | plt.gca().spines['right'].set_visible(False) 96 | plt.gca().tick_params(axis='both', which='both', length=0) 97 | ids = np.arange(len(weight_fraclen_list)) 98 | color_w = [cm['b'] for idx in ids] 99 | color_a = [cm['m'] for idx in ids] 100 | plt.bar(ids * barwidth, 101 | weight_fraclen_list, 102 | bottom=0.01, 103 | width=barwidth * 0.8, 104 | color=color_w, 105 | edgecolor='k', 106 | linewidth=0.3) 107 | plt.bar(ids * barwidth, 108 | input_fraclen_list, 109 | bottom=-0.01, 110 | width=barwidth * 0.8, 111 | color=color_a, 112 | edgecolor='k', 113 | linewidth=0.3) 114 | plt.plot(np.arange(-barwidth / 2, 115 | barwidth * len(ids) + barwidth / 2, barwidth), 116 | np.ones(len(ids) + 1) * 2, 117 | ls='--', 118 | lw=0.5, 119 | c='k') 120 | plt.plot(np.arange(-barwidth / 2, 121 | barwidth * len(ids) + barwidth / 2, barwidth), 122 | np.ones(len(ids) + 1) * 4, 123 | ls='--', 124 | lw=0.5, 125 | c='k') 126 | plt.plot(np.arange(-barwidth / 2, 127 | barwidth * len(ids) + barwidth / 2, barwidth), 128 | np.ones(len(ids) + 1) * 6, 129 | ls='--', 130 | lw=0.5, 131 | c='k') 132 | plt.plot(np.arange(-barwidth / 2, 133 | barwidth * len(ids) + barwidth / 2, barwidth), 134 | np.ones(len(ids) + 1) * 8, 135 | ls='--', 136 | lw=0.5, 137 | c='k') 138 | plt.plot(np.arange(-barwidth / 2, 139 | barwidth * len(ids) + barwidth / 2, barwidth), 140 | -np.ones(len(ids) + 1) * 8, 141 | ls='--', 142 | lw=0.5, 143 | c='k') 144 | plt.plot(np.arange(-barwidth / 2, 145 | barwidth * len(ids) + barwidth / 2, barwidth), 146 | -np.ones(len(ids) + 1) * 6, 147 | ls='--', 148 | lw=0.5, 149 | c='k') 150 | plt.plot(np.arange(-barwidth / 2, 151 | barwidth * len(ids) + barwidth / 2, barwidth), 152 | -np.ones(len(ids) + 1) * 4, 153 | ls='--', 154 | lw=0.5, 155 | c='k') 156 | plt.plot(np.arange(-barwidth / 2, 157 | barwidth * len(ids) + barwidth / 2, barwidth), 158 | -np.ones(len(ids) + 1) * 2, 159 | ls='--', 160 | lw=0.5, 161 | c='k') 162 | plt.arrow(-barwidth / 2, 163 | 0, 164 | barwidth * len(ids) + barwidth / 2 + 165 | barwidth * arrow_extension, 166 | 0, 167 | ls='-', 168 | color='k', 169 | width=.005, 170 | head_width=0.15, 171 | head_length=0.1 * arrow_extension) 172 | rect_w_pw = patches.Rectangle((barwidth * len(ids) / 2 * 0, -10), 173 | 2.2 * patch_width, 174 | 1.2 * patch_width, 175 | linewidth=.5, 176 | edgecolor='k', 177 | facecolor=cm['b']) 178 | rect_a_pw = patches.Rectangle((barwidth * len(ids) / 2 * 1.0, -10), 179 | 2.2 * patch_width, 180 | 1.2 * patch_width, 181 | linewidth=.5, 182 | edgecolor='k', 183 | facecolor=cm['m']) 184 | plt.gca().add_patch(rect_w_pw) 185 | plt.gca().add_patch(rect_a_pw) 186 | if model in ['resnet50']: 187 | plt.text(barwidth * len(ids) / 2 * 0 + patch_width * 2.6, 188 | -9.75, 189 | '#Weight FL', 190 | fontsize=text_size) 191 | plt.text(barwidth * len(ids) / 2 * 1 + patch_width * 2.6, 192 | -9.75, 193 | '#Activation FL', 194 | fontsize=text_size) 195 | plt.xticks([]) 196 | plt.yticks(np.arange(-8, 9, 2), np.abs(np.arange(-8, 9, 2))) 197 | plt.xlabel('Layer', fontsize=axes_label_size) 198 | plt.ylabel('Fractional Length', fontsize=axes_label_size) 199 | plt.setp(plt.gca().get_xticklabels(), 200 | fontsize=axes_label_size, 201 | fontweight=font_weight) 202 | plt.setp(plt.gca().get_yticklabels(), 203 | fontsize=axes_label_size, 204 | fontweight=font_weight) 205 | plt.gca().xaxis.set_label_coords(1.02, 0.52) 206 | plt.gca().yaxis.set_label_coords(-0.05, 0.58) 207 | plt.xlim(-0.6, 208 | barwidth * len(ids) + 1.2 * barwidth * arrow_extension) 209 | plt.ylim(-10, 8.5) 210 | plt.savefig(f'./{model}_{pretrained_method}_8bit_fraclens_wo_title.pdf', 211 | dpi=300, 212 | bbox_inches='tight') 213 | plt.title( 214 | f'Fractional Length vs Layer (8-bit {model_name[model]})', 215 | fontsize=title_size) 216 | plt.savefig(f'./{model}_{pretrained_method}_8bit_fraclens.pdf', 217 | dpi=300, 218 | bbox_inches='tight') 219 | 220 | 221 | if __name__ == '__main__': 222 | main() 223 | -------------------------------------------------------------------------------- /fraclen_visual/mobilenetv2_8bit_fraclens.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/fraclen_visual/mobilenetv2_8bit_fraclens.pdf -------------------------------------------------------------------------------- /fraclen_visual/mobilenetv2_8bit_fraclens_wo_title.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/fraclen_visual/mobilenetv2_8bit_fraclens_wo_title.pdf -------------------------------------------------------------------------------- /fraclen_visual/resnet50_nvidia_8bit_fraclens.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/fraclen_visual/resnet50_nvidia_8bit_fraclens.pdf -------------------------------------------------------------------------------- /fraclen_visual/resnet50_nvidia_8bit_fraclens_wo_title.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/fraclen_visual/resnet50_nvidia_8bit_fraclens_wo_title.pdf -------------------------------------------------------------------------------- /fraclen_visual/resnet50_ptcv_8bit_fraclens.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/fraclen_visual/resnet50_ptcv_8bit_fraclens.pdf -------------------------------------------------------------------------------- /fraclen_visual/resnet50_ptcv_8bit_fraclens_wo_title.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/fraclen_visual/resnet50_ptcv_8bit_fraclens_wo_title.pdf -------------------------------------------------------------------------------- /imagenet_classes: -------------------------------------------------------------------------------- 1 | n01440764 2 | n01443537 3 | n01484850 4 | n01491361 5 | n01494475 6 | n01496331 7 | n01498041 8 | n01514668 9 | n01514859 10 | n01518878 11 | n01530575 12 | n01531178 13 | n01532829 14 | n01534433 15 | n01537544 16 | n01558993 17 | n01560419 18 | n01580077 19 | n01582220 20 | n01592084 21 | n01601694 22 | n01608432 23 | n01614925 24 | n01616318 25 | n01622779 26 | n01629819 27 | n01630670 28 | n01631663 29 | n01632458 30 | n01632777 31 | n01641577 32 | n01644373 33 | n01644900 34 | n01664065 35 | n01665541 36 | n01667114 37 | n01667778 38 | n01669191 39 | n01675722 40 | n01677366 41 | n01682714 42 | n01685808 43 | n01687978 44 | n01688243 45 | n01689811 46 | n01692333 47 | n01693334 48 | n01694178 49 | n01695060 50 | n01697457 51 | n01698640 52 | n01704323 53 | n01728572 54 | n01728920 55 | n01729322 56 | n01729977 57 | n01734418 58 | n01735189 59 | n01737021 60 | n01739381 61 | n01740131 62 | n01742172 63 | n01744401 64 | n01748264 65 | n01749939 66 | n01751748 67 | n01753488 68 | n01755581 69 | n01756291 70 | n01768244 71 | n01770081 72 | n01770393 73 | n01773157 74 | n01773549 75 | n01773797 76 | n01774384 77 | n01774750 78 | n01775062 79 | n01776313 80 | n01784675 81 | n01795545 82 | n01796340 83 | n01797886 84 | n01798484 85 | n01806143 86 | n01806567 87 | n01807496 88 | n01817953 89 | n01818515 90 | n01819313 91 | n01820546 92 | n01824575 93 | n01828970 94 | n01829413 95 | n01833805 96 | n01843065 97 | n01843383 98 | n01847000 99 | n01855032 100 | n01855672 101 | n01860187 102 | n01871265 103 | n01872401 104 | n01873310 105 | n01877812 106 | n01882714 107 | n01883070 108 | n01910747 109 | n01914609 110 | n01917289 111 | n01924916 112 | n01930112 113 | n01943899 114 | n01944390 115 | n01945685 116 | n01950731 117 | n01955084 118 | n01968897 119 | n01978287 120 | n01978455 121 | n01980166 122 | n01981276 123 | n01983481 124 | n01984695 125 | n01985128 126 | n01986214 127 | n01990800 128 | n02002556 129 | n02002724 130 | n02006656 131 | n02007558 132 | n02009229 133 | n02009912 134 | n02011460 135 | n02012849 136 | n02013706 137 | n02017213 138 | n02018207 139 | n02018795 140 | n02025239 141 | n02027492 142 | n02028035 143 | n02033041 144 | n02037110 145 | n02051845 146 | n02056570 147 | n02058221 148 | n02066245 149 | n02071294 150 | n02074367 151 | n02077923 152 | n02085620 153 | n02085782 154 | n02085936 155 | n02086079 156 | n02086240 157 | n02086646 158 | n02086910 159 | n02087046 160 | n02087394 161 | n02088094 162 | n02088238 163 | n02088364 164 | n02088466 165 | n02088632 166 | n02089078 167 | n02089867 168 | n02089973 169 | n02090379 170 | n02090622 171 | n02090721 172 | n02091032 173 | n02091134 174 | n02091244 175 | n02091467 176 | n02091635 177 | n02091831 178 | n02092002 179 | n02092339 180 | n02093256 181 | n02093428 182 | n02093647 183 | n02093754 184 | n02093859 185 | n02093991 186 | n02094114 187 | n02094258 188 | n02094433 189 | n02095314 190 | n02095570 191 | n02095889 192 | n02096051 193 | n02096177 194 | n02096294 195 | n02096437 196 | n02096585 197 | n02097047 198 | n02097130 199 | n02097209 200 | n02097298 201 | n02097474 202 | n02097658 203 | n02098105 204 | n02098286 205 | n02098413 206 | n02099267 207 | n02099429 208 | n02099601 209 | n02099712 210 | n02099849 211 | n02100236 212 | n02100583 213 | n02100735 214 | n02100877 215 | n02101006 216 | n02101388 217 | n02101556 218 | n02102040 219 | n02102177 220 | n02102318 221 | n02102480 222 | n02102973 223 | n02104029 224 | n02104365 225 | n02105056 226 | n02105162 227 | n02105251 228 | n02105412 229 | n02105505 230 | n02105641 231 | n02105855 232 | n02106030 233 | n02106166 234 | n02106382 235 | n02106550 236 | n02106662 237 | n02107142 238 | n02107312 239 | n02107574 240 | n02107683 241 | n02107908 242 | n02108000 243 | n02108089 244 | n02108422 245 | n02108551 246 | n02108915 247 | n02109047 248 | n02109525 249 | n02109961 250 | n02110063 251 | n02110185 252 | n02110341 253 | n02110627 254 | n02110806 255 | n02110958 256 | n02111129 257 | n02111277 258 | n02111500 259 | n02111889 260 | n02112018 261 | n02112137 262 | n02112350 263 | n02112706 264 | n02113023 265 | n02113186 266 | n02113624 267 | n02113712 268 | n02113799 269 | n02113978 270 | n02114367 271 | n02114548 272 | n02114712 273 | n02114855 274 | n02115641 275 | n02115913 276 | n02116738 277 | n02117135 278 | n02119022 279 | n02119789 280 | n02120079 281 | n02120505 282 | n02123045 283 | n02123159 284 | n02123394 285 | n02123597 286 | n02124075 287 | n02125311 288 | n02127052 289 | n02128385 290 | n02128757 291 | n02128925 292 | n02129165 293 | n02129604 294 | n02130308 295 | n02132136 296 | n02133161 297 | n02134084 298 | n02134418 299 | n02137549 300 | n02138441 301 | n02165105 302 | n02165456 303 | n02167151 304 | n02168699 305 | n02169497 306 | n02172182 307 | n02174001 308 | n02177972 309 | n02190166 310 | n02206856 311 | n02219486 312 | n02226429 313 | n02229544 314 | n02231487 315 | n02233338 316 | n02236044 317 | n02256656 318 | n02259212 319 | n02264363 320 | n02268443 321 | n02268853 322 | n02276258 323 | n02277742 324 | n02279972 325 | n02280649 326 | n02281406 327 | n02281787 328 | n02317335 329 | n02319095 330 | n02321529 331 | n02325366 332 | n02326432 333 | n02328150 334 | n02342885 335 | n02346627 336 | n02356798 337 | n02361337 338 | n02363005 339 | n02364673 340 | n02389026 341 | n02391049 342 | n02395406 343 | n02396427 344 | n02397096 345 | n02398521 346 | n02403003 347 | n02408429 348 | n02410509 349 | n02412080 350 | n02415577 351 | n02417914 352 | n02422106 353 | n02422699 354 | n02423022 355 | n02437312 356 | n02437616 357 | n02441942 358 | n02442845 359 | n02443114 360 | n02443484 361 | n02444819 362 | n02445715 363 | n02447366 364 | n02454379 365 | n02457408 366 | n02480495 367 | n02480855 368 | n02481823 369 | n02483362 370 | n02483708 371 | n02484975 372 | n02486261 373 | n02486410 374 | n02487347 375 | n02488291 376 | n02488702 377 | n02489166 378 | n02490219 379 | n02492035 380 | n02492660 381 | n02493509 382 | n02493793 383 | n02494079 384 | n02497673 385 | n02500267 386 | n02504013 387 | n02504458 388 | n02509815 389 | n02510455 390 | n02514041 391 | n02526121 392 | n02536864 393 | n02606052 394 | n02607072 395 | n02640242 396 | n02641379 397 | n02643566 398 | n02655020 399 | n02666196 400 | n02667093 401 | n02669723 402 | n02672831 403 | n02676566 404 | n02687172 405 | n02690373 406 | n02692877 407 | n02699494 408 | n02701002 409 | n02704792 410 | n02708093 411 | n02727426 412 | n02730930 413 | n02747177 414 | n02749479 415 | n02769748 416 | n02776631 417 | n02777292 418 | n02782093 419 | n02783161 420 | n02786058 421 | n02787622 422 | n02788148 423 | n02790996 424 | n02791124 425 | n02791270 426 | n02793495 427 | n02794156 428 | n02795169 429 | n02797295 430 | n02799071 431 | n02802426 432 | n02804414 433 | n02804610 434 | n02807133 435 | n02808304 436 | n02808440 437 | n02814533 438 | n02814860 439 | n02815834 440 | n02817516 441 | n02823428 442 | n02823750 443 | n02825657 444 | n02834397 445 | n02835271 446 | n02837789 447 | n02840245 448 | n02841315 449 | n02843684 450 | n02859443 451 | n02860847 452 | n02865351 453 | n02869837 454 | n02870880 455 | n02871525 456 | n02877765 457 | n02879718 458 | n02883205 459 | n02892201 460 | n02892767 461 | n02894605 462 | n02895154 463 | n02906734 464 | n02909870 465 | n02910353 466 | n02916936 467 | n02917067 468 | n02927161 469 | n02930766 470 | n02939185 471 | n02948072 472 | n02950826 473 | n02951358 474 | n02951585 475 | n02963159 476 | n02965783 477 | n02966193 478 | n02966687 479 | n02971356 480 | n02974003 481 | n02977058 482 | n02978881 483 | n02979186 484 | n02980441 485 | n02981792 486 | n02988304 487 | n02992211 488 | n02992529 489 | n02999410 490 | n03000134 491 | n03000247 492 | n03000684 493 | n03014705 494 | n03016953 495 | n03017168 496 | n03018349 497 | n03026506 498 | n03028079 499 | n03032252 500 | n03041632 501 | n03042490 502 | n03045698 503 | n03047690 504 | n03062245 505 | n03063599 506 | n03063689 507 | n03065424 508 | n03075370 509 | n03085013 510 | n03089624 511 | n03095699 512 | n03100240 513 | n03109150 514 | n03110669 515 | n03124043 516 | n03124170 517 | n03125729 518 | n03126707 519 | n03127747 520 | n03127925 521 | n03131574 522 | n03133878 523 | n03134739 524 | n03141823 525 | n03146219 526 | n03160309 527 | n03179701 528 | n03180011 529 | n03187595 530 | n03188531 531 | n03196217 532 | n03197337 533 | n03201208 534 | n03207743 535 | n03207941 536 | n03208938 537 | n03216828 538 | n03218198 539 | n03220513 540 | n03223299 541 | n03240683 542 | n03249569 543 | n03250847 544 | n03255030 545 | n03259280 546 | n03271574 547 | n03272010 548 | n03272562 549 | n03290653 550 | n03291819 551 | n03297495 552 | n03314780 553 | n03325584 554 | n03337140 555 | n03344393 556 | n03345487 557 | n03347037 558 | n03355925 559 | n03372029 560 | n03376595 561 | n03379051 562 | n03384352 563 | n03388043 564 | n03388183 565 | n03388549 566 | n03393912 567 | n03394916 568 | n03400231 569 | n03404251 570 | n03417042 571 | n03424325 572 | n03425413 573 | n03443371 574 | n03444034 575 | n03445777 576 | n03445924 577 | n03447447 578 | n03447721 579 | n03450230 580 | n03452741 581 | n03457902 582 | n03459775 583 | n03461385 584 | n03467068 585 | n03476684 586 | n03476991 587 | n03478589 588 | n03481172 589 | n03482405 590 | n03483316 591 | n03485407 592 | n03485794 593 | n03492542 594 | n03494278 595 | n03495258 596 | n03496892 597 | n03498962 598 | n03527444 599 | n03529860 600 | n03530642 601 | n03532672 602 | n03534580 603 | n03535780 604 | n03538406 605 | n03544143 606 | n03584254 607 | n03584829 608 | n03590841 609 | n03594734 610 | n03594945 611 | n03595614 612 | n03598930 613 | n03599486 614 | n03602883 615 | n03617480 616 | n03623198 617 | n03627232 618 | n03630383 619 | n03633091 620 | n03637318 621 | n03642806 622 | n03649909 623 | n03657121 624 | n03658185 625 | n03661043 626 | n03662601 627 | n03666591 628 | n03670208 629 | n03673027 630 | n03676483 631 | n03680355 632 | n03690938 633 | n03691459 634 | n03692522 635 | n03697007 636 | n03706229 637 | n03709823 638 | n03710193 639 | n03710637 640 | n03710721 641 | n03717622 642 | n03720891 643 | n03721384 644 | n03724870 645 | n03729826 646 | n03733131 647 | n03733281 648 | n03733805 649 | n03742115 650 | n03743016 651 | n03759954 652 | n03761084 653 | n03763968 654 | n03764736 655 | n03769881 656 | n03770439 657 | n03770679 658 | n03773504 659 | n03775071 660 | n03775546 661 | n03776460 662 | n03777568 663 | n03777754 664 | n03781244 665 | n03782006 666 | n03785016 667 | n03786901 668 | n03787032 669 | n03788195 670 | n03788365 671 | n03791053 672 | n03792782 673 | n03792972 674 | n03793489 675 | n03794056 676 | n03796401 677 | n03803284 678 | n03804744 679 | n03814639 680 | n03814906 681 | n03825788 682 | n03832673 683 | n03837869 684 | n03838899 685 | n03840681 686 | n03841143 687 | n03843555 688 | n03854065 689 | n03857828 690 | n03866082 691 | n03868242 692 | n03868863 693 | n03871628 694 | n03873416 695 | n03874293 696 | n03874599 697 | n03876231 698 | n03877472 699 | n03877845 700 | n03884397 701 | n03887697 702 | n03888257 703 | n03888605 704 | n03891251 705 | n03891332 706 | n03895866 707 | n03899768 708 | n03902125 709 | n03903868 710 | n03908618 711 | n03908714 712 | n03916031 713 | n03920288 714 | n03924679 715 | n03929660 716 | n03929855 717 | n03930313 718 | n03930630 719 | n03933933 720 | n03935335 721 | n03937543 722 | n03938244 723 | n03942813 724 | n03944341 725 | n03947888 726 | n03950228 727 | n03954731 728 | n03956157 729 | n03958227 730 | n03961711 731 | n03967562 732 | n03970156 733 | n03976467 734 | n03976657 735 | n03977966 736 | n03980874 737 | n03982430 738 | n03983396 739 | n03991062 740 | n03992509 741 | n03995372 742 | n03998194 743 | n04004767 744 | n04005630 745 | n04008634 746 | n04009552 747 | n04019541 748 | n04023962 749 | n04026417 750 | n04033901 751 | n04033995 752 | n04037443 753 | n04039381 754 | n04040759 755 | n04041544 756 | n04044716 757 | n04049303 758 | n04065272 759 | n04067472 760 | n04069434 761 | n04070727 762 | n04074963 763 | n04081281 764 | n04086273 765 | n04090263 766 | n04099969 767 | n04111531 768 | n04116512 769 | n04118538 770 | n04118776 771 | n04120489 772 | n04125021 773 | n04127249 774 | n04131690 775 | n04133789 776 | n04136333 777 | n04141076 778 | n04141327 779 | n04141975 780 | n04146614 781 | n04147183 782 | n04149813 783 | n04152593 784 | n04153751 785 | n04154565 786 | n04162706 787 | n04179913 788 | n04192698 789 | n04200800 790 | n04201297 791 | n04204238 792 | n04204347 793 | n04208210 794 | n04209133 795 | n04209239 796 | n04228054 797 | n04229816 798 | n04235860 799 | n04238763 800 | n04239074 801 | n04243546 802 | n04251144 803 | n04252077 804 | n04252225 805 | n04254120 806 | n04254680 807 | n04254777 808 | n04258138 809 | n04259630 810 | n04263257 811 | n04264628 812 | n04265275 813 | n04266014 814 | n04270147 815 | n04273569 816 | n04275548 817 | n04277352 818 | n04285008 819 | n04286575 820 | n04296562 821 | n04310018 822 | n04311004 823 | n04311174 824 | n04317175 825 | n04325704 826 | n04326547 827 | n04328186 828 | n04330267 829 | n04332243 830 | n04335435 831 | n04336792 832 | n04344873 833 | n04346328 834 | n04347754 835 | n04350905 836 | n04355338 837 | n04355933 838 | n04356056 839 | n04357314 840 | n04366367 841 | n04367480 842 | n04370456 843 | n04371430 844 | n04371774 845 | n04372370 846 | n04376876 847 | n04380533 848 | n04389033 849 | n04392985 850 | n04398044 851 | n04399382 852 | n04404412 853 | n04409515 854 | n04417672 855 | n04418357 856 | n04423845 857 | n04428191 858 | n04429376 859 | n04435653 860 | n04442312 861 | n04443257 862 | n04447861 863 | n04456115 864 | n04458633 865 | n04461696 866 | n04462240 867 | n04465501 868 | n04467665 869 | n04476259 870 | n04479046 871 | n04482393 872 | n04483307 873 | n04485082 874 | n04486054 875 | n04487081 876 | n04487394 877 | n04493381 878 | n04501370 879 | n04505470 880 | n04507155 881 | n04509417 882 | n04515003 883 | n04517823 884 | n04522168 885 | n04523525 886 | n04525038 887 | n04525305 888 | n04532106 889 | n04532670 890 | n04536866 891 | n04540053 892 | n04542943 893 | n04548280 894 | n04548362 895 | n04550184 896 | n04552348 897 | n04553703 898 | n04554684 899 | n04557648 900 | n04560804 901 | n04562935 902 | n04579145 903 | n04579432 904 | n04584207 905 | n04589890 906 | n04590129 907 | n04591157 908 | n04591713 909 | n04592741 910 | n04596742 911 | n04597913 912 | n04599235 913 | n04604644 914 | n04606251 915 | n04612504 916 | n04613696 917 | n06359193 918 | n06596364 919 | n06785654 920 | n06794110 921 | n06874185 922 | n07248320 923 | n07565083 924 | n07579787 925 | n07583066 926 | n07584110 927 | n07590611 928 | n07613480 929 | n07614500 930 | n07615774 931 | n07684084 932 | n07693725 933 | n07695742 934 | n07697313 935 | n07697537 936 | n07711569 937 | n07714571 938 | n07714990 939 | n07715103 940 | n07716358 941 | n07716906 942 | n07717410 943 | n07717556 944 | n07718472 945 | n07718747 946 | n07720875 947 | n07730033 948 | n07734744 949 | n07742313 950 | n07745940 951 | n07747607 952 | n07749582 953 | n07753113 954 | n07753275 955 | n07753592 956 | n07754684 957 | n07760859 958 | n07768694 959 | n07802026 960 | n07831146 961 | n07836838 962 | n07860988 963 | n07871810 964 | n07873807 965 | n07875152 966 | n07880968 967 | n07892512 968 | n07920052 969 | n07930864 970 | n07932039 971 | n09193705 972 | n09229709 973 | n09246464 974 | n09256479 975 | n09288635 976 | n09332890 977 | n09399592 978 | n09421951 979 | n09428293 980 | n09468604 981 | n09472597 982 | n09835506 983 | n10148035 984 | n10565667 985 | n11879895 986 | n11939491 987 | n12057211 988 | n12144580 989 | n12267677 990 | n12620546 991 | n12768682 992 | n12985857 993 | n12998815 994 | n13037406 995 | n13040303 996 | n13044778 997 | n13052670 998 | n13054560 999 | n13133613 1000 | n15075141 1001 | -------------------------------------------------------------------------------- /images/comparisons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/images/comparisons.png -------------------------------------------------------------------------------- /models/fix_mobilenet_v1.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import torch 4 | import torch.nn as nn 5 | from torch.nn.modules.utils import _pair 6 | 7 | from .fix_quant_ops import ( 8 | fix_quant, 9 | int_op_only_fix_quant, 10 | FXQAvgPool2d, 11 | ReLUClipFXQConvBN, 12 | ReLUClipFXQLinear, 13 | ) 14 | from myutils.config import FLAGS 15 | 16 | 17 | class IntBlock(nn.Module): 18 | def __init__(self, body): 19 | super(IntBlock, self).__init__() 20 | self.body = body 21 | self.int_op_only = getattr(body, 'int_op_only', False) 22 | 23 | def forward(self, x): 24 | assert getattr(FLAGS, 'int_infer', False) 25 | if getattr(self, 'int_op_only', False): 26 | res = x 27 | for layer_ in self.body: 28 | if isinstance(layer_, nn.Conv2d): 29 | res = int_op_only_fix_quant(res, 8, 30 | layer_.input_fraclen.item(), 31 | res.output_fraclen, 32 | layer_.input_symmetric) 33 | res = layer_(res) 34 | output_fraclen = (layer_.weight_fraclen + 35 | layer_.input_fraclen).item() 36 | setattr(res, 'output_fraclen', output_fraclen) 37 | else: 38 | res = layer_(res) 39 | else: 40 | res = x 41 | for layer_ in self.body: 42 | if isinstance(layer_, nn.Conv2d): 43 | res = (fix_quant(res, 8, layer_.input_fraclen, 1, 44 | layer_.input_symmetric)[0] * 45 | (2**layer_.input_fraclen)).int().float() 46 | res = layer_(res) 47 | res.div_(2**(layer_.weight_fraclen + layer_.input_fraclen)) 48 | else: 49 | res = layer_(res) 50 | return res 51 | 52 | 53 | class DepthwiseSeparableConv(nn.Module): 54 | def __init__(self, inp, outp, stride): 55 | super(DepthwiseSeparableConv, self).__init__() 56 | assert stride in [1, 2] 57 | 58 | l1 = ReLUClipFXQConvBN(inp, inp, 3, stride, 1, groups=inp) 59 | l2 = ReLUClipFXQConvBN(inp, outp, 1, 1, 0) 60 | layers = [ 61 | l1, 62 | l2, 63 | nn.ReLU(inplace=True), 64 | ] 65 | self.body = nn.Sequential(*layers) 66 | self.layer_dict = {} 67 | 68 | def forward(self, x): 69 | return self.body(x) 70 | 71 | def set_following_layer(self, following_layer): 72 | self.layer_dict['following'] = following_layer 73 | self.body[0].set_following_layer(self.body[1]) 74 | self.body[1].set_following_layer(following_layer) 75 | 76 | def get_following_layer(self): 77 | return self.layer_dict['following'] 78 | 79 | def master_child(self): 80 | return self.body[0] 81 | 82 | def int_block(self, avgpool_scale=1.0): 83 | l1 = self.body[0].int_conv() 84 | l2 = self.body[1].int_conv(avgpool_scale=avgpool_scale) 85 | layers = [ 86 | l1, 87 | nn.ReLU(inplace=True), 88 | l2, 89 | nn.ReLU(inplace=True), 90 | ] 91 | body = nn.Sequential(*layers) 92 | return IntBlock(body) 93 | 94 | 95 | class IntModel(nn.Module): 96 | def __init__(self, head, body, classifier, block_setting): 97 | super(IntModel, self).__init__() 98 | 99 | self.block_setting = block_setting 100 | 101 | # head 102 | self.head = head 103 | 104 | # body 105 | for idx, [c, n, s] in enumerate(self.block_setting): 106 | for i in range(n): 107 | setattr(self, f'stage_{idx}_layer_{i}', 108 | body[f'stage_{idx}_layer_{i}']) 109 | 110 | if getattr(FLAGS, 'quant_avgpool', False): 111 | self.avgpool = FXQAvgPool2d(7) 112 | else: 113 | self.avgpool = nn.AdaptiveAvgPool2d(1) 114 | 115 | # classifier 116 | self.classifier = classifier 117 | 118 | self.int_op_only = getattr(head, 'int_op_only', False) 119 | 120 | def forward(self, x): 121 | assert getattr(FLAGS, 'int_infer', False) 122 | if getattr(self, 'int_op_only', False): 123 | x = self.head(x) 124 | output_fraclen = (self.head[0].weight_fraclen + 125 | self.head[0].input_fraclen).item() 126 | setattr(x, 'output_fraclen', output_fraclen) 127 | for idx, [_, n, _] in enumerate(self.block_setting): 128 | for i in range(n): 129 | blk = getattr(self, f'stage_{idx}_layer_{i}') 130 | x = blk(x) 131 | if getattr(FLAGS, 'quant_avgpool', False): 132 | x = self.avgpool(x) 133 | output_fraclen = x.output_fraclen 134 | x = x.view(x.size(0), -1) 135 | setattr(x, 'output_fraclen', output_fraclen) 136 | x = int_op_only_fix_quant( 137 | x, 8, self.classifier[0].input_fraclen.item(), 138 | x.output_fraclen, self.classifier[0].input_symmetric) 139 | else: 140 | output_fraclen = x.output_fraclen 141 | x = self.avgpool(x.float()) 142 | x = x.view(x.size(0), -1) 143 | x.div_(2**output_fraclen) 144 | x = (fix_quant(x, 8, self.classifier[0].input_fraclen.float(), 145 | 1, self.classifier[0].input_symmetric)[0] * 146 | (2**self.classifier[0].input_fraclen.float())).int() 147 | x = self.classifier(x).float() 148 | else: 149 | if getattr(FLAGS, 'normalize', False): 150 | x = (fix_quant(x, 8, self.head[0].input_fraclen, 1, 151 | self.head[0].input_symmetric)[0] * 152 | (2**self.head[0].input_fraclen)).int().float() 153 | else: 154 | x = (x * (2**self.head[0].input_fraclen)).int().float() 155 | x = self.head(x) 156 | x.div_(2**(self.head[0].input_fraclen + 157 | self.head[0].weight_fraclen)) 158 | for idx, [_, n, _] in enumerate(self.block_setting): 159 | for i in range(n): 160 | blk = getattr(self, f'stage_{idx}_layer_{i}') 161 | x = blk(x) 162 | x = self.avgpool(x) 163 | x = x.view(x.size(0), -1) 164 | x = (fix_quant(x, 8, self.classifier[0].input_fraclen, 1, 165 | self.classifier[0].input_symmetric)[0] * 166 | (2**self.classifier[0].input_fraclen)).int().float() 167 | x = self.classifier(x) 168 | return x 169 | 170 | 171 | class Model(nn.Module): 172 | def __init__(self, num_classes=1000): 173 | super(Model, self).__init__() 174 | 175 | # setting of inverted residual blocks 176 | self.block_setting = [ 177 | # c, n, s 178 | [64, 1, 1], 179 | [128, 2, 2], 180 | [256, 2, 2], 181 | [512, 6, 2], 182 | [1024, 2, 2], 183 | ] 184 | 185 | # head 186 | channels = 32 187 | first_stride = 2 188 | self.head = nn.Sequential( 189 | ReLUClipFXQConvBN( 190 | 3, 191 | channels, 192 | 3, 193 | first_stride, 194 | 1, 195 | bitw_min=None, 196 | bita_min=8, 197 | weight_only=not getattr(FLAGS, 'normalize', False), 198 | double_side=getattr(FLAGS, 'normalize', False)), 199 | nn.ReLU(inplace=True), 200 | ) 201 | prev_layer = self.head[0] 202 | 203 | # body 204 | for idx, [c, n, s] in enumerate(self.block_setting): 205 | outp = c 206 | for i in range(n): 207 | if i == 0: 208 | layer = DepthwiseSeparableConv(channels, outp, s) 209 | else: 210 | layer = DepthwiseSeparableConv(channels, outp, 1) 211 | setattr(self, 'stage_{}_layer_{}'.format(idx, i), layer) 212 | channels = outp 213 | prev_layer.set_following_layer(layer.master_child()) 214 | prev_layer = layer 215 | 216 | if getattr(FLAGS, 'quant_avgpool', False): 217 | self.avgpool = FXQAvgPool2d(7) 218 | if getattr(FLAGS, 'pool_fusing', False): 219 | stage_idx = len(self.block_setting) - 1 220 | layer_idx = self.block_setting[-1][1] - 1 221 | last_conv_layer = getattr( 222 | self, f'stage_{stage_idx}_layer_{layer_idx}') 223 | last_conv_layer.avgpool_scale = self.avgpool.scale 224 | else: 225 | self.avgpool = nn.AdaptiveAvgPool2d(1) 226 | 227 | # classifier 228 | self.classifier = nn.Sequential( 229 | ReLUClipFXQLinear(outp, num_classes, bitw_min=None)) 230 | prev_layer.set_following_layer(self.classifier[0]) 231 | 232 | if FLAGS.reset_parameters: 233 | self.reset_parameters() 234 | 235 | def forward(self, x): 236 | x = self.head(x) 237 | for idx, [_, n, _] in enumerate(self.block_setting): 238 | for i in range(n): 239 | x = getattr(self, 'stage_{}_layer_{}'.format(idx, i))(x) 240 | x = self.avgpool(x) 241 | x = x.view(x.size(0), -1) 242 | x = self.classifier(x) 243 | return x 244 | 245 | def reset_parameters(self): 246 | for m in self.modules(): 247 | if isinstance(m, nn.Conv2d): 248 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 249 | m.weight.data.normal_(0, math.sqrt(2. / n)) 250 | if m.bias is not None: 251 | m.bias.data.zero_() 252 | elif isinstance(m, nn.BatchNorm2d): 253 | if m.weight is not None: 254 | m.weight.data.fill_(1) 255 | if m.bias is not None: 256 | m.bias.data.zero_() 257 | elif isinstance(m, nn.Linear): 258 | n = m.weight.size(1) 259 | m.weight.data.normal_(0, 0.01) 260 | m.bias.data.zero_() 261 | 262 | def int_model(self): 263 | if getattr(FLAGS, 'quant_avgpool', False): 264 | avgpool = FXQAvgPool2d(7) 265 | avgpool_scale = avgpool.scale 266 | else: 267 | avgpool_scale = 1.0 268 | head = self.head 269 | head[0] = head[0].int_conv() 270 | body = { 271 | f'stage_{idx}_layer_{i}': 272 | getattr(self, f'stage_{idx}_layer_{i}').int_block( 273 | avgpool_scale=avgpool_scale if ( 274 | idx == len(self.block_setting) - 1 and i == n - 275 | 1) else 1.0) 276 | for idx, [c, n, s] in enumerate(self.block_setting) 277 | for i in range(n) 278 | } 279 | classifier = self.classifier 280 | classifier[0] = classifier[0].int_fc() 281 | return IntModel(head, body, classifier, self.block_setting) 282 | -------------------------------------------------------------------------------- /models/fix_mobilenet_v2.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import torch 4 | import torch.nn as nn 5 | 6 | from .fix_quant_ops import (fix_quant, int_op_only_fix_quant, FXQAvgPool2d, 7 | ReLUClipFXQConvBN, ReLUClipFXQLinear) 8 | from myutils.config import FLAGS 9 | 10 | 11 | class IntBlock(nn.Module): 12 | def __init__(self, body, residual_connection): 13 | super(IntBlock, self).__init__() 14 | self.body = body 15 | self.residual_connection = residual_connection 16 | self.int_op_only = getattr(body, 'int_op_only', False) 17 | 18 | def forward(self, x): 19 | assert getattr(FLAGS, 'int_infer', False) 20 | if getattr(self, 'int_op_only', False): 21 | res = x 22 | for layer_ in self.body: 23 | if isinstance(layer_, nn.Conv2d): 24 | res = int_op_only_fix_quant(res, 8, 25 | layer_.input_fraclen.item(), 26 | res.output_fraclen, 27 | layer_.input_symmetric) 28 | res = layer_(res) 29 | output_fraclen = (layer_.weight_fraclen + 30 | layer_.input_fraclen).item() 31 | setattr(res, 'output_fraclen', output_fraclen) 32 | else: 33 | res = layer_(res) 34 | if self.residual_connection: 35 | res_fraclen = res.output_fraclen 36 | x_fraclen = x.output_fraclen 37 | if res_fraclen >= x_fraclen: 38 | x = x << (res_fraclen - x_fraclen) 39 | res += x 40 | res.clamp_(max=(1 << 31) - 1, min=-(1 << 31) + 1) 41 | output_fraclen = res_fraclen 42 | setattr(res, 'output_fraclen', output_fraclen) 43 | else: 44 | res = res << (x_fraclen - res_fraclen) 45 | res += x 46 | res.clamp_(max=(1 << 31) - 1, min=-(1 << 31) + 1) 47 | output_fraclen = x_fraclen 48 | setattr(res, 'output_fraclen', output_fraclen) 49 | else: 50 | res = x 51 | for layer_ in self.body: 52 | if isinstance(layer_, nn.Conv2d): 53 | res = (fix_quant(res, 8, layer_.input_fraclen, 1, 54 | layer_.input_symmetric)[0] * 55 | (2**layer_.input_fraclen)).int().float() 56 | res = layer_(res) 57 | res.div_(2**(layer_.weight_fraclen + layer_.input_fraclen)) 58 | else: 59 | res = layer_(res) 60 | setattr(res, 'output_fraclen', 61 | self.body[-1].weight_fraclen + self.body[-1].input_fraclen) 62 | if self.residual_connection: 63 | res_fraclen = res.output_fraclen 64 | x_fraclen = x.output_fraclen 65 | output_fraclen = max(res_fraclen, x_fraclen) 66 | res = res * 2**output_fraclen 67 | x = x * 2**output_fraclen 68 | res += x 69 | res = torch.clamp(res, max=(1 << 31) - 1, min=-(1 << 31) + 1) 70 | res = res / 2**output_fraclen 71 | setattr(res, 'output_fraclen', output_fraclen) 72 | return res 73 | 74 | 75 | class InvertedResidual(nn.Module): 76 | def __init__(self, 77 | inp, 78 | outp, 79 | stride, 80 | expand_ratio, 81 | double_side=False, 82 | master_layer=None): 83 | super(InvertedResidual, self).__init__() 84 | assert stride in [1, 2] 85 | 86 | expand_inp = inp * expand_ratio 87 | if expand_ratio != 1: 88 | # expand 89 | l0 = ReLUClipFXQConvBN(inp, 90 | expand_inp, 91 | 1, 92 | 1, 93 | 0, 94 | double_side=double_side, 95 | master_layer=master_layer) 96 | # depthwise + project back 97 | l1 = ReLUClipFXQConvBN(expand_inp, 98 | expand_inp, 99 | 3, 100 | stride, 101 | 1, 102 | groups=expand_inp) 103 | l2 = ReLUClipFXQConvBN(expand_inp, outp, 1, 1, 0) 104 | layers = [ 105 | l0, 106 | l1, 107 | l2, 108 | ] 109 | else: 110 | # depthwise + project back 111 | l1 = ReLUClipFXQConvBN(expand_inp, 112 | expand_inp, 113 | 3, 114 | stride, 115 | 1, 116 | groups=expand_inp, 117 | double_side=double_side, 118 | master_layer=master_layer) 119 | l2 = ReLUClipFXQConvBN(expand_inp, outp, 1, 1, 0) 120 | layers = [ 121 | l1, 122 | l2, 123 | ] 124 | self.body = nn.Sequential(*layers) 125 | self.layer_dict = {} 126 | 127 | self.residual_connection = stride == 1 and inp == outp 128 | if self.residual_connection: 129 | self.set_master_layer(self.body[0]) 130 | else: 131 | self.set_master_layer(None) 132 | 133 | def forward(self, x): 134 | res = self.body(x) 135 | if self.residual_connection: 136 | if getattr(FLAGS, 'int_infer', False) and not self.training: 137 | res_fraclen = res.output_fraclen 138 | x_fraclen = x.output_fraclen 139 | output_fraclen = max(res_fraclen, x_fraclen) 140 | res = res * 2**output_fraclen 141 | x = x * 2**output_fraclen 142 | res += x 143 | res = torch.clamp(res, max=(1 << 31) - 1, min=-(1 << 31) + 1) 144 | res = res / 2**output_fraclen 145 | setattr(res, 'output_fraclen', output_fraclen) 146 | else: 147 | res += x 148 | return res 149 | 150 | def set_master_layer(self, master_layer): 151 | self.layer_dict['master'] = master_layer 152 | 153 | def get_master_layer(self): 154 | return self.layer_dict['master'] 155 | 156 | def set_following_layer(self, following_layer): 157 | self.layer_dict['following'] = following_layer 158 | for idx in range(len(self.body) - 1): 159 | self.body[idx].set_following_layer(self.body[idx + 1]) 160 | self.body[-1].set_following_layer(following_layer) 161 | 162 | def get_following_layer(self): 163 | return self.layer_dict['following'] 164 | 165 | def master_child(self): 166 | return self.body[0] 167 | 168 | def int_block(self): 169 | layers = [] 170 | layers.append(self.body[0].int_conv()) 171 | for layer_ in self.body[1:]: 172 | layers.append(nn.ReLU(inplace=True)) 173 | layers.append(layer_.int_conv()) 174 | body = nn.Sequential(*layers) 175 | residual_connection = self.residual_connection 176 | return IntBlock(body, residual_connection) 177 | 178 | 179 | class IntModel(nn.Module): 180 | def __init__(self, head, body, tail, classifier, block_setting): 181 | super(IntModel, self).__init__() 182 | 183 | self.block_setting = block_setting 184 | 185 | # head 186 | self.head = head 187 | 188 | # body 189 | for idx, [t, c, n, s] in enumerate(self.block_setting): 190 | for i in range(n): 191 | setattr(self, f'stage_{idx}_layer_{i}', 192 | body[f'stage_{idx}_layer_{i}']) 193 | 194 | # tail 195 | self.tail = tail 196 | 197 | if getattr(FLAGS, 'quant_avgpool', False): 198 | self.avgpool = FXQAvgPool2d(7) 199 | else: 200 | self.avgpool = nn.AdaptiveAvgPool2d(1) 201 | 202 | # classifier 203 | self.classifier = classifier 204 | 205 | self.int_op_only = getattr(head, 'int_op_only', False) 206 | 207 | def forward(self, x): 208 | assert getattr(FLAGS, 'int_infer', False) 209 | if getattr(self, 'int_op_only', False): 210 | x = self.head(x) 211 | output_fraclen = (self.head[0].weight_fraclen + 212 | self.head[0].input_fraclen).item() 213 | setattr(x, 'output_fraclen', output_fraclen) 214 | for idx, [_, _, n, _] in enumerate(self.block_setting): 215 | for i in range(n): 216 | blk = getattr(self, f'stage_{idx}_layer_{i}') 217 | x = blk(x) 218 | x = int_op_only_fix_quant(x, 8, self.tail[0].input_fraclen.item(), 219 | x.output_fraclen, 220 | self.tail[0].input_symmetric) 221 | x = self.tail(x) 222 | output_fraclen = (self.tail[0].weight_fraclen + 223 | self.tail[0].input_fraclen).item() 224 | setattr(x, 'output_fraclen', output_fraclen) 225 | if getattr(FLAGS, 'quant_avgpool', False): 226 | x = self.avgpool(x) 227 | output_fraclen = x.output_fraclen 228 | x = x.view(x.size(0), -1) 229 | setattr(x, 'output_fraclen', output_fraclen) 230 | x = int_op_only_fix_quant( 231 | x, 8, self.classifier[0].input_fraclen.item(), 232 | x.output_fraclen, self.classifier[0].input_symmetric) 233 | else: 234 | output_fraclen = x.output_fraclen 235 | x = self.avgpool(x.float()) 236 | x = x.view(x.size(0), -1) 237 | x.div_(2**output_fraclen) 238 | x = (fix_quant(x, 8, self.classifier[0].input_fraclen.float(), 239 | 1, self.classifier[0].input_symmetric)[0] * 240 | (2**self.classifier[0].input_fraclen.float())).int() 241 | x = self.classifier(x).float() 242 | else: 243 | if getattr(FLAGS, 'normalize', False): 244 | x = (fix_quant(x, 8, self.head[0].input_fraclen, 1, 245 | self.head[0].input_symmetric)[0] * 246 | (2**self.head[0].input_fraclen)).int().float() 247 | else: 248 | x = (x * (2**self.head[0].input_fraclen)).int().float() 249 | for layer_ in self.head: 250 | if hasattr(x, 'output_fraclen'): 251 | output_fraclen = x.output_fraclen 252 | x = layer_(x) 253 | else: 254 | x = layer_(x) 255 | output_fraclen = layer_.weight_fraclen + layer_.input_fraclen 256 | setattr(x, 'output_fraclen', output_fraclen) 257 | x.div_(2**x.output_fraclen) 258 | for idx, [_, _, n, _] in enumerate(self.block_setting): 259 | for i in range(n): 260 | blk = getattr(self, f'stage_{idx}_layer_{i}') 261 | x = blk(x) 262 | x = (fix_quant(x, 8, self.tail[0].input_fraclen, 1, 263 | self.tail[0].input_symmetric)[0] * 264 | (2**self.tail[0].input_fraclen)).int().float() 265 | x = self.tail(x) 266 | x.div_(2**(self.tail[0].input_fraclen + 267 | self.tail[0].weight_fraclen)) 268 | x = self.avgpool(x) 269 | x = x.view(x.size(0), -1) 270 | x = (fix_quant(x, 8, self.classifier[0].input_fraclen, 1, 271 | self.classifier[0].input_symmetric)[0] * 272 | (2**self.classifier[0].input_fraclen)).int().float() 273 | x = self.classifier(x) 274 | return x 275 | 276 | 277 | class Model(nn.Module): 278 | def __init__(self, num_classes=1000): 279 | super(Model, self).__init__() 280 | 281 | # setting of inverted residual blocks 282 | self.block_setting = [ 283 | # t, c, n, s 284 | [1, 16, 1, 1], 285 | [6, 24, 2, 2], 286 | [6, 32, 3, 2], 287 | [6, 64, 4, 2], 288 | [6, 96, 3, 1], 289 | [6, 160, 3, 2], 290 | [6, 320, 1, 1], 291 | ] 292 | 293 | # head 294 | channels = 32 295 | first_stride = 2 296 | self.head = nn.Sequential( 297 | ReLUClipFXQConvBN( 298 | 3, 299 | channels, 300 | 3, 301 | first_stride, 302 | 1, 303 | bitw_min=None, 304 | bita_min=8, 305 | weight_only=not getattr(FLAGS, 'normalize', False), 306 | double_side=getattr(FLAGS, 'normalize', False)), 307 | nn.ReLU(inplace=True), 308 | ) 309 | prev_layer = self.head[0] 310 | 311 | double_side = True 312 | # body 313 | master_layer = None 314 | for idx, [t, c, n, s] in enumerate(self.block_setting): 315 | outp = c 316 | for i in range(n): 317 | if i == 0: 318 | layer = InvertedResidual( 319 | channels, 320 | outp, 321 | s, 322 | t, 323 | double_side=double_side if idx != 0 else False, 324 | master_layer=master_layer) 325 | else: 326 | layer = InvertedResidual(channels, 327 | outp, 328 | 1, 329 | t, 330 | double_side=double_side, 331 | master_layer=master_layer) 332 | setattr(self, 'stage_{}_layer_{}'.format(idx, i), layer) 333 | channels = outp 334 | master_layer = layer.get_master_layer() 335 | prev_layer.set_following_layer(layer.master_child()) 336 | prev_layer = layer 337 | 338 | # tail 339 | outp = 1280 340 | self.tail = nn.Sequential( 341 | ReLUClipFXQConvBN(channels, 342 | outp, 343 | 1, 344 | 1, 345 | 0, 346 | double_side=double_side, 347 | master_layer=master_layer), 348 | nn.ReLU(inplace=True), 349 | ) 350 | prev_layer.set_following_layer(self.tail[0]) 351 | prev_layer = self.tail[0] 352 | 353 | if getattr(FLAGS, 'quant_avgpool', False): 354 | self.avgpool = FXQAvgPool2d(7) 355 | if getattr(FLAGS, 'pool_fusing', False): 356 | stage_idx = len(self.block_setting) - 1 357 | layer_idx = self.block_setting[-1][1] - 1 358 | last_conv_layer = self.tail[0] 359 | last_conv_layer.avgpool_scale = self.avgpool.scale 360 | else: 361 | self.avgpool = nn.AdaptiveAvgPool2d(1) 362 | 363 | # classifier 364 | self.classifier = nn.Sequential( 365 | ReLUClipFXQLinear( 366 | outp, 367 | num_classes, 368 | bitw_min=None, 369 | bias=True)) 370 | prev_layer.set_following_layer(self.classifier[0]) 371 | 372 | if FLAGS.reset_parameters: 373 | self.reset_parameters() 374 | 375 | def forward(self, x): 376 | x = self.head(x) 377 | for idx, [_, _, n, _] in enumerate(self.block_setting): 378 | for i in range(n): 379 | x = getattr(self, 'stage_{}_layer_{}'.format(idx, i))(x) 380 | x = self.tail(x) 381 | x = self.avgpool(x) 382 | x = x.view(x.size(0), -1) 383 | x = self.classifier(x) 384 | return x 385 | 386 | def reset_parameters(self): 387 | for m in self.modules(): 388 | if isinstance(m, nn.Conv2d): 389 | n = m.kernel_size[0] * m.kernel_size[ 390 | 1] * m.out_channels 391 | m.weight.data.normal_(0, math.sqrt(2. / n)) 392 | if m.bias is not None: 393 | m.bias.data.zero_() 394 | elif isinstance(m, nn.BatchNorm2d): 395 | if m.weight is not None: 396 | m.weight.data.fill_(1) 397 | if m.bias is not None: 398 | m.bias.data.zero_() 399 | elif isinstance(m, nn.Linear): 400 | n = m.weight.size(1) 401 | m.weight.data.normal_(0, 0.01) 402 | if m.bias is not None: 403 | m.bias.data.zero_() 404 | 405 | def int_model(self): 406 | if getattr(FLAGS, 'quant_avgpool', False): 407 | avgpool = FXQAvgPool2d(7) 408 | avgpool_scale = avgpool.scale 409 | else: 410 | avgpool_scale = 1.0 411 | head = self.head 412 | head[0] = head[0].int_conv() 413 | body = { 414 | f'stage_{idx}_layer_{i}': 415 | getattr(self, f'stage_{idx}_layer_{i}').int_block() 416 | for idx, [t, c, n, s] in enumerate(self.block_setting) 417 | for i in range(n) 418 | } 419 | tail = self.tail 420 | tail[0] = tail[0].int_conv(avgpool_scale=avgpool_scale) 421 | classifier = self.classifier 422 | classifier[0] = classifier[0].int_fc() 423 | return IntModel(head, body, tail, classifier, self.block_setting) 424 | -------------------------------------------------------------------------------- /models/fix_resnet.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import torch 4 | import torch.nn as nn 5 | from torch.nn.modules.utils import _pair 6 | 7 | from .fix_quant_ops import (fix_quant, int_op_only_fix_quant, FXQMaxPool2d, 8 | FXQAvgPool2d, ReLUClipFXQConvBN, ReLUClipFXQLinear) 9 | 10 | from myutils.config import FLAGS 11 | 12 | 13 | class IntBlock(nn.Module): 14 | def __init__(self, body, shortcut=None): 15 | super(IntBlock, self).__init__() 16 | self.body = body 17 | 18 | self.residual_connection = shortcut is None 19 | if not self.residual_connection: 20 | self.shortcut = shortcut 21 | self.post_relu = nn.ReLU(inplace=True) 22 | self.int_op_only = getattr(body, 'int_op_only', False) 23 | 24 | def forward(self, x): 25 | assert getattr(FLAGS, 'int_infer', False) 26 | if getattr(self, 'int_op_only', False): 27 | res = x 28 | for layer_ in self.body: 29 | if isinstance(layer_, nn.Conv2d): 30 | res = int_op_only_fix_quant(res, 8, 31 | layer_.input_fraclen.item(), 32 | res.output_fraclen, 33 | layer_.input_symmetric) 34 | res = layer_(res) 35 | output_fraclen = (layer_.weight_fraclen + 36 | layer_.input_fraclen).item() 37 | setattr(res, 'output_fraclen', output_fraclen) 38 | else: 39 | res = layer_(res) 40 | if self.residual_connection: 41 | res_fraclen = res.output_fraclen 42 | x_fraclen = x.output_fraclen 43 | if res_fraclen > x_fraclen: 44 | x = x << (res_fraclen - x_fraclen) 45 | res += x 46 | res.clamp_(max=(1 << 31) - 1, min=-(1 << 31) + 1) 47 | output_fraclen = res_fraclen 48 | setattr(res, 'output_fraclen', output_fraclen) 49 | else: 50 | res = res << (x_fraclen - res_fraclen) 51 | res += x 52 | res.clamp_(max=(1 << 31) - 1, min=-(1 << 31) + 1) 53 | output_fraclen = x_fraclen 54 | setattr(res, 'output_fraclen', output_fraclen) 55 | else: 56 | x = int_op_only_fix_quant( 57 | x, 8, self.shortcut[0].input_fraclen.item(), 58 | x.output_fraclen, self.shortcut[0].input_symmetric) 59 | x = self.shortcut(x) 60 | output_fraclen = (self.shortcut[-1].weight_fraclen + 61 | self.shortcut[-1].input_fraclen).item() 62 | setattr(x, 'output_fraclen', output_fraclen) 63 | res_fraclen = res.output_fraclen 64 | x_fraclen = x.output_fraclen 65 | if res_fraclen > x_fraclen: 66 | x = x << (res_fraclen - x_fraclen) 67 | res += x 68 | res.clamp_(max=(1 << 31) - 1, min=-(1 << 31) + 1) 69 | output_fraclen = res_fraclen 70 | setattr(res, 'output_fraclen', output_fraclen) 71 | else: 72 | res = res << (x_fraclen - res_fraclen) 73 | res += x 74 | res.clamp_(max=(1 << 31) - 1, min=-(1 << 31) + 1) 75 | output_fraclen = x_fraclen 76 | setattr(res, 'output_fraclen', output_fraclen) 77 | res = self.post_relu(res) 78 | else: 79 | res = x 80 | for layer_ in self.body: 81 | if isinstance(layer_, nn.Conv2d): 82 | res = (fix_quant(res, 8, layer_.input_fraclen, 1, 83 | layer_.input_symmetric)[0] * 84 | (2**layer_.input_fraclen)).int().float() 85 | res = layer_(res) 86 | res.div_(2**(layer_.weight_fraclen + layer_.input_fraclen)) 87 | else: 88 | res = layer_(res) 89 | setattr(res, 'output_fraclen', 90 | self.body[-1].weight_fraclen + self.body[-1].input_fraclen) 91 | if self.residual_connection: 92 | res_fraclen = res.output_fraclen 93 | x_fraclen = x.output_fraclen 94 | output_fraclen = max(res_fraclen, x_fraclen) 95 | res = res * 2**output_fraclen 96 | x = x * 2**output_fraclen 97 | res += x 98 | res = torch.clamp(res, max=(1 << 31) - 1, min=-(1 << 31) + 1) 99 | res = res / 2**output_fraclen 100 | else: 101 | x = (fix_quant(x, 8, self.shortcut[0].input_fraclen, 1, 102 | self.shortcut[0].input_symmetric)[0] * 103 | (2**self.shortcut[0].input_fraclen)).int().float() 104 | x = self.shortcut(x) 105 | setattr( 106 | x, 'output_fraclen', self.shortcut[-1].weight_fraclen + 107 | self.shortcut[-1].input_fraclen) 108 | x.div_(2**x.output_fraclen) 109 | res_fraclen = res.output_fraclen 110 | x_fraclen = x.output_fraclen 111 | output_fraclen = max(res_fraclen, x_fraclen) 112 | res = res * 2**output_fraclen 113 | x = x * 2**output_fraclen 114 | res += x 115 | res = torch.clamp(res, max=(1 << 31) - 1, min=-(1 << 31) + 1) 116 | res = res / 2**output_fraclen 117 | res = self.post_relu(res) 118 | setattr(res, 'output_fraclen', output_fraclen) 119 | return res 120 | 121 | 122 | class BasicBlock(nn.Module): 123 | expansion = 1 124 | 125 | def __init__(self, inp, outp, stride, master_layer=None): 126 | super(BasicBlock, self).__init__() 127 | assert stride in [1, 2] 128 | 129 | l1 = ReLUClipFXQConvBN(inp, 130 | outp, 131 | 3, 132 | stride, 133 | 1, 134 | master_layer=master_layer) 135 | l2 = ReLUClipFXQConvBN(outp, outp, 3, 1, 1) 136 | layers = [ 137 | l1, 138 | l2, 139 | ] 140 | self.body = nn.Sequential(*layers) 141 | self.layer_dict = {} 142 | 143 | self.residual_connection = stride == 1 and inp == outp 144 | if not self.residual_connection: 145 | self.shortcut = nn.Sequential( 146 | ReLUClipFXQConvBN(inp, 147 | outp, 148 | 1, 149 | stride=stride, 150 | master_layer=master_layer)) 151 | self.set_master_layer(None) 152 | else: 153 | self.set_master_layer(self.body[0]) 154 | self.post_relu = nn.ReLU(inplace=True) 155 | 156 | def forward(self, x): 157 | res = self.body(x) 158 | if getattr(FLAGS, 'int_infer', False) and not self.training: 159 | if self.residual_connection: 160 | res_fraclen = res.output_fraclen 161 | x_fraclen = x.output_fraclen 162 | output_fraclen = max(res_fraclen, x_fraclen) 163 | res = res * 2**output_fraclen 164 | x = x * 2**output_fraclen 165 | res += x 166 | res = torch.clamp(res, max=(1 << 31) - 1, min=-(1 << 31) + 1) 167 | res = res / 2**output_fraclen 168 | else: 169 | x = self.shortcut(x) 170 | res_fraclen = res.output_fraclen 171 | x_fraclen = x.output_fraclen 172 | output_fraclen = max(res_fraclen, x_fraclen) 173 | res = res * 2**output_fraclen 174 | x = x * 2**output_fraclen 175 | res += x 176 | res = torch.clamp(res, max=(1 << 31) - 1, min=-(1 << 31) + 1) 177 | res = res / 2**output_fraclen 178 | else: 179 | if self.residual_connection: 180 | res += x 181 | else: 182 | res += self.shortcut(x) 183 | res = self.post_relu(res) 184 | if getattr(FLAGS, 'int_infer', False) and not self.training: 185 | setattr(res, 'output_fraclen', output_fraclen) 186 | return res 187 | 188 | def set_master_layer(self, master_layer): 189 | self.layer_dict['master'] = master_layer 190 | 191 | def get_master_layer(self): 192 | return self.layer_dict['master'] 193 | 194 | def set_following_layer(self, following_layer): 195 | self.layer_dict['following'] = following_layer 196 | self.body[0].set_following_layer(self.body[1]) 197 | self.body[1].set_following_layer(following_layer) 198 | if not self.residual_connection: 199 | self.shortcut[0].set_following_layer(following_layer) 200 | 201 | def get_following_layer(self): 202 | return self.layer_dict['following'] 203 | 204 | def master_child(self): 205 | return self.body[0] 206 | 207 | def int_block(self, avgpool_scale=1.0): 208 | l1 = self.body[0].int_conv() 209 | l2 = self.body[1].int_conv(avgpool_scale=avgpool_scale) 210 | layers = [ 211 | l1, 212 | nn.ReLU(inplace=True), 213 | l2, 214 | ] 215 | body = nn.Sequential(*layers) 216 | 217 | if not self.residual_connection: 218 | shortcut = nn.Sequential(self.shortcut[0].int_conv()) 219 | else: 220 | shortcut = None 221 | return IntBlock(body, shortcut) 222 | 223 | 224 | class Bottleneck(nn.Module): 225 | expansion = 4 226 | 227 | def __init__(self, inp, outp, stride, master_layer=None): 228 | super(Bottleneck, self).__init__() 229 | assert stride in [1, 2] 230 | 231 | midp = outp // 4 232 | l1 = ReLUClipFXQConvBN(inp, midp, 1, 1, 0, master_layer=master_layer) 233 | l2 = ReLUClipFXQConvBN(midp, midp, 3, stride, 1) 234 | l3 = ReLUClipFXQConvBN(midp, outp, 1, 1, 0) 235 | layers = [ 236 | l1, 237 | l2, 238 | l3, 239 | ] 240 | self.body = nn.Sequential(*layers) 241 | self.layer_dict = {} 242 | 243 | self.residual_connection = stride == 1 and inp == outp 244 | if not self.residual_connection: 245 | self.shortcut = nn.Sequential( 246 | ReLUClipFXQConvBN(inp, 247 | outp, 248 | 1, 249 | stride=stride, 250 | master_layer=master_layer)) 251 | self.set_master_layer(None) 252 | else: 253 | self.set_master_layer(self.body[0]) 254 | self.post_relu = nn.ReLU(inplace=True) 255 | 256 | def forward(self, x): 257 | res = self.body(x) 258 | if getattr(FLAGS, 'int_infer', False) and not self.training: 259 | if self.residual_connection: 260 | res_fraclen = res.output_fraclen 261 | x_fraclen = x.output_fraclen 262 | output_fraclen = max(res_fraclen, x_fraclen) 263 | res = res * 2**output_fraclen 264 | x = x * 2**output_fraclen 265 | res += x 266 | res = torch.clamp(res, max=(1 << 31) - 1, min=-(1 << 31) + 1) 267 | res = res / 2**output_fraclen 268 | else: 269 | x = self.shortcut(x) 270 | res_fraclen = res.output_fraclen 271 | x_fraclen = x.output_fraclen 272 | output_fraclen = max(res_fraclen, x_fraclen) 273 | res = res * 2**output_fraclen 274 | x = x * 2**output_fraclen 275 | res += x 276 | res = torch.clamp(res, max=(1 << 31) - 1, min=-(1 << 31) + 1) 277 | res = res / 2**output_fraclen 278 | else: 279 | if self.residual_connection: 280 | res += x 281 | else: 282 | res += self.shortcut(x) 283 | res = self.post_relu(res) 284 | if getattr(FLAGS, 'int_infer', False) and not self.training: 285 | setattr(res, 'output_fraclen', output_fraclen) 286 | return res 287 | 288 | def set_master_layer(self, master_layer): 289 | self.layer_dict['master'] = master_layer 290 | 291 | def get_master_layer(self): 292 | return self.layer_dict['master'] 293 | 294 | def set_following_layer(self, following_layer): 295 | self.layer_dict['following'] = following_layer 296 | self.body[0].set_following_layer(self.body[1]) 297 | self.body[1].set_following_layer(self.body[2]) 298 | self.body[2].set_following_layer(following_layer) 299 | if not self.residual_connection: 300 | self.shortcut[0].set_following_layer(following_layer) 301 | 302 | def get_following_layer(self): 303 | return self.layer_dict['following'] 304 | 305 | def master_child(self): 306 | return self.body[0] 307 | 308 | def int_block(self, avgpool_scale=1.0): 309 | l1 = self.body[0].int_conv() 310 | l2 = self.body[1].int_conv() 311 | l3 = self.body[2].int_conv(avgpool_scale=avgpool_scale) 312 | layers = [l1, nn.ReLU(inplace=True), l2, nn.ReLU(inplace=True), l3] 313 | body = nn.Sequential(*layers) 314 | 315 | if not self.residual_connection: 316 | shortcut = nn.Sequential(self.shortcut[0].int_conv()) 317 | else: 318 | shortcut = None 319 | return IntBlock(body, shortcut) 320 | 321 | 322 | class IntModel(nn.Module): 323 | def __init__(self, head, body, classifier, block_setting): 324 | super(IntModel, self).__init__() 325 | 326 | self.block_setting = block_setting 327 | 328 | # head 329 | self.head = head 330 | 331 | if getattr(FLAGS, 'quant_maxpool', False): 332 | self.head[-1] = FXQMaxPool2d(self.head[-1].kernel_size, 333 | self.head[-1].stride, 334 | self.head[-1].padding) 335 | 336 | # body 337 | for idx, n in enumerate(self.block_setting): 338 | for i in range(n): 339 | setattr(self, f'stage_{idx}_layer_{i}', 340 | body[f'stage_{idx}_layer_{i}']) 341 | 342 | if getattr(FLAGS, 'quant_avgpool', False): 343 | self.avgpool = FXQAvgPool2d(7) 344 | else: 345 | self.avgpool = nn.AdaptiveAvgPool2d(1) 346 | 347 | # classifier 348 | self.classifier = classifier 349 | 350 | self.int_op_only = getattr(head, 'int_op_only', False) 351 | 352 | def forward(self, x): 353 | assert getattr(FLAGS, 'int_infer', False) 354 | if getattr(self, 'int_op_only', False): 355 | if getattr(FLAGS, 'quant_maxpool', False): 356 | x = self.head(x) 357 | else: 358 | x = self.head[:-1](x) 359 | x = self.head[-1](x.float()).int() 360 | output_fraclen = (self.head[0].weight_fraclen + 361 | self.head[0].input_fraclen).item() 362 | setattr(x, 'output_fraclen', output_fraclen) 363 | for idx, n in enumerate(self.block_setting): 364 | for i in range(n): 365 | blk = getattr(self, f'stage_{idx}_layer_{i}') 366 | x = blk(x) 367 | if getattr(FLAGS, 'quant_avgpool', False): 368 | x = self.avgpool(x) 369 | output_fraclen = x.output_fraclen 370 | x = x.view(x.size(0), -1) 371 | setattr(x, 'output_fraclen', output_fraclen) 372 | x = int_op_only_fix_quant( 373 | x, 8, self.classifier[0].input_fraclen.item(), 374 | x.output_fraclen, self.classifier[0].input_symmetric) 375 | else: 376 | output_fraclen = x.output_fraclen 377 | x = self.avgpool(x.float()) 378 | x = x.view(x.size(0), -1) 379 | x.div_(2**output_fraclen) 380 | x = (fix_quant(x, 8, self.classifier[0].input_fraclen.float(), 381 | 1, self.classifier[0].input_symmetric)[0] * 382 | (2**self.classifier[0].input_fraclen.float())).int() 383 | x = self.classifier(x).float() 384 | else: 385 | if getattr(FLAGS, 'normalize', False): 386 | x = (fix_quant(x, 8, self.head[0].input_fraclen, 1, 387 | self.head[0].input_symmetric)[0] * 388 | (2**self.head[0].input_fraclen)).int().float() 389 | else: 390 | x = (x * (2**self.head[0].input_fraclen)).int().float() 391 | for layer_ in self.head: 392 | if hasattr(x, 'output_fraclen'): 393 | output_fraclen = x.output_fraclen 394 | x = layer_(x) 395 | else: 396 | x = layer_(x) 397 | output_fraclen = layer_.weight_fraclen + layer_.input_fraclen 398 | setattr(x, 'output_fraclen', output_fraclen) 399 | x.div_(2**x.output_fraclen) 400 | for idx, n in enumerate(self.block_setting): 401 | for i in range(n): 402 | blk = getattr(self, f'stage_{idx}_layer_{i}') 403 | x = blk(x) 404 | x = self.avgpool(x) 405 | x = x.view(x.size(0), -1) 406 | x = (fix_quant(x, 8, self.classifier[0].input_fraclen, 1, 407 | self.classifier[0].input_symmetric)[0] * 408 | (2**self.classifier[0].input_fraclen)).int().float() 409 | x = self.classifier(x) 410 | return x 411 | 412 | 413 | class Model(nn.Module): 414 | def __init__(self, num_classes=1000): 415 | super(Model, self).__init__() 416 | 417 | block_type_dict = { 418 | 18: BasicBlock, 419 | 34: BasicBlock, 420 | 50: Bottleneck, 421 | 101: Bottleneck, 422 | 152: Bottleneck 423 | } 424 | block = block_type_dict[FLAGS.depth] 425 | 426 | # head 427 | channels = 64 428 | self.head = nn.Sequential( 429 | ReLUClipFXQConvBN( 430 | 3, 431 | channels, 432 | 7, 433 | 2, 434 | 3, 435 | bitw_min=None, 436 | bita_min=8, 437 | weight_only=not getattr(FLAGS, 'normalize', False), 438 | double_side=getattr(FLAGS, 'normalize', False)), 439 | nn.ReLU(inplace=True), nn.MaxPool2d(3, 2, 1)) 440 | prev_layer = self.head[0] 441 | 442 | # setting of inverted residual blocks 443 | self.block_setting_dict = { 444 | # : [stage1, stage2, stage3, stage4] 445 | 18: [2, 2, 2, 2], 446 | 34: [3, 4, 6, 3], 447 | 50: [3, 4, 6, 3], 448 | 101: [3, 4, 23, 3], 449 | 152: [3, 8, 36, 3], 450 | } 451 | self.block_setting = self.block_setting_dict[FLAGS.depth] 452 | 453 | feats = [64, 128, 256, 512] 454 | 455 | # body 456 | master_layer = None 457 | for idx, n in enumerate(self.block_setting): 458 | outp = feats[idx] * block.expansion 459 | for i in range(n): 460 | if i == 0 and idx != 0: 461 | layer = block(channels, outp, 2, master_layer=master_layer) 462 | else: 463 | layer = block(channels, outp, 1, master_layer=master_layer) 464 | setattr(self, 'stage_{}_layer_{}'.format(idx, i), layer) 465 | channels = outp 466 | master_layer = layer.get_master_layer() 467 | prev_layer.set_following_layer(layer.master_child()) 468 | prev_layer = layer 469 | 470 | if getattr(FLAGS, 'quant_avgpool', False): 471 | self.avgpool = FXQAvgPool2d(7) 472 | if getattr(FLAGS, 'pool_fusing', False): 473 | stage_idx = len(self.block_setting) - 1 474 | layer_idx = self.block_setting[-1] - 1 475 | last_conv_layer = getattr( 476 | self, f'stage_{stage_idx}_layer_{layer_idx}') 477 | last_conv_layer.avgpool_scale = self.avgpool.scale 478 | else: 479 | self.avgpool = nn.AdaptiveAvgPool2d(1) 480 | 481 | # classifier 482 | self.classifier = nn.Sequential( 483 | ReLUClipFXQLinear(outp, num_classes, bitw_min=None)) 484 | prev_layer.set_following_layer(self.classifier[0]) 485 | 486 | if FLAGS.reset_parameters: 487 | self.reset_parameters() 488 | 489 | def forward(self, x): 490 | if getattr(FLAGS, 'int_infer', False) and not self.training: 491 | for layer_ in self.head: 492 | if hasattr(x, 'output_fraclen'): 493 | output_fraclen = x.output_fraclen 494 | x = layer_(x) 495 | else: 496 | x = layer_(x) 497 | output_fraclen = x.output_fraclen 498 | setattr(x, 'output_fraclen', output_fraclen) 499 | else: 500 | x = self.head(x) 501 | for idx, n in enumerate(self.block_setting): 502 | for i in range(n): 503 | x = getattr(self, 'stage_{}_layer_{}'.format(idx, i))(x) 504 | x = self.avgpool(x) 505 | x = x.view(x.size(0), -1) 506 | x = self.classifier(x) 507 | return x 508 | 509 | def reset_parameters(self): 510 | for m in self.modules(): 511 | if isinstance(m, nn.Conv2d): 512 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 513 | m.weight.data.normal_(0, math.sqrt(2. / n)) 514 | if m.bias is not None: 515 | m.bias.data.zero_() 516 | elif isinstance(m, nn.BatchNorm2d): 517 | if m.weight is not None: 518 | m.weight.data.fill_(1) 519 | if m.bias is not None: 520 | m.bias.data.zero_() 521 | elif isinstance(m, nn.Linear): 522 | n = m.weight.size(1) 523 | m.weight.data.normal_(0, 0.01) 524 | m.bias.data.zero_() 525 | 526 | def int_model(self): 527 | if getattr(FLAGS, 'quant_avgpool', False): 528 | avgpool = FXQAvgPool2d(7) 529 | avgpool_scale = avgpool.scale 530 | else: 531 | avgpool_scale = 1.0 532 | head = self.head 533 | head[0] = head[0].int_conv() 534 | body = { 535 | f'stage_{idx}_layer_{i}': 536 | getattr(self, f'stage_{idx}_layer_{i}').int_block( 537 | avgpool_scale=avgpool_scale if ( 538 | idx == len(self.block_setting) - 1 and i == n - 539 | 1) else 1.0) 540 | for idx, n in enumerate(self.block_setting) for i in range(n) 541 | } 542 | classifier = self.classifier 543 | classifier[0] = classifier[0].int_fc() 544 | return IntModel(head, body, classifier, self.block_setting) 545 | -------------------------------------------------------------------------------- /myutils/config.py: -------------------------------------------------------------------------------- 1 | """config utilities for yml file.""" 2 | import os 3 | import sys 4 | import yaml 5 | 6 | # singletone 7 | FLAGS = None 8 | 9 | 10 | class LoaderMeta(type): 11 | """Constructor for supporting `!include`. 12 | """ 13 | def __new__(mcs, __name__, __bases__, __dict__): 14 | """Add include constructer to class.""" 15 | # register the include constructor on the class 16 | cls = super().__new__(mcs, __name__, __bases__, __dict__) 17 | cls.add_constructor('!include', cls.construct_include) 18 | return cls 19 | 20 | 21 | class Loader(yaml.Loader, metaclass=LoaderMeta): 22 | """YAML Loader with `!include` constructor. 23 | """ 24 | def __init__(self, stream): 25 | try: 26 | self._root = os.path.split(stream.name)[0] 27 | except AttributeError: 28 | self._root = os.path.curdir 29 | super().__init__(stream) 30 | 31 | def construct_include(self, node): 32 | """Include file referenced at node.""" 33 | filename = os.path.abspath( 34 | os.path.join(self._root, self.construct_scalar(node))) 35 | extension = os.path.splitext(filename)[1].lstrip('.') 36 | with open(filename, 'r') as f: 37 | if extension in ('yaml', 'yml'): 38 | return yaml.load(f, Loader) 39 | else: 40 | return ''.join(f.readlines()) 41 | 42 | 43 | class AttrDict(dict): 44 | """Dict as attribute trick. 45 | 46 | """ 47 | def __init__(self, *args, **kwargs): 48 | super(AttrDict, self).__init__(*args, **kwargs) 49 | self.__dict__ = self 50 | for key in self.__dict__: 51 | value = self.__dict__[key] 52 | if isinstance(value, dict): 53 | self.__dict__[key] = AttrDict(value) 54 | elif isinstance(value, list): 55 | if isinstance(value[0], dict): 56 | self.__dict__[key] = [AttrDict(item) for item in value] 57 | else: 58 | self.__dict__[key] = value 59 | 60 | def yaml(self): 61 | """Convert object to yaml dict and return. 62 | 63 | """ 64 | yaml_dict = {} 65 | for key in self.__dict__: 66 | value = self.__dict__[key] 67 | if isinstance(value, AttrDict): 68 | yaml_dict[key] = value.yaml() 69 | elif isinstance(value, list): 70 | if isinstance(value[0], AttrDict): 71 | new_l = [] 72 | for item in value: 73 | new_l.append(item.yaml()) 74 | yaml_dict[key] = new_l 75 | else: 76 | yaml_dict[key] = value 77 | else: 78 | yaml_dict[key] = value 79 | return yaml_dict 80 | 81 | def __repr__(self): 82 | """Print all variables. 83 | 84 | """ 85 | ret_str = [] 86 | for key in self.__dict__: 87 | value = self.__dict__[key] 88 | if isinstance(value, AttrDict): 89 | ret_str.append('{}:'.format(key)) 90 | child_ret_str = value.__repr__().split('\n') 91 | for item in child_ret_str: 92 | ret_str.append(' ' + item) 93 | elif isinstance(value, list): 94 | if isinstance(value[0], AttrDict): 95 | ret_str.append('{}:'.format(key)) 96 | for item in value: 97 | # treat as AttrDict above 98 | child_ret_str = item.__repr__().split('\n') 99 | for item in child_ret_str: 100 | ret_str.append(' ' + item) 101 | else: 102 | ret_str.append('{}: {}'.format(key, value)) 103 | else: 104 | ret_str.append('{}: {}'.format(key, value)) 105 | return '\n'.join(ret_str) 106 | 107 | 108 | class Config(AttrDict): 109 | """Config with yaml file. 110 | 111 | This class is used to config model hyper-parameters, global constants, and 112 | other settings with yaml file. All settings in yaml file will be 113 | automatically logged into file. 114 | 115 | Args: 116 | filename(str): File name. 117 | 118 | Examples: 119 | 120 | yaml file ``model.yml``:: 121 | 122 | NAME: 'neuralgym' 123 | ALPHA: 1.0 124 | DATASET: '/mnt/data/imagenet' 125 | 126 | Usage in .py: 127 | 128 | >>> from neuralgym import Config 129 | >>> config = Config('model.yml') 130 | >>> print(config.NAME) 131 | neuralgym 132 | >>> print(config.ALPHA) 133 | 1.0 134 | >>> print(config.DATASET) 135 | /mnt/data/imagenet 136 | 137 | """ 138 | def __init__(self, filename=None, verbose=False): 139 | assert os.path.exists(filename), 'File {} not exist.'.format(filename) 140 | try: 141 | with open(filename, 'r') as f: 142 | cfg_dict = yaml.load(f, Loader) 143 | except EnvironmentError: 144 | print('Please check the file with name of "%s"', filename) 145 | super(Config, self).__init__(cfg_dict) 146 | if verbose: 147 | print(' pi.cfg '.center(80, '-')) 148 | print(self.__repr__()) 149 | print(''.center(80, '-')) 150 | 151 | 152 | def app(): 153 | """Load app via stdin from subprocess""" 154 | global FLAGS 155 | if FLAGS is None: 156 | job_yaml_file = None 157 | batch_size = None 158 | for arg in sys.argv: 159 | if arg.startswith('app:'): 160 | job_yaml_file = arg[4:] 161 | if arg.startswith('bs:'): 162 | batch_size = int(arg[3:]) 163 | if job_yaml_file is None: 164 | job_yaml_file = sys.stdin.readline() 165 | FLAGS = Config(job_yaml_file) 166 | if batch_size is not None: 167 | FLAGS.batch_size = batch_size 168 | if FLAGS.batch_size > 256: 169 | FLAGS.warmup_epochs = getattr(FLAGS, 'warmup_epochs', 5) 170 | FLAGS.lr = FLAGS.lr * FLAGS.batch_size / 256 171 | else: 172 | FLAGS.warmup_epochs = 0 173 | return FLAGS 174 | else: 175 | return FLAGS 176 | 177 | 178 | app() 179 | -------------------------------------------------------------------------------- /myutils/distributed.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import os 4 | import functools 5 | 6 | import torch 7 | import torch.nn as nn 8 | import torch.distributed as dist 9 | import torch.multiprocessing as mp 10 | from torch.nn.parallel.scatter_gather import scatter_kwargs 11 | from torch._utils import _flatten_dense_tensors 12 | from torch._utils import _unflatten_dense_tensors 13 | from torch._utils import _take_tensors 14 | 15 | 16 | def init_dist(launcher='pytorch', backend='nccl', **kwargs): 17 | if dist.is_initialized(): 18 | return torch.cuda.current_device() 19 | if mp.get_start_method(allow_none=True) is None: 20 | mp.set_start_method('spawn') 21 | rank = int(os.environ['RANK']) 22 | num_gpus = torch.cuda.device_count() 23 | gpu_id = rank % num_gpus 24 | torch.cuda.set_device(gpu_id) 25 | dist.init_process_group(backend=backend, **kwargs) 26 | return gpu_id 27 | 28 | 29 | def get_rank(): 30 | if dist.is_initialized(): 31 | rank = dist.get_rank() 32 | else: 33 | rank = 0 34 | return rank 35 | 36 | 37 | def get_world_size(): 38 | if dist.is_initialized(): 39 | world_size = dist.get_world_size() 40 | else: 41 | world_size = 1 42 | return world_size 43 | 44 | 45 | def master_only(func): 46 | @functools.wraps(func) 47 | def wrapper(*args, **kwargs): 48 | if get_rank() == 0: 49 | return func(*args, **kwargs) 50 | else: 51 | return None 52 | 53 | return wrapper 54 | 55 | 56 | def is_master(): 57 | """check if current process is the master""" 58 | return get_rank() == 0 59 | 60 | 61 | @master_only 62 | def master_only_print(*args): 63 | """master-only print""" 64 | print(*args) 65 | 66 | 67 | def dist_reduce_tensor(tensor): 68 | """ Reduce to rank 0 """ 69 | world_size = get_world_size() 70 | if world_size < 2: 71 | return tensor 72 | with torch.no_grad(): 73 | dist.reduce(tensor, dst=0) 74 | if get_rank() == 0: 75 | tensor /= world_size 76 | return tensor 77 | 78 | 79 | def dist_all_reduce_tensor(tensor): 80 | """ Reduce to all ranks """ 81 | world_size = get_world_size() 82 | if world_size < 2: 83 | return tensor 84 | with torch.no_grad(): 85 | dist.all_reduce(tensor) 86 | tensor.div_(world_size) 87 | return tensor 88 | 89 | 90 | def _allreduce_coalesced(tensors, world_size, bucket_size_mb=-1): 91 | if bucket_size_mb > 0: 92 | bucket_size_bytes = bucket_size_mb * 1024 * 1024 93 | buckets = _take_tensors(tensors, bucket_size_bytes) 94 | else: 95 | buckets = OrderedDict() 96 | for tensor in tensors: 97 | tp = tensor.type() 98 | if tp not in buckets: 99 | buckets[tp] = [] 100 | buckets[tp].append(tensor) 101 | buckets = buckets.values() 102 | 103 | for bucket in buckets: 104 | flat_tensors = _flatten_dense_tensors(bucket) 105 | dist.all_reduce(flat_tensors) 106 | flat_tensors.div_(world_size) 107 | for tensor, synced in zip( 108 | bucket, _unflatten_dense_tensors(flat_tensors, bucket)): 109 | tensor.copy_(synced) 110 | 111 | 112 | def allreduce_grads(model, coalesce=True, bucket_size_mb=-1): 113 | grads = [ 114 | param.grad.data for param in model.parameters() 115 | if param.requires_grad and param.grad is not None 116 | ] 117 | world_size = dist.get_world_size() 118 | if coalesce: 119 | _allreduce_coalesced(grads, world_size, bucket_size_mb) 120 | else: 121 | for tensor in grads: 122 | dist.all_reduce(tensor.div_(world_size)) 123 | 124 | 125 | class AllReduceDistributedDataParallel(nn.Module): 126 | def __init__(self, 127 | module, 128 | dim=0, 129 | broadcast_buffers=True, 130 | bucket_cap_mb=25): 131 | super(AllReduceDistributedDataParallel, self).__init__() 132 | self.module = module 133 | self.dim = dim 134 | self.broadcast_buffers = broadcast_buffers 135 | 136 | self.broadcast_bucket_size = bucket_cap_mb * 1024 * 1024 137 | self._sync_params() 138 | 139 | def _dist_broadcast_coalesced(self, tensors, buffer_size): 140 | for tensors in _take_tensors(tensors, buffer_size): 141 | flat_tensors = _flatten_dense_tensors(tensors) 142 | dist.broadcast(flat_tensors, 0) 143 | for tensor, synced in zip( 144 | tensors, _unflatten_dense_tensors(flat_tensors, tensors)): 145 | tensor.copy_(synced) 146 | 147 | def _sync_params(self): 148 | module_states = list(self.module.state_dict().values()) 149 | if len(module_states) > 0: 150 | self._dist_broadcast_coalesced(module_states, 151 | self.broadcast_bucket_size) 152 | if self.broadcast_buffers: 153 | buffers = [b.data for b in self.module.buffers()] 154 | if len(buffers) > 0: 155 | self._dist_broadcast_coalesced(buffers, 156 | self.broadcast_bucket_size) 157 | 158 | def scatter(self, inputs, kwargs, device_ids): 159 | return scatter_kwargs(inputs, kwargs, device_ids, dim=self.dim) 160 | 161 | def forward(self, *inputs, **kwargs): 162 | inputs, kwargs = self.scatter(inputs, kwargs, 163 | [torch.cuda.current_device()]) 164 | return self.module(*inputs[0], **kwargs[0]) 165 | -------------------------------------------------------------------------------- /myutils/export.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | 4 | def onnx_export(model, data_shape, data_dtype, device, output_file): 5 | print("\nExporting...\n") 6 | batch_size = 1 7 | _, data_channel, data_height, data_width = data_shape 8 | rand_input = torch.randn(batch_size, 9 | data_channel, 10 | data_height, 11 | data_width, 12 | requires_grad=True).to(dtype=data_dtype, 13 | device=device) 14 | torch.onnx.export(model.cpu(), 15 | rand_input.cpu(), 16 | output_file, 17 | export_params=True, 18 | opset_version=11, 19 | do_constant_folding=True, 20 | input_names=['input'], 21 | output_names=['output'], 22 | dynamic_axes={ 23 | 'input': { 24 | 0: 'batch_size' 25 | }, 26 | 'output': { 27 | 0: 'batch_size' 28 | } 29 | }) 30 | model = model.to(device) 31 | print("\nModel exported!\n") 32 | -------------------------------------------------------------------------------- /myutils/meters.py: -------------------------------------------------------------------------------- 1 | class Meter(object): 2 | """Meter is to keep track of statistics along steps. 3 | Meters cache values for purpose like printing average values. 4 | Meters can be flushed to log files (i.e. TensorBoard) regularly. 5 | 6 | Args: 7 | name (str): the name of meter 8 | 9 | """ 10 | def __init__(self, name): 11 | self.name = name 12 | self.steps = 0 13 | self.reset() 14 | 15 | def __repr__(self): 16 | return '{}: {!r}'.format(self.__class__, self.__dict__) 17 | 18 | def reset(self): 19 | self.values = [] 20 | 21 | def cache(self, value, pstep=1): 22 | self.steps += pstep 23 | self.values.append(value) 24 | 25 | def cache_list(self, value_list, pstep=1): 26 | self.steps += pstep 27 | self.values += value_list 28 | 29 | def flush(self, value, reset=True): 30 | pass 31 | 32 | 33 | class ScalarMeter(Meter): 34 | """ScalarMeter records scalar over steps. 35 | 36 | """ 37 | def __init__(self, name): 38 | super(ScalarMeter, self).__init__(name) 39 | 40 | def flush(self, value, step=-1, reset=True): 41 | if reset: 42 | self.reset() 43 | 44 | 45 | def flush_scalar_meters(meters, method='avg'): 46 | """Docstring for flush_scalar_meters""" 47 | results = {} 48 | assert isinstance(meters, dict), "meters should be a dict." 49 | for name, meter in meters.items(): 50 | if not isinstance(meter, ScalarMeter): 51 | results[name] = meter 52 | continue 53 | if method == 'avg': 54 | value = sum(meter.values) / len(meter.values) 55 | elif method == 'sum': 56 | value = sum(meter.values) 57 | elif method == 'max': 58 | value = max(meter.values) 59 | elif method == 'min': 60 | value = min(meter.values) 61 | else: 62 | raise NotImplementedError( 63 | 'flush method: {} is not yet implemented.'.format(method)) 64 | results[name] = float(format(value, '.3f')) 65 | meter.flush(value) 66 | return results 67 | -------------------------------------------------------------------------------- /requirements.in: -------------------------------------------------------------------------------- 1 | numpy==1.19.5 2 | torch==1.11.0 3 | torchvision==0.12.0 4 | pytorchcv==0.0.67 5 | PyYAML==6.0 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with python 3.7 3 | # To update, run: 4 | # 5 | # pip-compile --output-file=requirements.txt requirements.in 6 | # 7 | certifi==2021.10.8 8 | # via requests 9 | charset-normalizer==2.0.12 10 | # via requests 11 | idna==3.3 12 | # via requests 13 | numpy==1.19.5 14 | # via 15 | # -r requirements.in 16 | # pytorchcv 17 | # torchvision 18 | pillow==9.1.0 19 | # via torchvision 20 | pytorchcv==0.0.67 21 | # via -r requirements.in 22 | pyyaml==6.0 23 | # via -r requirements.in 24 | requests==2.27.1 25 | # via 26 | # pytorchcv 27 | # torchvision 28 | torch==1.11.0 29 | # via 30 | # -r requirements.in 31 | # torchvision 32 | torchvision==0.12.0 33 | # via -r requirements.in 34 | typing-extensions==4.2.0 35 | # via 36 | # torch 37 | # torchvision 38 | urllib3==1.26.9 39 | # via requests 40 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cfg=$1 3 | bs=${2:-256} 4 | echo "Total batch size: " $bs 5 | if [ ! -f $cfg ]; then 6 | echo "Config not found!" 7 | fi 8 | 9 | python3 -W ignore fix_train.py app:$cfg bs:$bs 10 | -------------------------------------------------------------------------------- /weight_boxplot/mobilenetv2_pytorchcv_eff_weight.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/weight_boxplot/mobilenetv2_pytorchcv_eff_weight.pdf -------------------------------------------------------------------------------- /weight_boxplot/mobilenetv2_pytorchcv_eff_weight_wo_title.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/weight_boxplot/mobilenetv2_pytorchcv_eff_weight_wo_title.pdf -------------------------------------------------------------------------------- /weight_boxplot/mobilenetv2_torchvision_eff_weight.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/weight_boxplot/mobilenetv2_torchvision_eff_weight.pdf -------------------------------------------------------------------------------- /weight_boxplot/mobilenetv2_torchvision_eff_weight_wo_title.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snap-research/F8Net/9f8c3549d1f6f801e8db568411388695c486e585/weight_boxplot/mobilenetv2_torchvision_eff_weight_wo_title.pdf -------------------------------------------------------------------------------- /weight_boxplot/weight_boxplot.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib 3 | matplotlib.use('Agg') 4 | import matplotlib.pyplot as plt 5 | 6 | import torch 7 | import torch.nn as nn 8 | import torchvision.models as tv_models 9 | from pytorchcv.model_provider import get_model as ptcv_get_model 10 | 11 | 12 | def main(): 13 | fig_size = (6, 4) 14 | axes_label_size = 16 15 | text_size = 12 16 | title_size = 16 17 | legend_size = 8 18 | font_weight = 'normal' 19 | for ckpt in ['torchvision', 'pytorchcv']: 20 | if ckpt == 'torchvision': 21 | net = tv_models.mobilenetv2.mobilenet_v2(pretrained=True) 22 | elif ckpt == 'pytorchcv': 23 | net = ptcv_get_model('mobilenetv2b_w1', pretrained=True) 24 | eff_weight_list = [] 25 | conv_weight = None 26 | fc_weight = None 27 | for n, m in net.named_modules(): 28 | if isinstance(m, nn.Conv2d): 29 | conv_weight = m.weight 30 | elif isinstance(m, nn.BatchNorm2d): 31 | bn_weight = m.weight 32 | bn_var = m.running_var 33 | bn_eps = m.eps 34 | eff_weight = conv_weight * ( 35 | bn_weight / torch.sqrt(bn_var + bn_eps))[:, None, None, 36 | None] 37 | eff_weight_list.append( 38 | eff_weight.detach().cpu().flatten().numpy()) 39 | conv_weight = None 40 | elif isinstance(m, nn.Linear): 41 | eff_weight = m.weight 42 | eff_weight_list.append( 43 | eff_weight.detach().cpu().flatten().numpy()) 44 | conv_weight = None 45 | else: 46 | conv_weight = None 47 | plt.figure(figsize=fig_size) 48 | box_edge_color = 'k' 49 | box_bar_color = 'r' 50 | plt.boxplot(eff_weight_list, 51 | showfliers=False, 52 | boxprops={'color': box_edge_color}, 53 | capprops={'color': box_edge_color}, 54 | whiskerprops={'color': box_edge_color}, 55 | flierprops={'markeredgecolor': box_edge_color}, 56 | medianprops={'color': box_bar_color}) 57 | plt.xticks([]) 58 | plt.xlabel('Layer', fontsize=axes_label_size) 59 | plt.ylabel('Effective Weight', fontsize=axes_label_size) 60 | plt.setp(plt.gca().get_xticklabels(), 61 | fontsize=axes_label_size, 62 | fontweight=font_weight) 63 | plt.setp(plt.gca().get_yticklabels(), 64 | fontsize=axes_label_size, 65 | fontweight=font_weight) 66 | plt.savefig(f'./mobilenetv2_{ckpt}_eff_weight_wo_title.pdf', 67 | dpi=300, 68 | bbox_inches='tight') 69 | plt.title('Effective Weight Range (FP MobileNet V2)', 70 | fontsize=title_size) 71 | plt.savefig(f'./mobilenetv2_{ckpt}_eff_weight.pdf', 72 | dpi=300, 73 | bbox_inches='tight') 74 | 75 | 76 | if __name__ == '__main__': 77 | main() 78 | --------------------------------------------------------------------------------