From 93b0a4c8336ed3791f03d2d5a4b951199a1acd93 Mon Sep 17 00:00:00 2001 From: Hongwei Chen Date: Wed, 16 Sep 2026 05:40:15 +0000 Subject: [PATCH] Depreacte compression examples Signed-off-by: Hongwei Chen --- compression/README.md | 11 +- compression/bert/README.md | 17 - .../bert/bash_script/XTC/layer_reduction.sh | 69 - .../bash_script/XTC/layer_reduction_1bit.sh | 41 - .../bert/bash_script/XTC/quant_1bit.sh | 64 - .../bert/bash_script/ZeroQuant/zero_quant.sh | 58 - .../bash_script/ZeroQuant/zero_quant_lkd.sh | 60 - .../bert/bash_script/layer_reduction.sh | 90 - compression/bert/bash_script/pruning_head.sh | 92 - compression/bert/bash_script/pruning_row.sh | 92 - .../bert/bash_script/pruning_sparse.sh | 92 - .../pruning_sparse_snip_momentum.sh | 103 - .../bert/bash_script/quant_activation.sh | 92 - compression/bert/bash_script/quant_weight.sh | 91 - .../XTC/ds_config_W1A8_Qgroup1_fp32.json | 148 -- .../ds_config_layer_reduction_W1Q8_fp32.json | 149 -- .../XTC/ds_config_layer_reduction_fp16.json | 149 -- .../ds_config_W48A8_Qgroup48_lkd_fp32.json | 156 -- .../ds_config_W8A8_Qgroup48_fp32.json | 148 -- compression/bert/config/ds_config.json | 155 -- .../bert/config/ds_config_TEMPLATE.json | 166 -- .../config/ds_config_W1A8_Qgroup64_fp16.json | 148 -- .../config/ds_config_W1A8_Qgroup64_fp32.json | 148 -- .../ds_config_W1or2A8_Qgroup64_fp16.json | 157 -- ...ds_config_structural_pruning_TEMPLATE.json | 161 -- .../huggingface_transformer/modeling_bert.py | 1886 ----------------- compression/bert/requirements.txt | 9 - compression/bert/run_glue_lkd.py | 540 ----- compression/bert/run_glue_no_trainer.py | 530 ----- compression/bert/util.py | 368 ---- compression/cifar/README.md | 16 - compression/cifar/config/ds_config.json | 32 - .../cifar/config/ds_config_channel_prune.json | 128 -- compression/cifar/resnet.py | 255 --- compression/cifar/run_compress.sh | 43 - compression/cifar/train.py | 155 -- compression/cifar/utils.py | 85 - compression/gpt2/README.md | 21 - .../gpt2/bash_script/run_zero_quant.sh | 72 - compression/gpt2/config/ds_config.json | 32 - .../ds_config_W4or8A8_Qgroup64_fp16.json | 90 - .../ds_config_W4or8A8_Qgroup64_fp32.json | 90 - .../config/ds_config_W8A8_Qgroup64_fp16.json | 80 - .../config/ds_config_W8A8_Qgroup64_fp32.json | 80 - compression/gpt2/requirements.txt | 5 - compression/gpt2/run_clm_no_trainer.py | 544 ----- 46 files changed, 4 insertions(+), 7714 deletions(-) delete mode 100644 compression/bert/README.md delete mode 100644 compression/bert/bash_script/XTC/layer_reduction.sh delete mode 100644 compression/bert/bash_script/XTC/layer_reduction_1bit.sh delete mode 100644 compression/bert/bash_script/XTC/quant_1bit.sh delete mode 100644 compression/bert/bash_script/ZeroQuant/zero_quant.sh delete mode 100644 compression/bert/bash_script/ZeroQuant/zero_quant_lkd.sh delete mode 100644 compression/bert/bash_script/layer_reduction.sh delete mode 100644 compression/bert/bash_script/pruning_head.sh delete mode 100644 compression/bert/bash_script/pruning_row.sh delete mode 100644 compression/bert/bash_script/pruning_sparse.sh delete mode 100644 compression/bert/bash_script/pruning_sparse_snip_momentum.sh delete mode 100644 compression/bert/bash_script/quant_activation.sh delete mode 100644 compression/bert/bash_script/quant_weight.sh delete mode 100644 compression/bert/config/XTC/ds_config_W1A8_Qgroup1_fp32.json delete mode 100644 compression/bert/config/XTC/ds_config_layer_reduction_W1Q8_fp32.json delete mode 100644 compression/bert/config/XTC/ds_config_layer_reduction_fp16.json delete mode 100644 compression/bert/config/ZeroQuant/ds_config_W48A8_Qgroup48_lkd_fp32.json delete mode 100644 compression/bert/config/ZeroQuant/ds_config_W8A8_Qgroup48_fp32.json delete mode 100644 compression/bert/config/ds_config.json delete mode 100644 compression/bert/config/ds_config_TEMPLATE.json delete mode 100644 compression/bert/config/ds_config_W1A8_Qgroup64_fp16.json delete mode 100644 compression/bert/config/ds_config_W1A8_Qgroup64_fp32.json delete mode 100644 compression/bert/config/ds_config_W1or2A8_Qgroup64_fp16.json delete mode 100644 compression/bert/config/ds_config_structural_pruning_TEMPLATE.json delete mode 100644 compression/bert/huggingface_transformer/modeling_bert.py delete mode 100644 compression/bert/requirements.txt delete mode 100644 compression/bert/run_glue_lkd.py delete mode 100644 compression/bert/run_glue_no_trainer.py delete mode 100644 compression/bert/util.py delete mode 100644 compression/cifar/README.md delete mode 100644 compression/cifar/config/ds_config.json delete mode 100644 compression/cifar/config/ds_config_channel_prune.json delete mode 100644 compression/cifar/resnet.py delete mode 100644 compression/cifar/run_compress.sh delete mode 100644 compression/cifar/train.py delete mode 100644 compression/cifar/utils.py delete mode 100644 compression/gpt2/README.md delete mode 100644 compression/gpt2/bash_script/run_zero_quant.sh delete mode 100644 compression/gpt2/config/ds_config.json delete mode 100644 compression/gpt2/config/ds_config_W4or8A8_Qgroup64_fp16.json delete mode 100644 compression/gpt2/config/ds_config_W4or8A8_Qgroup64_fp32.json delete mode 100644 compression/gpt2/config/ds_config_W8A8_Qgroup64_fp16.json delete mode 100644 compression/gpt2/config/ds_config_W8A8_Qgroup64_fp32.json delete mode 100644 compression/gpt2/requirements.txt delete mode 100644 compression/gpt2/run_clm_no_trainer.py diff --git a/compression/README.md b/compression/README.md index 63b07c17d..025a92d33 100644 --- a/compression/README.md +++ b/compression/README.md @@ -1,12 +1,9 @@ -# DeepSpeed Model Compression examples +# Compression examples -Examples in this folder are helpful to try out some features and models that take advantage of the DeepSpeed compression library. - -A detailed tutorial for understanding and using DeepSpeed model compression features can be seen from here: https://www.deepspeed.ai/tutorials/model-compression/ +The legacy BERT, GPT-2, and CIFAR examples were removed because they depended +on `deepspeed.compression`, which was removed in +[deepspeedai/DeepSpeed#8490](https://github.com/deepspeedai/DeepSpeed/pull/8490). | Example | Description | | --- | --- | -| [bert](bert) | Quantization, pruning and layer reduction on BERT (ZeroQuant, XTC) | -| [gpt2](gpt2) | ZeroQuant post-training quantization on GPT-2 | -| [cifar](cifar) | Channel pruning and quantization on a CIFAR ResNet | | [reasoning_aware_compression](reasoning_aware_compression) | One-shot pruning of reasoning LLMs (DeepSeek-R1 distills, Qwen3) calibrated on their own chain-of-thought traces — [RAC, ICLR 2026](https://arxiv.org/abs/2509.12464) | diff --git a/compression/bert/README.md b/compression/bert/README.md deleted file mode 100644 index 4e38525cb..000000000 --- a/compression/bert/README.md +++ /dev/null @@ -1,17 +0,0 @@ -#### Install - -``pip install -r requirements.txt`` - -You will also need to install updated DeepSpeed version (>0.7.0), which contains the compression library. - -#### Key File: run_glue_no_trainer.py - -The python code is modified based on [HuggingFace's PyTorch text_classification](https://github.com/huggingface/transformers/tree/main/examples/pytorch/text-classification). The key added feature is the implementation of knowledge distillation (KD)(--distill_method one_stage). If no KD, run (--distill_method zero_stage). - -#### Folders (config, huggingface_transformer, bash_script) - -* **config:** This folder provides DeepSpeed configuration, including quantization, pruning and layer reduction. -* **huggingface_transformer:** This folder serves the implementation of knowledge distillation. It's based on [HuggingFace's transformer](https://github.com/huggingface/transformers/blob/main/src/transformers/models/bert/modeling_bert.py) - The change is line 383, where we output attention_scores instead of attention_prob. -* **bash_script** This folder contains many bash scripts for various kinds of compression. See more descriptions and results in our [tutorial page](https://www.deepspeed.ai/). - diff --git a/compression/bert/bash_script/XTC/layer_reduction.sh b/compression/bert/bash_script/XTC/layer_reduction.sh deleted file mode 100644 index b8af70200..000000000 --- a/compression/bert/bash_script/XTC/layer_reduction.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash - -#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%. run_jobs.sh (for mnli) - -export CUDA_VISIBLE_DEVICES=7 -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -STAGE=one_stage -LRATE=5e-5 - -EPOCH=18 -WARMUP_EPOCH=1 -#CONFIG=./config/ds_config_W1A8_Qgroup64_fp16.json # <=====================it's less stable -#CONFIG=./config/ds_config_W1or2A8_Qgroup64_fp16.json -CONFIG=./config/XTC/ds_config_layer_reduction_fp16.json -SAVE_PATH=./out/XTC/layer_reduction -mkdir -p ${SAVE_PATH} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66665 \ - run_glue_no_trainer.py \ - --seed 42 \ - --distill_method ${STAGE} \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size 32 \ - --per_device_eval_batch_size 128 \ - --learning_rate $LRATE \ - --num_train_epochs ${EPOCH}\ - --num_warmup_epochs ${WARMUP_EPOCH} \ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} &>> ${SAVE_PATH}/train.log - - -# CONFIG=./config/XTC/ds_config_layer_reduction_W1Q8_fp32.json -# SAVE_PATH=./out/XTC/layer_reduction_W1A8_quantization -# mkdir -p ${SAVE_PATH} -# # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -# MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -# student_model=./out/XTC/layer_reduction/best/pytorch_model.bin # <====================================================================Need student model -# python -m torch.distributed.launch --nproc_per_node=1 \ -# --master_port 66665 \ -# run_glue_no_trainer.py \ -# --pretrained_dir_student ${student_model} \ -# --seed 42 \ -# --distill_method ${STAGE} \ -# --model_name_or_path ${MODEL} \ -# --task_name $TASK_NAME \ -# --max_length 128 \ -# --pad_to_max_length \ -# --per_device_train_batch_size 32 \ -# --per_device_eval_batch_size 128 \ -# --learning_rate $LRATE \ -# --num_train_epochs ${EPOCH}\ -# --num_warmup_epochs ${WARMUP_EPOCH} \ -# --eval_step 1000 \ -# --deepspeed_config ${CONFIG} \ -# --deepspeed \ -# --save_best_model --clean_best_model \ -# --gradient_accumulation_steps 1 \ -# --output_dir ${SAVE_PATH} &>> ${SAVE_PATH}/train.log diff --git a/compression/bert/bash_script/XTC/layer_reduction_1bit.sh b/compression/bert/bash_script/XTC/layer_reduction_1bit.sh deleted file mode 100644 index 12a40e05b..000000000 --- a/compression/bert/bash_script/XTC/layer_reduction_1bit.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%. run_jobs.sh (for mnli) - -export CUDA_VISIBLE_DEVICES=0 -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -STAGE=one_stage -LRATE=5e-5 -QGROUP=1 -EPOCH=18 -WARMUP_EPOCH=1 -#CONFIG=./config/ds_config_W1A8_Qgroup64_fp16.json # <=====================it's less stable -#CONFIG=./config/ds_config_W1or2A8_Qgroup64_fp16.json -CONFIG=./config/XTC/ds_config_layer_reduction_W1Q8_fp32.json -SAVE_PATH=./out/XTC/layer_reduction_W1A8_quantization -mkdir -p ${SAVE_PATH} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -student_model=./out/XTC/layer_reduction/best/pytorch_model.bin # <====================================================================Need student model -python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66664 \ - run_glue_no_trainer.py \ - --pretrained_dir_student ${student_model} \ - --seed 42 \ - --distill_method ${STAGE} \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size 32 \ - --per_device_eval_batch_size 128 \ - --learning_rate $LRATE \ - --num_train_epochs ${EPOCH}\ - --num_warmup_epochs ${WARMUP_EPOCH} \ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} &>> ${SAVE_PATH}/train.log diff --git a/compression/bert/bash_script/XTC/quant_1bit.sh b/compression/bert/bash_script/XTC/quant_1bit.sh deleted file mode 100644 index b6c17861e..000000000 --- a/compression/bert/bash_script/XTC/quant_1bit.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash - -#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%. run_jobs.sh (for mnli) - -export CUDA_VISIBLE_DEVICES=0 -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -STAGE=one_stage -LRATE=5e-5 -QGROUP=1 -EPOCH=18 -WARMUP_EPOCH=1 -#CONFIG=./config/ds_config_W1A8_Qgroup64_fp16.json # <=====================it's less stable -#CONFIG=./config/ds_config_W1or2A8_Qgroup64_fp16.json -CONFIG=./config/XTC/ds_config_W1A8_Qgroup1_fp32.json -SAVE_PATH=./out/XTC/W1A8_quantization -mkdir -p ${SAVE_PATH} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66664 \ - run_glue_no_trainer.py \ - --seed 42 \ - --distill_method ${STAGE} \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size 32 \ - --per_device_eval_batch_size 128 \ - --learning_rate $LRATE \ - --num_train_epochs ${EPOCH}\ - --num_warmup_epochs ${WARMUP_EPOCH} \ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} &>> ${SAVE_PATH}/train.log - -#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% users provide models %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# MODEL_BASE=/blob/users/xwu/compression/huggingface_models/bert_base_uncased ## or you could use bert-base-uncased -# TEACHER=/blob/users/xwu/compression/huggingface_models/bert-base-uncased-${TASK_NAME}/pytorch_model.bin -# STUDENT=${TEACHER} -# python -m torch.distributed.launch --nproc_per_node=1 \ -# --master_port 66667 \ -# run_glue_no_trainer_clean.py \ -# --seed 42 \ -# --distill_method ${STAGE} \ -# --model_name_or_path ${MODEL_BASE} \ -# --pretrained_dir_student ${STUDENT} \ -# --pretrained_dir_teacher ${TEACHER} \ -# --task_name $TASK_NAME \ -# --max_length 128 \ -# --pad_to_max_length \ -# --per_device_train_batch_size 32 \ -# --learning_rate 2e-5 \ -# --num_train_epochs 18 \ -# --num_warmup_epochs 1 \ -# --deepspeed_config ${CONFIG} --weight_bit 1 \ -# --deepspeed \ -# --save_best_model --clean_best_model \ -# --gradient_accumulation_steps 1 \ -# --output_dir ${SAVE_PATH} &>> ${SAVE_PATH}/train.log diff --git a/compression/bert/bash_script/ZeroQuant/zero_quant.sh b/compression/bert/bash_script/ZeroQuant/zero_quant.sh deleted file mode 100644 index 71c638e0f..000000000 --- a/compression/bert/bash_script/ZeroQuant/zero_quant.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%. run_jobs.sh (for mnli) - - -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -export CUDA_VISIBLE_DEVICES=0 -QGROUP=48 -EPOCH=0 -CONFIG=./config/ZeroQuant/ds_config_W8A8_Qgroup48_fp32.json -SAVE_PATH=./out/ZeroQuant/W8A8_quantization -mkdir -p ${SAVE_PATH} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66664 \ - run_glue_no_trainer.py \ - --seed 42 \ - --distill_method one_stage \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size 32 \ - --per_device_eval_batch_size 128 \ - --num_train_epochs ${EPOCH}\ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} &>> ${SAVE_PATH}/train.log - -#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% users provide models %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# MODEL_BASE=/blob/users/xwu/compression/huggingface_models/bert_base_uncased ## or you could use bert-base-uncased -# TEACHER=/blob/users/xwu/compression/huggingface_models/bert-base-uncased-${TASK_NAME}/pytorch_model.bin -# STUDENT=${TEACHER} -# python -m torch.distributed.launch --nproc_per_node=1 \ -# --master_port 66667 \ -# run_glue_no_trainer_clean.py \ -# --seed 42 \ -# --distill_method ${STAGE} \ -# --model_name_or_path ${MODEL_BASE} \ -# --pretrained_dir_student ${STUDENT} \ -# --pretrained_dir_teacher ${TEACHER} \ -# --task_name $TASK_NAME \ -# --max_length 128 \ -# --pad_to_max_length \ -# --per_device_train_batch_size 32 \ -# --learning_rate 2e-5 \ -# --num_train_epochs 18 \ -# --num_warmup_epochs 1 \ -# --deepspeed_config ${CONFIG} --weight_bit 1 \ -# --deepspeed \ -# --save_best_model --clean_best_model \ -# --gradient_accumulation_steps 1 \ -# --output_dir ${SAVE_PATH} &>> ${SAVE_PATH}/train.log diff --git a/compression/bert/bash_script/ZeroQuant/zero_quant_lkd.sh b/compression/bert/bash_script/ZeroQuant/zero_quant_lkd.sh deleted file mode 100644 index 528226952..000000000 --- a/compression/bert/bash_script/ZeroQuant/zero_quant_lkd.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash - -#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%. run_jobs.sh (for mnli) - - -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -export CUDA_VISIBLE_DEVICES=0 -QGROUP=48 -EPOCH=0 -CONFIG=./config/ZeroQuant/ds_config_W48A8_Qgroup48_lkd_fp32.json -SAVE_PATH=./out/ZeroQuant/W48A8_quantization -mkdir -p ${SAVE_PATH} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 10000 \ - run_glue_lkd.py \ - --seed 42 \ - --distill_method one_stage \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size 32 \ - --per_device_eval_batch_size 128 \ - --num_train_epochs ${EPOCH}\ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --max_train_steps 100 \ - --learning_rate 5e-6 \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} &>> ${SAVE_PATH}/train.log - -#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% users provide models %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# MODEL_BASE=/blob/users/xwu/compression/huggingface_models/bert_base_uncased ## or you could use bert-base-uncased -# TEACHER=/blob/users/xwu/compression/huggingface_models/bert-base-uncased-${TASK_NAME}/pytorch_model.bin -# STUDENT=${TEACHER} -# python -m torch.distributed.launch --nproc_per_node=1 \ -# --master_port 66667 \ -# run_glue_no_trainer_clean.py \ -# --seed 42 \ -# --distill_method ${STAGE} \ -# --model_name_or_path ${MODEL_BASE} \ -# --pretrained_dir_student ${STUDENT} \ -# --pretrained_dir_teacher ${TEACHER} \ -# --task_name $TASK_NAME \ -# --max_length 128 \ -# --pad_to_max_length \ -# --per_device_train_batch_size 32 \ -# --learning_rate 2e-5 \ -# --num_train_epochs 18 \ -# --num_warmup_epochs 1 \ -# --deepspeed_config ${CONFIG} --weight_bit 1 \ -# --deepspeed \ -# --save_best_model --clean_best_model \ -# --gradient_accumulation_steps 1 \ -# --output_dir ${SAVE_PATH} &>> ${SAVE_PATH}/train.log diff --git a/compression/bert/bash_script/layer_reduction.sh b/compression/bert/bash_script/layer_reduction.sh deleted file mode 100644 index 31e01b210..000000000 --- a/compression/bert/bash_script/layer_reduction.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash -DIR=`pwd` -export CUDA_VISIBLE_DEVICES=0 -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -STAGE=one_stage -LRATE=5e-5 -EPOCH=18 -WARMUP_EPOCH=1 -BATCH_SIZE_PER_GPU=32 -SAVE_PATH=./out/layer_reduction/ -mkdir -p ${SAVE_PATH} -###Layer Reduction -LAYER_REDUCTION_ENABLE="true" #<============================================================= -FP16_ENABLE="true" - -###weight quantization -WEIGHT_QUANT_ENABLE="false" -Q_GROUP=1 -W_BIT1=8 -W_BIT2=4 -###activation quantization -ACTIVATION_QUANT_ENABLE="false" -A_BIT1=4 -A_BIT2=8 -#############pruning -###sparse_pruning (unstructure pruning) -SPARSE_PRUNING_ENABLE="false" -S_DENSE_RATIO=0.6 -###row_pruning (unstructure pruning) -ROW_PRUNING_ENABLE="false" -R_DENSE_RATIO=0.6 -###HEAD_PRUNING_ENABLE -HEAD_PRUNING_ENABLE="false" -H_DENSE_RATIO=0.6 -NAME="layer_reduction" -template_json="config/ds_config_TEMPLATE.json" -config_json="config/ds_config_${NAME}.json" - -if [ "${FP16_ENABLE}" = "true" ]; then - QuantW_FORWARD="false" -else - QuantW_FORWARD="true" -fi -sed "s/LAYER_REDUCTION_ENABLE/${LAYER_REDUCTION_ENABLE}/" ${template_json} \ - | sed "s/WEIGHT_QUANT_ENABLE/${WEIGHT_QUANT_ENABLE}/" \ - | sed "s/Q_GROUP/${Q_GROUP}/" \ - | sed "s/W_BIT1/${W_BIT1}/" \ - | sed "s/W_BIT2/${W_BIT2}/" \ - | sed "s/ACTIVATION_QUANT_ENABLE/${ACTIVATION_QUANT_ENABLE}/" \ - | sed "s/A_BIT1/${A_BIT1}/" \ - | sed "s/A_BIT2/${A_BIT2}/" \ - | sed "s/SPARSE_PRUNING_ENABLE/${SPARSE_PRUNING_ENABLE}/" \ - | sed "s/S_DENSE_RATIO/${S_DENSE_RATIO}/" \ - | sed "s/ROW_PRUNING_ENABLE/${ROW_PRUNING_ENABLE}/" \ - | sed "s/R_DENSE_RATIO/${R_DENSE_RATIO}/" \ - | sed "s/HEAD_PRUNING_ENABLE/${HEAD_PRUNING_ENABLE}/" \ - | sed "s/H_DENSE_RATIO/${H_DENSE_RATIO}/" \ - | sed "s/FP16_ENABLE/${FP16_ENABLE}/" \ - | sed "s/QuantW_FORWARD/${QuantW_FORWARD}/" \ - | sed "s/BATCH_SIZE_PER_GPU/${BATCH_SIZE_PER_GPU}/" \ - > ${config_json} - -CONFIG=${config_json} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -run_cmd="python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66664 \ - run_glue_no_trainer.py \ - --seed 42 \ - --distill_method ${STAGE} \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size ${BATCH_SIZE_PER_GPU} \ - --per_device_eval_batch_size 128 \ - --learning_rate $LRATE \ - --num_train_epochs ${EPOCH}\ - --num_warmup_epochs ${WARMUP_EPOCH} \ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} | tee -a ${SAVE_PATH}/train.log" -echo ${config_json} -echo ${run_cmd} -eval ${run_cmd} -set +x \ No newline at end of file diff --git a/compression/bert/bash_script/pruning_head.sh b/compression/bert/bash_script/pruning_head.sh deleted file mode 100644 index 85b0eb900..000000000 --- a/compression/bert/bash_script/pruning_head.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash -DIR=`pwd` -export CUDA_VISIBLE_DEVICES=5 -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -STAGE=one_stage -LRATE=5e-5 -EPOCH=2 -WARMUP_EPOCH=1 -BATCH_SIZE_PER_GPU=32 -NAME="pruning_head" -SAVE_PATH=./out/${NAME}/ -mkdir -p ${SAVE_PATH} - -###Layer Reduction -LAYER_REDUCTION_ENABLE="false" -FP16_ENABLE="false" - -###weight quantization -WEIGHT_QUANT_ENABLE="false" -Q_GROUP=64 -W_BIT1=4 -W_BIT2=2 -###activation quantization -ACTIVATION_QUANT_ENABLE="false" -A_BIT1=8 -A_BIT2=4 -#############pruning -###sparse_pruning (unstructure pruning) -SPARSE_PRUNING_ENABLE="false" -S_DENSE_RATIO=0.6 -###row_pruning (unstructure pruning) -ROW_PRUNING_ENABLE="false" -R_DENSE_RATIO=0.6 -###HEAD_PRUNING_ENABLE -HEAD_PRUNING_ENABLE="true" #<============================================================= -H_DENSE_RATIO=0.6 #<============================================================= - -template_json="config/ds_config_TEMPLATE.json" -config_json="config/ds_config_${NAME}.json" - -if [ "${FP16_ENABLE}" = "true" ]; then - QuantW_FORWARD="false" -else - QuantW_FORWARD="true" -fi -sed "s/LAYER_REDUCTION_ENABLE/${LAYER_REDUCTION_ENABLE}/" ${template_json} \ - | sed "s/WEIGHT_QUANT_ENABLE/${WEIGHT_QUANT_ENABLE}/" \ - | sed "s/Q_GROUP/${Q_GROUP}/" \ - | sed "s/W_BIT1/${W_BIT1}/" \ - | sed "s/W_BIT2/${W_BIT2}/" \ - | sed "s/ACTIVATION_QUANT_ENABLE/${ACTIVATION_QUANT_ENABLE}/" \ - | sed "s/A_BIT1/${A_BIT1}/" \ - | sed "s/A_BIT2/${A_BIT2}/" \ - | sed "s/SPARSE_PRUNING_ENABLE/${SPARSE_PRUNING_ENABLE}/" \ - | sed "s/S_DENSE_RATIO/${S_DENSE_RATIO}/" \ - | sed "s/ROW_PRUNING_ENABLE/${ROW_PRUNING_ENABLE}/" \ - | sed "s/R_DENSE_RATIO/${R_DENSE_RATIO}/" \ - | sed "s/HEAD_PRUNING_ENABLE/${HEAD_PRUNING_ENABLE}/" \ - | sed "s/H_DENSE_RATIO/${H_DENSE_RATIO}/" \ - | sed "s/FP16_ENABLE/${FP16_ENABLE}/" \ - | sed "s/QuantW_FORWARD/${QuantW_FORWARD}/" \ - | sed "s/BATCH_SIZE_PER_GPU/${BATCH_SIZE_PER_GPU}/" \ - > ${config_json} - -CONFIG=${config_json} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -run_cmd="python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66670 \ - run_glue_no_trainer.py \ - --seed 42 \ - --distill_method ${STAGE} \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size ${BATCH_SIZE_PER_GPU} \ - --per_device_eval_batch_size 64 \ - --learning_rate $LRATE \ - --num_train_epochs ${EPOCH}\ - --num_warmup_epochs ${WARMUP_EPOCH} \ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} | tee -a ${SAVE_PATH}/train.log" - -echo ${run_cmd} -eval ${run_cmd} -set +x \ No newline at end of file diff --git a/compression/bert/bash_script/pruning_row.sh b/compression/bert/bash_script/pruning_row.sh deleted file mode 100644 index 8836b201b..000000000 --- a/compression/bert/bash_script/pruning_row.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash -DIR=`pwd` -export CUDA_VISIBLE_DEVICES=4 -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -STAGE=one_stage -LRATE=5e-5 -EPOCH=2 -WARMUP_EPOCH=1 -BATCH_SIZE_PER_GPU=32 -NAME="pruning_row" -SAVE_PATH=./out/${NAME}/ -mkdir -p ${SAVE_PATH} - -###Layer Reduction -LAYER_REDUCTION_ENABLE="false" -FP16_ENABLE="false" - -###weight quantization -WEIGHT_QUANT_ENABLE="false" -Q_GROUP=64 -W_BIT1=4 -W_BIT2=2 -###activation quantization -ACTIVATION_QUANT_ENABLE="false" -A_BIT1=8 -A_BIT2=4 -#############pruning -###sparse_pruning (unstructure pruning) -SPARSE_PRUNING_ENABLE="false" -S_DENSE_RATIO=0.6 -###row_pruning (unstructure pruning) -ROW_PRUNING_ENABLE="true" #<============================================================= -R_DENSE_RATIO=0.6 #<============================================================= -###HEAD_PRUNING_ENABLE -HEAD_PRUNING_ENABLE="false" -H_DENSE_RATIO=0.6 - -template_json="config/ds_config_TEMPLATE.json" -config_json="config/ds_config_${NAME}.json" - -if [ "${FP16_ENABLE}" = "true" ]; then - QuantW_FORWARD="false" -else - QuantW_FORWARD="true" -fi -sed "s/LAYER_REDUCTION_ENABLE/${LAYER_REDUCTION_ENABLE}/" ${template_json} \ - | sed "s/WEIGHT_QUANT_ENABLE/${WEIGHT_QUANT_ENABLE}/" \ - | sed "s/Q_GROUP/${Q_GROUP}/" \ - | sed "s/W_BIT1/${W_BIT1}/" \ - | sed "s/W_BIT2/${W_BIT2}/" \ - | sed "s/ACTIVATION_QUANT_ENABLE/${ACTIVATION_QUANT_ENABLE}/" \ - | sed "s/A_BIT1/${A_BIT1}/" \ - | sed "s/A_BIT2/${A_BIT2}/" \ - | sed "s/SPARSE_PRUNING_ENABLE/${SPARSE_PRUNING_ENABLE}/" \ - | sed "s/S_DENSE_RATIO/${S_DENSE_RATIO}/" \ - | sed "s/ROW_PRUNING_ENABLE/${ROW_PRUNING_ENABLE}/" \ - | sed "s/R_DENSE_RATIO/${R_DENSE_RATIO}/" \ - | sed "s/HEAD_PRUNING_ENABLE/${HEAD_PRUNING_ENABLE}/" \ - | sed "s/H_DENSE_RATIO/${H_DENSE_RATIO}/" \ - | sed "s/FP16_ENABLE/${FP16_ENABLE}/" \ - | sed "s/QuantW_FORWARD/${QuantW_FORWARD}/" \ - | sed "s/BATCH_SIZE_PER_GPU/${BATCH_SIZE_PER_GPU}/" \ - > ${config_json} - -CONFIG=${config_json} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -run_cmd="python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66669 \ - run_glue_no_trainer.py \ - --seed 42 \ - --distill_method ${STAGE} \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size ${BATCH_SIZE_PER_GPU} \ - --per_device_eval_batch_size 64 \ - --learning_rate $LRATE \ - --num_train_epochs ${EPOCH}\ - --num_warmup_epochs ${WARMUP_EPOCH} \ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} | tee -a ${SAVE_PATH}/train.log" - -echo ${run_cmd} -eval ${run_cmd} -set +x \ No newline at end of file diff --git a/compression/bert/bash_script/pruning_sparse.sh b/compression/bert/bash_script/pruning_sparse.sh deleted file mode 100644 index e6b916f52..000000000 --- a/compression/bert/bash_script/pruning_sparse.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash -DIR=`pwd` -export CUDA_VISIBLE_DEVICES=3 -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -STAGE=one_stage -LRATE=5e-5 -EPOCH=2 -WARMUP_EPOCH=1 -BATCH_SIZE_PER_GPU=32 -NAME="pruning_sparse" -SAVE_PATH=./out/${NAME}/ -mkdir -p ${SAVE_PATH} - -###Layer Reduction -LAYER_REDUCTION_ENABLE="false" -FP16_ENABLE="false" - -###weight quantization -WEIGHT_QUANT_ENABLE="false" -Q_GROUP=64 -W_BIT1=4 -W_BIT2=2 -###activation quantization -ACTIVATION_QUANT_ENABLE="false" -A_BIT1=8 -A_BIT2=4 -#############pruning -###sparse_pruning (unstructure pruning) -SPARSE_PRUNING_ENABLE="true" #<============================================================= -S_DENSE_RATIO=0.4 #<============================================================= -###row_pruning (unstructure pruning) -ROW_PRUNING_ENABLE="false" -R_DENSE_RATIO=0.6 -###HEAD_PRUNING_ENABLE -HEAD_PRUNING_ENABLE="false" -H_DENSE_RATIO=0.6 - -template_json="config/ds_config_TEMPLATE.json" -config_json="config/ds_config_${NAME}.json" - -if [ "${FP16_ENABLE}" = "true" ]; then - QuantW_FORWARD="false" -else - QuantW_FORWARD="true" -fi -sed "s/LAYER_REDUCTION_ENABLE/${LAYER_REDUCTION_ENABLE}/" ${template_json} \ - | sed "s/WEIGHT_QUANT_ENABLE/${WEIGHT_QUANT_ENABLE}/" \ - | sed "s/Q_GROUP/${Q_GROUP}/" \ - | sed "s/W_BIT1/${W_BIT1}/" \ - | sed "s/W_BIT2/${W_BIT2}/" \ - | sed "s/ACTIVATION_QUANT_ENABLE/${ACTIVATION_QUANT_ENABLE}/" \ - | sed "s/A_BIT1/${A_BIT1}/" \ - | sed "s/A_BIT2/${A_BIT2}/" \ - | sed "s/SPARSE_PRUNING_ENABLE/${SPARSE_PRUNING_ENABLE}/" \ - | sed "s/S_DENSE_RATIO/${S_DENSE_RATIO}/" \ - | sed "s/ROW_PRUNING_ENABLE/${ROW_PRUNING_ENABLE}/" \ - | sed "s/R_DENSE_RATIO/${R_DENSE_RATIO}/" \ - | sed "s/HEAD_PRUNING_ENABLE/${HEAD_PRUNING_ENABLE}/" \ - | sed "s/H_DENSE_RATIO/${H_DENSE_RATIO}/" \ - | sed "s/FP16_ENABLE/${FP16_ENABLE}/" \ - | sed "s/QuantW_FORWARD/${QuantW_FORWARD}/" \ - | sed "s/BATCH_SIZE_PER_GPU/${BATCH_SIZE_PER_GPU}/" \ - > ${config_json} - -CONFIG=${config_json} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -run_cmd="python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66668 \ - run_glue_no_trainer.py \ - --seed 42 \ - --distill_method ${STAGE} \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size ${BATCH_SIZE_PER_GPU} \ - --per_device_eval_batch_size 64 \ - --learning_rate $LRATE \ - --num_train_epochs ${EPOCH}\ - --num_warmup_epochs ${WARMUP_EPOCH} \ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} | tee -a ${SAVE_PATH}/train.log" - -echo ${run_cmd} -eval ${run_cmd} -set +x \ No newline at end of file diff --git a/compression/bert/bash_script/pruning_sparse_snip_momentum.sh b/compression/bert/bash_script/pruning_sparse_snip_momentum.sh deleted file mode 100644 index f37cdb614..000000000 --- a/compression/bert/bash_script/pruning_sparse_snip_momentum.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash -DIR=`pwd` -export CUDA_VISIBLE_DEVICES=0 -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -STAGE=one_stage -LRATE=5e-5 -EPOCH=10 -WARMUP_EPOCH=1 -BATCH_SIZE_PER_GPU=32 -NAME="pruning_sparse" -SAVE_PATH=./out/${NAME}/ -mkdir -p ${SAVE_PATH} - -###Layer Reduction -LAYER_REDUCTION_ENABLE="false" -FP16_ENABLE="false" - -###weight quantization -WEIGHT_QUANT_ENABLE="false" -Q_GROUP=64 -W_BIT1=4 -W_BIT2=2 -###activation quantization -ACTIVATION_QUANT_ENABLE="false" -A_BIT1=8 -A_BIT2=4 -#############pruning -###sparse_pruning (structural pruning) -SPARSE_PRUNING_ENABLE="true" #<============================================================= -SPARSE_PRUNING_BLOCK_PATTERN="\"4x1\"" -SPARSE_PRUNING_OFFSET_STRIDE=1000 -SPARSE_PRUNING_OFFSET=1000 -SPARSE_PRUNING_OFFSET_END=51000 -SPARSE_PRUNING_EXCLUDED_MODULES="[\"classifier\", \"pooler\"]" -S_DENSE_RATIO=0.2 #<============================================================= -###row_pruning (unstructure pruning) -ROW_PRUNING_ENABLE="false" -R_DENSE_RATIO=0.6 -###HEAD_PRUNING_ENABLE -HEAD_PRUNING_ENABLE="false" -H_DENSE_RATIO=0.6 - -template_json="config/ds_config_structural_pruning_TEMPLATE.json" -config_json="config/ds_config_structural_${NAME}.json" - - -if [ "${FP16_ENABLE}" = "true" ]; then - QuantW_FORWARD="false" -else - QuantW_FORWARD="true" -fi -sed "s/LAYER_REDUCTION_ENABLE/${LAYER_REDUCTION_ENABLE}/" ${template_json} \ - | sed "s/WEIGHT_QUANT_ENABLE/${WEIGHT_QUANT_ENABLE}/" \ - | sed "s/Q_GROUP/${Q_GROUP}/" \ - | sed "s/W_BIT1/${W_BIT1}/" \ - | sed "s/W_BIT2/${W_BIT2}/" \ - | sed "s/ACTIVATION_QUANT_ENABLE/${ACTIVATION_QUANT_ENABLE}/" \ - | sed "s/A_BIT1/${A_BIT1}/" \ - | sed "s/A_BIT2/${A_BIT2}/" \ - | sed "s/SPARSE_PRUNING_ENABLE/${SPARSE_PRUNING_ENABLE}/" \ - | sed "s/SPARSE_PRUNING_BLOCK_PATTERN/${SPARSE_PRUNING_BLOCK_PATTERN}/" \ - | sed "s/SPARSE_PRUNING_OFFSET_STRIDE/${SPARSE_PRUNING_OFFSET_STRIDE}/" \ - | sed "s/SPARSE_PRUNING_OFFSET_END/${SPARSE_PRUNING_OFFSET_END}/" \ - | sed "s/SPARSE_PRUNING_OFFSET/${SPARSE_PRUNING_OFFSET}/" \ - | sed "s/SPARSE_PRUNING_EXCLUDED_MODULES/${SPARSE_PRUNING_EXCLUDED_MODULES}/" \ - | sed "s/S_DENSE_RATIO/${S_DENSE_RATIO}/" \ - | sed "s/ROW_PRUNING_ENABLE/${ROW_PRUNING_ENABLE}/" \ - | sed "s/R_DENSE_RATIO/${R_DENSE_RATIO}/" \ - | sed "s/HEAD_PRUNING_ENABLE/${HEAD_PRUNING_ENABLE}/" \ - | sed "s/H_DENSE_RATIO/${H_DENSE_RATIO}/" \ - | sed "s/FP16_ENABLE/${FP16_ENABLE}/" \ - | sed "s/QuantW_FORWARD/${QuantW_FORWARD}/" \ - | sed "s/BATCH_SIZE_PER_GPU/${BATCH_SIZE_PER_GPU}/" \ - > ${config_json} - -CONFIG=${config_json} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -run_cmd="python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 6618 \ - run_glue_no_trainer.py \ - --seed 42 \ - --distill_method ${STAGE} \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size ${BATCH_SIZE_PER_GPU} \ - --per_device_eval_batch_size 64 \ - --learning_rate $LRATE \ - --num_train_epochs ${EPOCH}\ - --num_warmup_epochs ${WARMUP_EPOCH} \ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} | tee -a ${SAVE_PATH}/train.log" - -echo ${run_cmd} -eval ${run_cmd} -set +x diff --git a/compression/bert/bash_script/quant_activation.sh b/compression/bert/bash_script/quant_activation.sh deleted file mode 100644 index 9f308cd4c..000000000 --- a/compression/bert/bash_script/quant_activation.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash -DIR=`pwd` -export CUDA_VISIBLE_DEVICES=2 -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -STAGE=one_stage -LRATE=5e-5 -EPOCH=2 -WARMUP_EPOCH=1 -BATCH_SIZE_PER_GPU=32 -NAME="quant_activation" -SAVE_PATH=./out/${NAME} -mkdir -p ${SAVE_PATH} - -###Layer Reduction -LAYER_REDUCTION_ENABLE="false" -FP16_ENABLE="false" - -###weight quantization -WEIGHT_QUANT_ENABLE="false" -Q_GROUP=64 -W_BIT1=4 -W_BIT2=2 -###activation quantization -ACTIVATION_QUANT_ENABLE="true" #<============================================================= -A_BIT1=8 #<============================================================= -A_BIT2=4 #<============================================================= -#############pruning -###sparse_pruning (unstructure pruning) -SPARSE_PRUNING_ENABLE="false" -S_DENSE_RATIO=0.6 -###row_pruning (unstructure pruning) -ROW_PRUNING_ENABLE="false" -R_DENSE_RATIO=0.6 -###HEAD_PRUNING_ENABLE -HEAD_PRUNING_ENABLE="false" -H_DENSE_RATIO=0.6 - -template_json="config/ds_config_TEMPLATE.json" -config_json="config/ds_config_${NAME}.json" - -if [ "${FP16_ENABLE}" = "true" ]; then - QuantW_FORWARD="false" -else - QuantW_FORWARD="true" -fi -sed "s/LAYER_REDUCTION_ENABLE/${LAYER_REDUCTION_ENABLE}/" ${template_json} \ - | sed "s/WEIGHT_QUANT_ENABLE/${WEIGHT_QUANT_ENABLE}/" \ - | sed "s/Q_GROUP/${Q_GROUP}/" \ - | sed "s/W_BIT1/${W_BIT1}/" \ - | sed "s/W_BIT2/${W_BIT2}/" \ - | sed "s/ACTIVATION_QUANT_ENABLE/${ACTIVATION_QUANT_ENABLE}/" \ - | sed "s/A_BIT1/${A_BIT1}/" \ - | sed "s/A_BIT2/${A_BIT2}/" \ - | sed "s/SPARSE_PRUNING_ENABLE/${SPARSE_PRUNING_ENABLE}/" \ - | sed "s/S_DENSE_RATIO/${S_DENSE_RATIO}/" \ - | sed "s/ROW_PRUNING_ENABLE/${ROW_PRUNING_ENABLE}/" \ - | sed "s/R_DENSE_RATIO/${R_DENSE_RATIO}/" \ - | sed "s/HEAD_PRUNING_ENABLE/${HEAD_PRUNING_ENABLE}/" \ - | sed "s/H_DENSE_RATIO/${H_DENSE_RATIO}/" \ - | sed "s/FP16_ENABLE/${FP16_ENABLE}/" \ - | sed "s/QuantW_FORWARD/${QuantW_FORWARD}/" \ - | sed "s/BATCH_SIZE_PER_GPU/${BATCH_SIZE_PER_GPU}/" \ - > ${config_json} - -CONFIG=${config_json} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -run_cmd="python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66666 \ - run_glue_no_trainer.py \ - --seed 42 \ - --distill_method ${STAGE} \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size ${BATCH_SIZE_PER_GPU} \ - --per_device_eval_batch_size 64 \ - --learning_rate $LRATE \ - --num_train_epochs ${EPOCH}\ - --num_warmup_epochs ${WARMUP_EPOCH} \ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} | tee -a ${SAVE_PATH}/train.log" - -echo ${run_cmd} -eval ${run_cmd} -set +x \ No newline at end of file diff --git a/compression/bert/bash_script/quant_weight.sh b/compression/bert/bash_script/quant_weight.sh deleted file mode 100644 index e08311d26..000000000 --- a/compression/bert/bash_script/quant_weight.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash -DIR=`pwd` -export CUDA_VISIBLE_DEVICES=1 -TASK_NAME=mnli #mnli sst2 stsb mnli qqp rte cola mrpc qnli -STAGE=one_stage -LRATE=5e-5 -EPOCH=9 -WARMUP_EPOCH=1 -BATCH_SIZE_PER_GPU=32 -NAME="quant_weight" -SAVE_PATH=./out/${NAME}/ -mkdir -p ${SAVE_PATH} - -###Layer Reduction -LAYER_REDUCTION_ENABLE="false" -FP16_ENABLE="false" - -###weight quantization -WEIGHT_QUANT_ENABLE="true" #<============================================================= -Q_GROUP=64 #<============================================================= -W_BIT1=4 #<============================================================= -W_BIT2=2 #<============================================================= -###activation quantization -ACTIVATION_QUANT_ENABLE="false" -A_BIT1=8 -A_BIT2=4 -#############pruning -###sparse_pruning (unstructure pruning) -SPARSE_PRUNING_ENABLE="false" -S_DENSE_RATIO=0.6 -###row_pruning (unstructure pruning) -ROW_PRUNING_ENABLE="false" -R_DENSE_RATIO=0.6 -###HEAD_PRUNING_ENABLE -HEAD_PRUNING_ENABLE="false" -H_DENSE_RATIO=0.6 - -template_json="config/ds_config_TEMPLATE.json" -config_json="config/ds_config_${NAME}.json" - -if [ "${FP16_ENABLE}" = "true" ]; then - QuantW_FORWARD="false" -else - QuantW_FORWARD="true" -fi -sed "s/LAYER_REDUCTION_ENABLE/${LAYER_REDUCTION_ENABLE}/" ${template_json} \ - | sed "s/WEIGHT_QUANT_ENABLE/${WEIGHT_QUANT_ENABLE}/" \ - | sed "s/Q_GROUP/${Q_GROUP}/" \ - | sed "s/W_BIT1/${W_BIT1}/" \ - | sed "s/W_BIT2/${W_BIT2}/" \ - | sed "s/ACTIVATION_QUANT_ENABLE/${ACTIVATION_QUANT_ENABLE}/" \ - | sed "s/A_BIT1/${A_BIT1}/" \ - | sed "s/A_BIT2/${A_BIT2}/" \ - | sed "s/SPARSE_PRUNING_ENABLE/${SPARSE_PRUNING_ENABLE}/" \ - | sed "s/S_DENSE_RATIO/${S_DENSE_RATIO}/" \ - | sed "s/ROW_PRUNING_ENABLE/${ROW_PRUNING_ENABLE}/" \ - | sed "s/R_DENSE_RATIO/${R_DENSE_RATIO}/" \ - | sed "s/HEAD_PRUNING_ENABLE/${HEAD_PRUNING_ENABLE}/" \ - | sed "s/H_DENSE_RATIO/${H_DENSE_RATIO}/" \ - | sed "s/FP16_ENABLE/${FP16_ENABLE}/" \ - | sed "s/QuantW_FORWARD/${QuantW_FORWARD}/" \ - | sed "s/BATCH_SIZE_PER_GPU/${BATCH_SIZE_PER_GPU}/" > ${config_json} - -CONFIG=${config_json} -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if users provide *NO* models, use the following script %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% the following command will first download huggingface models and then compress %%%%%%% -MODEL=yoshitomo-matsubara/bert-base-uncased-${TASK_NAME} ## for both student and teacher -run_cmd="python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66665 \ - run_glue_no_trainer.py \ - --seed 42 \ - --distill_method ${STAGE} \ - --model_name_or_path ${MODEL} \ - --task_name $TASK_NAME \ - --max_length 128 \ - --pad_to_max_length \ - --per_device_train_batch_size ${BATCH_SIZE_PER_GPU} \ - --per_device_eval_batch_size 64 \ - --learning_rate $LRATE \ - --num_train_epochs ${EPOCH}\ - --num_warmup_epochs ${WARMUP_EPOCH} \ - --eval_step 1000 \ - --deepspeed_config ${CONFIG} \ - --deepspeed \ - --save_best_model --clean_best_model \ - --gradient_accumulation_steps 1 \ - --output_dir ${SAVE_PATH} | tee -a ${SAVE_PATH}/train.log" - -echo ${run_cmd} -eval ${run_cmd} -set +x \ No newline at end of file diff --git a/compression/bert/config/XTC/ds_config_W1A8_Qgroup1_fp32.json b/compression/bert/config/XTC/ds_config_W1A8_Qgroup1_fp32.json deleted file mode 100644 index e3d1c5304..000000000 --- a/compression/bert/config/XTC/ds_config_W1A8_Qgroup1_fp32.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": false - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": false, - "keep_number_layer": 5, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 2, - 4, - 6, - 8, - 10 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 1, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": true, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": 1, - "target_bits": 1, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "intermediate", - "word_embeddings", - "output.dense" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attention.self", - "intermediate", - "output.dense" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "l1" - }, - "different_groups": { - "sp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.self" - ] - } - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } - } diff --git a/compression/bert/config/XTC/ds_config_layer_reduction_W1Q8_fp32.json b/compression/bert/config/XTC/ds_config_layer_reduction_W1Q8_fp32.json deleted file mode 100644 index 5ebd2851c..000000000 --- a/compression/bert/config/XTC/ds_config_layer_reduction_W1Q8_fp32.json +++ /dev/null @@ -1,149 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": false - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": true, - "keep_number_layer": 6, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 1, - 3, - 5, - 7, - 9, - 11 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 1, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": true, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": 1, - "target_bits": 1, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "intermediate", - "word_embeddings", - "output.dense" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attention.self", - "intermediate", - "output.dense" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "l1" - }, - "different_groups": { - "sp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.self" - ] - } - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } - } diff --git a/compression/bert/config/XTC/ds_config_layer_reduction_fp16.json b/compression/bert/config/XTC/ds_config_layer_reduction_fp16.json deleted file mode 100644 index a8083d8ad..000000000 --- a/compression/bert/config/XTC/ds_config_layer_reduction_fp16.json +++ /dev/null @@ -1,149 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": false - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": true, - "keep_number_layer": 6, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 1, - 3, - 5, - 7, - 9, - 11 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": false, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 1, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": true, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": 1, - "target_bits": 1, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "intermediate", - "word_embeddings", - "output.dense" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": false, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attention.self", - "intermediate", - "output.dense" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "l1" - }, - "different_groups": { - "sp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.self" - ] - } - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } - } diff --git a/compression/bert/config/ZeroQuant/ds_config_W48A8_Qgroup48_lkd_fp32.json b/compression/bert/config/ZeroQuant/ds_config_W48A8_Qgroup48_lkd_fp32.json deleted file mode 100644 index c6a95cac5..000000000 --- a/compression/bert/config/ZeroQuant/ds_config_W48A8_Qgroup48_lkd_fp32.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": false - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": false, - "keep_number_layer": 5, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 2, - 4, - 6, - 8, - 10 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 48, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": true, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": 8, - "target_bits": 8, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "attention.output.dense" - ] - }, - "wq2": { - "params": { - "start_bits": 4, - "target_bits": 4, - "quantization_period": 0 - }, - "modules": [ - "intermediate", - "layer.\\w+.output.dense" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attention.self", - "attention.output.dense" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "l1" - }, - "different_groups": { - "sp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.self" - ] - } - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } - } diff --git a/compression/bert/config/ZeroQuant/ds_config_W8A8_Qgroup48_fp32.json b/compression/bert/config/ZeroQuant/ds_config_W8A8_Qgroup48_fp32.json deleted file mode 100644 index bb72a2d4c..000000000 --- a/compression/bert/config/ZeroQuant/ds_config_W8A8_Qgroup48_fp32.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": false - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": false, - "keep_number_layer": 5, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 2, - 4, - 6, - 8, - 10 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 48, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": true, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": 8, - "target_bits": 8, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "intermediate", - "word_embeddings", - "output.dense" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attention.self", - "intermediate", - "output.dense" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "l1" - }, - "different_groups": { - "sp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.self" - ] - } - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } - } diff --git a/compression/bert/config/ds_config.json b/compression/bert/config/ds_config.json deleted file mode 100644 index 8ef662684..000000000 --- a/compression/bert/config/ds_config.json +++ /dev/null @@ -1,155 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": true - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": false, - "keep_number_layer": 5, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 2, - 4, - 6, - 8, - 10 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": false, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 1, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": true, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": 1, - "target_bits": 1, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "intermediate", - "word_embeddings" - ] - }, - "wq2": { - "params": { - "start_bits": 1, - "target_bits": 1, - "quantization_period": 0 - }, - "modules": [ - "output.dense" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": false, - "quantization_type": "asymmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "bert.encoder" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "l1" - }, - "different_groups": { - "sp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.self" - ] - } - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } - } diff --git a/compression/bert/config/ds_config_TEMPLATE.json b/compression/bert/config/ds_config_TEMPLATE.json deleted file mode 100644 index 7eb519552..000000000 --- a/compression/bert/config/ds_config_TEMPLATE.json +++ /dev/null @@ -1,166 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": BATCH_SIZE_PER_GPU, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": FP16_ENABLE - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": LAYER_REDUCTION_ENABLE, - "keep_number_layer": 5, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 2, - 4, - 6, - 8, - 10 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": WEIGHT_QUANT_ENABLE, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": Q_GROUP, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": QuantW_FORWARD, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": W_BIT1, - "target_bits": W_BIT1, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "word_embeddings" - ] - }, - "wq2": { - "params": { - "start_bits": W_BIT2, - "target_bits": W_BIT2, - "quantization_period": 0 - }, - "modules": [ - "output.dense", - "intermediate" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": ACTIVATION_QUANT_ENABLE, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": A_BIT1 - }, - "modules": [ - "attention.self" - ] - }, - "aq2": { - "params": { - "bits": A_BIT2 - }, - "modules": [ - "output.dense", - "intermediate" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": SPARSE_PRUNING_ENABLE, - "schedule_offset": 2000, - "method": "l1" - }, - "different_groups": { - "sp1": { - "params": { - "dense_ratio": S_DENSE_RATIO - }, - "modules": [ - "attention.self", - "output.dense", - "intermediate" - ] - } - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": ROW_PRUNING_ENABLE, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": R_DENSE_RATIO - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": HEAD_PRUNING_ENABLE, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": H_DENSE_RATIO - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } - } diff --git a/compression/bert/config/ds_config_W1A8_Qgroup64_fp16.json b/compression/bert/config/ds_config_W1A8_Qgroup64_fp16.json deleted file mode 100644 index 0ba863abb..000000000 --- a/compression/bert/config/ds_config_W1A8_Qgroup64_fp16.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": true - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": false, - "keep_number_layer": 5, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 2, - 4, - 6, - 8, - 10 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 64, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": false, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": 1, - "target_bits": 1, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "intermediate", - "word_embeddings", - "output.dense" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attention.self", - "intermediate", - "output.dense" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "l1" - }, - "different_groups": { - "sp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.self" - ] - } - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } -} diff --git a/compression/bert/config/ds_config_W1A8_Qgroup64_fp32.json b/compression/bert/config/ds_config_W1A8_Qgroup64_fp32.json deleted file mode 100644 index 39976eed9..000000000 --- a/compression/bert/config/ds_config_W1A8_Qgroup64_fp32.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": false - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": false, - "keep_number_layer": 5, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 2, - 4, - 6, - 8, - 10 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 64, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": true, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": 1, - "target_bits": 1, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "intermediate", - "word_embeddings", - "output.dense" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attention.self", - "intermediate", - "output.dense" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "l1" - }, - "different_groups": { - "sp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.self" - ] - } - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } - } diff --git a/compression/bert/config/ds_config_W1or2A8_Qgroup64_fp16.json b/compression/bert/config/ds_config_W1or2A8_Qgroup64_fp16.json deleted file mode 100644 index 9b301326d..000000000 --- a/compression/bert/config/ds_config_W1or2A8_Qgroup64_fp16.json +++ /dev/null @@ -1,157 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": true - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": false, - "keep_number_layer": 5, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 2, - 4, - 6, - 8, - 10 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 64, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": false, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": 1, - "target_bits": 1, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "intermediate", - "word_embeddings" - ] - }, - "wq2": { - "params": { - "start_bits": 2, - "target_bits": 2, - "quantization_period": 0 - }, - "modules": [ - "output.dense" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attention.self", - "intermediate", - "output.dense" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "l1" - }, - "different_groups": { - "sp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.self" - ] - } - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": false, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } -} diff --git a/compression/bert/config/ds_config_structural_pruning_TEMPLATE.json b/compression/bert/config/ds_config_structural_pruning_TEMPLATE.json deleted file mode 100644 index f2218f144..000000000 --- a/compression/bert/config/ds_config_structural_pruning_TEMPLATE.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "train_batch_size": 32, - "train_micro_batch_size_per_gpu": BATCH_SIZE_PER_GPU, - "steps_per_print": 200, - "zero_optimization": { - "stage": 0 - }, - "fp16": { - "enabled": FP16_ENABLE - }, - "gradient_clipping": 1.0, - "prescale_gradients": true, - "wall_clock_breakdown": false, - "compression_training": { - "layer_reduction": { - "enabled": LAYER_REDUCTION_ENABLE, - "keep_number_layer": 5, - "module_name_prefix": "bert.encoder.layer", - "teacher_layer": [ - 2, - 4, - 6, - 8, - 10 - ], - "other_module_name": [ - "bert.pooler", - "bert.embeddings", - "classifier" - ] - }, - "weight_quantization": { - "shared_parameters": { - "enabled": WEIGHT_QUANT_ENABLE, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": Q_GROUP, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": QuantW_FORWARD, - "rounding": "nearest", - "fp16_mixed_quantize": { - "enabled": false, - "quantize_change_ratio": 0.1 - } - }, - "different_groups": { - "wq1": { - "params": { - "start_bits": W_BIT1, - "target_bits": W_BIT1, - "quantization_period": 0 - }, - "modules": [ - "attention.self", - "word_embeddings" - ] - }, - "wq2": { - "params": { - "start_bits": W_BIT2, - "target_bits": W_BIT2, - "quantization_period": 0 - }, - "modules": [ - "output.dense", - "intermediate" - ] - } - } - }, - "activation_quantization": { - "shared_parameters": { - "enabled": ACTIVATION_QUANT_ENABLE, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups": { - "aq1": { - "params": { - "bits": A_BIT1 - }, - "modules": [ - "attention.self" - ] - }, - "aq2": { - "params": { - "bits": A_BIT2 - }, - "modules": [ - "output.dense", - "intermediate" - ] - } - } - }, - "sparse_pruning": { - "shared_parameters": { - "enabled": SPARSE_PRUNING_ENABLE, - "schedule_offset": SPARSE_PRUNING_OFFSET, - "schedule_offset_end": SPARSE_PRUNING_OFFSET_END, - "schedule_offset_stride": SPARSE_PRUNING_OFFSET_STRIDE, - "method": "snip_momentum", - "block_pattern": SPARSE_PRUNING_BLOCK_PATTERN, - "dense_ratio": S_DENSE_RATIO, - "excluded_modules": SPARSE_PRUNING_EXCLUDED_MODULES - }, - "different_groups": { - } - }, - "row_pruning": { - "shared_parameters": { - "enabled": ROW_PRUNING_ENABLE, - "schedule_offset": 2000, - "method": "topk" - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": R_DENSE_RATIO - }, - "modules": [ - "intermediate.dense" - ], - "related_modules": [ - [ - "layer.\\w+.output.dense" - ] - ] - } - } - }, - "head_pruning": { - "shared_parameters": { - "enabled": HEAD_PRUNING_ENABLE, - "schedule_offset": 2000, - "method": "topk", - "num_heads": 12 - }, - "different_groups": { - "rp1": { - "params": { - "dense_ratio": H_DENSE_RATIO - }, - "modules": [ - "attention.output.dense" - ], - "related_modules": [ - [ - "self.query", - "self.key", - "self.value" - ] - ] - } - } - } - } - } diff --git a/compression/bert/huggingface_transformer/modeling_bert.py b/compression/bert/huggingface_transformer/modeling_bert.py deleted file mode 100644 index 51cca53b6..000000000 --- a/compression/bert/huggingface_transformer/modeling_bert.py +++ /dev/null @@ -1,1886 +0,0 @@ -# coding=utf-8 -# Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team. -# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""PyTorch BERT model. """ - - -import math -import os -import warnings -from dataclasses import dataclass -from typing import Optional, Tuple - -import torch -import torch.utils.checkpoint -from packaging import version -from torch import nn -from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss - -import transformers -from transformers.activations import ACT2FN -from transformers.file_utils import ( - ModelOutput, - add_code_sample_docstrings, - add_start_docstrings, - add_start_docstrings_to_model_forward, - replace_return_docstrings, -) -from transformers.modeling_outputs import ( - BaseModelOutputWithPastAndCrossAttentions, - BaseModelOutputWithPoolingAndCrossAttentions, - CausalLMOutputWithCrossAttentions, - MaskedLMOutput, - MultipleChoiceModelOutput, - NextSentencePredictorOutput, - QuestionAnsweringModelOutput, - SequenceClassifierOutput, - TokenClassifierOutput, -) -from transformers.modeling_utils import ( - PreTrainedModel, - apply_chunking_to_forward, - find_pruneable_heads_and_indices, - prune_linear_layer, -) -from transformers.utils import logging -from transformers.models.bert.configuration_bert import BertConfig - - -logger = logging.get_logger(__name__) - -_CHECKPOINT_FOR_DOC = "bert-base-uncased" -_CONFIG_FOR_DOC = "BertConfig" -_TOKENIZER_FOR_DOC = "BertTokenizer" - -BERT_PRETRAINED_MODEL_ARCHIVE_LIST = [ - "bert-base-uncased", - "bert-large-uncased", - "bert-base-cased", - "bert-large-cased", - "bert-base-multilingual-uncased", - "bert-base-multilingual-cased", - "bert-base-chinese", - "bert-base-german-cased", - "bert-large-uncased-whole-word-masking", - "bert-large-cased-whole-word-masking", - "bert-large-uncased-whole-word-masking-finetuned-squad", - "bert-large-cased-whole-word-masking-finetuned-squad", - "bert-base-cased-finetuned-mrpc", - "bert-base-german-dbmdz-cased", - "bert-base-german-dbmdz-uncased", - "cl-tohoku/bert-base-japanese", - "cl-tohoku/bert-base-japanese-whole-word-masking", - "cl-tohoku/bert-base-japanese-char", - "cl-tohoku/bert-base-japanese-char-whole-word-masking", - "TurkuNLP/bert-base-finnish-cased-v1", - "TurkuNLP/bert-base-finnish-uncased-v1", - "wietsedv/bert-base-dutch-cased", - # See all BERT models at https://huggingface.co/models?filter=bert -] - - -def load_tf_weights_in_bert(model, config, tf_checkpoint_path): - """Load tf checkpoints in a pytorch model.""" - try: - import re - - import numpy as np - import tensorflow as tf - except ImportError: - logger.error( - "Loading a TensorFlow model in PyTorch, requires TensorFlow to be installed. Please see " - "https://www.tensorflow.org/install/ for installation instructions." - ) - raise - tf_path = os.path.abspath(tf_checkpoint_path) - logger.info(f"Converting TensorFlow checkpoint from {tf_path}") - # Load weights from TF model - init_vars = tf.train.list_variables(tf_path) - names = [] - arrays = [] - for name, shape in init_vars: - logger.info(f"Loading TF weight {name} with shape {shape}") - array = tf.train.load_variable(tf_path, name) - names.append(name) - arrays.append(array) - - for name, array in zip(names, arrays): - name = name.split("/") - # adam_v and adam_m are variables used in AdamWeightDecayOptimizer to calculated m and v - # which are not required for using pretrained model - if any( - n in ["adam_v", "adam_m", "AdamWeightDecayOptimizer", "AdamWeightDecayOptimizer_1", "global_step"] - for n in name - ): - logger.info(f"Skipping {'/'.join(name)}") - continue - pointer = model - for m_name in name: - if re.fullmatch(r"[A-Za-z]+_\d+", m_name): - scope_names = re.split(r"_(\d+)", m_name) - else: - scope_names = [m_name] - if scope_names[0] == "kernel" or scope_names[0] == "gamma": - pointer = getattr(pointer, "weight") - elif scope_names[0] == "output_bias" or scope_names[0] == "beta": - pointer = getattr(pointer, "bias") - elif scope_names[0] == "output_weights": - pointer = getattr(pointer, "weight") - elif scope_names[0] == "squad": - pointer = getattr(pointer, "classifier") - else: - try: - pointer = getattr(pointer, scope_names[0]) - except AttributeError: - logger.info(f"Skipping {'/'.join(name)}") - continue - if len(scope_names) >= 2: - num = int(scope_names[1]) - pointer = pointer[num] - if m_name[-11:] == "_embeddings": - pointer = getattr(pointer, "weight") - elif m_name == "kernel": - array = np.transpose(array) - try: - if pointer.shape != array.shape: - raise ValueError(f"Pointer shape {pointer.shape} and array shape {array.shape} mismatched") - except AssertionError as e: - e.args += (pointer.shape, array.shape) - raise - logger.info(f"Initialize PyTorch weight {name}") - pointer.data = torch.from_numpy(array) - return model - - -class BertEmbeddings(nn.Module): - """Construct the embeddings from word, position and token_type embeddings.""" - - def __init__(self, config): - super().__init__() - self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id) - self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size) - self.token_type_embeddings = nn.Embedding(config.type_vocab_size, config.hidden_size) - - # self.LayerNorm is not snake-cased to stick with TensorFlow model variable name and be able to load - # any TensorFlow checkpoint file - self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps) - self.dropout = nn.Dropout(config.hidden_dropout_prob) - # position_ids (1, len position emb) is contiguous in memory and exported when serialized - self.position_embedding_type = getattr(config, "position_embedding_type", "absolute") - self.register_buffer("position_ids", torch.arange(config.max_position_embeddings).expand((1, -1))) - if version.parse(torch.__version__) > version.parse("1.6.0"): - self.register_buffer( - "token_type_ids", - torch.zeros(self.position_ids.size(), dtype=torch.long), - persistent=False, - ) - - def forward( - self, input_ids=None, token_type_ids=None, position_ids=None, inputs_embeds=None, past_key_values_length=0 - ): - if input_ids is not None: - input_shape = input_ids.size() - else: - input_shape = inputs_embeds.size()[:-1] - - seq_length = input_shape[1] - - if position_ids is None: - position_ids = self.position_ids[:, past_key_values_length : seq_length + past_key_values_length] - - # Setting the token_type_ids to the registered buffer in constructor where it is all zeros, which usually occurs - # when its auto-generated, registered buffer helps users when tracing the model without passing token_type_ids, solves - # issue #5664 - if token_type_ids is None: - if hasattr(self, "token_type_ids"): - buffered_token_type_ids = self.token_type_ids[:, :seq_length] - buffered_token_type_ids_expanded = buffered_token_type_ids.expand(input_shape[0], seq_length) - token_type_ids = buffered_token_type_ids_expanded - else: - token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=self.position_ids.device) - - if inputs_embeds is None: - inputs_embeds = self.word_embeddings(input_ids) - token_type_embeddings = self.token_type_embeddings(token_type_ids) - - embeddings = inputs_embeds + token_type_embeddings - if self.position_embedding_type == "absolute": - position_embeddings = self.position_embeddings(position_ids) - embeddings += position_embeddings - embeddings = self.LayerNorm(embeddings) - embeddings = self.dropout(embeddings) - return embeddings - - -class BertSelfAttention(nn.Module): - def __init__(self, config, position_embedding_type=None): - super().__init__() - if config.hidden_size % config.num_attention_heads != 0 and not hasattr(config, "embedding_size"): - raise ValueError( - f"The hidden size ({config.hidden_size}) is not a multiple of the number of attention " - f"heads ({config.num_attention_heads})" - ) - - self.num_attention_heads = config.num_attention_heads - self.attention_head_size = int(config.hidden_size / config.num_attention_heads) - self.all_head_size = self.num_attention_heads * self.attention_head_size - - self.query = nn.Linear(config.hidden_size, self.all_head_size) - self.key = nn.Linear(config.hidden_size, self.all_head_size) - self.value = nn.Linear(config.hidden_size, self.all_head_size) - - self.dropout = nn.Dropout(config.attention_probs_dropout_prob) - self.position_embedding_type = position_embedding_type or getattr( - config, "position_embedding_type", "absolute" - ) - if self.position_embedding_type == "relative_key" or self.position_embedding_type == "relative_key_query": - self.max_position_embeddings = config.max_position_embeddings - self.distance_embedding = nn.Embedding(2 * config.max_position_embeddings - 1, self.attention_head_size) - - self.is_decoder = config.is_decoder - - def transpose_for_scores(self, x): - new_x_shape = x.size()[:-1] + (self.num_attention_heads, self.attention_head_size) - x = x.view(*new_x_shape) - return x.permute(0, 2, 1, 3) - - def forward( - self, - hidden_states, - attention_mask=None, - head_mask=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - past_key_value=None, - output_attentions=False, - ): - mixed_query_layer = self.query(hidden_states) - - # If this is instantiated as a cross-attention module, the keys - # and values come from an encoder; the attention mask needs to be - # such that the encoder's padding tokens are not attended to. - is_cross_attention = encoder_hidden_states is not None - - if is_cross_attention and past_key_value is not None: - # reuse k,v, cross_attentions - key_layer = past_key_value[0] - value_layer = past_key_value[1] - attention_mask = encoder_attention_mask - elif is_cross_attention: - key_layer = self.transpose_for_scores(self.key(encoder_hidden_states)) - value_layer = self.transpose_for_scores(self.value(encoder_hidden_states)) - attention_mask = encoder_attention_mask - elif past_key_value is not None: - key_layer = self.transpose_for_scores(self.key(hidden_states)) - value_layer = self.transpose_for_scores(self.value(hidden_states)) - key_layer = torch.cat([past_key_value[0], key_layer], dim=2) - value_layer = torch.cat([past_key_value[1], value_layer], dim=2) - else: - key_layer = self.transpose_for_scores(self.key(hidden_states)) - value_layer = self.transpose_for_scores(self.value(hidden_states)) - - query_layer = self.transpose_for_scores(mixed_query_layer) - - if self.is_decoder: - # if cross_attention save Tuple(torch.Tensor, torch.Tensor) of all cross attention key/value_states. - # Further calls to cross_attention layer can then reuse all cross-attention - # key/value_states (first "if" case) - # if uni-directional self-attention (decoder) save Tuple(torch.Tensor, torch.Tensor) of - # all previous decoder key/value_states. Further calls to uni-directional self-attention - # can concat previous decoder key/value_states to current projected key/value_states (third "elif" case) - # if encoder bi-directional self-attention `past_key_value` is always `None` - past_key_value = (key_layer, value_layer) - - # Take the dot product between "query" and "key" to get the raw attention scores. - attention_scores = torch.matmul(query_layer, key_layer.transpose(-1, -2)) - - if self.position_embedding_type == "relative_key" or self.position_embedding_type == "relative_key_query": - seq_length = hidden_states.size()[1] - position_ids_l = torch.arange(seq_length, dtype=torch.long, device=hidden_states.device).view(-1, 1) - position_ids_r = torch.arange(seq_length, dtype=torch.long, device=hidden_states.device).view(1, -1) - distance = position_ids_l - position_ids_r - positional_embedding = self.distance_embedding(distance + self.max_position_embeddings - 1) - positional_embedding = positional_embedding.to(dtype=query_layer.dtype) # fp16 compatibility - - if self.position_embedding_type == "relative_key": - relative_position_scores = torch.einsum("bhld,lrd->bhlr", query_layer, positional_embedding) - attention_scores = attention_scores + relative_position_scores - elif self.position_embedding_type == "relative_key_query": - relative_position_scores_query = torch.einsum("bhld,lrd->bhlr", query_layer, positional_embedding) - relative_position_scores_key = torch.einsum("bhrd,lrd->bhlr", key_layer, positional_embedding) - attention_scores = attention_scores + relative_position_scores_query + relative_position_scores_key - - attention_scores = attention_scores / math.sqrt(self.attention_head_size) - if attention_mask is not None: - # Apply the attention mask is (precomputed for all layers in BertModel forward() function) - attention_scores = attention_scores + attention_mask - - # Normalize the attention scores to probabilities. - attention_probs = nn.functional.softmax(attention_scores, dim=-1) - - # This is actually dropping out entire tokens to attend to, which might - # seem a bit unusual, but is taken from the original Transformer paper. - attention_probs = self.dropout(attention_probs) - - # Mask heads if we want to - if head_mask is not None: - attention_probs = attention_probs * head_mask - - context_layer = torch.matmul(attention_probs, value_layer) - - context_layer = context_layer.permute(0, 2, 1, 3).contiguous() - new_context_layer_shape = context_layer.size()[:-2] + (self.all_head_size,) - context_layer = context_layer.view(*new_context_layer_shape) - - #outputs = (context_layer, attention_probs) if output_attentions else (context_layer,) - outputs = (context_layer, attention_scores) if output_attentions else (context_layer,) #<===============================================this is the change we make - if self.is_decoder: - outputs = outputs + (past_key_value,) - return outputs - - -class BertSelfOutput(nn.Module): - def __init__(self, config): - super().__init__() - self.dense = nn.Linear(config.hidden_size, config.hidden_size) - self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps) - self.dropout = nn.Dropout(config.hidden_dropout_prob) - - def forward(self, hidden_states, input_tensor): - hidden_states = self.dense(hidden_states) - hidden_states = self.dropout(hidden_states) - hidden_states = self.LayerNorm(hidden_states + input_tensor) - return hidden_states - - -class BertAttention(nn.Module): - def __init__(self, config, position_embedding_type=None): - super().__init__() - self.self = BertSelfAttention(config, position_embedding_type=position_embedding_type) - self.output = BertSelfOutput(config) - self.pruned_heads = set() - - def prune_heads(self, heads): - if len(heads) == 0: - return - heads, index = find_pruneable_heads_and_indices( - heads, self.self.num_attention_heads, self.self.attention_head_size, self.pruned_heads - ) - - # Prune linear layers - self.self.query = prune_linear_layer(self.self.query, index) - self.self.key = prune_linear_layer(self.self.key, index) - self.self.value = prune_linear_layer(self.self.value, index) - self.output.dense = prune_linear_layer(self.output.dense, index, dim=1) - - # Update hyper params and store pruned heads - self.self.num_attention_heads = self.self.num_attention_heads - len(heads) - self.self.all_head_size = self.self.attention_head_size * self.self.num_attention_heads - self.pruned_heads = self.pruned_heads.union(heads) - - def forward( - self, - hidden_states, - attention_mask=None, - head_mask=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - past_key_value=None, - output_attentions=False, - ): - self_outputs = self.self( - hidden_states, - attention_mask, - head_mask, - encoder_hidden_states, - encoder_attention_mask, - past_key_value, - output_attentions, - ) - attention_output = self.output(self_outputs[0], hidden_states) - outputs = (attention_output,) + self_outputs[1:] # add attentions if we output them - return outputs - - -class BertIntermediate(nn.Module): - def __init__(self, config): - super().__init__() - self.dense = nn.Linear(config.hidden_size, config.intermediate_size) - if isinstance(config.hidden_act, str): - self.intermediate_act_fn = ACT2FN[config.hidden_act] - else: - self.intermediate_act_fn = config.hidden_act - - def forward(self, hidden_states): - hidden_states = self.dense(hidden_states) - hidden_states = self.intermediate_act_fn(hidden_states) - return hidden_states - - -class BertOutput(nn.Module): - def __init__(self, config): - super().__init__() - self.dense = nn.Linear(config.intermediate_size, config.hidden_size) - self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps) - self.dropout = nn.Dropout(config.hidden_dropout_prob) - - def forward(self, hidden_states, input_tensor): - hidden_states = self.dense(hidden_states) - hidden_states = self.dropout(hidden_states) - hidden_states = self.LayerNorm(hidden_states + input_tensor) - return hidden_states - - -class BertLayer(nn.Module): - def __init__(self, config): - super().__init__() - self.chunk_size_feed_forward = config.chunk_size_feed_forward - self.seq_len_dim = 1 - self.attention = BertAttention(config) - self.is_decoder = config.is_decoder - self.add_cross_attention = config.add_cross_attention - if self.add_cross_attention: - if not self.is_decoder: - raise ValueError(f"{self} should be used as a decoder model if cross attention is added") - self.crossattention = BertAttention(config, position_embedding_type="absolute") - self.intermediate = BertIntermediate(config) - self.output = BertOutput(config) - - def forward( - self, - hidden_states, - attention_mask=None, - head_mask=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - past_key_value=None, - output_attentions=False, - ): - # decoder uni-directional self-attention cached key/values tuple is at positions 1,2 - self_attn_past_key_value = past_key_value[:2] if past_key_value is not None else None - self_attention_outputs = self.attention( - hidden_states, - attention_mask, - head_mask, - output_attentions=output_attentions, - past_key_value=self_attn_past_key_value, - ) - attention_output = self_attention_outputs[0] - - # if decoder, the last output is tuple of self-attn cache - if self.is_decoder: - outputs = self_attention_outputs[1:-1] - present_key_value = self_attention_outputs[-1] - else: - outputs = self_attention_outputs[1:] # add self attentions if we output attention weights - - cross_attn_present_key_value = None - if self.is_decoder and encoder_hidden_states is not None: - if not hasattr(self, "crossattention"): - raise ValueError( - f"If `encoder_hidden_states` are passed, {self} has to be instantiated with cross-attention layers by setting `config.add_cross_attention=True`" - ) - - # cross_attn cached key/values tuple is at positions 3,4 of past_key_value tuple - cross_attn_past_key_value = past_key_value[-2:] if past_key_value is not None else None - cross_attention_outputs = self.crossattention( - attention_output, - attention_mask, - head_mask, - encoder_hidden_states, - encoder_attention_mask, - cross_attn_past_key_value, - output_attentions, - ) - attention_output = cross_attention_outputs[0] - outputs = outputs + cross_attention_outputs[1:-1] # add cross attentions if we output attention weights - - # add cross-attn cache to positions 3,4 of present_key_value tuple - cross_attn_present_key_value = cross_attention_outputs[-1] - present_key_value = present_key_value + cross_attn_present_key_value - - layer_output = apply_chunking_to_forward( - self.feed_forward_chunk, self.chunk_size_feed_forward, self.seq_len_dim, attention_output - ) - outputs = (layer_output,) + outputs - - # if decoder, return the attn key/values as the last output - if self.is_decoder: - outputs = outputs + (present_key_value,) - - return outputs - - def feed_forward_chunk(self, attention_output): - intermediate_output = self.intermediate(attention_output) - layer_output = self.output(intermediate_output, attention_output) - return layer_output - - -class BertEncoder(nn.Module): - def __init__(self, config): - super().__init__() - self.config = config - self.layer = nn.ModuleList([BertLayer(config) for _ in range(config.num_hidden_layers)]) - self.gradient_checkpointing = False - - def forward( - self, - hidden_states, - attention_mask=None, - head_mask=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - past_key_values=None, - use_cache=None, - output_attentions=False, - output_hidden_states=False, - return_dict=True, - ): - all_hidden_states = () if output_hidden_states else None - all_self_attentions = () if output_attentions else None - all_cross_attentions = () if output_attentions and self.config.add_cross_attention else None - - next_decoder_cache = () if use_cache else None - for i, layer_module in enumerate(self.layer): - if output_hidden_states: - all_hidden_states = all_hidden_states + (hidden_states,) - - layer_head_mask = head_mask[i] if head_mask is not None else None - past_key_value = past_key_values[i] if past_key_values is not None else None - - if self.gradient_checkpointing and self.training: - - if use_cache: - logger.warning( - "`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`..." - ) - use_cache = False - - def create_custom_forward(module): - def custom_forward(*inputs): - return module(*inputs, past_key_value, output_attentions) - - return custom_forward - - layer_outputs = torch.utils.checkpoint.checkpoint( - create_custom_forward(layer_module), - hidden_states, - attention_mask, - layer_head_mask, - encoder_hidden_states, - encoder_attention_mask, - ) - else: - layer_outputs = layer_module( - hidden_states, - attention_mask, - layer_head_mask, - encoder_hidden_states, - encoder_attention_mask, - past_key_value, - output_attentions, - ) - - hidden_states = layer_outputs[0] - if use_cache: - next_decoder_cache += (layer_outputs[-1],) - if output_attentions: - all_self_attentions = all_self_attentions + (layer_outputs[1],) - if self.config.add_cross_attention: - all_cross_attentions = all_cross_attentions + (layer_outputs[2],) - - if output_hidden_states: - all_hidden_states = all_hidden_states + (hidden_states,) - - if not return_dict: - return tuple( - v - for v in [ - hidden_states, - next_decoder_cache, - all_hidden_states, - all_self_attentions, - all_cross_attentions, - ] - if v is not None - ) - return BaseModelOutputWithPastAndCrossAttentions( - last_hidden_state=hidden_states, - past_key_values=next_decoder_cache, - hidden_states=all_hidden_states, - attentions=all_self_attentions, - cross_attentions=all_cross_attentions, - ) - - -class BertPooler(nn.Module): - def __init__(self, config): - super().__init__() - self.dense = nn.Linear(config.hidden_size, config.hidden_size) - self.activation = nn.Tanh() - - def forward(self, hidden_states): - # We "pool" the model by simply taking the hidden state corresponding - # to the first token. - first_token_tensor = hidden_states[:, 0] - pooled_output = self.dense(first_token_tensor) - pooled_output = self.activation(pooled_output) - return pooled_output - - -class BertPredictionHeadTransform(nn.Module): - def __init__(self, config): - super().__init__() - self.dense = nn.Linear(config.hidden_size, config.hidden_size) - if isinstance(config.hidden_act, str): - self.transform_act_fn = ACT2FN[config.hidden_act] - else: - self.transform_act_fn = config.hidden_act - self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps) - - def forward(self, hidden_states): - hidden_states = self.dense(hidden_states) - hidden_states = self.transform_act_fn(hidden_states) - hidden_states = self.LayerNorm(hidden_states) - return hidden_states - - -class BertLMPredictionHead(nn.Module): - def __init__(self, config): - super().__init__() - self.transform = BertPredictionHeadTransform(config) - - # The output weights are the same as the input embeddings, but there is - # an output-only bias for each token. - self.decoder = nn.Linear(config.hidden_size, config.vocab_size, bias=False) - - self.bias = nn.Parameter(torch.zeros(config.vocab_size)) - - # Need a link between the two variables so that the bias is correctly resized with `resize_token_embeddings` - self.decoder.bias = self.bias - - def forward(self, hidden_states): - hidden_states = self.transform(hidden_states) - hidden_states = self.decoder(hidden_states) - return hidden_states - - -class BertOnlyMLMHead(nn.Module): - def __init__(self, config): - super().__init__() - self.predictions = BertLMPredictionHead(config) - - def forward(self, sequence_output): - prediction_scores = self.predictions(sequence_output) - return prediction_scores - - -class BertOnlyNSPHead(nn.Module): - def __init__(self, config): - super().__init__() - self.seq_relationship = nn.Linear(config.hidden_size, 2) - - def forward(self, pooled_output): - seq_relationship_score = self.seq_relationship(pooled_output) - return seq_relationship_score - - -class BertPreTrainingHeads(nn.Module): - def __init__(self, config): - super().__init__() - self.predictions = BertLMPredictionHead(config) - self.seq_relationship = nn.Linear(config.hidden_size, 2) - - def forward(self, sequence_output, pooled_output): - prediction_scores = self.predictions(sequence_output) - seq_relationship_score = self.seq_relationship(pooled_output) - return prediction_scores, seq_relationship_score - - -class BertPreTrainedModel(PreTrainedModel): - """ - An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained - models. - """ - - config_class = BertConfig - load_tf_weights = load_tf_weights_in_bert - base_model_prefix = "bert" - supports_gradient_checkpointing = True - _keys_to_ignore_on_load_missing = [r"position_ids"] - - def _init_weights(self, module): - """Initialize the weights""" - if isinstance(module, nn.Linear): - # Slightly different from the TF version which uses truncated_normal for initialization - # cf https://github.com/pytorch/pytorch/pull/5617 - module.weight.data.normal_(mean=0.0, std=self.config.initializer_range) - if module.bias is not None: - module.bias.data.zero_() - elif isinstance(module, nn.Embedding): - module.weight.data.normal_(mean=0.0, std=self.config.initializer_range) - if module.padding_idx is not None: - module.weight.data[module.padding_idx].zero_() - elif isinstance(module, nn.LayerNorm): - module.bias.data.zero_() - module.weight.data.fill_(1.0) - - def _set_gradient_checkpointing(self, module, value=False): - if isinstance(module, BertEncoder): - module.gradient_checkpointing = value - - -@dataclass -class BertForPreTrainingOutput(ModelOutput): - """ - Output type of [`BertForPreTraining`]. - - Args: - loss (*optional*, returned when `labels` is provided, `torch.FloatTensor` of shape `(1,)`): - Total loss as the sum of the masked language modeling loss and the next sequence prediction - (classification) loss. - prediction_logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.vocab_size)`): - Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax). - seq_relationship_logits (`torch.FloatTensor` of shape `(batch_size, 2)`): - Prediction scores of the next sequence prediction (classification) head (scores of True/False continuation - before SoftMax). - hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`): - Tuple of `torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer) of - shape `(batch_size, sequence_length, hidden_size)`. - - Hidden-states of the model at the output of each layer plus the initial embedding outputs. - attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`): - Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length, - sequence_length)`. - - Attentions weights after the attention softmax, used to compute the weighted average in the self-attention - heads. - """ - - loss: Optional[torch.FloatTensor] = None - prediction_logits: torch.FloatTensor = None - seq_relationship_logits: torch.FloatTensor = None - hidden_states: Optional[Tuple[torch.FloatTensor]] = None - attentions: Optional[Tuple[torch.FloatTensor]] = None - - -BERT_START_DOCSTRING = r""" - - This model inherits from [`PreTrainedModel`]. Check the superclass documentation for the generic methods the - library implements for all its model (such as downloading or saving, resizing the input embeddings, pruning heads - etc.) - - This model is also a PyTorch [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) subclass. - Use it as a regular PyTorch Module and refer to the PyTorch documentation for all matter related to general usage - and behavior. - - Parameters: - config ([`BertConfig`]): Model configuration class with all the parameters of the model. - Initializing with a config file does not load the weights associated with the model, only the - configuration. Check out the [`~PreTrainedModel.from_pretrained`] method to load the model weights. -""" - -BERT_INPUTS_DOCSTRING = r""" - Args: - input_ids (`torch.LongTensor` of shape `({0})`): - Indices of input sequence tokens in the vocabulary. - - Indices can be obtained using [`BertTokenizer`]. See [`PreTrainedTokenizer.encode`] and - [`PreTrainedTokenizer.__call__`] for details. - - [What are input IDs?](../glossary#input-ids) - attention_mask (`torch.FloatTensor` of shape `({0})`, *optional*): - Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`: - - - 1 for tokens that are **not masked**, - - 0 for tokens that are **masked**. - - [What are attention masks?](../glossary#attention-mask) - token_type_ids (`torch.LongTensor` of shape `({0})`, *optional*): - Segment token indices to indicate first and second portions of the inputs. Indices are selected in `[0, - 1]`: - - - 0 corresponds to a *sentence A* token, - - 1 corresponds to a *sentence B* token. - - [What are token type IDs?](../glossary#token-type-ids) - position_ids (`torch.LongTensor` of shape `({0})`, *optional*): - Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0, - config.max_position_embeddings - 1]`. - - [What are position IDs?](../glossary#position-ids) - head_mask (`torch.FloatTensor` of shape `(num_heads,)` or `(num_layers, num_heads)`, *optional*): - Mask to nullify selected heads of the self-attention modules. Mask values selected in `[0, 1]`: - - - 1 indicates the head is **not masked**, - - 0 indicates the head is **masked**. - - inputs_embeds (`torch.FloatTensor` of shape `({0}, hidden_size)`, *optional*): - Optionally, instead of passing `input_ids` you can choose to directly pass an embedded representation. This - is useful if you want more control over how to convert `input_ids` indices into associated vectors than the - model's internal embedding lookup matrix. - output_attentions (`bool`, *optional*): - Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned - tensors for more detail. - output_hidden_states (`bool`, *optional*): - Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for - more detail. - return_dict (`bool`, *optional*): - Whether or not to return a [`~file_utils.ModelOutput`] instead of a plain tuple. -""" - - -@add_start_docstrings( - "The bare Bert Model transformer outputting raw hidden-states without any specific head on top.", - BERT_START_DOCSTRING, -) -class BertModel(BertPreTrainedModel): - """ - - The model can behave as an encoder (with only self-attention) as well as a decoder, in which case a layer of - cross-attention is added between the self-attention layers, following the architecture described in [Attention is - all you need](https://arxiv.org/abs/1706.03762) by Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, - Llion Jones, Aidan N. Gomez, Lukasz Kaiser and Illia Polosukhin. - - To behave as an decoder the model needs to be initialized with the `is_decoder` argument of the configuration set - to `True`. To be used in a Seq2Seq model, the model needs to initialized with both `is_decoder` argument and - `add_cross_attention` set to `True`; an `encoder_hidden_states` is then expected as an input to the forward pass. - """ - - def __init__(self, config, add_pooling_layer=True): - super().__init__(config) - self.config = config - - self.embeddings = BertEmbeddings(config) - self.encoder = BertEncoder(config) - - self.pooler = BertPooler(config) if add_pooling_layer else None - - # Initialize weights and apply final processing - self.post_init() - - def get_input_embeddings(self): - return self.embeddings.word_embeddings - - def set_input_embeddings(self, value): - self.embeddings.word_embeddings = value - - def _prune_heads(self, heads_to_prune): - """ - Prunes heads of the model. heads_to_prune: dict of {layer_num: list of heads to prune in this layer} See base - class PreTrainedModel - """ - for layer, heads in heads_to_prune.items(): - self.encoder.layer[layer].attention.prune_heads(heads) - - @add_start_docstrings_to_model_forward(BERT_INPUTS_DOCSTRING.format("batch_size, sequence_length")) - @add_code_sample_docstrings( - processor_class=_TOKENIZER_FOR_DOC, - checkpoint=_CHECKPOINT_FOR_DOC, - output_type=BaseModelOutputWithPoolingAndCrossAttentions, - config_class=_CONFIG_FOR_DOC, - ) - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - head_mask=None, - inputs_embeds=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - past_key_values=None, - use_cache=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - ): - r""" - encoder_hidden_states (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*): - Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention if - the model is configured as a decoder. - encoder_attention_mask (`torch.FloatTensor` of shape `(batch_size, sequence_length)`, *optional*): - Mask to avoid performing attention on the padding token indices of the encoder input. This mask is used in - the cross-attention if the model is configured as a decoder. Mask values selected in `[0, 1]`: - - - 1 for tokens that are **not masked**, - - 0 for tokens that are **masked**. - past_key_values (`tuple(tuple(torch.FloatTensor))` of length `config.n_layers` with each tuple having 4 tensors of shape `(batch_size, num_heads, sequence_length - 1, embed_size_per_head)`): - Contains precomputed key and value hidden states of the attention blocks. Can be used to speed up decoding. - - If `past_key_values` are used, the user can optionally input only the last `decoder_input_ids` (those that - don't have their past key value states given to this model) of shape `(batch_size, 1)` instead of all - `decoder_input_ids` of shape `(batch_size, sequence_length)`. - use_cache (`bool`, *optional*): - If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding (see - `past_key_values`). - """ - output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions - output_hidden_states = ( - output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states - ) - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - if self.config.is_decoder: - use_cache = use_cache if use_cache is not None else self.config.use_cache - else: - use_cache = False - - if input_ids is not None and inputs_embeds is not None: - raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time") - elif input_ids is not None: - input_shape = input_ids.size() - elif inputs_embeds is not None: - input_shape = inputs_embeds.size()[:-1] - else: - raise ValueError("You have to specify either input_ids or inputs_embeds") - - batch_size, seq_length = input_shape - device = input_ids.device if input_ids is not None else inputs_embeds.device - - # past_key_values_length - past_key_values_length = past_key_values[0][0].shape[2] if past_key_values is not None else 0 - - if attention_mask is None: - attention_mask = torch.ones(((batch_size, seq_length + past_key_values_length)), device=device) - - if token_type_ids is None: - if hasattr(self.embeddings, "token_type_ids"): - buffered_token_type_ids = self.embeddings.token_type_ids[:, :seq_length] - buffered_token_type_ids_expanded = buffered_token_type_ids.expand(batch_size, seq_length) - token_type_ids = buffered_token_type_ids_expanded - else: - token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=device) - - # We can provide a self-attention mask of dimensions [batch_size, from_seq_length, to_seq_length] - # ourselves in which case we just need to make it broadcastable to all heads. - extended_attention_mask: torch.Tensor = self.get_extended_attention_mask(attention_mask, input_shape, device) - - # If a 2D or 3D attention mask is provided for the cross-attention - # we need to make broadcastable to [batch_size, num_heads, seq_length, seq_length] - if self.config.is_decoder and encoder_hidden_states is not None: - encoder_batch_size, encoder_sequence_length, _ = encoder_hidden_states.size() - encoder_hidden_shape = (encoder_batch_size, encoder_sequence_length) - if encoder_attention_mask is None: - encoder_attention_mask = torch.ones(encoder_hidden_shape, device=device) - encoder_extended_attention_mask = self.invert_attention_mask(encoder_attention_mask) - else: - encoder_extended_attention_mask = None - - # Prepare head mask if needed - # 1.0 in head_mask indicate we keep the head - # attention_probs has shape bsz x n_heads x N x N - # input head_mask has shape [num_heads] or [num_hidden_layers x num_heads] - # and head_mask is converted to shape [num_hidden_layers x batch x num_heads x seq_length x seq_length] - head_mask = self.get_head_mask(head_mask, self.config.num_hidden_layers) - - embedding_output = self.embeddings( - input_ids=input_ids, - position_ids=position_ids, - token_type_ids=token_type_ids, - inputs_embeds=inputs_embeds, - past_key_values_length=past_key_values_length, - ) - encoder_outputs = self.encoder( - embedding_output, - attention_mask=extended_attention_mask, - head_mask=head_mask, - encoder_hidden_states=encoder_hidden_states, - encoder_attention_mask=encoder_extended_attention_mask, - past_key_values=past_key_values, - use_cache=use_cache, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - ) - sequence_output = encoder_outputs[0] - pooled_output = self.pooler(sequence_output) if self.pooler is not None else None - - if not return_dict: - return (sequence_output, pooled_output) + encoder_outputs[1:] - - return BaseModelOutputWithPoolingAndCrossAttentions( - last_hidden_state=sequence_output, - pooler_output=pooled_output, - past_key_values=encoder_outputs.past_key_values, - hidden_states=encoder_outputs.hidden_states, - attentions=encoder_outputs.attentions, - cross_attentions=encoder_outputs.cross_attentions, - ) - - -@add_start_docstrings( - """ - Bert Model with two heads on top as done during the pretraining: a `masked language modeling` head and a `next - sentence prediction (classification)` head. - """, - BERT_START_DOCSTRING, -) -class BertForPreTraining(BertPreTrainedModel): - def __init__(self, config): - super().__init__(config) - - self.bert = BertModel(config) - self.cls = BertPreTrainingHeads(config) - - # Initialize weights and apply final processing - self.post_init() - - def get_output_embeddings(self): - return self.cls.predictions.decoder - - def set_output_embeddings(self, new_embeddings): - self.cls.predictions.decoder = new_embeddings - - @add_start_docstrings_to_model_forward(BERT_INPUTS_DOCSTRING.format("batch_size, sequence_length")) - @replace_return_docstrings(output_type=BertForPreTrainingOutput, config_class=_CONFIG_FOR_DOC) - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - head_mask=None, - inputs_embeds=None, - labels=None, - next_sentence_label=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - ): - r""" - labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*): - Labels for computing the masked language modeling loss. Indices should be in `[-100, 0, ..., - config.vocab_size]` (see `input_ids` docstring) Tokens with indices set to `-100` are ignored (masked), - the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]` - next_sentence_label (`torch.LongTensor` of shape `(batch_size,)`, *optional*): - Labels for computing the next sequence prediction (classification) loss. Input should be a sequence - pair (see `input_ids` docstring) Indices should be in `[0, 1]`: - - - 0 indicates sequence B is a continuation of sequence A, - - 1 indicates sequence B is a random sequence. - kwargs (`Dict[str, any]`, optional, defaults to *{}*): - Used to hide legacy arguments that have been deprecated. - - Returns: - - Example: - - ```python - >>> from transformers import BertTokenizer, BertForPreTraining - >>> import torch - - >>> tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') - >>> model = BertForPreTraining.from_pretrained('bert-base-uncased') - - >>> inputs = tokenizer("Hello, my dog is cute", return_tensors="pt") - >>> outputs = model(**inputs) - - >>> prediction_logits = outputs.prediction_logits - >>> seq_relationship_logits = outputs.seq_relationship_logits - ``` - """ - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - outputs = self.bert( - input_ids, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - ) - - sequence_output, pooled_output = outputs[:2] - prediction_scores, seq_relationship_score = self.cls(sequence_output, pooled_output) - - total_loss = None - if labels is not None and next_sentence_label is not None: - loss_fct = CrossEntropyLoss() - masked_lm_loss = loss_fct(prediction_scores.view(-1, self.config.vocab_size), labels.view(-1)) - next_sentence_loss = loss_fct(seq_relationship_score.view(-1, 2), next_sentence_label.view(-1)) - total_loss = masked_lm_loss + next_sentence_loss - - if not return_dict: - output = (prediction_scores, seq_relationship_score) + outputs[2:] - return ((total_loss,) + output) if total_loss is not None else output - - return BertForPreTrainingOutput( - loss=total_loss, - prediction_logits=prediction_scores, - seq_relationship_logits=seq_relationship_score, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - ) - - -@add_start_docstrings( - """Bert Model with a `language modeling` head on top for CLM fine-tuning. """, BERT_START_DOCSTRING -) -class BertLMHeadModel(BertPreTrainedModel): - - _keys_to_ignore_on_load_unexpected = [r"pooler"] - _keys_to_ignore_on_load_missing = [r"position_ids", r"predictions.decoder.bias"] - - def __init__(self, config): - super().__init__(config) - - if not config.is_decoder: - logger.warning("If you want to use `BertLMHeadModel` as a standalone, add `is_decoder=True.`") - - self.bert = BertModel(config, add_pooling_layer=False) - self.cls = BertOnlyMLMHead(config) - - # Initialize weights and apply final processing - self.post_init() - - def get_output_embeddings(self): - return self.cls.predictions.decoder - - def set_output_embeddings(self, new_embeddings): - self.cls.predictions.decoder = new_embeddings - - @add_start_docstrings_to_model_forward(BERT_INPUTS_DOCSTRING.format("batch_size, sequence_length")) - @replace_return_docstrings(output_type=CausalLMOutputWithCrossAttentions, config_class=_CONFIG_FOR_DOC) - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - head_mask=None, - inputs_embeds=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - labels=None, - past_key_values=None, - use_cache=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - ): - r""" - encoder_hidden_states (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*): - Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention - if the model is configured as a decoder. - encoder_attention_mask (`torch.FloatTensor` of shape `(batch_size, sequence_length)`, *optional*): - Mask to avoid performing attention on the padding token indices of the encoder input. This mask is used - in the cross-attention if the model is configured as a decoder. Mask values selected in `[0, 1]`: - - - 1 for tokens that are **not masked**, - - 0 for tokens that are **masked**. - labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*): - Labels for computing the left-to-right language modeling loss (next word prediction). Indices should be - in `[-100, 0, ..., config.vocab_size]` (see `input_ids` docstring) Tokens with indices set to `-100` - are ignored (masked), the loss is only computed for the tokens with labels n `[0, ..., - config.vocab_size]` - past_key_values (`tuple(tuple(torch.FloatTensor))` of length `config.n_layers` with each tuple having 4 tensors of shape `(batch_size, num_heads, sequence_length - 1, embed_size_per_head)`): - Contains precomputed key and value hidden states of the attention blocks. Can be used to speed up - decoding. - - If `past_key_values` are used, the user can optionally input only the last `decoder_input_ids` (those - that don't have their past key value states given to this model) of shape `(batch_size, 1)` instead of - all `decoder_input_ids` of shape `(batch_size, sequence_length)`. - use_cache (`bool`, *optional*): - If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding - (see `past_key_values`). - - Returns: - - Example: - - ```python - >>> from transformers import BertTokenizer, BertLMHeadModel, BertConfig - >>> import torch - - >>> tokenizer = BertTokenizer.from_pretrained('bert-base-cased') - >>> config = BertConfig.from_pretrained("bert-base-cased") - >>> config.is_decoder = True - >>> model = BertLMHeadModel.from_pretrained('bert-base-cased', config=config) - - >>> inputs = tokenizer("Hello, my dog is cute", return_tensors="pt") - >>> outputs = model(**inputs) - - >>> prediction_logits = outputs.logits - ``` - """ - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - if labels is not None: - use_cache = False - - outputs = self.bert( - input_ids, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - encoder_hidden_states=encoder_hidden_states, - encoder_attention_mask=encoder_attention_mask, - past_key_values=past_key_values, - use_cache=use_cache, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - ) - - sequence_output = outputs[0] - prediction_scores = self.cls(sequence_output) - - lm_loss = None - if labels is not None: - # we are doing next-token prediction; shift prediction scores and input ids by one - shifted_prediction_scores = prediction_scores[:, :-1, :].contiguous() - labels = labels[:, 1:].contiguous() - loss_fct = CrossEntropyLoss() - lm_loss = loss_fct(shifted_prediction_scores.view(-1, self.config.vocab_size), labels.view(-1)) - - if not return_dict: - output = (prediction_scores,) + outputs[2:] - return ((lm_loss,) + output) if lm_loss is not None else output - - return CausalLMOutputWithCrossAttentions( - loss=lm_loss, - logits=prediction_scores, - past_key_values=outputs.past_key_values, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - cross_attentions=outputs.cross_attentions, - ) - - def prepare_inputs_for_generation(self, input_ids, past=None, attention_mask=None, **model_kwargs): - input_shape = input_ids.shape - # if model is used as a decoder in encoder-decoder model, the decoder attention mask is created on the fly - if attention_mask is None: - attention_mask = input_ids.new_ones(input_shape) - - # cut decoder_input_ids if past is used - if past is not None: - input_ids = input_ids[:, -1:] - - return {"input_ids": input_ids, "attention_mask": attention_mask, "past_key_values": past} - - def _reorder_cache(self, past, beam_idx): - reordered_past = () - for layer_past in past: - reordered_past += (tuple(past_state.index_select(0, beam_idx) for past_state in layer_past),) - return reordered_past - - -@add_start_docstrings("""Bert Model with a `language modeling` head on top. """, BERT_START_DOCSTRING) -class BertForMaskedLM(BertPreTrainedModel): - - _keys_to_ignore_on_load_unexpected = [r"pooler"] - _keys_to_ignore_on_load_missing = [r"position_ids", r"predictions.decoder.bias"] - - def __init__(self, config): - super().__init__(config) - - if config.is_decoder: - logger.warning( - "If you want to use `BertForMaskedLM` make sure `config.is_decoder=False` for " - "bi-directional self-attention." - ) - - self.bert = BertModel(config, add_pooling_layer=False) - self.cls = BertOnlyMLMHead(config) - - # Initialize weights and apply final processing - self.post_init() - - def get_output_embeddings(self): - return self.cls.predictions.decoder - - def set_output_embeddings(self, new_embeddings): - self.cls.predictions.decoder = new_embeddings - - @add_start_docstrings_to_model_forward(BERT_INPUTS_DOCSTRING.format("batch_size, sequence_length")) - @add_code_sample_docstrings( - processor_class=_TOKENIZER_FOR_DOC, - checkpoint=_CHECKPOINT_FOR_DOC, - output_type=MaskedLMOutput, - config_class=_CONFIG_FOR_DOC, - ) - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - head_mask=None, - inputs_embeds=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - labels=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - ): - r""" - labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*): - Labels for computing the masked language modeling loss. Indices should be in `[-100, 0, ..., - config.vocab_size]` (see `input_ids` docstring) Tokens with indices set to `-100` are ignored (masked), the - loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]` - """ - - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - outputs = self.bert( - input_ids, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - encoder_hidden_states=encoder_hidden_states, - encoder_attention_mask=encoder_attention_mask, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - ) - - sequence_output = outputs[0] - prediction_scores = self.cls(sequence_output) - - masked_lm_loss = None - if labels is not None: - loss_fct = CrossEntropyLoss() # -100 index = padding token - masked_lm_loss = loss_fct(prediction_scores.view(-1, self.config.vocab_size), labels.view(-1)) - - if not return_dict: - output = (prediction_scores,) + outputs[2:] - return ((masked_lm_loss,) + output) if masked_lm_loss is not None else output - - return MaskedLMOutput( - loss=masked_lm_loss, - logits=prediction_scores, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - ) - - def prepare_inputs_for_generation(self, input_ids, attention_mask=None, **model_kwargs): - input_shape = input_ids.shape - effective_batch_size = input_shape[0] - - # add a dummy token - if self.config.pad_token_id is None: - raise ValueError("The PAD token should be defined for generation") - - attention_mask = torch.cat([attention_mask, attention_mask.new_zeros((attention_mask.shape[0], 1))], dim=-1) - dummy_token = torch.full( - (effective_batch_size, 1), self.config.pad_token_id, dtype=torch.long, device=input_ids.device - ) - input_ids = torch.cat([input_ids, dummy_token], dim=1) - - return {"input_ids": input_ids, "attention_mask": attention_mask} - - -@add_start_docstrings( - """Bert Model with a `next sentence prediction (classification)` head on top. """, - BERT_START_DOCSTRING, -) -class BertForNextSentencePrediction(BertPreTrainedModel): - def __init__(self, config): - super().__init__(config) - - self.bert = BertModel(config) - self.cls = BertOnlyNSPHead(config) - - # Initialize weights and apply final processing - self.post_init() - - @add_start_docstrings_to_model_forward(BERT_INPUTS_DOCSTRING.format("batch_size, sequence_length")) - @replace_return_docstrings(output_type=NextSentencePredictorOutput, config_class=_CONFIG_FOR_DOC) - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - head_mask=None, - inputs_embeds=None, - labels=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - **kwargs, - ): - r""" - labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*): - Labels for computing the next sequence prediction (classification) loss. Input should be a sequence pair - (see `input_ids` docstring). Indices should be in `[0, 1]`: - - - 0 indicates sequence B is a continuation of sequence A, - - 1 indicates sequence B is a random sequence. - - Returns: - - Example: - - ```python - >>> from transformers import BertTokenizer, BertForNextSentencePrediction - >>> import torch - - >>> tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') - >>> model = BertForNextSentencePrediction.from_pretrained('bert-base-uncased') - - >>> prompt = "In Italy, pizza served in formal settings, such as at a restaurant, is presented unsliced." - >>> next_sentence = "The sky is blue due to the shorter wavelength of blue light." - >>> encoding = tokenizer(prompt, next_sentence, return_tensors='pt') - - >>> outputs = model(**encoding, labels=torch.LongTensor([1])) - >>> logits = outputs.logits - >>> assert logits[0, 0] < logits[0, 1] # next sentence was random - ``` - """ - - if "next_sentence_label" in kwargs: - warnings.warn( - "The `next_sentence_label` argument is deprecated and will be removed in a future version, use `labels` instead.", - FutureWarning, - ) - labels = kwargs.pop("next_sentence_label") - - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - outputs = self.bert( - input_ids, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - ) - - pooled_output = outputs[1] - - seq_relationship_scores = self.cls(pooled_output) - - next_sentence_loss = None - if labels is not None: - loss_fct = CrossEntropyLoss() - next_sentence_loss = loss_fct(seq_relationship_scores.view(-1, 2), labels.view(-1)) - - if not return_dict: - output = (seq_relationship_scores,) + outputs[2:] - return ((next_sentence_loss,) + output) if next_sentence_loss is not None else output - - return NextSentencePredictorOutput( - loss=next_sentence_loss, - logits=seq_relationship_scores, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - ) - - -@add_start_docstrings( - """ - Bert Model transformer with a sequence classification/regression head on top (a linear layer on top of the pooled - output) e.g. for GLUE tasks. - """, - BERT_START_DOCSTRING, -) -class BertForSequenceClassification(BertPreTrainedModel): - def __init__(self, config): - super().__init__(config) - self.num_labels = config.num_labels - self.config = config - - self.bert = BertModel(config) - classifier_dropout = ( - config.classifier_dropout if config.classifier_dropout is not None else config.hidden_dropout_prob - ) - self.dropout = nn.Dropout(classifier_dropout) - self.classifier = nn.Linear(config.hidden_size, config.num_labels) - - # Initialize weights and apply final processing - self.post_init() - - @add_start_docstrings_to_model_forward(BERT_INPUTS_DOCSTRING.format("batch_size, sequence_length")) - @add_code_sample_docstrings( - processor_class=_TOKENIZER_FOR_DOC, - checkpoint=_CHECKPOINT_FOR_DOC, - output_type=SequenceClassifierOutput, - config_class=_CONFIG_FOR_DOC, - ) - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - head_mask=None, - inputs_embeds=None, - labels=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - ): - r""" - labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*): - Labels for computing the sequence classification/regression loss. Indices should be in `[0, ..., - config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If - `config.num_labels > 1` a classification loss is computed (Cross-Entropy). - """ - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - outputs = self.bert( - input_ids, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - ) - - pooled_output = outputs[1] - - pooled_output = self.dropout(pooled_output) - logits = self.classifier(pooled_output) - - loss = None - if labels is not None: - if self.config.problem_type is None: - if self.num_labels == 1: - self.config.problem_type = "regression" - elif self.num_labels > 1 and (labels.dtype == torch.long or labels.dtype == torch.int): - self.config.problem_type = "single_label_classification" - else: - self.config.problem_type = "multi_label_classification" - - if self.config.problem_type == "regression": - loss_fct = MSELoss() - if self.num_labels == 1: - loss = loss_fct(logits.squeeze(), labels.squeeze()) - else: - loss = loss_fct(logits, labels) - elif self.config.problem_type == "single_label_classification": - loss_fct = CrossEntropyLoss() - loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1)) - elif self.config.problem_type == "multi_label_classification": - loss_fct = BCEWithLogitsLoss() - loss = loss_fct(logits, labels) - if not return_dict: - output = (logits,) + outputs[2:] - return ((loss,) + output) if loss is not None else output - - return SequenceClassifierOutput( - loss=loss, - logits=logits, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - ) - - -@add_start_docstrings( - """ - Bert Model with a multiple choice classification head on top (a linear layer on top of the pooled output and a - softmax) e.g. for RocStories/SWAG tasks. - """, - BERT_START_DOCSTRING, -) -class BertForMultipleChoice(BertPreTrainedModel): - def __init__(self, config): - super().__init__(config) - - self.bert = BertModel(config) - classifier_dropout = ( - config.classifier_dropout if config.classifier_dropout is not None else config.hidden_dropout_prob - ) - self.dropout = nn.Dropout(classifier_dropout) - self.classifier = nn.Linear(config.hidden_size, 1) - - # Initialize weights and apply final processing - self.post_init() - - @add_start_docstrings_to_model_forward(BERT_INPUTS_DOCSTRING.format("batch_size, num_choices, sequence_length")) - @add_code_sample_docstrings( - processor_class=_TOKENIZER_FOR_DOC, - checkpoint=_CHECKPOINT_FOR_DOC, - output_type=MultipleChoiceModelOutput, - config_class=_CONFIG_FOR_DOC, - ) - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - head_mask=None, - inputs_embeds=None, - labels=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - ): - r""" - labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*): - Labels for computing the multiple choice classification loss. Indices should be in `[0, ..., - num_choices-1]` where `num_choices` is the size of the second dimension of the input tensors. (See - `input_ids` above) - """ - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - num_choices = input_ids.shape[1] if input_ids is not None else inputs_embeds.shape[1] - - input_ids = input_ids.view(-1, input_ids.size(-1)) if input_ids is not None else None - attention_mask = attention_mask.view(-1, attention_mask.size(-1)) if attention_mask is not None else None - token_type_ids = token_type_ids.view(-1, token_type_ids.size(-1)) if token_type_ids is not None else None - position_ids = position_ids.view(-1, position_ids.size(-1)) if position_ids is not None else None - inputs_embeds = ( - inputs_embeds.view(-1, inputs_embeds.size(-2), inputs_embeds.size(-1)) - if inputs_embeds is not None - else None - ) - - outputs = self.bert( - input_ids, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - ) - - pooled_output = outputs[1] - - pooled_output = self.dropout(pooled_output) - logits = self.classifier(pooled_output) - reshaped_logits = logits.view(-1, num_choices) - - loss = None - if labels is not None: - loss_fct = CrossEntropyLoss() - loss = loss_fct(reshaped_logits, labels) - - if not return_dict: - output = (reshaped_logits,) + outputs[2:] - return ((loss,) + output) if loss is not None else output - - return MultipleChoiceModelOutput( - loss=loss, - logits=reshaped_logits, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - ) - - -@add_start_docstrings( - """ - Bert Model with a token classification head on top (a linear layer on top of the hidden-states output) e.g. for - Named-Entity-Recognition (NER) tasks. - """, - BERT_START_DOCSTRING, -) -class BertForTokenClassification(BertPreTrainedModel): - - _keys_to_ignore_on_load_unexpected = [r"pooler"] - - def __init__(self, config): - super().__init__(config) - self.num_labels = config.num_labels - - self.bert = BertModel(config, add_pooling_layer=False) - classifier_dropout = ( - config.classifier_dropout if config.classifier_dropout is not None else config.hidden_dropout_prob - ) - self.dropout = nn.Dropout(classifier_dropout) - self.classifier = nn.Linear(config.hidden_size, config.num_labels) - - # Initialize weights and apply final processing - self.post_init() - - @add_start_docstrings_to_model_forward(BERT_INPUTS_DOCSTRING.format("batch_size, sequence_length")) - @add_code_sample_docstrings( - processor_class=_TOKENIZER_FOR_DOC, - checkpoint=_CHECKPOINT_FOR_DOC, - output_type=TokenClassifierOutput, - config_class=_CONFIG_FOR_DOC, - ) - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - head_mask=None, - inputs_embeds=None, - labels=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - ): - r""" - labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*): - Labels for computing the token classification loss. Indices should be in `[0, ..., config.num_labels - 1]`. - """ - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - outputs = self.bert( - input_ids, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - ) - - sequence_output = outputs[0] - - sequence_output = self.dropout(sequence_output) - logits = self.classifier(sequence_output) - - loss = None - if labels is not None: - loss_fct = CrossEntropyLoss() - # Only keep active parts of the loss - if attention_mask is not None: - active_loss = attention_mask.view(-1) == 1 - active_logits = logits.view(-1, self.num_labels) - active_labels = torch.where( - active_loss, labels.view(-1), torch.tensor(loss_fct.ignore_index).type_as(labels) - ) - loss = loss_fct(active_logits, active_labels) - else: - loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1)) - - if not return_dict: - output = (logits,) + outputs[2:] - return ((loss,) + output) if loss is not None else output - - return TokenClassifierOutput( - loss=loss, - logits=logits, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - ) - - -@add_start_docstrings( - """ - Bert Model with a span classification head on top for extractive question-answering tasks like SQuAD (a linear - layers on top of the hidden-states output to compute `span start logits` and `span end logits`). - """, - BERT_START_DOCSTRING, -) -class BertForQuestionAnswering(BertPreTrainedModel): - - _keys_to_ignore_on_load_unexpected = [r"pooler"] - - def __init__(self, config): - super().__init__(config) - self.num_labels = config.num_labels - - self.bert = BertModel(config, add_pooling_layer=False) - self.qa_outputs = nn.Linear(config.hidden_size, config.num_labels) - - # Initialize weights and apply final processing - self.post_init() - - @add_start_docstrings_to_model_forward(BERT_INPUTS_DOCSTRING.format("batch_size, sequence_length")) - @add_code_sample_docstrings( - processor_class=_TOKENIZER_FOR_DOC, - checkpoint=_CHECKPOINT_FOR_DOC, - output_type=QuestionAnsweringModelOutput, - config_class=_CONFIG_FOR_DOC, - ) - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - head_mask=None, - inputs_embeds=None, - start_positions=None, - end_positions=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - ): - r""" - start_positions (`torch.LongTensor` of shape `(batch_size,)`, *optional*): - Labels for position (index) of the start of the labelled span for computing the token classification loss. - Positions are clamped to the length of the sequence (`sequence_length`). Position outside of the sequence - are not taken into account for computing the loss. - end_positions (`torch.LongTensor` of shape `(batch_size,)`, *optional*): - Labels for position (index) of the end of the labelled span for computing the token classification loss. - Positions are clamped to the length of the sequence (`sequence_length`). Position outside of the sequence - are not taken into account for computing the loss. - """ - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - outputs = self.bert( - input_ids, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - ) - - sequence_output = outputs[0] - - logits = self.qa_outputs(sequence_output) - start_logits, end_logits = logits.split(1, dim=-1) - start_logits = start_logits.squeeze(-1).contiguous() - end_logits = end_logits.squeeze(-1).contiguous() - - total_loss = None - if start_positions is not None and end_positions is not None: - # If we are on multi-GPU, split add a dimension - if len(start_positions.size()) > 1: - start_positions = start_positions.squeeze(-1) - if len(end_positions.size()) > 1: - end_positions = end_positions.squeeze(-1) - # sometimes the start/end positions are outside our model inputs, we ignore these terms - ignored_index = start_logits.size(1) - start_positions = start_positions.clamp(0, ignored_index) - end_positions = end_positions.clamp(0, ignored_index) - - loss_fct = CrossEntropyLoss(ignore_index=ignored_index) - start_loss = loss_fct(start_logits, start_positions) - end_loss = loss_fct(end_logits, end_positions) - total_loss = (start_loss + end_loss) / 2 - - if not return_dict: - output = (start_logits, end_logits) + outputs[2:] - return ((total_loss,) + output) if total_loss is not None else output - - return QuestionAnsweringModelOutput( - loss=total_loss, - start_logits=start_logits, - end_logits=end_logits, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - ) diff --git a/compression/bert/requirements.txt b/compression/bert/requirements.txt deleted file mode 100644 index 92e3417c4..000000000 --- a/compression/bert/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -accelerate -transformers == 4.15.0 -datasets >= 1.8.0 -sentencepiece != 0.1.92 -scipy -scikit-learn -protobuf -gpustat -torch >= 1.3 diff --git a/compression/bert/run_glue_lkd.py b/compression/bert/run_glue_lkd.py deleted file mode 100644 index 75185d06e..000000000 --- a/compression/bert/run_glue_lkd.py +++ /dev/null @@ -1,540 +0,0 @@ -# coding=utf-8 -# Copyright 2021 The HuggingFace Inc. team. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" Finetuning a 🤗 Transformers model for sequence classification on GLUE.""" -import argparse -import logging -import math -import time -import os -import random -import json -import numpy as np -from pathlib import Path - -import datasets -from datasets import load_dataset, load_metric -import torch -from torch.utils.data import DataLoader, RandomSampler, SequentialSampler -from torch.utils.data.distributed import DistributedSampler -from tqdm.auto import tqdm - -import transformers -from huggingface_hub import Repository -from transformers import ( - AdamW, - AutoConfig, - AutoModelForSequenceClassification, - AutoTokenizer, - DataCollatorWithPadding, - PretrainedConfig, - SchedulerType, - default_data_collator, - get_scheduler, - set_seed, -) -from transformers.file_utils import get_full_repo_name -from transformers.utils.versions import require_version -from huggingface_transformer.modeling_bert import BertForSequenceClassification -import deepspeed -from deepspeed.compression.compress import init_compression, redundancy_clean -from deepspeed.compression.helper import recursive_getattr -from util import * -logger = logging.getLogger(__name__) - -require_version("datasets>=1.8.0", "To fix: pip install -r examples/pytorch/text-classification/requirements.txt") - -task_to_keys = { - "cola": ("sentence", None), - "mnli": ("premise", "hypothesis"), - "mrpc": ("sentence1", "sentence2"), - "qnli": ("question", "sentence"), - "qqp": ("question1", "question2"), - "rte": ("sentence1", "sentence2"), - "sst2": ("sentence", None), - "stsb": ("sentence1", "sentence2"), - "wnli": ("sentence1", "sentence2"), -} - - -def parse_args(): - parser = argparse.ArgumentParser(description="Finetune a transformers model on a text classification task") - parser.add_argument( - "--task_name", - type=str, - default=None, - help="The name of the glue task to train on.", - choices=list(task_to_keys.keys()), - ) - parser.add_argument( - "--train_file", type=str, default=None, help="A csv or a json file containing the training data." - ) - parser.add_argument( - "--validation_file", type=str, default=None, help="A csv or a json file containing the validation data." - ) - parser.add_argument( - "--max_length", - type=int, - default=128, - help=( - "The maximum total input sequence length after tokenization. Sequences longer than this will be truncated," - " sequences shorter will be padded if `--pad_to_max_lengh` is passed." - ), - ) - parser.add_argument( - "--pad_to_max_length", - action="store_true", - help="If passed, pad all samples to `max_length`. Otherwise, dynamic padding is used.", - ) - parser.add_argument( - "--model_name_or_path", - type=str, - help="Path to pretrained model or model identifier from huggingface.co/models.", - required=True, - ) - parser.add_argument( - "--use_slow_tokenizer", - action="store_true", - help="If passed, will use a slow tokenizer (not backed by the 🤗 Tokenizers library).", - ) - parser.add_argument( - "--per_device_train_batch_size", - type=int, - default=64, - help="Batch size (per device) for the training dataloader.", - ) - parser.add_argument( - "--per_device_eval_batch_size", - type=int, - default=32, - help="Batch size (per device) for the evaluation dataloader.", - ) - parser.add_argument( - "--learning_rate", - type=float, - default=5e-5, - help="Initial learning rate (after the potential warmup period) to use.", - ) - parser.add_argument("--weight_decay", type=float, default=0.01, help="Weight decay to use.") - parser.add_argument("--num_train_epochs", type=int, default=3, help="Total number of training epochs to perform.") - parser.add_argument( - "--max_train_steps", - type=int, - default=None, - help="Total number of training steps to perform. If provided, overrides num_train_epochs.", - ) - parser.add_argument( - "--gradient_accumulation_steps", - type=int, - default=1, - help="Number of updates steps to accumulate before performing a backward/update pass.", - ) - parser.add_argument( - "--lr_scheduler_type", - type=SchedulerType, - default="linear", - help="The scheduler type to use.", - choices=["linear", "cosine", "cosine_with_restarts", "polynomial", "constant", "constant_with_warmup"], - ) - parser.add_argument( - "--num_warmup_epochs", type=float, default=0, help="Number of epochs for the warmup in the lr scheduler." - ) - parser.add_argument("--output_dir", type=str, default=None, help="Where to store the final model.") - parser.add_argument("--seed", type=int, default=None, help="A seed for reproducible training.") - - - #############deepspeed, compression, and knowledage distillation######### - parser.add_argument("--deepspeed", action="store_true", help="use deepspeed or not") - parser.add_argument("--deepspeed_config", type=str, default=None, help="deepspeed config") - parser.add_argument("--save_best_model", action="store_true", help="save best checkpoint model") - parser.add_argument("--clean_best_model", action="store_true", help="clean the model") - parser.add_argument("--lkd_enabled", action="store_true", help="using lkd or not") - parser.add_argument("--distill_method", type=str, default=None, help="knowledage distillation") - parser.add_argument( - "--local_rank", - type=int, - default=-1, - help="local_rank for distributed training on gpus") - parser.add_argument( - "--model_name_or_path_teacher", - default=None, - type=str, - help= - "Path to pretrained model or model identifier from huggingface.co/models.", - ) - - parser.add_argument( - "--pretrained_dir_student", - type=str, - default=None, - help="Where to load the student pretrained model.") - parser.add_argument( - "--pretrained_dir_teacher", - type=str, - default=None, - help="Where to load the teacher pretrained model.") - parser.add_argument( - "--eval_step", - type=int, - default=1000, - help="when to eval the model.") - - args = parser.parse_args() - - # Sanity checks - if args.task_name is None and args.train_file is None and args.validation_file is None: - raise ValueError("Need either a task name or a training/validation file.") - else: - if args.train_file is not None: - extension = args.train_file.split(".")[-1] - assert extension in ["csv", "json"], "`train_file` should be a csv or a json file." - if args.validation_file is not None: - extension = args.validation_file.split(".")[-1] - assert extension in ["csv", "json"], "`validation_file` should be a csv or a json file." - - return args - - -def main(): - args = parse_args() - print_rank_0 = print_rank(args) - ds_config = None - if args.deepspeed: - with open(args.deepspeed_config) as f: - ds_config = json.load(f) - layer_reduction_enabled, prune_enabled, quantization_enabled = check_and_identify_compresssion(args, ds_config) - args.layer_reduction_enabled = layer_reduction_enabled - # Make one log on every process with the configuration for debugging. - logging.basicConfig( - format="%(asctime)s - %(levelname)s - %(name)s - %(message)s", - datefmt="%m/%d/%Y %H:%M:%S", - level=logging.INFO, - ) - - if args.lkd_enabled: - assert args.distill_method != "zero_stage", "zero_stage is not supported for lkd since we need the teacher model" - - # Setup logging, we only want one process per machine to log things on the screen. - # accelerator.is_local_main_process is only True for one process per machine. - logger.setLevel(logging.ERROR) - datasets.utils.logging.set_verbosity_error() - transformers.utils.logging.set_verbosity_error() - - if args.local_rank == -1: - device = torch.device("cuda") - else: - torch.cuda.set_device(args.local_rank) - device = torch.device("cuda", args.local_rank) - # Initializes the distributed backend which will take care of sychronizing nodes/GPUs - #torch.distributed.init_process_group(backend='nccl') - deepspeed.init_distributed() - if args.seed is not None: - set_seed(args.seed) - random.seed(args.seed) - np.random.seed(args.seed) - torch.manual_seed(args.seed) - torch.cuda.manual_seed_all(args.seed) - torch.distributed.barrier() - # Get the datasets: you can either provide your own CSV/JSON training and evaluation files (see below) - # or specify a GLUE benchmark task (the dataset will be downloaded automatically from the datasets Hub). - - # For CSV/JSON files, this script will use as labels the column called 'label' and as pair of sentences the - # sentences in columns called 'sentence1' and 'sentence2' if such column exists or the first two columns not named - # label if at least two columns are provided. - - # If the CSVs/JSONs contain only one non-label column, the script does single sentence classification on this - # single column. You can easily tweak this behavior (see below) - - # In distributed training, the load_dataset function guarantee that only one local process can concurrently - # download the dataset. - if args.task_name is not None: - # Downloading and loading a dataset from the hub. - raw_datasets = load_dataset("glue", args.task_name) - else: - # Loading the dataset from local csv or json file. - data_files = {} - if args.train_file is not None: - data_files["train"] = args.train_file - if args.validation_file is not None: - data_files["validation"] = args.validation_file - extension = (args.train_file if args.train_file is not None else args.valid_file).split(".")[-1] - raw_datasets = load_dataset(extension, data_files=data_files) - # See more about loading any type of standard or custom dataset at - # https://huggingface.co/docs/datasets/loading_datasets.html. - - # Labels - if args.task_name is not None: - is_regression = args.task_name == "stsb" - if not is_regression: - label_list = raw_datasets["train"].features["label"].names - num_labels = len(label_list) - else: - label_list=None - num_labels = 1 - else: - # Trying to have good defaults here, don't hesitate to tweak to your needs. - is_regression = raw_datasets["train"].features["label"].dtype in ["float32", "float64"] - if is_regression: - label_list=None - num_labels = 1 - else: - # A useful fast method: - # https://huggingface.co/docs/datasets/package_reference/main_classes.html#datasets.Dataset.unique - label_list = raw_datasets["train"].unique("label") - label_list.sort() # Let's sort it for determinism - num_labels = len(label_list) - output_mode = output_modes[args.task_name] - # Load pretrained model and tokenizer - # - # In distributed training, the .from_pretrained methods guarantee that only one local process can concurrently - # download model & vocab. - config = AutoConfig.from_pretrained(args.model_name_or_path, num_labels=num_labels, finetuning_task=args.task_name) - if layer_reduction_enabled: - config.num_hidden_layers = ds_config["compression_training"][ "layer_reduction"]["keep_number_layer"] #<==========================================here we assume there is an "num_hidden_layers" argument - - tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path, use_fast=not args.use_slow_tokenizer) - model = BertForSequenceClassification.from_pretrained( - args.model_name_or_path, - from_tf=bool(".ckpt" in args.model_name_or_path), - config=config, - ) - model.to(device) - teacher_model = None - #### load teacher models - if args.distill_method != 'zero_stage': - if not args.model_name_or_path_teacher: - args.model_name_or_path_teacher = args.model_name_or_path - teacher_config = AutoConfig.from_pretrained( - args.model_name_or_path_teacher, - num_labels=num_labels, - finetuning_task=args.task_name) - teacher_model = BertForSequenceClassification.from_pretrained( - args.model_name_or_path_teacher, - from_tf=bool(".ckpt" in args.model_name_or_path), - config=teacher_config, - ) - teacher_model.to(device) - if args.pretrained_dir_teacher is not None: - teacher_model.load_state_dict( - torch.load(args.pretrained_dir_teacher)) - # model inititalization, config, - if args.deepspeed: - if quantization_enabled or prune_enabled or layer_reduction_enabled: - model = init_compression(model, args.deepspeed_config, teacher_model=teacher_model) #<==========================================compression argument - - if args.pretrained_dir_student is not None: - model.load_state_dict(torch.load(args.pretrained_dir_student)) #<==========================================add weight to students if users provides difference models - - # Preprocessing the datasets - if args.task_name is not None: - sentence1_key, sentence2_key = task_to_keys[args.task_name] - else: - # Again, we try to have some nice defaults but don't hesitate to tweak to your use case. - non_label_column_names = [name for name in raw_datasets["train"].column_names if name != "label"] - if "sentence1" in non_label_column_names and "sentence2" in non_label_column_names: - sentence1_key, sentence2_key = "sentence1", "sentence2" - else: - if len(non_label_column_names) >= 2: - sentence1_key, sentence2_key = non_label_column_names[:2] - else: - sentence1_key, sentence2_key = non_label_column_names[0], None - - # Some models have set the order of the labels to use, so let's make sure we do use it. - label_to_id = None - if ( - model.config.label2id != PretrainedConfig(num_labels=num_labels).label2id - and args.task_name is not None - and not is_regression - ): - # Some have all caps in their config, some don't. - label_name_to_id = {k.lower(): v for k, v in model.config.label2id.items()} - if list(sorted(label_name_to_id.keys())) == list(sorted(label_list)): - print_rank_0( - f"The configuration of the model provided the following label correspondence: {label_name_to_id}. " - "Using it!" - ) - label_to_id = {i: label_name_to_id[label_list[i]] for i in range(num_labels)} - else: - logger.warning( - "Your model seems to have been trained with labels, but they don't match the dataset: ", - f"model labels: {list(sorted(label_name_to_id.keys()))}, dataset labels: {list(sorted(label_list))}." - "\nIgnoring the model labels as a result.", - ) - elif args.task_name is None: - label_to_id = {v: i for i, v in enumerate(label_list)} - - if label_to_id is not None: - model.config.label2id = label_to_id - model.config.id2label = {id: label for label, id in config.label2id.items()} - elif args.task_name is not None and not is_regression: - model.config.label2id = {l: i for i, l in enumerate(label_list)} - model.config.id2label = {id: label for label, id in config.label2id.items()} - - label_to_id = None - replace_config(args, config, model, label_list, num_labels=num_labels, label_to_id=None, is_regression=is_regression) - - padding = "max_length" if args.pad_to_max_length else False - - def preprocess_function(examples): - # Tokenize the texts - texts = ( - (examples[sentence1_key],) if sentence2_key is None else (examples[sentence1_key], examples[sentence2_key]) - ) - result = tokenizer(*texts, padding=padding, max_length=args.max_length, truncation=True) - - if "label" in examples: - if label_to_id is not None: - # Map labels to IDs (not necessary for GLUE tasks) - result["labels"] = [label_to_id[l] for l in examples["label"]] - else: - # In all cases, rename the column to labels because the model will expect that. - result["labels"] = examples["label"] - return result - - processed_datasets = raw_datasets.map( - preprocess_function, - batched=True, - remove_columns=raw_datasets["train"].column_names, - desc="Running tokenizer on dataset", - ) - - train_dataset = processed_datasets["train"] - eval_dataset = processed_datasets["validation_matched" if args.task_name == "mnli" else "validation"] - - # Log a few random samples from the training set: - for index in random.sample(range(len(train_dataset)), 3): - print_rank_0(f"Sample {index} of the training set: {train_dataset[index]}.") - - # DataLoaders creation: - if args.local_rank == -1: - train_sampler = RandomSampler(train_dataset) - else: - train_sampler = DistributedSampler(train_dataset) - train_dataloader = DataLoader(train_dataset, - collate_fn=default_data_collator, - sampler=train_sampler, - batch_size=args.per_device_train_batch_size) - eval_sampler = SequentialSampler(eval_dataset) - eval_dataloader = DataLoader(eval_dataset, - collate_fn=default_data_collator, - sampler=eval_sampler, - batch_size=args.per_device_eval_batch_size) - mm_eval_dataloader = None - if args.task_name == "mnli": - # Final evaluation on mismatched validation set - mm_eval_dataset = processed_datasets["validation_mismatched"] - mm_eval_sampler = SequentialSampler(mm_eval_dataset) - mm_eval_dataloader = DataLoader( - mm_eval_dataset, - collate_fn=default_data_collator, - sampler=mm_eval_sampler, - batch_size=args.per_device_eval_batch_size) - # Optimizer - # Split weights in two groups, one with weight decay and the other not. - no_decay = ["bias", "LayerNorm.weight"] - optimizer_grouped_parameters = [ - { - "params": [p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay)], - "weight_decay": args.weight_decay, - }, - { - "params": [p for n, p in model.named_parameters() if any(nd in n for nd in no_decay)], - "weight_decay": 0.0, - }, - ] - optimizer = AdamW(optimizer_grouped_parameters, lr=args.learning_rate) - - # Scheduler and math around the number of training steps. - num_update_steps_per_epoch = math.ceil(len(train_dataloader) / args.gradient_accumulation_steps) - if args.max_train_steps is None: - args.max_train_steps = math.ceil(args.num_train_epochs * num_update_steps_per_epoch) - else: - args.num_train_epochs = math.ceil(args.max_train_steps / num_update_steps_per_epoch) - - num_warmup_steps = int(args.num_warmup_epochs * num_update_steps_per_epoch) - lr_scheduler = get_scheduler( - name=args.lr_scheduler_type, - optimizer=optimizer, - num_warmup_steps=num_warmup_steps, - num_training_steps=args.max_train_steps, - ) - # Prepare the model first eo enable compression feature - model, optimizer, _, lr_scheduler = deepspeed.initialize( - args=args, - model=model, - optimizer=optimizer, - lr_scheduler=lr_scheduler, - dist_init_required=True) - - - out = do_eval(args, model, eval_dataloader, mm_eval_dataloader, device, is_regression=is_regression) - current_result, _, _, _ = arrange_output(args.task_name, out, None, 0.0) - print_rank_0(f"at step 0 (without LKD) the (student) model's performance for {args.task_name}: {current_result}") - - model.eval() - teacher_model.eval() - start_time = time.time() - - for l in range(model.module.config.num_hidden_layers): # iterate across BERT layers - print_rank_0(f"layer {l}") - student_layer = recursive_getattr(model.module, f'bert.encoder.layer.{l}') # extract the lth layer of student - - optimizer_param = [ - { - "params": [p for n, p in student_layer.named_parameters() if not any(nd in n for nd in no_decay)], - "weight_decay": args.weight_decay, - }, - { - "params": [p for n, p in student_layer.named_parameters() if any(nd in n for nd in no_decay)], - "weight_decay": 0.0, - }, - ] - - optimizer = AdamW(optimizer_param, lr=args.learning_rate) - - updated_steps = 0 - - for _ in range(args.num_train_epochs): - for _, batch in enumerate(train_dataloader): # load each batch - batch = to_device(batch, device) - with torch.no_grad(): - # for simplicity, we always run the full inference of the teacher model. - # To get the best performance, you can run the teacher model only for the first l layers, - # which requires some modifications to the modeling code. - teacher_out = teacher_model(**batch, output_hidden_states=True) # get the output of the teacher model - layer_input = teacher_out.hidden_states[l] # extract the lth-layer's input of teacher - teacher_o = teacher_out.hidden_states[l+1] # extract the lth-layer's output of teacher - - real_mask = teacher_model.bert.get_extended_attention_mask(batch['attention_mask'], \ - batch['input_ids'].shape, batch['input_ids'].device) # get the mask - student_o = student_layer(layer_input, real_mask)[0] # run inference for the student - - loss = torch.nn.functional.mse_loss(student_o, teacher_o) - optimizer.zero_grad() - loss.backward() - optimizer.step() - - updated_steps += 1 - if updated_steps >= args.max_train_steps : # break when the number of steps is reached, typically in hundreds - break - if updated_steps >= args.max_train_steps: - break - - out = do_eval(args, model, eval_dataloader, mm_eval_dataloader, device, is_regression=is_regression) - current_result, _, _, _ = arrange_output(args.task_name, out, None, 0.0) - print_rank_0(f"After {time.time() - start_time}s, (with LKD) the (student) model's performance for {args.task_name}: {current_result}") - - -if __name__ == "__main__": - main() diff --git a/compression/bert/run_glue_no_trainer.py b/compression/bert/run_glue_no_trainer.py deleted file mode 100644 index 6e07d9a3b..000000000 --- a/compression/bert/run_glue_no_trainer.py +++ /dev/null @@ -1,530 +0,0 @@ -# coding=utf-8 -# Copyright 2021 The HuggingFace Inc. team. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" Finetuning a 🤗 Transformers model for sequence classification on GLUE.""" -import argparse -import logging -import math -import time -import os -import random -import json -import numpy as np -from pathlib import Path - -import datasets -from datasets import load_dataset, load_metric -import torch -from torch.utils.data import DataLoader, RandomSampler, SequentialSampler -from torch.utils.data.distributed import DistributedSampler -from tqdm.auto import tqdm - -import transformers -from huggingface_hub import Repository -from transformers import ( - AdamW, - AutoConfig, - AutoModelForSequenceClassification, - AutoTokenizer, - DataCollatorWithPadding, - PretrainedConfig, - SchedulerType, - default_data_collator, - get_scheduler, - set_seed, -) -from transformers.file_utils import get_full_repo_name -from transformers.utils.versions import require_version -from huggingface_transformer.modeling_bert import BertForSequenceClassification -import deepspeed -from deepspeed.compression.compress import init_compression, redundancy_clean - -from util import * -logger = logging.getLogger(__name__) - -require_version("datasets>=1.8.0", "To fix: pip install -r examples/pytorch/text-classification/requirements.txt") - -task_to_keys = { - "cola": ("sentence", None), - "mnli": ("premise", "hypothesis"), - "mrpc": ("sentence1", "sentence2"), - "qnli": ("question", "sentence"), - "qqp": ("question1", "question2"), - "rte": ("sentence1", "sentence2"), - "sst2": ("sentence", None), - "stsb": ("sentence1", "sentence2"), - "wnli": ("sentence1", "sentence2"), -} - - -def parse_args(): - parser = argparse.ArgumentParser(description="Finetune a transformers model on a text classification task") - parser.add_argument( - "--task_name", - type=str, - default=None, - help="The name of the glue task to train on.", - choices=list(task_to_keys.keys()), - ) - parser.add_argument( - "--train_file", type=str, default=None, help="A csv or a json file containing the training data." - ) - parser.add_argument( - "--validation_file", type=str, default=None, help="A csv or a json file containing the validation data." - ) - parser.add_argument( - "--max_length", - type=int, - default=128, - help=( - "The maximum total input sequence length after tokenization. Sequences longer than this will be truncated," - " sequences shorter will be padded if `--pad_to_max_lengh` is passed." - ), - ) - parser.add_argument( - "--pad_to_max_length", - action="store_true", - help="If passed, pad all samples to `max_length`. Otherwise, dynamic padding is used.", - ) - parser.add_argument( - "--model_name_or_path", - type=str, - help="Path to pretrained model or model identifier from huggingface.co/models.", - required=True, - ) - parser.add_argument( - "--use_slow_tokenizer", - action="store_true", - help="If passed, will use a slow tokenizer (not backed by the 🤗 Tokenizers library).", - ) - parser.add_argument( - "--per_device_train_batch_size", - type=int, - default=64, - help="Batch size (per device) for the training dataloader.", - ) - parser.add_argument( - "--per_device_eval_batch_size", - type=int, - default=32, - help="Batch size (per device) for the evaluation dataloader.", - ) - parser.add_argument( - "--learning_rate", - type=float, - default=5e-5, - help="Initial learning rate (after the potential warmup period) to use.", - ) - parser.add_argument("--weight_decay", type=float, default=0.01, help="Weight decay to use.") - parser.add_argument("--num_train_epochs", type=int, default=3, help="Total number of training epochs to perform.") - parser.add_argument( - "--max_train_steps", - type=int, - default=None, - help="Total number of training steps to perform. If provided, overrides num_train_epochs.", - ) - parser.add_argument( - "--gradient_accumulation_steps", - type=int, - default=1, - help="Number of updates steps to accumulate before performing a backward/update pass.", - ) - parser.add_argument( - "--lr_scheduler_type", - type=SchedulerType, - default="linear", - help="The scheduler type to use.", - choices=["linear", "cosine", "cosine_with_restarts", "polynomial", "constant", "constant_with_warmup"], - ) - parser.add_argument( - "--num_warmup_epochs", type=float, default=0, help="Number of epochs for the warmup in the lr scheduler." - ) - parser.add_argument("--output_dir", type=str, default=None, help="Where to store the final model.") - parser.add_argument("--seed", type=int, default=None, help="A seed for reproducible training.") - - - #############deepspeed, compression, and knowledage distillation######### - parser.add_argument("--deepspeed", action="store_true", help="use deepspeed or not") - parser.add_argument("--deepspeed_config", type=str, default=None, help="deepspeed config") - parser.add_argument("--save_best_model", action="store_true", help="save best checkpoint model") - parser.add_argument("--clean_best_model", action="store_true", help="clean the model") - parser.add_argument("--distill_method", type=str, default=None, help="knowledage distillation") - parser.add_argument( - "--local_rank", - type=int, - default=-1, - help="local_rank for distributed training on gpus") - parser.add_argument( - "--model_name_or_path_teacher", - default=None, - type=str, - help= - "Path to pretrained model or model identifier from huggingface.co/models.", - ) - parser.add_argument( - "--pretrained_dir_student", - type=str, - default=None, - help="Where to load the student pretrained model.") - parser.add_argument( - "--pretrained_dir_teacher", - type=str, - default=None, - help="Where to load the teacher pretrained model.") - parser.add_argument( - "--eval_step", - type=int, - default=1000, - help="when to eval the model.") - - args = parser.parse_args() - - # Sanity checks - if args.task_name is None and args.train_file is None and args.validation_file is None: - raise ValueError("Need either a task name or a training/validation file.") - else: - if args.train_file is not None: - extension = args.train_file.split(".")[-1] - assert extension in ["csv", "json"], "`train_file` should be a csv or a json file." - if args.validation_file is not None: - extension = args.validation_file.split(".")[-1] - assert extension in ["csv", "json"], "`validation_file` should be a csv or a json file." - - return args - - -def main(): - args = parse_args() - print_rank_0 = print_rank(args) - ds_config = None - if args.deepspeed: - with open(args.deepspeed_config) as f: - ds_config = json.load(f) - layer_reduction_enabled, prune_enabled, quantization_enabled = check_and_identify_compresssion(args, ds_config) - args.layer_reduction_enabled = layer_reduction_enabled - # Make one log on every process with the configuration for debugging. - logging.basicConfig( - format="%(asctime)s - %(levelname)s - %(name)s - %(message)s", - datefmt="%m/%d/%Y %H:%M:%S", - level=logging.INFO, - ) - - # Setup logging, we only want one process per machine to log things on the screen. - # accelerator.is_local_main_process is only True for one process per machine. - logger.setLevel(logging.ERROR) - datasets.utils.logging.set_verbosity_error() - transformers.utils.logging.set_verbosity_error() - - if args.local_rank == -1: - device = torch.device("cuda") - else: - torch.cuda.set_device(args.local_rank) - device = torch.device("cuda", args.local_rank) - # Initializes the distributed backend which will take care of sychronizing nodes/GPUs - #torch.distributed.init_process_group(backend='nccl') - deepspeed.init_distributed() - if args.seed is not None: - set_seed(args.seed) - random.seed(args.seed) - np.random.seed(args.seed) - torch.manual_seed(args.seed) - torch.cuda.manual_seed_all(args.seed) - torch.distributed.barrier() - # Get the datasets: you can either provide your own CSV/JSON training and evaluation files (see below) - # or specify a GLUE benchmark task (the dataset will be downloaded automatically from the datasets Hub). - - # For CSV/JSON files, this script will use as labels the column called 'label' and as pair of sentences the - # sentences in columns called 'sentence1' and 'sentence2' if such column exists or the first two columns not named - # label if at least two columns are provided. - - # If the CSVs/JSONs contain only one non-label column, the script does single sentence classification on this - # single column. You can easily tweak this behavior (see below) - - # In distributed training, the load_dataset function guarantee that only one local process can concurrently - # download the dataset. - if args.task_name is not None: - # Downloading and loading a dataset from the hub. - raw_datasets = load_dataset("glue", args.task_name) - else: - # Loading the dataset from local csv or json file. - data_files = {} - if args.train_file is not None: - data_files["train"] = args.train_file - if args.validation_file is not None: - data_files["validation"] = args.validation_file - extension = (args.train_file if args.train_file is not None else args.valid_file).split(".")[-1] - raw_datasets = load_dataset(extension, data_files=data_files) - # See more about loading any type of standard or custom dataset at - # https://huggingface.co/docs/datasets/loading_datasets.html. - - # Labels - if args.task_name is not None: - is_regression = args.task_name == "stsb" - if not is_regression: - label_list = raw_datasets["train"].features["label"].names - num_labels = len(label_list) - else: - label_list=None - num_labels = 1 - else: - # Trying to have good defaults here, don't hesitate to tweak to your needs. - is_regression = raw_datasets["train"].features["label"].dtype in ["float32", "float64"] - if is_regression: - label_list=None - num_labels = 1 - else: - # A useful fast method: - # https://huggingface.co/docs/datasets/package_reference/main_classes.html#datasets.Dataset.unique - label_list = raw_datasets["train"].unique("label") - label_list.sort() # Let's sort it for determinism - num_labels = len(label_list) - output_mode = output_modes[args.task_name] - # Load pretrained model and tokenizer - # - # In distributed training, the .from_pretrained methods guarantee that only one local process can concurrently - # download model & vocab. - config = AutoConfig.from_pretrained(args.model_name_or_path, num_labels=num_labels, finetuning_task=args.task_name) - if layer_reduction_enabled: - config.num_hidden_layers = ds_config["compression_training"][ "layer_reduction"]["keep_number_layer"] #<==========================================here we assume there is an "num_hidden_layers" argument - - tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path, use_fast=not args.use_slow_tokenizer) - model = BertForSequenceClassification.from_pretrained( - args.model_name_or_path, - from_tf=bool(".ckpt" in args.model_name_or_path), - config=config, - ) - model.to(device) - teacher_model = None - #### load teacher models - if args.distill_method != 'zero_stage': - if not args.model_name_or_path_teacher: - args.model_name_or_path_teacher = args.model_name_or_path - teacher_config = AutoConfig.from_pretrained( - args.model_name_or_path_teacher, - num_labels=num_labels, - finetuning_task=args.task_name) - teacher_model = BertForSequenceClassification.from_pretrained( - args.model_name_or_path_teacher, - from_tf=bool(".ckpt" in args.model_name_or_path), - config=teacher_config, - ) - teacher_model.to(device) - if args.pretrained_dir_teacher is not None: - teacher_model.load_state_dict( - torch.load(args.pretrained_dir_teacher)) - # model inititalization, config, - if args.deepspeed: - if quantization_enabled or prune_enabled or layer_reduction_enabled: - model = init_compression(model, args.deepspeed_config, teacher_model=teacher_model) #<==========================================compression argument - - if args.pretrained_dir_student is not None: - model.load_state_dict(torch.load(args.pretrained_dir_student)) #<==========================================add weight to students if users provides difference models - - # Preprocessing the datasets - if args.task_name is not None: - sentence1_key, sentence2_key = task_to_keys[args.task_name] - else: - # Again, we try to have some nice defaults but don't hesitate to tweak to your use case. - non_label_column_names = [name for name in raw_datasets["train"].column_names if name != "label"] - if "sentence1" in non_label_column_names and "sentence2" in non_label_column_names: - sentence1_key, sentence2_key = "sentence1", "sentence2" - else: - if len(non_label_column_names) >= 2: - sentence1_key, sentence2_key = non_label_column_names[:2] - else: - sentence1_key, sentence2_key = non_label_column_names[0], None - - # Some models have set the order of the labels to use, so let's make sure we do use it. - label_to_id = None - if ( - model.config.label2id != PretrainedConfig(num_labels=num_labels).label2id - and args.task_name is not None - and not is_regression - ): - # Some have all caps in their config, some don't. - label_name_to_id = {k.lower(): v for k, v in model.config.label2id.items()} - if list(sorted(label_name_to_id.keys())) == list(sorted(label_list)): - print_rank_0( - f"The configuration of the model provided the following label correspondence: {label_name_to_id}. " - "Using it!" - ) - label_to_id = {i: label_name_to_id[label_list[i]] for i in range(num_labels)} - else: - logger.warning( - "Your model seems to have been trained with labels, but they don't match the dataset: ", - f"model labels: {list(sorted(label_name_to_id.keys()))}, dataset labels: {list(sorted(label_list))}." - "\nIgnoring the model labels as a result.", - ) - elif args.task_name is None: - label_to_id = {v: i for i, v in enumerate(label_list)} - - if label_to_id is not None: - model.config.label2id = label_to_id - model.config.id2label = {id: label for label, id in config.label2id.items()} - elif args.task_name is not None and not is_regression: - model.config.label2id = {l: i for i, l in enumerate(label_list)} - model.config.id2label = {id: label for label, id in config.label2id.items()} - - label_to_id = None - replace_config(args, config, model, label_list, num_labels=num_labels, label_to_id=None, is_regression=is_regression) - - padding = "max_length" if args.pad_to_max_length else False - - def preprocess_function(examples): - # Tokenize the texts - texts = ( - (examples[sentence1_key],) if sentence2_key is None else (examples[sentence1_key], examples[sentence2_key]) - ) - result = tokenizer(*texts, padding=padding, max_length=args.max_length, truncation=True) - - if "label" in examples: - if label_to_id is not None: - # Map labels to IDs (not necessary for GLUE tasks) - result["labels"] = [label_to_id[l] for l in examples["label"]] - else: - # In all cases, rename the column to labels because the model will expect that. - result["labels"] = examples["label"] - return result - - processed_datasets = raw_datasets.map( - preprocess_function, - batched=True, - remove_columns=raw_datasets["train"].column_names, - desc="Running tokenizer on dataset", - ) - - train_dataset = processed_datasets["train"] - eval_dataset = processed_datasets["validation_matched" if args.task_name == "mnli" else "validation"] - - # Log a few random samples from the training set: - for index in random.sample(range(len(train_dataset)), 3): - print_rank_0(f"Sample {index} of the training set: {train_dataset[index]}.") - - # DataLoaders creation: - if args.local_rank == -1: - train_sampler = RandomSampler(train_dataset) - else: - train_sampler = DistributedSampler(train_dataset) - train_dataloader = DataLoader(train_dataset, - collate_fn=default_data_collator, - sampler=train_sampler, - batch_size=args.per_device_train_batch_size) - eval_sampler = SequentialSampler(eval_dataset) - eval_dataloader = DataLoader(eval_dataset, - collate_fn=default_data_collator, - sampler=eval_sampler, - batch_size=args.per_device_eval_batch_size) - mm_eval_dataloader = None - if args.task_name == "mnli": - # Final evaluation on mismatched validation set - mm_eval_dataset = processed_datasets["validation_mismatched"] - mm_eval_sampler = SequentialSampler(mm_eval_dataset) - mm_eval_dataloader = DataLoader( - mm_eval_dataset, - collate_fn=default_data_collator, - sampler=mm_eval_sampler, - batch_size=args.per_device_eval_batch_size) - # Optimizer - # Split weights in two groups, one with weight decay and the other not. - no_decay = ["bias", "LayerNorm.weight"] - optimizer_grouped_parameters = [ - { - "params": [p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay)], - "weight_decay": args.weight_decay, - }, - { - "params": [p for n, p in model.named_parameters() if any(nd in n for nd in no_decay)], - "weight_decay": 0.0, - }, - ] - optimizer = AdamW(optimizer_grouped_parameters, lr=args.learning_rate) - - # Scheduler and math around the number of training steps. - num_update_steps_per_epoch = math.ceil(len(train_dataloader) / args.gradient_accumulation_steps) - if args.max_train_steps is None: - args.max_train_steps = math.ceil(args.num_train_epochs * num_update_steps_per_epoch) - else: - args.num_train_epochs = math.ceil(args.max_train_steps / num_update_steps_per_epoch) - num_warmup_steps = int(args.num_warmup_epochs * num_update_steps_per_epoch) - lr_scheduler = get_scheduler( - name=args.lr_scheduler_type, - optimizer=optimizer, - num_warmup_steps=num_warmup_steps, - num_training_steps=args.max_train_steps, - ) - # Prepare the model first - model, optimizer, _, lr_scheduler = deepspeed.initialize( - args=args, - model=model, - optimizer=optimizer, - lr_scheduler=lr_scheduler, - dist_init_required=True) - - if teacher_model is not None: - teacher_model, _, _, _ = deepspeed.initialize(args=args, model=teacher_model) - - print_rank_0("***** Running training *****") - print_rank_0(f" Num examples = {len(train_dataset)}") - print_rank_0(f" Num Epochs = {args.num_train_epochs}") - print_rank_0(f" Instantaneous batch size per device = {args.per_device_train_batch_size}") - print_rank_0(f" Gradient Accumulation steps = {args.gradient_accumulation_steps}") - print_rank_0(f" Total optimization steps = {args.max_train_steps}") - # Only show the progress bar once on each machine. - # If passed along, set the training seed now. - updated_steps = 0 - forward_step = 0 - best_dev_acc = 0.0 - previous_best = None - teacher_result = None - if teacher_model is not None: - teacher_out = do_eval(args, teacher_model, eval_dataloader, mm_eval_dataloader, device, is_regression=is_regression) - teacher_result, _, _, _ = arrange_output(args.task_name, teacher_out, previous_best, 0) - print_rank_0(f"teacher model: {teacher_result}") - teacher_model.eval() - stat_history = {"lr1": [], "lr2": [], 'train_att_loss': [], 'train_ffn_loss': [], 'train_loss': [], 'eval': [], 'tmp_loss':[0,0,0,0], 'forward_step':[], 'teacher_result':teacher_result} - out = do_eval(args, model, eval_dataloader, mm_eval_dataloader, device, is_regression=is_regression) - current_result, _, _, _ = arrange_output(args.task_name, out, previous_best, best_dev_acc) - print_rank_0(f"at step 0 the (student) model's performance for {args.task_name}: {current_result}") - forward_fun = forward_loss(args, ds_config, output_mode) - for epoch in range(args.num_train_epochs): - model.train() - start_time = time.time() - for step, batch in enumerate(train_dataloader): - batch = to_device(batch, device) - all_loss = forward_fun(batch, model, teacher_model=teacher_model) - model.backward(all_loss[0]) #<=======================when using deepspedd engine fp16, we should not use loss.backward() - model.step() - stat_history = record_stat(stat_history, all_loss,) - if step % args.gradient_accumulation_steps == 0 or step == len(train_dataloader) - 1: - updated_steps += 1 - optimizer.zero_grad() - forward_step += 1 - if forward_step % args.eval_step ==0 or updated_steps == args.max_train_steps or step == len(train_dataloader) - 1: - results = do_eval(args, model, eval_dataloader, mm_eval_dataloader, device, is_regression=is_regression) - arrange_out = arrange_output(args.task_name, results, previous_best, best_dev_acc) - stat_history, best_dev_acc, save_model = update_stat_and_print(args, print_rank_0, forward_step, stat_history, optimizer, arrange_out, ds_config) - if save_model and args.save_best_model: - print_rank_0(f'new best checkpoint, saving model to {args.output_dir}') - save_checkpoint_and_config(args, model, config, tokenizer, ds_config=ds_config) - if updated_steps > args.max_train_steps: - break - end_time = time.time() - epoch_mins, epoch_secs = epoch_time(start_time, end_time) - print_rank_0(f'Epoch: {epoch+1:02} | Time: {epoch_mins}m {epoch_secs}s') - - if args.clean_best_model and args.save_best_model: - save_clean_best_model(args, print_rank_0, model, tokenizer, config, redundancy_clean, eval_dataloader, mm_eval_dataloader, device, is_regression, previous_best, best_dev_acc, ds_config=ds_config) - -if __name__ == "__main__": - main() diff --git a/compression/bert/util.py b/compression/bert/util.py deleted file mode 100644 index d40ae8d27..000000000 --- a/compression/bert/util.py +++ /dev/null @@ -1,368 +0,0 @@ -import torch -from torch.nn import CrossEntropyLoss, MSELoss -import datasets -from datasets import load_dataset, load_metric -import copy -import os -import json -import transformers -from transformers import AutoConfig, PretrainedConfig -import huggingface_transformer -from huggingface_transformer.modeling_bert import BertForSequenceClassification -import logging -import numpy as np -import math - -logger = logging.getLogger(__name__) -acc_tasks = ["mnli", "mrpc", "sst2", "qqp", "qnli", "rte"] -corr_tasks = ["stsb"] -mcc_tasks = ["cola"] -output_modes = { - "cola": "classification", - "mnli": "classification", - "mrpc": "classification", - "sst2": "classification", - "stsb": "regression", - "qqp": "classification", - "qnli": "classification", - "rte": "classification" -} -def epoch_time(start_time: int, end_time: int): - elapsed_time = end_time - start_time - elapsed_mins = int(elapsed_time / 60) - elapsed_secs = int(elapsed_time - (elapsed_mins * 60)) - return elapsed_mins, elapsed_secs - -def print_rank(args): - def _print_rank_0(msg): - if args.local_rank <= 0: - print(msg) - return _print_rank_0 -def to_device(batch, device): - output = {} - for k, v in batch.items(): - try: - output[k] = v.to(device) - except: - output[k] = v - return output - -def check_and_identify_compresssion(args, ds_config): - assert args.per_device_train_batch_size == ds_config["train_micro_batch_size_per_gpu"] - assert args.gradient_accumulation_steps == ds_config["train_batch_size"] / ds_config["train_micro_batch_size_per_gpu"] - quantization_enabled, prune_enabled, layer_reduction_enabled = False, False, False - if ds_config["compression_training"]["layer_reduction"]["enabled"]: - layer_reduction_enabled = True - - if ds_config["compression_training"]["sparse_pruning"]["shared_parameters"]["enabled"] or \ - ds_config["compression_training"]["row_pruning"]["shared_parameters"]["enabled"] or \ - ds_config["compression_training"]["head_pruning"]["shared_parameters"]["enabled"]: - prune_enabled = True - - if ds_config["compression_training"]["weight_quantization"]["shared_parameters"]["enabled"] or \ - ds_config["compression_training"]["activation_quantization"]["shared_parameters"]["enabled"]: - quantization_enabled = True - - return layer_reduction_enabled, prune_enabled, quantization_enabled - -def soft_cross_entropy(predicts, targets): - student_likelihood = torch.nn.functional.log_softmax(predicts, dim=-1) - targets_prob = torch.nn.functional.softmax(targets, dim=-1) - return (-targets_prob * student_likelihood).mean() - - -# Some models have set the order of the labels to use, so let's make sure we do use it. -def replace_config(args, config, model_tmp, label_list, num_labels=2,label_to_id=None, is_regression=False): - if (model_tmp.config.label2id != PretrainedConfig(num_labels=num_labels).label2id - and args.task_name is not None and not is_regression): - # Some have all caps in their config, some don't. - label_name_to_id = { - k.lower(): v - for k, v in model_tmp.config.label2id.items() - } - if list(sorted(label_name_to_id.keys())) == list( - sorted(label_list)): - logger.info( - f"The configuration of the model provided the following label correspondence: {label_name_to_id}. " - "Using it!") - label_to_id = { - i: label_name_to_id[label_list[i]] - for i in range(num_labels) - } - else: - logger.warning( - "Your model seems to have been trained with labels, but they don't match the dataset: ", - f"model labels: {list(sorted(label_name_to_id.keys()))}, dataset labels: {list(sorted(label_list))}." - "\nIgnoring the model labels as a result.", - ) - elif args.task_name is None: - label_to_id = {v: i for i, v in enumerate(label_list)} - if label_to_id is not None: - model_tmp.config.label2id = label_to_id - model_tmp.config.id2label = { - id: label - for label, id in config.label2id.items() - } - elif args.task_name is not None and not is_regression: - model_tmp.config.label2id = { - l: i - for i, l in enumerate(label_list) - } - model_tmp.config.id2label = { - id: label - for label, id in config.label2id.items() - } - - -def do_eval(args, model, eval_dataloader, mm_eval_dataloader, device, is_regression=False): - model.eval() - if args.task_name is not None: - metric = load_metric("glue", args.task_name) - else: - metric = load_metric("accuracy") - - for step, batch in enumerate(eval_dataloader): - batch = to_device(batch, device) - outputs = model(**batch) - predictions = outputs.logits.argmax(dim=-1) if not is_regression else outputs.logits.squeeze() - metric.add_batch(predictions=predictions, references=batch["labels"]) - eval_metric = metric.compute() - - eval_metric1 = None - if args.task_name == 'mnli': - metric1 = load_metric("accuracy") - for step, batch in enumerate(mm_eval_dataloader): - batch = to_device(batch, device) - outputs = model(**batch) - predictions = outputs.logits.argmax(dim=-1) if not is_regression else outputs.logits.squeeze() - metric1.add_batch(predictions=predictions, references=batch["labels"]) - eval_metric1 = metric1.compute() - model.train() - return eval_metric, eval_metric1 - -def arrange_output(task_name, results, previous_best, best_dev_acc): - result = results[0] - result1 = results[1] - save_model = False - if task_name in acc_tasks: - if task_name in ['sst2', 'qnli', 'rte']: - current_result = f"acc:{result['accuracy']}" - elif task_name == 'mnli': - current_result = f"acc/mm-acc:{result['accuracy']}/{result1['accuracy']}" - elif task_name in ['mrpc', 'qqp']: - current_result = f"f1/acc:{result['f1']}/{result['accuracy']}" - - if result['accuracy'] > best_dev_acc: - save_model = True - best_dev_acc = result['accuracy'] - previous_best = current_result - - elif task_name in corr_tasks: - current_result = f"pearson/spearmanr:{result['pearson']}/{result['spearmanr']}" - if result['pearson'] > best_dev_acc: - best_dev_acc = result['pearson'] - save_model = True - previous_best = current_result - elif task_name in mcc_tasks: - current_result = f"mcc:{result['matthews_correlation']}" - if result['matthews_correlation'] > best_dev_acc: - best_dev_acc = result['matthews_correlation'] - save_model = True - previous_best = current_result - return current_result, previous_best, best_dev_acc, save_model - - -def forward_loss(args, ds_config, output_mode): - assert args.distill_method in ['zero_stage', 'one_stage'] - - if args.distill_method == 'zero_stage': - def _simple_function(batch, model, teacher_model=None): - outputs = model(**batch) - return [outputs.loss, 0, 0 ,0 ] - return _simple_function - - elif args.distill_method == 'one_stage': - loss_mse = MSELoss() - if output_mode == "classification": - cls_loss_func = soft_cross_entropy - elif output_mode == "regression": - cls_loss_func = loss_mse - - def _kd_function(batch, model, teacher_model): - att_loss, rep_loss, loss, = 0., 0., 0. - outputs = model(**batch, output_attentions=True, output_hidden_states=True) - student_logits, student_reps, student_atts = outputs.logits, outputs.hidden_states, outputs.attentions - with torch.no_grad(): - outputs_teacher = teacher_model(**batch, output_attentions=True, output_hidden_states=True) - teacher_logits, teacher_reps, teacher_atts = outputs_teacher.logits, outputs_teacher.hidden_states, outputs_teacher.attentions - cls_loss = cls_loss_func(student_logits, teacher_logits) - loss += cls_loss - teacher_layer_num, student_layer_num = len(teacher_atts), len(student_atts) - if args.layer_reduction_enabled: - teacher_layers = [x for x in ds_config["compression_training"]["layer_reduction"]['teacher_layer']] - att_list = [x for x in teacher_layers] - rep_list = [teacher_layers[0] - 1,] + [x + 1 for x in teacher_layers] - else: - ## ATTENTION: The knowledge distillation is designed for skip-layer KD - layers_per_block = int(teacher_layer_num / student_layer_num) ###[1, 3, 5, 7, 9, 11] - att_list = [i * layers_per_block + layers_per_block - 1 for i in range(student_layer_num)] - rep_list = [i * layers_per_block for i in range(student_layer_num + 1)] ###[0, 2, 4, 6, 8, 10, 12] - - new_teacher_reps = [teacher_reps[i] for i in rep_list] - new_teacher_atts = [teacher_atts[i] for i in att_list] - - for student_att, teacher_att in zip(student_atts, new_teacher_atts): - tmp_loss = loss_mse(student_att, teacher_att) - att_loss += tmp_loss - - for student_rep, teacher_rep in zip(student_reps, new_teacher_reps): - tmp_loss = loss_mse(student_rep, teacher_rep) - rep_loss += tmp_loss - loss += att_loss + rep_loss - return [loss, rep_loss.item(), cls_loss.item(), att_loss.item(), ] - - return _kd_function - - -def record_stat(stat_history, all_loss): - past_loss = stat_history['tmp_loss'] - tr_loss, tr_rep_loss, tr_cls_loss, tr_att_loss = past_loss[0]+all_loss[0].item(), past_loss[1]+all_loss[1], past_loss[2]+all_loss[2], past_loss[3]+all_loss[3] - stat_history['tmp_loss'] = [tr_loss, tr_rep_loss, tr_cls_loss, tr_att_loss] - return stat_history - - -def update_stat_and_print(args, print_rank_0, forward_step, stat_history, optimizer, arrange_out, ds_config): - eval_result, previous_best, best_dev_acc, save_model = arrange_out[0], arrange_out[1], arrange_out[2], arrange_out[3] - print_rank_0( f"***** Running evaluation Stage {args.distill_method}*****") - print_rank_0(" {} step of {}".format(forward_step, args.max_train_steps)) - - past_loss = stat_history['tmp_loss'] - tr_loss, tr_rep_loss, tr_cls_loss, tr_att_loss = past_loss[0], past_loss[1], past_loss[2], past_loss[3], - loss = tr_loss / (args.eval_step + 1) - cls_loss = tr_cls_loss / (args.eval_step + 1) - att_loss = tr_att_loss / (args.eval_step + 1) - rep_loss = tr_rep_loss / (args.eval_step + 1) - - stat_history['lr1'].append(optimizer.param_groups[0]["lr"]) - stat_history['lr2'].append(optimizer.param_groups[1]["lr"]) - stat_history['train_ffn_loss'].append(rep_loss) - stat_history['train_att_loss'].append(att_loss) - stat_history['train_loss'].append(loss) - stat_history['eval'].append(eval_result) - stat_history['forward_step'].append(forward_step) - teacher_result = stat_history['teacher_result'] - try: - print_rank_0( - '{' + - f"eval_result: {eval_result}, step: {forward_step/args.max_train_steps}, train_loss: {stat_history['train_loss'][-1]}, train_ffn_loss: {stat_history['train_ffn_loss'][-1]}, train_att_loss:{stat_history['train_att_loss'][-1]}, lr1: { stat_history['lr1'][-1]}, lr2: { stat_history['lr2'][-1]}, " - + '}') - except: - print_rank_0(eval_result) - if previous_best is not None: - print_rank_0(f"task {args.task_name}, teacher_result: {teacher_result}\nPrevious best: {previous_best}") - - tr_loss, tr_rep_loss, tr_cls_loss, tr_att_loss = 0., 0., 0., 0., - stat_history['tmp_loss'] = [ 0, 0., 0., 0.,] - - ##############for pruning - sparse_prune, row_prune, head_prune = False, False, False - sparse_iter, row_iter, head_iter = 0, 0, 0 - if ds_config["compression_training"]["sparse_pruning"]["shared_parameters"]["enabled"]: - sparse_prune = True - sparse_iter = ds_config["compression_training"]["sparse_pruning"]["shared_parameters"]["schedule_offset"] - if ds_config["compression_training"]["row_pruning"]["shared_parameters"]["enabled"]: - row_prune = True - row_iter = ds_config["compression_training"]["row_pruning"]["shared_parameters"]["schedule_offset"] - if ds_config["compression_training"]["head_pruning"]["shared_parameters"]["enabled"]: - head_prune = True - head_iter = ds_config["compression_training"]["head_pruning"]["shared_parameters"]["schedule_offset"] - if sparse_prune or row_prune or head_prune: - save_iter = np.max([sparse_iter, row_iter, head_iter]) - if forward_step0.7.0), which contains the compression library. - -#### Key File: train.py - -The python code is modified based on (https://github.com/deepspeedai/DeepSpeedExamples/tree/master/cifar). The key added feature is the compression pipeline. - -#### Folders (config) - -* **config:** This folder provides DeepSpeed configuration, including quantization, pruning and layer reduction. - -#### bash script -* **run_compress.sh** This bash script contains jobs for training a checkpoint and then compressing this checkpoint. See more descriptions and results in our [tutorial page](https://www.deepspeed.ai/). - diff --git a/compression/cifar/config/ds_config.json b/compression/cifar/config/ds_config.json deleted file mode 100644 index 82f5cf705..000000000 --- a/compression/cifar/config/ds_config.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "train_batch_size" : 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 50, - - "optimizer": { - "type": "Adam", - "params": { - "lr": 0.001, - "betas": [ - 0.8, - 0.999 - ], - "eps": 1e-8, - "weight_decay": 3e-7 - } - }, - - "zero_optimization": { - "stage": 0 - }, - - "fp16":{ - "enabled": true - }, - - "gradient_clipping": 1.0, - "prescale_gradients": true, - - "wall_clock_breakdown" : false - } - diff --git a/compression/cifar/config/ds_config_channel_prune.json b/compression/cifar/config/ds_config_channel_prune.json deleted file mode 100644 index 9d55ad2c6..000000000 --- a/compression/cifar/config/ds_config_channel_prune.json +++ /dev/null @@ -1,128 +0,0 @@ -{ - "train_batch_size" : 32, - "train_micro_batch_size_per_gpu": 32, - "steps_per_print": 50, - - "optimizer": { - "type": "Adam", - "params": { - "lr": 0.001, - "betas": [ - 0.8, - 0.999 - ], - "eps": 1e-8, - "weight_decay": 3e-7 - } - }, - - "zero_optimization": { - "stage": 0 - }, - - "fp16":{ - "enabled": true - }, - - "gradient_clipping": 1.0, - "prescale_gradients": true, - - "wall_clock_breakdown" : false, - "compression_training": { - "weight_quantization": { - "shared_parameters":{ - "enabled": false, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 1, - "quantize_verbose": true, - "quantization_type": "asymmetric", - "quantize_weight_in_forward": false, - "rounding": "nearest", - "fp16_mixed_quantize":{ - "enabled": false, - "quantize_change_ratio": 0.001 - } - }, - "different_groups":{ - "wq1": { - "params": { - "start_bits": 12, - "target_bits": 8, - "quantization_period": 50 - }, - "modules": [ - "conv1" - ] - }, - "wq2": { - "params": { - "start_bits": 12, - "target_bits": 4, - "quantization_period": 50 - }, - "modules": [ - "conv2" - ] - } - } - }, - "activation_quantization": { - "shared_parameters":{ - "enabled": false, - "quantization_type": "asymmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups":{ - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "conv1" - ] - } - } - }, - "sparse_pruning":{ - "shared_parameters":{ - "enabled": false, - "schedule_offset": 0, - "method": "l1" - }, - "different_groups":{ - "sp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "conv1", - "conv2" - ] - } - } - }, - "channel_pruning":{ - "shared_parameters":{ - "enabled": true, - "schedule_offset": 0, - "method": "topk" - }, - "different_groups":{ - "cp1": { - "params": { - "dense_ratio": 0.5 - }, - "modules": [ - "layer....conv1" - ], - "related_modules": [ - ["layer....conv2", "layer....bn1"] - ] - } - } - } - } - } - diff --git a/compression/cifar/resnet.py b/compression/cifar/resnet.py deleted file mode 100644 index 21f45be72..000000000 --- a/compression/cifar/resnet.py +++ /dev/null @@ -1,255 +0,0 @@ -from __future__ import absolute_import -'''Resnet for cifar dataset. -Ported form -https://github.com/facebook/fb.resnet.torch -and -https://github.com/pytorch/vision/blob/master/torchvision/models/resnet.py -(c) YANG, Wei -''' -import torch.nn as nn -import math -from copy import deepcopy - -__all__ = ['resnet'] - - -def conv3x3(in_planes, out_planes, stride=1): - "3x3 convolution with padding" - return nn.Conv2d(in_planes, - out_planes, - kernel_size=3, - stride=stride, - padding=1, - bias=False) - - -class BasicBlock(nn.Module): - expansion = 1 - - def __init__(self, - inplanes, - planes, - residual_not, - batch_norm_not, - stride=1, - downsample=None): - super(BasicBlock, self).__init__() - self.residual_not = residual_not - self.batch_norm_not = batch_norm_not - self.conv1 = conv3x3(inplanes, planes, stride) - if self.batch_norm_not: - self.bn1 = nn.BatchNorm2d(planes) - self.relu = nn.ReLU(inplace=True) - self.conv2 = conv3x3(planes, planes) - if self.batch_norm_not: - self.bn2 = nn.BatchNorm2d(planes) - self.downsample = downsample - self.stride = stride - - def forward(self, x): - residual = x - - out = self.conv1(x) - if self.batch_norm_not: - out = self.bn1(out) - out = self.relu(out) - - out = self.conv2(out) - if self.batch_norm_not: - out = self.bn2(out) - - if self.downsample is not None: - residual = self.downsample(x) - if self.residual_not: - out += residual - out = self.relu(out) - - return out - - -class Bottleneck(nn.Module): - expansion = 4 - - def __init__(self, - inplanes, - planes, - residual_not, - batch_norm_not, - stride=1, - downsample=None): - super(Bottleneck, self).__init__() - self.residual_not = residual_not - self.batch_norm_not = batch_norm_not - self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False) - if self.batch_norm_not: - self.bn1 = nn.BatchNorm2d(planes) - self.conv2 = nn.Conv2d(planes, - planes, - kernel_size=3, - stride=stride, - padding=1, - bias=False) - if self.batch_norm_not: - self.bn2 = nn.BatchNorm2d(planes) - self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) - if self.batch_norm_not: - self.bn3 = nn.BatchNorm2d(planes * 4) - self.relu = nn.ReLU(inplace=True) - self.downsample = downsample - self.stride = stride - - def forward(self, x): - residual = x - - out = self.conv1(x) - if self.batch_norm_not: - out = self.bn1(out) - out = self.relu(out) - - out = self.conv2(out) - if self.batch_norm_not: - out = self.bn2(out) - out = self.relu(out) - - out = self.conv3(out) - if self.batch_norm_not: - out = self.bn3(out) - - if self.downsample is not None: - residual = self.downsample(x) - if self.residual_not: - out += residual - - out = self.relu(out) - - return out - - -ALPHA_ = 1 - - -class ResNet(nn.Module): - - def __init__(self, - depth, - residual_not=True, - batch_norm_not=True, - base_channel=16, - num_classes=10): - super(ResNet, self).__init__() - # Model type specifies number of layers for CIFAR-10 model - assert (depth - 2) % 6 == 0, 'depth should be 6n+2' - n = (depth - 2) // 6 - - # block = Bottleneck if depth >=44 else BasicBlock - block = BasicBlock - - self.base_channel = int(base_channel) - self.residual_not = residual_not - self.batch_norm_not = batch_norm_not - self.inplanes = self.base_channel * ALPHA_ - self.conv1 = nn.Conv2d(3, - self.base_channel * ALPHA_, - kernel_size=3, - padding=1, - bias=False) - if self.batch_norm_not: - self.bn1 = nn.BatchNorm2d(self.base_channel * ALPHA_) - self.relu = nn.ReLU(inplace=True) - self.layer1 = self._make_layer(block, self.base_channel * ALPHA_, n, - self.residual_not, self.batch_norm_not) - self.layer2 = self._make_layer(block, - self.base_channel * 2 * ALPHA_, - n, - self.residual_not, - self.batch_norm_not, - stride=2) - self.layer3 = self._make_layer(block, - self.base_channel * 4 * ALPHA_, - n, - self.residual_not, - self.batch_norm_not, - stride=2) - self.avgpool = nn.AvgPool2d(8) - self.fc = nn.Linear(self.base_channel * 4 * ALPHA_ * block.expansion, - num_classes) - - for m in self.modules(): - if isinstance(m, nn.Conv2d): - n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels - m.weight.data.normal_(0, math.sqrt(2. / n)) - elif isinstance(m, nn.BatchNorm2d): - m.weight.data.fill_(1) - m.bias.data.zero_() - - def _make_layer(self, - block, - planes, - blocks, - residual_not, - batch_norm_not, - stride=1): - downsample = None - if (stride != 1 or - self.inplanes != planes * block.expansion) and (residual_not): - if batch_norm_not: - downsample = nn.Sequential( - nn.Conv2d(self.inplanes, - planes * block.expansion, - kernel_size=1, - stride=stride, - bias=False), - nn.BatchNorm2d(planes * block.expansion), - ) - else: - downsample = nn.Sequential( - nn.Conv2d(self.inplanes, - planes * block.expansion, - kernel_size=1, - stride=stride, - bias=False),) - - layers = nn.ModuleList() - layers.append( - block(self.inplanes, planes, residual_not, batch_norm_not, stride, - downsample)) - self.inplanes = planes * block.expansion - for i in range(1, blocks): - layers.append( - block(self.inplanes, planes, residual_not, batch_norm_not)) - - # return nn.Sequential(*layers) - return layers - - def forward(self, x): - output_list = [] - x = self.conv1(x) - if self.batch_norm_not: - x = self.bn1(x) - x = self.relu(x) # 32x32 - output_list.append(x.view(x.size(0), -1)) - - for layer in self.layer1: - x = layer(x) # 32x32 - output_list.append(x.view(x.size(0), -1)) - for layer in self.layer2: - x = layer(x) # 16x16 - output_list.append(x.view(x.size(0), -1)) - for layer in self.layer3: - x = layer(x) # 8x8 - output_list.append(x.view(x.size(0), -1)) - - x = self.avgpool(x) - x = x.view(x.size(0), -1) - x = self.fc(x) - output_list.append(x.view(x.size(0), -1)) - - # return output_list, x - return x - - -def resnet(**kwargs): - """ - Constructs a ResNet model. - """ - return ResNet(**kwargs) \ No newline at end of file diff --git a/compression/cifar/run_compress.sh b/compression/cifar/run_compress.sh deleted file mode 100644 index 8a4a7a71b..000000000 --- a/compression/cifar/run_compress.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -export CUDA_VISIBLE_DEVICES=0 - -############Note that The following script is *without* batch-norm############ -## Step 1: obtain a checkpoint (to be compressed) -python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 6665 \ - train.py \ - --deepspeed_config config/ds_config.json \ - --deepspeed --batch-norm --epochs 10 -### Step 2: compress: channel pruning -### you may enbale other compression methods, see ds_config.json or our compression tutorial -python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 66665 \ - train.py \ - --deepspeed_config config/ds_config_channel_prune.json \ - --deepspeed \ - --epochs 10 --batch-norm \ - --compression --path-to-model ./checkpoints/net.pkl \ - --saving-folder ./checkpoints/ - - - -############Note that The following Script is **with** batch-norm -### Step 1: obtain a checkpoint (to be compressed) -# python -m torch.distributed.launch --nproc_per_node=1 \ -# --master_port 6665 \ -# train.py \ -# --deepspeed_config config/ds_config.json \ -# --deepspeed --epochs 3 -##### the output here is -#### Step 2: compress: channel pruning -#### you may enbale other compression methods, see ds_config.json or our compression tutorial -# python -m torch.distributed.launch --nproc_per_node=1 \ -# --master_port 66665 \ -# train.py \ -# --deepspeed_config config/ds_config_channel_prune.json \ -# --deepspeed \ -# --epochs 3 \ -# --compression --path-to-model ./checkpoints/net.pkl \ -# --saving-folder ./checkpoints/ - - diff --git a/compression/cifar/train.py b/compression/cifar/train.py deleted file mode 100644 index 5034e81e4..000000000 --- a/compression/cifar/train.py +++ /dev/null @@ -1,155 +0,0 @@ -from __future__ import print_function -import os - -import argparse -import torch -import torch.nn as nn -import torch.nn.functional as F -import torch.optim as optim - -from utils import * -from resnet import resnet -from tqdm import tqdm -import deepspeed -from deepspeed.compression.compress import init_compression, redundancy_clean - -# Training settings -parser = argparse.ArgumentParser(description='Training on Cifar10') - -parser.add_argument('--batch-size', - type=int, - default=128, - metavar='N', - help='input batch size for training (default: 128)') -parser.add_argument('--test-batch-size', - type=int, - default=256, - metavar='N', - help='input batch size for testing (default: 256)') -parser.add_argument('--epochs', - type=int, - default=10, - metavar='N', - help='number of epochs to train (default: 10)') -parser.add_argument('--local_rank', - type=int, - default=-1, - help='local rank passed from distributed launcher') -parser.add_argument('--lr', - type=float, - default=0.1, - metavar='LR', - help='learning rate (default: 0.01)') -parser.add_argument('--lr-decay', - type=float, - default=0.1, - help='learning rate ratio') -parser.add_argument('--lr-decay-epoch', - type=int, - nargs='+', - default=[4, 8], - help='Decrease learning rate at these epochs.') - -parser.add_argument('--seed', - type=int, - default=1, - metavar='S', - help='random seed (default: 1)') -parser.add_argument('--weight-decay', - default=5e-4, - type=float, - metavar='W', - help='weight decay (default: 1e-4)') -parser.add_argument('--batch-norm', - action='store_false', - help='do we need batch norm or not') -parser.add_argument('--residual', - action='store_false', - help='do we need residula connect or not') - -parser.add_argument('--cuda', - action='store_false', - help='do we use gpu or not') -parser.add_argument('--saving-folder', - type=str, - default='checkpoints/', - help='choose saving name') -parser.add_argument('--compression', - action='store_true', - help='do we use compression or not') -parser.add_argument('--path-to-model', - type=str, - default=None) - -parser = deepspeed.add_config_arguments(parser) -args = parser.parse_args() - -deepspeed.init_distributed() - -# set random seed to reproduce the work -torch.manual_seed(args.seed) -if args.cuda: - torch.cuda.manual_seed(args.seed) - -for arg in vars(args): - print(arg, getattr(args, arg)) - -# get dataset -train_loader, test_loader = getData(name='cifar10', - train_bs=args.batch_size, - test_bs=args.test_batch_size) - -# get model and optimizer -model = resnet(num_classes=10, - depth=20, - residual_not=args.residual, - batch_norm_not=args.batch_norm) -if args.cuda: - model = model.cuda() - -if args.compression: - assert args.path_to_model is not None - model.load_state_dict(torch.load(args.path_to_model)) - model = init_compression(model, args.deepspeed_config) - -criterion = nn.CrossEntropyLoss() -model_engine, optimizer, _, __ = deepspeed.initialize( - args=args, model=model, model_parameters=model.parameters()) - - -if not os.path.isdir(args.saving_folder): - os.makedirs(args.saving_folder) - -for epoch in range(1, args.epochs + 1): - print('Current Epoch: ', epoch) - train_loss = 0. - total_num = 0 - correct = 0 - with tqdm(total=len(train_loader.dataset)) as progressbar: - for batch_idx, (data, target) in enumerate(train_loader): - - model_engine.train() - if args.cuda: - data, target = data.cuda().half(), target.cuda() - output = model(data) - loss = criterion(output, target) - model_engine.backward(loss) - train_loss += loss.item() * target.size()[0] - total_num += target.size()[0] - _, predicted = output.max(1) - correct += predicted.eq(target).sum().item() - model_engine.step() - - progressbar.set_postfix(loss=train_loss / total_num, - acc=100. * correct / total_num) - - progressbar.update(target.size(0)) - - acc = test(epoch, model, test_loader, fp16=True) -if args.compression: - model = redundancy_clean(model, args.deepspeed_config) - print ('after_clean') - acc = test(epoch, model, test_loader, fp16=True) - torch.save(model.state_dict(), args.saving_folder + 'clean_net.pkl') -else: - torch.save(model.state_dict(), args.saving_folder + 'net.pkl') \ No newline at end of file diff --git a/compression/cifar/utils.py b/compression/cifar/utils.py deleted file mode 100644 index 98f7d8aa9..000000000 --- a/compression/cifar/utils.py +++ /dev/null @@ -1,85 +0,0 @@ -#* -# @file Different utility functions -# Copyright (c) Zhewei Yao, Amir Gholami -# All rights reserved. -# This file is part of PyHessian library. -# -# PyHessian is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# PyHessian is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with PyHessian. If not, see . -#* - -import numpy as np -import torch -import torch.nn as nn -import torch.nn.functional as F -import torch.optim as optim -from torchvision import datasets, transforms -from torch.autograd import Variable - - -def getData(name='cifar10', train_bs=128, test_bs=1000): - """ - Get the dataloader - """ - if name == 'cifar10': - transform_train = transforms.Compose([ - transforms.RandomCrop(32, padding=4), - transforms.RandomHorizontalFlip(), - transforms.ToTensor(), - transforms.Normalize((0.4914, 0.4822, 0.4465), - (0.2023, 0.1994, 0.2010)), - ]) - - transform_test = transforms.Compose([ - transforms.ToTensor(), - transforms.Normalize((0.4914, 0.4822, 0.4465), - (0.2023, 0.1994, 0.2010)), - ]) - - trainset = datasets.CIFAR10(root='../data', - train=True, - download=True, - transform=transform_train) - train_loader = torch.utils.data.DataLoader(trainset, - batch_size=train_bs, - shuffle=True) - - testset = datasets.CIFAR10(root='../data', - train=False, - download=False, - transform=transform_test) - test_loader = torch.utils.data.DataLoader(testset, - batch_size=test_bs, - shuffle=False) - return train_loader, test_loader - - -def test(epoch, model, test_loader, cuda=True, fp16=False): - """ - Get the test performance - """ - model.eval() - correct = 0 - total_num = 0 - for data, target in test_loader: - if cuda: - data, target = data.cuda(), target.cuda() - if fp16: - data = data.half() - output = model(data) - pred = output.data.max( - 1, keepdim=True)[1] # get the index of the max log-probability - correct += pred.eq(target.data.view_as(pred)).cpu().sum().item() - total_num += len(data) - print(f'epoch {epoch} testing_correct: {correct / total_num}') - return correct / total_num \ No newline at end of file diff --git a/compression/gpt2/README.md b/compression/gpt2/README.md deleted file mode 100644 index d2e51c68e..000000000 --- a/compression/gpt2/README.md +++ /dev/null @@ -1,21 +0,0 @@ -#### Install - -``pip install -r requirements.txt`` - -You will also need to install updated DeepSpeed version (>0.7.0), which contains the compression library. - - -#### Key File: run_clm_no_trainer.py - -The python code is modified based on huggingface (https://github.com/huggingface/transformers/blob/main/examples/pytorch/language-modeling/run_clm_no_trainer.py). The key added feature is the compression pipeline. - -#### Folders (config) - -* **config:** This folder provides DeepSpeed configuration, including quantization, pruning and layer reduction. - -#### bash script -* **run_zero_quant.sh** This bash script contains jobs for training a checkpoint and then compressing this checkpoint. Run the job under the gpt2 directory: - - ```DeepSpeedExamples/model_compression/gpt2$ . ./bash_script/run_zero_quant.sh``` - See more descriptions and results in our [tutorial page](https://www.deepspeed.ai/). - diff --git a/compression/gpt2/bash_script/run_zero_quant.sh b/compression/gpt2/bash_script/run_zero_quant.sh deleted file mode 100644 index 982d0bc41..000000000 --- a/compression/gpt2/bash_script/run_zero_quant.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash -##################fine-tune the origin model and then apply zeroquant, the following command will take approximately 10 mins in A100 -###zero-quant https://arxiv.org/abs/2206.01861 -export CUDA_VISIBLE_DEVICES=0 - -######### fp16 -python -m torch.distributed.launch --nproc_per_node=1 \ - --master_port 12345 \ - run_clm_no_trainer.py \ - --dataset_name wikitext \ - --dataset_config_name wikitext-2-raw-v1 \ - --model_name_or_path gpt2-large \ - --per_device_train_batch_size 4 \ - --num_train_epochs 0 \ - --deepspeed_config config/ds_config_W8A8_Qgroup64_fp32.json \ - --deepspeed \ - --output_dir ./output/W8A8 -### the following is the output of the above command -### Before converting the module COVN1D to linear and init_compression: 19.371443732303174 -### Before cleaning, Epoch at 0 with Perplexity: 19.47031304212775 -### After cleaning with Perplexity: 19.47031304212775 - -# python -m torch.distributed.launch --nproc_per_node=1 \ -# --master_port 12345 \ -# run_clm_no_trainer.py \ -# --dataset_name wikitext \ -# --dataset_config_name wikitext-2-raw-v1 \ -# --model_name_or_path gpt2-large \ -# --per_device_train_batch_size 4 \ -# --num_train_epochs 0 \ -# --deepspeed_config config/ds_config_W4or8A8_Qgroup64_fp32.json \ -# --deepspeed \ -# --output_dir ./output/W4or8A8 -### the following is the output of the above command -### Before converting the module COVN1D to linear and init_compression: 19.371443732303174 -### Before cleaning, Epoch at 0 with Perplexity: 27.518339759793506 -### After cleaning with Perplexity: 27.518339759793506 - - -######### fp16 -# python -m torch.distributed.launch --nproc_per_node=1 \ -# --master_port 12345 \ -# run_clm_no_trainer.py \ -# --dataset_name wikitext \ -# --dataset_config_name wikitext-2-raw-v1 \ -# --model_name_or_path gpt2-large \ -# --per_device_train_batch_size 4 \ -# --num_train_epochs 0 \ -# --deepspeed_config config/ds_config_W8A8_Qgroup64_fp16.json \ -# --deepspeed \ -# --output_dir ./output/W8A8_fp16 -### the following is the output of the above command -### Before converting the module COVN1D to linear and init_compression: 19.371443732303174 -### Before cleaning, Epoch at 0 with Perplexity: 19.618978642663098 -### After cleaning with Perplexity: 19.789594118891802 - - -# python -m torch.distributed.launch --nproc_per_node=1 \ -# --master_port 12346 \ -# run_clm_no_trainer.py \ -# --dataset_name wikitext \ -# --dataset_config_name wikitext-2-raw-v1 \ -# --model_name_or_path gpt2-large \ -# --per_device_train_batch_size 4 \ -# --num_train_epochs 0 \ -# --deepspeed_config config/ds_config_W4or8A8_Qgroup64_fp16.json \ -# --deepspeed \ -# --output_dir ./output/W4or8A8_fp16 -### the following is the output of the above command -### Before converting the module COVN1D to linear and init_compression: 19.371443732303174 -### Before cleaning, Epoch at 0 with Perplexity: 31.62779929329135 -### After cleaning with Perplexity: 32.426349685127285 diff --git a/compression/gpt2/config/ds_config.json b/compression/gpt2/config/ds_config.json deleted file mode 100644 index 7e1da4419..000000000 --- a/compression/gpt2/config/ds_config.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "train_batch_size" : 8, - "train_micro_batch_size_per_gpu": 4, - "steps_per_print": 50, - - "optimizer": { - "type": "Adam", - "params": { - "lr": 0.001, - "betas": [ - 0.8, - 0.999 - ], - "eps": 1e-8, - "weight_decay": 3e-7 - } - }, - - "zero_optimization": { - "stage": 0 - }, - - "fp16":{ - "enabled": true - }, - - "gradient_clipping": 1.0, - "prescale_gradients": true, - - "wall_clock_breakdown" : false - } - diff --git a/compression/gpt2/config/ds_config_W4or8A8_Qgroup64_fp16.json b/compression/gpt2/config/ds_config_W4or8A8_Qgroup64_fp16.json deleted file mode 100644 index 59743bc87..000000000 --- a/compression/gpt2/config/ds_config_W4or8A8_Qgroup64_fp16.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "train_batch_size" : 8, - "train_micro_batch_size_per_gpu": 4, - "steps_per_print": 50, - - "optimizer": { - "type": "Adam", - "params": { - "lr": 0.001, - "betas": [ - 0.8, - 0.999 - ], - "eps": 1e-8, - "weight_decay": 3e-7 - } - }, - - "zero_optimization": { - "stage": 0 - }, - - "fp16":{ - "enabled": true - }, - - "gradient_clipping": 1.0, - "prescale_gradients": true, - - "wall_clock_breakdown" : false, - - "compression_training": { - "weight_quantization": { - "shared_parameters":{ - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 64, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": false, - "rounding": "nearest", - "fp16_mixed_quantize":{ - "enabled": false, - "quantize_change_ratio": 1 - } - }, - "different_groups":{ - "wq1": { - "params": { - "start_bits": 4, - "target_bits": 4, - "quantization_period": 0 - }, - "modules": [ - "mlp.c_fc", "mlp.c_proj" - ] - }, - "wq2": { - "params": { - "start_bits": 8, - "target_bits": 8, - "quantization_period": 0 - }, - "modules": [ - "attn.c_attn", "attn.c_proj" - ] - } - } - }, - "activation_quantization": { - "shared_parameters":{ - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups":{ - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attn.c_attn", "attn.c_proj", "mlp.c_fc", "mlp.c_proj" - ] - } - } - } - } - } \ No newline at end of file diff --git a/compression/gpt2/config/ds_config_W4or8A8_Qgroup64_fp32.json b/compression/gpt2/config/ds_config_W4or8A8_Qgroup64_fp32.json deleted file mode 100644 index 54ccf5e3e..000000000 --- a/compression/gpt2/config/ds_config_W4or8A8_Qgroup64_fp32.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "train_batch_size" : 8, - "train_micro_batch_size_per_gpu": 4, - "steps_per_print": 50, - - "optimizer": { - "type": "Adam", - "params": { - "lr": 0.001, - "betas": [ - 0.8, - 0.999 - ], - "eps": 1e-8, - "weight_decay": 3e-7 - } - }, - - "zero_optimization": { - "stage": 0 - }, - - "fp16":{ - "enabled": false - }, - - "gradient_clipping": 1.0, - "prescale_gradients": true, - - "wall_clock_breakdown" : false, - - "compression_training": { - "weight_quantization": { - "shared_parameters":{ - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 64, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": true, - "rounding": "nearest", - "fp16_mixed_quantize":{ - "enabled": false, - "quantize_change_ratio": 1 - } - }, - "different_groups":{ - "wq1": { - "params": { - "start_bits": 4, - "target_bits": 4, - "quantization_period": 0 - }, - "modules": [ - "mlp.c_fc", "mlp.c_proj" - ] - }, - "wq2": { - "params": { - "start_bits": 8, - "target_bits": 8, - "quantization_period": 0 - }, - "modules": [ - "attn.c_attn", "attn.c_proj" - ] - } - } - }, - "activation_quantization": { - "shared_parameters":{ - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups":{ - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attn.c_attn", "attn.c_proj", "mlp.c_fc", "mlp.c_proj" - ] - } - } - } - } - } \ No newline at end of file diff --git a/compression/gpt2/config/ds_config_W8A8_Qgroup64_fp16.json b/compression/gpt2/config/ds_config_W8A8_Qgroup64_fp16.json deleted file mode 100644 index 8ff7f8baa..000000000 --- a/compression/gpt2/config/ds_config_W8A8_Qgroup64_fp16.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "train_batch_size" : 8, - "train_micro_batch_size_per_gpu": 4, - "steps_per_print": 50, - - "optimizer": { - "type": "Adam", - "params": { - "lr": 0.001, - "betas": [ - 0.8, - 0.999 - ], - "eps": 1e-8, - "weight_decay": 3e-7 - } - }, - - "zero_optimization": { - "stage": 0 - }, - - "fp16":{ - "enabled": true - }, - - "gradient_clipping": 1.0, - "prescale_gradients": true, - - "wall_clock_breakdown" : false, - - "compression_training": { - "weight_quantization": { - "shared_parameters":{ - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 64, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": false, - "rounding": "nearest", - "fp16_mixed_quantize":{ - "enabled": false, - "quantize_change_ratio": 1 - } - }, - "different_groups":{ - "wq1": { - "params": { - "start_bits": 8, - "target_bits": 8, - "quantization_period": 0 - }, - "modules": [ - "attn.c_attn", "attn.c_proj", "mlp.c_fc", "mlp.c_proj" - ] - } - } - }, - "activation_quantization": { - "shared_parameters":{ - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups":{ - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attn.c_attn", "attn.c_proj", "mlp.c_fc", "mlp.c_proj" - ] - } - } - } - } - } \ No newline at end of file diff --git a/compression/gpt2/config/ds_config_W8A8_Qgroup64_fp32.json b/compression/gpt2/config/ds_config_W8A8_Qgroup64_fp32.json deleted file mode 100644 index dbbca58f1..000000000 --- a/compression/gpt2/config/ds_config_W8A8_Qgroup64_fp32.json +++ /dev/null @@ -1,80 +0,0 @@ -{ -"train_batch_size" : 8, -"train_micro_batch_size_per_gpu": 4, -"steps_per_print": 50, - -"optimizer": { - "type": "Adam", - "params": { - "lr": 0.001, - "betas": [ - 0.8, - 0.999 - ], - "eps": 1e-8, - "weight_decay": 3e-7 - } -}, - -"zero_optimization": { - "stage": 0 -}, - -"fp16":{ - "enabled": false -}, - -"gradient_clipping": 1.0, -"prescale_gradients": true, - -"wall_clock_breakdown" : false, - -"compression_training": { - "weight_quantization": { - "shared_parameters":{ - "enabled": true, - "quantizer_kernel": false, - "schedule_offset": 0, - "quantize_groups": 64, - "quantize_verbose": false, - "quantization_type": "symmetric", - "quantize_weight_in_forward": true, - "rounding": "nearest", - "fp16_mixed_quantize":{ - "enabled": false, - "quantize_change_ratio": 1 - } - }, - "different_groups":{ - "wq1": { - "params": { - "start_bits": 8, - "target_bits": 8, - "quantization_period": 0 - }, - "modules": [ - "attn.c_attn", "attn.c_proj", "mlp.c_fc", "mlp.c_proj" - ] - } - } - }, - "activation_quantization": { - "shared_parameters":{ - "enabled": true, - "quantization_type": "symmetric", - "range_calibration": "dynamic", - "schedule_offset": 0 - }, - "different_groups":{ - "aq1": { - "params": { - "bits": 8 - }, - "modules": [ - "attn.c_attn", "attn.c_proj", "mlp.c_fc", "mlp.c_proj" - ] - } - } - } -} -} \ No newline at end of file diff --git a/compression/gpt2/requirements.txt b/compression/gpt2/requirements.txt deleted file mode 100644 index b11238706..000000000 --- a/compression/gpt2/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -datasets >= 1.8.0 -sentencepiece != 0.1.92 -protobuf -transformers == 4.15.0 -accelerate \ No newline at end of file diff --git a/compression/gpt2/run_clm_no_trainer.py b/compression/gpt2/run_clm_no_trainer.py deleted file mode 100644 index 2b3242103..000000000 --- a/compression/gpt2/run_clm_no_trainer.py +++ /dev/null @@ -1,544 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -# Copyright 2021 The HuggingFace Inc. team. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Fine-tuning the library models for causal language modeling (GPT, GPT-2, CTRL, ...) -on a text file or a dataset without using HuggingFace Trainer. - -Here is the full list of checkpoints on the hub that can be fine-tuned by this script: -https://huggingface.co/models?filter=causal-lm -""" -# You can also adapt this script on your own causal language modeling task. Pointers for this are left as comments. - -import argparse -import logging -import math -import os -import random -from pathlib import Path -from re import L - -import datasets -import torch -from datasets import load_dataset -from torch.utils.data import DataLoader, RandomSampler, SequentialSampler -from torch.utils.data.distributed import DistributedSampler -from tqdm.auto import tqdm - -from transformers import ( - CONFIG_MAPPING, - MODEL_MAPPING, - AdamW, - AutoConfig, - AutoModelForCausalLM, - AutoTokenizer, - SchedulerType, - default_data_collator, - get_scheduler, - set_seed, -) -# from transformers.file_utils import get_full_repo_name -from transformers.utils.versions import require_version -import deepspeed -from deepspeed.compression.compress import init_compression, redundancy_clean -import numpy as np -from transformers.modeling_utils import Conv1D -from deepspeed.compression.helper import convert_conv1d_to_linear - -logger = logging.getLogger(__name__) - -require_version("datasets>=1.8.0", "To fix: pip install -r examples/pytorch/language-modeling/requirements.txt") - -MODEL_CONFIG_CLASSES = list(MODEL_MAPPING.keys()) -MODEL_TYPES = tuple(conf.model_type for conf in MODEL_CONFIG_CLASSES) - - -def parse_args(): - parser = argparse.ArgumentParser(description="Finetune a transformers model on a causal language modeling task") - parser.add_argument( - "--dataset_name", - type=str, - default=None, - help="The name of the dataset to use (via the datasets library).", - ) - parser.add_argument( - "--dataset_config_name", - type=str, - default=None, - help="The configuration name of the dataset to use (via the datasets library).", - ) - parser.add_argument( - "--train_file", type=str, default=None, help="A csv or a json file containing the training data." - ) - parser.add_argument( - "--validation_file", type=str, default=None, help="A csv or a json file containing the validation data." - ) - parser.add_argument( - "--validation_split_percentage", - default=5, - help="The percentage of the train set used as validation set in case there's no validation split", - ) - parser.add_argument( - "--model_name_or_path", - type=str, - help="Path to pretrained model or model identifier from huggingface.co/models.", - required=True, - ) - parser.add_argument( - "--path-to-model", - type=str, - help="Path to fine-tuned model or model identifier from huggingface.co/models.", - default=None, - ) - parser.add_argument( - "--config_name", - type=str, - default=None, - help="Pretrained config name or path if not the same as model_name", - ) - parser.add_argument( - "--tokenizer_name", - type=str, - default=None, - help="Pretrained tokenizer name or path if not the same as model_name", - ) - parser.add_argument( - "--use_slow_tokenizer", - action="store_true", - help="If passed, will use a slow tokenizer (not backed by the 🤗 Tokenizers library).", - ) - parser.add_argument( - "--per_device_train_batch_size", - type=int, - default=8, - help="Batch size (per device) for the training dataloader.", - ) - parser.add_argument( - "--per_device_eval_batch_size", - type=int, - default=8, - help="Batch size (per device) for the evaluation dataloader.", - ) - parser.add_argument( - "--learning_rate", - type=float, - default=5e-5, - help="Initial learning rate (after the potential warmup period) to use.", - ) - parser.add_argument("--weight_decay", type=float, default=0.0, help="Weight decay to use.") - parser.add_argument("--num_train_epochs", type=int, default=3, help="Total number of training epochs to perform.") - parser.add_argument( - "--max_train_steps", - type=int, - default=None, - help="Total number of training steps to perform. If provided, overrides num_train_epochs.", - ) - parser.add_argument( - "--gradient_accumulation_steps", - type=int, - default=1, - help="Number of updates steps to accumulate before performing a backward/update pass.", - ) - parser.add_argument( - "--lr_scheduler_type", - type=SchedulerType, - default="linear", - help="The scheduler type to use.", - choices=["linear", "cosine", "cosine_with_restarts", "polynomial", "constant", "constant_with_warmup"], - ) - parser.add_argument( - "--num_warmup_steps", type=int, default=0, help="Number of steps for the warmup in the lr scheduler." - ) - parser.add_argument("--output_dir", type=str, default=None, help="Where to store the model.") - parser.add_argument("--seed", type=int, default=None, help="A seed for reproducible training.") - parser.add_argument( - "--model_type", - type=str, - default=None, - help="Model type to use if training from scratch.", - choices=MODEL_TYPES, - ) - parser.add_argument( - "--block_size", - type=int, - default=None, - help="Optional input sequence length after tokenization. The training dataset will be truncated in block of this size for training. Default to the model max input length for single sentence inputs (take into account special tokens).", - ) - parser.add_argument( - "--preprocessing_num_workers", - type=int, - default=None, - help="The number of processes to use for the preprocessing.", - ) - parser.add_argument( - "--overwrite_cache", type=bool, default=False, help="Overwrite the cached training and evaluation sets" - ) - parser.add_argument( - "--no_keep_linebreaks", action="store_true", help="Do not keep line breaks when using TXT files." - ) - parser.add_argument("--not_tie_wre", action="store_true", help="tie the last layer and embedding or not." - ) - parser.add_argument("--push_to_hub", action="store_true", help="Whether or not to push the model to the Hub.") - parser.add_argument( - "--hub_model_id", type=str, help="The name of the repository to keep in sync with the local `output_dir`." - ) - parser.add_argument("--hub_token", type=str, help="The token to use to push to the Model Hub.") - parser.add_argument("--data_folder", type=str, help="The token to use to push to the Model Hub.") - parser.add_argument("--local_rank", - type=int, - default=-1, - help="local_rank for distributed training on gpus") - parser = deepspeed.add_config_arguments(parser) - args = parser.parse_args() - - # Sanity checks - if args.dataset_name is None and args.train_file is None and args.validation_file is None: - raise ValueError("Need either a dataset name or a training/validation file.") - else: - if args.train_file is not None: - extension = args.train_file.split(".")[-1] - assert extension in ["csv", "json", "txt"], "`train_file` should be a csv, json or txt file." - if args.validation_file is not None: - extension = args.validation_file.split(".")[-1] - assert extension in ["csv", "json", "txt"], "`validation_file` should be a csv, json or txt file." - - if args.push_to_hub: - assert args.output_dir is not None, "Need an `output_dir` to create a repo when `--push_to_hub` is passed." - - return args - - -def main(): - args = parse_args() - - # Initialize the accelerator. We will let the accelerator handle device placement for us in this example. - - # Make one log on every process with the configuration for debugging. - logging.basicConfig( - format="%(asctime)s - %(levelname)s - %(name)s - %(message)s", - datefmt="%m/%d/%Y %H:%M:%S", - level=logging.INFO, - ) - - if args.local_rank == -1: - device = torch.device("cuda") - else: - torch.cuda.set_device(args.local_rank) - device = torch.device("cuda", args.local_rank) - # Initializes the distributed backend which will take care of sychronizing nodes/GPUs - # torch.distributed.init_process_group(backend='nccl') - deepspeed.init_distributed() - def print_rank_0(msg): - if args.local_rank <= 0: - print(msg) - # If passed along, set the training seed now. - if args.seed is not None: - set_seed(args.seed) - - torch.distributed.barrier() - - if args.dataset_name is not None: - # Downloading and loading a dataset from the hub. - raw_datasets = load_dataset(args.dataset_name, args.dataset_config_name) - if "validation" not in raw_datasets.keys(): - raw_datasets["validation"] = load_dataset( - args.dataset_name, - args.dataset_config_name, - split=f"train[:{args.validation_split_percentage}%]", - ) - raw_datasets["train"] = load_dataset( - args.dataset_name, - args.dataset_config_name, - split=f"train[{args.validation_split_percentage}%:]", - ) - else: - data_files = {} - dataset_args = {} - if args.train_file is not None: - data_files["train"] = args.train_file - if args.validation_file is not None: - data_files["validation"] = args.validation_file - extension = args.train_file.split(".")[-1] - if extension == "txt": - extension = "text" - dataset_args["keep_linebreaks"] = not args.no_keep_linebreaks - raw_datasets = load_dataset(extension, data_files=data_files, **dataset_args) - # If no validation data is there, validation_split_percentage will be used to divide the dataset. - if "validation" not in raw_datasets.keys(): - raw_datasets["validation"] = load_dataset( - extension, - data_files=data_files, - split=f"train[:{args.validation_split_percentage}%]", - **dataset_args, - ) - raw_datasets["train"] = load_dataset( - extension, - data_files=data_files, - split=f"train[{args.validation_split_percentage}%:]", - **dataset_args, - ) - - - if args.model_name_or_path is not None: - config = AutoConfig.from_pretrained(args.model_name_or_path) - else: - config = CONFIG_MAPPING[args.model_type]() - logger.warning("You are instantiating a new config instance from scratch.") - #print (config) - if args.not_tie_wre: - config.tie_word_embeddings=False - - - if args.model_name_or_path is not None: - tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path, use_fast=not args.use_slow_tokenizer) - else: - raise ValueError( - "You are instantiating a new tokenizer from scratch. This is not supported by this script." - "You can do it from another script, save it, and load it from here, using --tokenizer_name." - ) - if args.model_name_or_path: - model = AutoModelForCausalLM.from_pretrained( - args.model_name_or_path, - from_tf=bool(".ckpt" in args.model_name_or_path), - config=config, - ) - else: - print_rank_0("Training new model from scratch") - model = AutoModelForCausalLM.from_config(config) - - model.resize_token_embeddings(len(tokenizer)) - model.to(device) - # Preprocessing the datasets. - # First we tokenize all the texts. - column_names = raw_datasets["train"].column_names - text_column_name = "text" if "text" in column_names else column_names[0] - - def tokenize_function(examples): - return tokenizer(examples[text_column_name]) - - tokenized_datasets = raw_datasets.map( - tokenize_function, - batched=True, - num_proc=args.preprocessing_num_workers, - remove_columns=column_names, - load_from_cache_file=not args.overwrite_cache, - desc="Running tokenizer on dataset", - ) - - if args.block_size is None: - block_size = tokenizer.model_max_length - if block_size > 1024: - logger.warning( - f"The tokenizer picked seems to have a very large `model_max_length` ({tokenizer.model_max_length}). " - "Picking 1024 instead. You can change that default value by passing --block_size xxx." - ) - block_size = 1024 - else: - if args.block_size > tokenizer.model_max_length: - logger.warning( - f"The block_size passed ({args.block_size}) is larger than the maximum length for the model" - f"({tokenizer.model_max_length}). Using block_size={tokenizer.model_max_length}." - ) - block_size = min(args.block_size, tokenizer.model_max_length) - - # Main data processing function that will concatenate all texts from our dataset and generate chunks of block_size. - def group_texts(examples): - # Concatenate all texts. - concatenated_examples = {k: sum(examples[k], []) for k in examples.keys()} - total_length = len(concatenated_examples[list(examples.keys())[0]]) - # We drop the small remainder, we could add padding if the model supported it instead of this drop, you can - # customize this part to your needs. - if total_length >= block_size: - total_length = (total_length // block_size) * block_size - # Split by chunks of max_len. - result = { - k: [t[i : i + block_size] for i in range(0, total_length, block_size)] - for k, t in concatenated_examples.items() - } - result["labels"] = result["input_ids"].copy() - return result - - lm_datasets = tokenized_datasets.map( - group_texts, - batched=True, - num_proc=args.preprocessing_num_workers, - load_from_cache_file=not args.overwrite_cache, - desc=f"Grouping texts in chunks of {block_size}", - ) - - train_dataset = lm_datasets["train"] - eval_dataset = lm_datasets["validation"] - - # train_dataset = torch.load(f'{args.data_folder}/train_dataset.pt') #lm_datasets["train"] - # eval_dataset = torch.load(f'{args.data_folder}/eval_dataset.pt') #lm_datasets["validation"] - - # Log a few random samples from the training set: - # for index in random.sample(range(len(train_dataset)), 3): - # print_rank_0(f"Sample {index} of the training set: {train_dataset[index]}.") - - # DataLoaders creation: - if args.local_rank == -1: - train_sampler = RandomSampler(train_dataset) - else: - train_sampler = DistributedSampler(train_dataset) - train_dataloader = DataLoader( - train_dataset, collate_fn=default_data_collator, sampler=train_sampler, batch_size=args.per_device_train_batch_size - ) - eval_sampler = SequentialSampler(eval_dataset) - eval_dataloader = DataLoader( - eval_dataset, collate_fn=default_data_collator, sampler=eval_sampler, batch_size=args.per_device_eval_batch_size - ) - - # Note -> the training dataloader needs to be prepared before we grab his length below (cause its length will be - # shorter in multiprocess) - - # Scheduler and math around the number of training steps. - num_update_steps_per_epoch = math.ceil(len(train_dataloader) / args.gradient_accumulation_steps) - if args.max_train_steps is None: - args.max_train_steps = args.num_train_epochs * num_update_steps_per_epoch - else: - args.num_train_epochs = math.ceil(args.max_train_steps / num_update_steps_per_epoch) - - # Train! - print_rank_0("***** Running training *****") - print_rank_0(f" Num examples = {len(train_dataset)}") - print_rank_0(f" Num Epochs = {args.num_train_epochs}") - print_rank_0(f" Instantaneous batch size per device = {args.per_device_train_batch_size}") - print_rank_0(f" Gradient Accumulation steps = {args.gradient_accumulation_steps}") - print_rank_0(f" Total optimization steps = {args.max_train_steps}") - - - num_p = sum([p.numel() for p in model.parameters()]) - print_rank_0('Number of parameters: {}'.format(num_p)) - - def to_device(batch): - output = {} - for k, v in batch.items(): - try: - output[k] = v.to(device) - except: - output[k] = v - return output - - def evaluation(model, eval_dataloader): - model.eval() - losses = [] - for step, batch in enumerate(eval_dataloader): - # batch = tuple(t.to(device) for t in batch) - batch = to_device(batch) - with torch.no_grad(): - outputs = model(**batch) - - loss = outputs.loss - losses.append(loss.cpu().item()) - losses = losses[: len(eval_dataset)] - try: - perplexity = math.exp(np.mean(losses)) - except OverflowError: - perplexity = float("inf") - return perplexity - - - def training(model, train_dataloader, eval_dataloader, num_train_epochs, args): - # Optimizer - previous_best = None - # Split weights in two groups, one with weight decay and the other not. - no_decay = ["bias", "LayerNorm.weight"] - optimizer_grouped_parameters = [ - { - "params": [p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay)], - "weight_decay": args.weight_decay, - }, - { - "params": [p for n, p in model.named_parameters() if any(nd in n for nd in no_decay)], - "weight_decay": 0.0, - }, - ] - optimizer = AdamW(optimizer_grouped_parameters, lr=args.learning_rate) - - lr_scheduler = get_scheduler( - name=args.lr_scheduler_type, - optimizer=optimizer, - num_warmup_steps=args.num_warmup_steps, - num_training_steps=args.max_train_steps, - ) - model, optimizer, _, lr_scheduler = deepspeed.initialize( - model=model, - optimizer=optimizer, - args=args, - lr_scheduler=lr_scheduler, - dist_init_required=True) - # Only show the progress bar once on each machine. - # completed_steps = 0 - for epoch in range(num_train_epochs): - if epoch == 0: - perplexity = evaluation(model, eval_dataloader) - print_rank_0 (f"*************************initialization with {perplexity}***********************************") - model.train() - for step, batch in enumerate(train_dataloader): - batch = to_device(batch) - outputs = model(**batch, output_hidden_states=True, output_attentions=True) - loss = outputs.loss - # loss = loss / args.gradient_accumulation_steps - model.backward(loss) - model.step() - - # Evaluate perplexity on the validation set. - if epoch != args.num_train_epochs-1: - print_rank_0(f"***** Evaluating perplexity, Epoch {epoch+1}/{num_train_epochs} *****") - perplexity = evaluation(model, eval_dataloader) - print_rank_0(f"Epoch at {epoch+1} with Perplexity: {perplexity}") - - print_rank_0(f"***** Evaluating perplexity, Epoch {args.num_train_epochs}/{num_train_epochs} *****") - perplexity = evaluation(model, eval_dataloader) - print_rank_0(f"Before cleaning, Epoch at {args.num_train_epochs} with Perplexity: {perplexity}") - if args.output_dir is not None: - print_rank_0('saving model ...') - if not os.path.isdir(args.output_dir): - os.makedirs(args.output_dir) - if torch.distributed.get_rank() == 0: - model_to_save = model.module if hasattr(model, 'module') else model - # CONFIG_NAME = "config.json" - WEIGHTS_NAME = "pytorch_model.bin" - output_model_file = os.path.join(args.output_dir, WEIGHTS_NAME) - #output_config_file = os.path.join(args.output_dir, CONFIG_NAME) - torch.save(model_to_save.state_dict(), output_model_file) - #output_config_file = os.path.join(args.output_dir, CONFIG_NAME) - #model_to_save.config.to_json_file(output_config_file) - tokenizer.save_vocabulary(args.output_dir) - - perplexity = evaluation(model, eval_dataloader) - print_rank_0(f"Before converting the module COVN1D to linear, and before applying init_compression: {perplexity}") - model = convert_conv1d_to_linear(model, Conv1D) - model = init_compression(model, args.deepspeed_config) - print_rank_0('WARNING: saving the quantized model with Linear Module instead of COV1D') - - training(model, train_dataloader, eval_dataloader, args.num_train_epochs, args) - - model = redundancy_clean(model, args.deepspeed_config) - perplexity = evaluation(model, eval_dataloader) - print_rank_0(f"After cleaning with Perplexity: {perplexity}") - - quant_output_dir = args.output_dir+'/quant' - print_rank_0(f'saving model to {quant_output_dir}') - if not os.path.isdir(quant_output_dir): - os.makedirs(quant_output_dir) - model_to_save = model.module if hasattr(model, 'module') else model - output_model_file = os.path.join(quant_output_dir, "pytorch_model.bin") - torch.save(model_to_save.state_dict(), output_model_file) - - -if __name__ == "__main__": - main()