@inproceedings{li2021neurobfuscator,
title={NeurObfuscator: A Full-stack Obfuscation Tool to Mitigate Neural Architecture Stealing},
author={Li, Jingtao and He, Zhezhi and Rakin, Adnan Siraj and Fan, Deliang and Chakrabarti, Chaitali},
booktitle={2021 IEEE International Symposium on Hardware Oriented Security and Trust (HOST)},
pages={248--258},
year={2021},
organization={IEEE}
}
(This work is to appear in HOST 2021! Cleaned-up version/Documentary for detailed usage will be updated soon.)
NeurObfuscator is a full-stack obfuscation tool to obfuscate the neural network architecture while preserving its functionality with very limited performance overhead.
At the heart of this tool is a set of obfuscating knobs, including layer branching, layer widening, selective fusion and schedule pruning, that increase the number of operators, reduce/increase the latency, and number of cache and DRAM accesses.
A genetic algorithm-based approach is adopted to orchestrate the combination of obfuscating knobs to achieve the best obfuscating effect on the layer sequence and dimension parameters that both architecture secrets cannot be extracted successfully.
Results on sequence obfuscation show that the proposed tool obfuscates a ResNet-18 ImageNet model to a totally different architecture (with 44 layer difference) without affecting its functionality with only 2% overall latency overhead.
For dimension obfuscation, we demonstrate that an example convolution layer with 64 input and 128 output channels is extracted to 207 input and 93 output channels with only a 2% latency overhead.
Follow the instruction below to install the NVIDIA docker.
https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker
On Linux, you should also enable Docker CLI for the non-root user account that will be used to run VS Code. (Otherwise, you have to use sudo all the time with docker command.)
docker pull zlijingtao/neurobfuscator:lastest
docker tag zlijingtao/neurobfuscator:lastest neurob
docker build -t neurob .
PS: This could be a slow building process.
Test the tool using provided run.sh
script to go through all necessary steps of NeurObfuscator. This includes:
- Dataset Generation
- Sequence Predictor Training
- Sequence Predictor Validation
- Sequence Obfuscation
- Dimension Predictor Training
- Dimension Predictor Validation
- Dimension Obfuscation
cd NeurObfuscator, we create a container and mount local folder for easy dev
docker run --gpus all -it -v $(pwd):/root/neurob neurob
bash run.sh
The log file is saved under ./seq_obfuscator/
, a snapshot of the result:
where, we applied several sequence obfuscating knobs and achieves a LER of 0.294
. (This is a toy example.)
The compiled runtime for the obfuscated model is saved under ./seq_obfuscator/deploy_lib/
Unfortunately, some systems may fail to execute relay.build
in a docker environment - throwing segmentation fault
error. This can be circumvented by building a local environment. That is, setting up all necessary tools and library scripted in the Dockerfile in your local machien without using docker. This can be a tedious process.
To use the tool in practice, first, you need script/coding the original neural network model following the tutorial in the tempalte ./seq_obfuscator/model_file/model_template.py
and properly label it using label_maker.py
in the same directory. (We currently only supports a specific format, need to match the format as other example networks in this directory)
Importantly, a reasonable large parameter need to be set by simply re-commenting and run the run above
setting we provide. (need to check all scripts)
# your_model_id=
# your_budget=
# budget_list=(${your_budget})
# nn_id_list=(${your_model_id})
# restore_step=149
# num_predictor_model=5
# predict_type=all
# n_pop=16
# n_generation=20
#Run below for testing, run above for bagging of 15 LSTM predictors
budget_list=(0.20)
nn_id_list=(4)
restore_step=49
num_predictor_model=1
predict_type=full
n_pop=4
n_generation=2
After re-commenting, you need to set a budget in ./scripts/seq_obfuscate_cifar.sh
(as an example). Suppose your model_id is 15
and budget is 0.20
.
your_model_id=15
your_budget=0.20
budget_list=(${your_budget})
nn_id_list=(${your_model_id})
restore_step=149
num_predictor_model=5
predict_type=all
n_pop=16
n_generation=20
#Run below for testing, run above for bagging of 15 LSTM predictors
# budget_list=(0.20)
# nn_id_list=(4)
# restore_step=49
# num_predictor_model=1
# predict_type=full
# n_pop=4
# n_generation=2
Download the model from here:
https://drive.google.com/drive/folders/1UDDFvnbWdP1nXZEUjBHo1id-eBt6620c?usp=sharing
(Before building the dockerfile) Copy them to ./test_attack/
, after build and login to the container:
bash test_attack.sh
cd test_attack
bash test_attack.sh
The results will be saved under ./test_attack/attack_result/
.
Model-B (extravgg_3)
decompo_list = [0, 0, 2, 4, 0, 4, 4, 0, 1, 4, 3]
deepen_list = [0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]
Model-C (newvgg_9)
decompo_list = [0, 0, 2, 4, 0, 4, 4, 0, 1, 4, 3]
deepen_list = [0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]
widen_list = [1.5, 1, 1.5, 1, 1.5, 1, 1, 1, 1, 1, 1]
kerneladd_list = [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
Metrics {
Label: "Cycles"
Name: "sm__cycles_active.sum"
}
Metrics {
Label: "Mem Read"
Name: "dram__sectors_read.sum"
}
Metrics {
Label: "Mem Write"
Name: "dram__sectors_write.sum"
}
Metrics {
Label: "L1/TEX Hit Rate"
Name: "l1tex__t_sector_hit_rate.pct"
}
Metrics {
Label: "L1 Utilization"
Name: "l1tex__lsu_writeback_active.avg.pct_of_peak_sustained_active"
}
Metrics {
Label: "L1 Read Transactions"
Name: "l1tex__t_sectors_pipe_lsu_mem_global_op_ld.sum"
}
Metrics {
Label: "L1 Write Transactions"
Name: "l1tex__t_sectors_pipe_lsu_mem_global_op_st.sum"
}
Metrics {
Label: "L2 Utilization"
Name: "lts__t_sectors.avg.pct_of_peak_sustained_elapsed"
}
Metrics {
Label: "L2 Hit Rate"
Name: "lts__t_sector_hit_rate.pct"
}
Metrics {
Label: "L2 Read Transactions"
Name: "lts__t_sectors_op_read.sum"
}
Metrics {
Label: "L2 Write Transactions"
Name: "lts__t_sectors_op_write.sum"
}
For the experiments presented in the published version Section VI. C "Effectiveness of NeurObfuscator", the experiments are done by directly training using the obfuscated-pytorch-scripts, where 6 script-level obfuscating knobs are added. And we can get high validation accuracy as a result. However, this is a result of rushing in rebuttal phase, and it is not rigorous.
We want to point out, effectiveness should be properly evaluated by the attacker's view - which is the extracted model from the trace of obfuscated model since attacker cannot get access to the pytorch scripts.
Why don't we perform it properly? - We only did the sequence extraction and dimension extraction seperately, but did not extract the fully executable model (as you may notice, this requires lots of effort...)
Luckily This paper NeuroUnlock did it properly. In Fig. 19, they showed the extracted model (from a real attacker's view) of an obfuscated model using neurobfuscator cannot converge properly and get an 10% accuracy on CIFAR-10. Please refer to their repository for reference, Thanks!
Our Fix In our upcoming upgraded version of Neurobfuscator, we will address this issue (Timeline: by summer 2023).