# Block Pattern-Connectivity Pruning with ADMM: YOLOv3 ## Overall Description We first explain the file structure, followed by instructions on downloading the pretrained weights and the COCO2014 dataset, as well as setting up the environment. Next, we introduce the scripts for training, testing, and detection, along with a script for checking the model's pattern structure and another for launching TensorBoard. Finally, we present the experimental results. We refer to Block Pattern-Connectivity Pruning as BPCP. [GitHub Link](https://github.com/martin0310/PyTorch-YOLOv3) [GitLab Link](https://gitlab.aislab.ee.ncku.edu.tw/aislab-internal/research/archive-research/model-compression/yolov3_block_pattern) ## Overall README Structure * File Structure * Download pretrained weights * Data Preparation: COCO2014 * Environment Setup * Train (training script) * Block Pattern-Connectivity Prune (no ADMM) * Block Pattern-Connectivity Prune + ADMM (ADMM train) * Block Pattern-Connectivity Prune + ADMM (ADMM retrain) * Output file after training * Test (testing script) * Detect (detection script) * check pattern (Verify that the pattern and block size are correct after training) * calculate paramters and MACs * run tensorboard * Experimental Results ## File Structure <pre style="font-size: 0.5em; white-space: pre-wrap;"> <code> . ├── LICENSE ├── README.md ├── admm_logs --> Save ADMM training logs ├── admm_retrain_logs --> Save ADMM retraining logs ├── assets ├── checkpoints --> Save checkpoints ├── coco2014 -> /storage/share/coco2014 --> Symbolic link to COCO2014 dataset ├── config │   ├── coco.data --> Specifying the number of classes (80), training and validation file paths, the class names file. │   ├── custom.data │   ├── yolov3-tiny.cfg │   └── yolov3.cfg --> Config of YOLOv3 ├── data │   ├── coco.names │   ├── custom │   └── samples ├── logs ├── output ├── poetry.lock ├── pyproject.toml ├── pytorchyolo │   ├── __init__.py │   ├── __pycache__ │   ├── admm_train.py --> For ADMM training │   ├── cal_param_flops.py --> Calculate the MACs and the number of parameters │   ├── check_pattern.py --> Verify that the pattern and block size are correct after training │   ├── detect.py │   ├── models.py │   ├── test.py │   ├── train.py --> Only Prune by magnitude, Retraining after ADMM training │   └── utils │   ├── __init__.py │   ├── admm.py --> Contain admm function │   ├── augmentations.py │   ├── datasets.py │   ├── logger.py │   ├── loss.py │   ├── parse_config.py │   ├── pattern_utils.py --> Contain function for find pattern for every layer and block pattern pruning │   ├── transforms.py │   └── utils.py └── weights --> Pre-trained weight folder └── yolov3.weights --> YOLOv3 pre-trained weight </code> </pre> ## Download Pre-trained Weights Copy the pre-trained weight from /mnt/Data-Weight/1xN_new/yolov3_pretrained/yolov3.weights to the weights folder. ## Data Preparation: COCO2014 If using 140.116.178.179 port 105 server, the COCO2014 data is already downloaded at /storage/share/coco2014. Step 1 - Download Kaggle API ```bash= pip install --user kaggle ``` Step 2 - Setup API Credentials Log in to Kaggle and navigate to the Account page. In the API section, click on "Create New API Token." This will download a file named kaggle.json, which contains your API credentials. The JSON file will contain a single entry in the following format: ``` {"username":<USER_NAME>,"key":<API_KEY>} ``` Make a directory .kaggle at home directory(~), and place kaggle.json in that directory. (~/.kaggle/kaggle.json): ```bash= mkdir ~/.kaggle mv kaggle.json ~/.kaggle ``` Verify the JSON file by running the following command: ```bash= cat ~/.kaggle/kaggle.json ``` Step 2 - Download Dataset Modify the file permissions to prevent other users from reading it: ```bash= chmod 600 ~/.kaggle/kaggle.json ``` To download the dataset from Kaggle, click the Download button on the dataset page and select Download via Kaggle CLI. After clicking the Kaggle CLI option, a script will be displayed—copy and paste this content into a file with a .sh extension. ``` #!/bin/bash kaggle datasets download jeffaudi/coco-2014-dataset-for-yolov3 ``` Change the file’s permission to make it executable, then run it. For example: ```bash= chmod 764 download.sh ./download.sh ``` Create a symbolic link by running the following command: ```bash= ln -s coco2014_data_path coco2014 ``` ## Environment Setup ```bash= conda create --name env_name python=3.11.7 pip install pytorchyolo ``` ## Train pytorchyolo/train.py argument table | argument | argument description | | --------- | ---- | | `--data` | Path to data config file (.data) | | `--pretrained_weights` | Pre-trained weight path | | `--block_pattern_prune` | block pattern prune (no argument needed) | | `--kernel_pattern_num` | pattern number of every layer | | `--epochs` | Number of epochs | | `--resume_from` | Path to a checkpoint (.pth) to resume training | | `--N` | Block size | ### Block Pattern-Connectivity Prune (no ADMM) Block Pattern-Connectivity Prune ```bash= python -m pytorchyolo.train --data config/coco.data --pretrained_weights weights/yolov3.weights --block_pattern_prune --kernel_pattern_num $kernel_pattern_num --epochs 300 ``` resume Block Pattern-Connectivity Prune ```bash= python -m pytorchyolo.train --data config/coco.data --pretrained_weights weights/yolov3.weights --block_pattern_prune --kernel_pattern_num $kernel_pattern_num --epochs 300 --resume_from $resume_path ``` ### Block Pattern-Connectivity Prune + ADMM (ADMM train) pytorchyolo/admm_train.py argument table | argument | argument description | | --------- | ---- | | `--data` | Path to data config file (.data) | | `--pretrained_weights` | Pre-trained weight path | | `--kernel_pattern_num` | pattern number of every layer | | `--epochs` | Number of epochs | | `--resume_from` | Path to a checkpoint (.pth) to resume training | | `--N` | Block size | Block Pattern-Connectivity Prune + ADMM: admm train ```bash= python -m pytorchyolo.admm_train --data config/coco.data --pretrained_weights weights/yolov3.weights --kernel_pattern_num $kernel_pattern_num --epochs 200 --rho 0.0001 ``` Block Pattern-Connectivity Prune + ADMM: resume admm train ```bash= python -m pytorchyolo.admm_train --data config/coco.data --pretrained_weights weights/yolov3.weights --kernel_pattern_num $kernel_pattern_num --epochs 200 --resume_from $admm_train_resume_file ``` ### Block Pattern-Connectivity Prune + ADMM (ADMM retrain) pytorchyolo/train.py argument table | argument | argument description | | --------- | ---- | | `--data` | Path to data config file (.data) | | `--pretrained_weights` | Pre-trained weight path | | `--block_pattern_prune` | block pattern prune (no argument needed) | | `--admm_retrain` | ADMM retrain or not (no argument needed) | | `--resume_from` | Path to a checkpoint (.pth) to resume training | | `--kernel_pattern_num` | pattern number of every layer | | `--epochs` | Number of epochs | | `--admm_checkpoint` | Path to checkpoint after ADMM training | | `--N` | Block size | Block Pattern-Connectivity Prune + ADMM: retrain admm ```bash= python -m pytorchyolo.train --data config/coco.data --pretrained_weights weights/yolov3.weights --admm_retrain --admm_checkpoint checkpoints/admm_yolov3_best_pruned.pth --kernel_pattern_num $kernel_pattern_num --epochs 150 ``` Block Pattern-Connectivity Prune + ADMM: resume retrain admm ```bash= python -m pytorchyolo.train --data config/coco.data --pretrained_weights weights/yolov3.weights --block_pattern_prune --admm_retrain --resume_from $resume_file_last_pth --kernel_pattern_num $kernel_pattern_num --epochs 150 ``` ### Output File After Training #### Block Pattern-Connectivity Prune (no ADMM) After training, it will have following files in checkpoints folder: ``` . ├── yolov3_best.pth --> best model after training └── yolov3_last.pth --> last model after training ``` it will also have training log for experiment folder, for example: ``` logs └── events.out.tfevents.1743661991.ais15.13490.0 --> log for training ``` #### Block Pattern-Connectivity Prune + ADMM After training, it will have following files in checkpoints folder: ``` . ├── admm_yolov3_best.pth --> best model after ADMM training ├── admm_yolov3_last.pth --> last model after ADMM training ├── admm_yolov3_best_pruned.pth --> pruned best model when finishing ADMM training ├── admm_retrain_yolov3_best.pth --> best model after ADMM retraining └── admm_retrain_yolov3_last.pth --> last model after ADMM retraining ``` it will also have training log for experiment folder, for example: ``` admm_logs └── events.out.tfevents.1743661991.ais15.13490.0 --> log for ADMM training admm_retrain_logs └── events.out.tfevents.1743985390.ais15.73625.0 --> log for ADMM retraining ``` ## Test pytorchyolo/test.py argument table | argument | argument description | | --------- | ---- | | `--weights_to_test` | weights path to test | ```bash= python -m pytorchyolo.test --weights_to_test $weight_path ``` ## Detect Result will be saved in output folder. pytorchyolo/detect.py argument table | argument | argument description | | --------- | ---- | | `--images` | Path to directory with images to inference | | `--weights_to_detect` | Weight path to detect | detect (not yolov3.weights): ```bash= python -m pytorchyolo.detect --images data/samples/ --weights_to_detect $weight_to_detect ``` detect (using yolov3.weights): ```bash= python -m pytorchyolo.detect --images data/samples/ ``` ## Check Pattern pytorchyolo/check_pattern.py argument table | argument | argument description | | --------- | ---- | | `--weights` | Path to weights or checkpoint file (.weights or .pth) | | `--kernel_pattern_num` | pattern number of every layer | ```bash= python -m pytorchyolo.check_pattern --kernel_pattern_num $kernel_pattern_num --weights $weight_path ``` ## Calculate Paramters and MACs | argument | argument description | | --------- | ---- | | `--weights` | Path to weights or checkpoint file (.weights or .pth) | | `--load_pruned_model` | check whether to load pruned model or not to calculate MACs and parameters (no argument needed) | unpruned model: ```bash= python -m pytorchyolo.cal_param_flops --weights $weighs_path ``` pruned model: ```bash= python -m pytorchyolo.cal_param_flops --load_pruned_model --weights $weighs_path ``` ## Run Tensorboard ```bash= tensorboard --logdir=log_dir --port=6006 ``` port forwarding: ```bash= ssh -L 6006:localhost:6006 -p $server_port ${server_user_name}@140.116.178.179 ``` open browser and type: ```bash= http://localhost:6006/ ``` ## Experimental Results YOLOv3 + ADMM (N = 4) | | mAP-50 | | --------- | ---- | | Origin | 55.3% | | 1xN | 52.0% | | BPCP (pattern number = 12) | 51.2% | | BPCP (pattern number = 8) | 51.0% | | BPCP (pattern number = 4) | 50.5% | Final training checkpoints (admm_retrain_yolov3_best.pth) locate in: /mnt/Data-Weight/1xN_new/yolov3/checkpoint/N_4/admm_retrain (We try to find the best value of rho when pattern number is 4) ``` . ├── 12_patterns ├── 4_patterns │   ├── rho_0_00001 │   ├── rho_0_0001 --> checkpoints for 4 patterns │   ├── rho_0_001 │   └── rho_0_01 └── 8_patterns ```