Giter VIP home page Giter VIP logo

geometric_adv's Introduction

Geometric Adversarial Attacks and Defenses on 3D Point Clouds

Created by Itai Lang, Uriel Kotlicki, and Shai Avidan from Tel Aviv University.

[Paper] [Introduction Video (2 minutes)] [Introduction Slides] [Full Video (10 minutes)] [Full Slides] [Poster]

teaser

Introduction

This code repository is based on our arXiv tech report. Please read it for more information.

Deep neural networks are prone to adversarial examples that maliciously alter the network's outcome. Due to the increasing popularity of 3D sensors in safety-critical systems and the vast deployment of deep learning models for 3D point sets, there is a growing interest in adversarial attacks and defenses for such models. So far, the research has focused on the semantic level, namely, deep point cloud classifiers. However, point clouds are also widely used in a geometric-related form that includes encoding and reconstructing the geometry.

In this work, we are the first to consider the problem of adversarial examples at a geometric level. In this setting, the question is how to craft a small change to a clean source point cloud that leads, after passing through an autoencoder model, to the reconstruction of a different target shape. Our attack is in sharp contrast to existing semantic attacks on 3D point clouds. While such works aim to modify the predicted label by a classifier, we alter the entire reconstructed geometry. Additionally, we demonstrate the robustness of our attack in the case of defense, where we show that remnant characteristics of the target shape are still present at the output after applying the defense to the adversarial input.

Citation

If you find our work useful in your research, please consider citing:

@InProceedings{lang2021geometric_adv,
  author = {Lang, Itai and Kotlicki, Uriel and Avidan, Shai},
  title = {{Geometric Adversarial Attacks and Defenses on 3D Point Clouds}},
  booktitle = {Proceedings of the International Conference on 3D Vision (3DV)},
  pages = {1196--1205},
  year = {2021}
}

Installation

The code has been tested with Python 3.6.12, TensorFlow 1.13.2, TFLearn 0.3.2, PyTorch 1.6.0, CUDA 10.1, and cuDNN 7.6.5 on Ubuntu 16.04.

Clone this code repository:

git clone https://github.com/itailang/geometric_adv.git

Create a conda environment and install dependencies:

conda create -n geometric_adv python=3.6 --yes
conda activate geometric_adv
cd geometric_adv
cat requirements.txt | xargs -n 1 pip install
conda install pytorch==1.6.0 torchvision==0.7.0 cudatoolkit=10.1 -c pytorch --yes

Compilation of Ops

Compile TensorFlow ops: nearest neighbor grouping, implemented by Qi et al., and structural losses, implemented by Fan et al. The ops are located under external folder, in grouping and structural losses folders, respectively. The compilation scripts uses CUDA 10.1 path. If needed, modify the corresponding sh file of each op to point to your CUDA path. Then, use:

cd geometric_adv
sh compile_ops_tf.sh

An o and so files should be created in the corresponding folder of each op.

Compile PyTorch op: Chamfer Distance, implemented by Groueix et al. The op is located under transfer/atlasnet/auxiliary/ChamferDistancePytorch/chamfer3D folder. The following sh compilation script uses CUDA 10.1 path. If needed, modify script to point to your CUDA path. Then, use:

cd geometric_adv
sh compile_op_pt.sh

The compilation results should be created under transfer/atlasnet/build folder.

Usage

Overview

Our code is organized in the following folders:

  • autoencoder: scripts for training a victim autoencoder and an autoencoder for attack transfer.
  • attacker: scripts for running the attacks.
  • defender: scripts for running the defenses.
  • classifier: source code for training a classifier for semantic interpretation, and scripts for semantic evaluation of the attacks and defenses.
  • transfer: source code for training an AtlasNet autoencoder and a FoldingNet autoencoder for attack transfer (under atlasnet and foldingnet folders, respectively), and scripts for running attack transfer.
  • src: implementation of the autoencoder for attack, the adversary, and utility helper functions.
  • external: external public source code, implementing TensorFlow ops and Python i/o for ply files.

The following sub-sections explain the following items:

Download Models and Data

Download the trained models and data for our experiments:

cd geometric_adv
bash download_models_and_data.sh

The models (about 200MB) will be saved under log folder, in the following folders:

  • autoencoder_victim: a victim autoencoder for the attack and defense experiments.
  • pointnet: a classifier for the semantic interpretation experiment.
  • autoencoder_for_transfer, atlasnet_for_transfer, and foldingnet_for_transfer: autoencoders for the attack transfer experiment.

The data (about 220MB) will be saved under log/autoencoder_victim/eval folder.

Attacks

First, save the default configuration of the victim autoencoder using:

cd autoencoder
python train_ae.py --train_folder log/autoencoder_victim --save_config_and_exit 1

The configuration will be saved to the folder log/autoencoder_victim.

Then, prepare indices for the attack using:

cd ../attacker
bash runner_indices_for_attack.sh

The script will prepare random indices for source point clouds to attack. It will also prepare a nearest neighbors matrix that will be used for selecting target point cloud candidates for the attack. The data will be saved to log/autoencoder_victim/eval folder.

Next, run and evaluate the output and latent space attacks using:

cd ../attacker
sh runner_attacker.sh

Attack results will be saved to the folders log/autoencoder_victim/eval/output_space_attack and log/autoencoder_victim/eval/latent_space_attack. Under the attack folder there is a folder for each source class.

The script runner_attacker.sh uses the following scripts:

  • run_attack.py is used to optimize the attack. For each source class folder, it saves adversarial metrics (adversarial_metrics.npy), adversarial examples (adversarial_pc_input.npy), and their reconstruction by the victim autoencoder (adversarial_pc_recon.npy).
  • get_dists_per_point.py computes additional data required for the attack evaluation (adversarial_pc_input_dists.npy).
  • evaluate_attack.py analyzes the attack results. Statistics for the attack will be saved to the file over_classes/eval_stats.txt.

When running evaluate_attack.py, you can use the following additional flags:

  • --save_graphs 1: to save graphs of adversarial metrics for each source class.
  • --save_pc_plots 1: to save visualization of the source point clouds, adversarial examples, target point clouds, and their reconstruction.

Defenses

Run critical points and off-surface defenses against the output and latent space attacks using:

cd ../defender
sh runner_defender.sh

Under each attack folder, defense results will be saved to the folders defense_critical_res and defense_surface_res. Under these defense folders, there is a folder for each source class.

The script runner_defender.sh uses the following scripts:

  • run_defense_critical.py and run_defense_surface.py save defense metrics (defense_metrics.npy), defended point clouds (defended_pc_input.npy), and their reconstruction by the victim autoencoder (defended_pc_recon.npy). These files will be saved to each source class folder.
  • evaluate_defense.py analyzes the defense results. Statistics for the defense will be saved to the file over_classes/eval_stats.txt.

When running evaluate_defense.py, you can use the following additional flags:

  • --save_graphs 1: to save graphs of defense metrics for each source class.
  • --save_pc_plots 1: to save visualization of the source point clouds, adversarial examples, defended point clouds, and their reconstructions. In the adversarial examples, points that are filtered by the defense will be marked in Red.
  • --use_adversarial_data 0: to evaluate the defense results on source point clouds.

Semantic Interpretation

Use the trained classifier to evaluate the semantic interpretation of reconstructed adversarial and defended point clouds:

cd ../classifier
sh runner_classifier.sh

The script runner_classifier.sh uses the following scripts:

  • run_classifier.py gets the classifier's predictions for reconstructed adversarial and defended point clouds. The classifier's results will be saved under the corresponding attack and defense folders to a folder named classifer_res. Under this folder, there is a folder for each source class with the classifier's predictions.
  • evaluate_classifier.py evaluates the semantic interpretation of the reconstructed point clouds. Statistics for the classifier will be saved to the folder classifer_res/over_classes.

Note:

  • The semantic interpretation of reconstructed source and target point clouds is also evaluated (for reference). The name for the classifier's folder, in this case, is classifer_res_orig.
  • When running evaluate_classifier.py, you can use an additional flag --save_graphs 1, to save graphs of the classifier's predictions for each source class.

Transfer

Run and evaluate the adversarial examples through the autoencoders for attack transfer using:

cd ../transfer
sh runner_transfer.sh

This script will run the adversarial examples of the output and latent space attacks through the three autoencoders for transfer described above. If you trained part of these autoencoders, edit the script accordingly.

The script runner_transfer.sh uses the following scripts:

  • run_transfer.py uses an autoencoder for transfer to reconstruct adversarial point clouds (transferred_pc_recon.npy) and compute transfer metrics (transfer_metrics.npy) for each source class. The results are saved to an attack transfer folder, under the autoencoder for transfer. For instance: log/autoencoder_for_transfer/output_space_attack_transfer.
  • evaluate_transfer.py compute transfer statistics that are saved to the file over_classes/eval_stats.txt under the attack transfer folder.

When running evaluate_transfer.py, you can use the following additional flags:

  • --save_graphs 1: to save graphs of transfer metrics for each source class.
  • --save_pc_plots 1: to save visualization of the source point clouds, adversarial examples, and their reconstructions by the victim autoencoder or autoencoder for transfer.

Retrain Models

In the previous section you employed the models that we used in our work. In this section we explain the steps for retraining these models. It may be useful as a reference example, in case you want to use different data than that we used.

Data Set

Download point clouds of ShapeNetCore shape models, provided by Achlioptas et al. (about 1.4GB, in ply format):

cd geometric_adv
sh download_data_set.sh

Each point cloud contains 2048 points, uniformly sampled from the shape surface. The data will be downloaded to a folder named geometric_adv/data/shape_net_core_uniform_samples_2048.

Victim Autoencoder

Train a victim autoencoder model using:

cd autoencoder
sh runner_ae_for_attack.sh

The model will be saved to the folder log/autoencoder_victim.

The script runner_ae_for_attack.sh uses the following scripts:

  • train_ae.py is used to train the autoencoder.
  • tst_ae.py prepares data for attack. The data will be saved to the folder log/autoencoder_victim/eval.

Classifier

First, prepare data for training a classifier for semantic interpretation using:

cd ../autoencoder
sh runner_ae_for_classifier.sh

This script saves the point clouds of the train and validation sets that were used during the victim autoencoder's training. These points clouds and their labels will be used for training the classifier. The data will be saved to the folders log/autoencoder_victim/eval_train and log/autoencoder_victim/eval_val. Note that these point clouds of the train the validation sets will be used for the training of autoencoders for transfer (see seb-section Autoencoders for Attack Transfer below).

Then, train the classifier using:

cd ../classifier
python train_classifier.py

Autoencoders for Attack Transfer

Train autoencoders other than the victim one to perform attack transfer. These autoencoders will be trained on the same data set as the attacked autoencoder. Note that the autoencoders for transfer are independent of each other, and you can choose which one to train and run transfer with.

To train an autoencoder with the same architecture of the victim and different weight initialization, use:

cd ../autoencoder
sh runner_ae_for_transfer.sh

The model will be saved to the folder log/autoencoder_for_transfer.

To train an AtlasNet autoencoder, use:

cd ../transfer/atlasnet
sh runner_atlasnet.sh

The model will be saved to the folder log/atlasnet_for_transfer.

To train a FoldingNet autoencoder, use:

cd ../../transfer/foldingnet
sh runner_foldingnet.sh

The model will be saved to the folder log/foldingnet_for_transfer.

License

This project is licensed under the terms of the MIT license (see the LICENSE file for more details).

Acknowledgment

Our code builds upon the code provided by Achlioptas et al., Qi et al., Groueix et al., and Yan Wei. We thank the authors for sharing their code.

geometric_adv's People

Contributors

itailang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

geometric_adv's Issues

where is file attack_configuration.pickle?

When I run the command “python run_classifier.py --data_type target --attack_folder out_space_attack”

the log:
Instructions for updating: Colocations handled automatically by placer. Run classifier flags: Namespace(ae_folder='log/autoencoder_victim', attack_folder='output_space_attack', attack_pc_idx='log/autoencoder_victim/eval/sel_idx_rand_100_test_set_13l.npy', classifier_folder='log/pointnet', classifier_restore_epoch=150, data_type='target', defense_folder='defense_critical_res', num_classes=13, num_points=2048, output_folder_name='classifier_res') Traceback (most recent call last): File "run_classifier.py", line 72, in <module> conf = Conf.load(osp.join(classifier_data_path, 'attack_configuration')) File "/media/l1/Disk28/Luogyu/3D_Attack_Defense/geometric_adv/geometric_adv/src/autoencoder.py", line 82, in load return unpickle_data(file_name + '.pickle').__next__() File "/media/l1/Disk28/Luogyu/3D_Attack_Defense/geometric_adv/geometric_adv/src/in_out.py", line 63, in unpickle_data inFile = open(file_name, 'rb') FileNotFoundError: [Errno 2] No such file or directory: '/media/l1/Disk28/Luogyu/3D_Attack_Defense/geometric_adv/geometric_adv/log/autoencoder_victim/eval/output_space_attack/attack_configuration.pickle'

And I search the file name ‘attack_configuration.pickle' , just have the file named 'configuration.pickle'

Is this normal?Thanks.

CUDA path not updated when compiling sh compile_op_pt.sh

I have updated the necessary cuda paths in the recommended files.
I am using cuda-11.1. When I run sh compile_op_pt.sh, the CUDA paths in the build.ninja gets restored back to cuda-10.1 path everytime I compile it.

i have updated the cuda paths several times but it changes back to cuda-10.1 after running sh compile_op_pt.sh
Please find the errors below

sh compile_op_pt.sh
running install
running bdist_egg
running egg_info
writing chamfer_3D.egg-info/PKG-INFO
writing dependency_links to chamfer_3D.egg-info/dependency_links.txt
writing top-level names to chamfer_3D.egg-info/top_level.txt
reading manifest file 'chamfer_3D.egg-info/SOURCES.txt'
writing manifest file 'chamfer_3D.egg-info/SOURCES.txt'
installing library code to build/bdist.linux-x86_64/egg
running install_lib
running build_ext
building 'chamfer_3D' extension
Emitting ninja build file /home/20020006/geometric_adv/transfer/atlasnet/build/temp.linux-x86_64-3.6/build.ninja...
Compiling objects...
Allowing ninja to set a default number of workers... (overridable by setting the environment variable MAX_JOBS=N)
[1/1] /usr/local/cuda-10.1/bin/nvcc -I/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/include -I/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/include/torch/csrc/api/include -I/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/include/TH -I/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/include/THC -I/usr/local/cuda-10.1/include -I/home/20020006/.conda/envs/geo_adv/include/python3.6m -c -c /home/20020006/geometric_adv/transfer/atlasnet/auxiliary/ChamferDistancePytorch/chamfer3D/chamfer3D.cu -o /home/20020006/geometric_adv/transfer/atlasnet/build/temp.linux-x86_64-3.6/auxiliary/ChamferDistancePytorch/chamfer3D/chamfer3D.o -D__CUDA_NO_HALF_OPERATORS__ -D__CUDA_NO_HALF_CONVERSIONS__ -D__CUDA_NO_HALF2_OPERATORS__ --expt-relaxed-constexpr --compiler-options ''"'"'-fPIC'"'"'' -DTORCH_API_INCLUDE_EXTENSION_H -DTORCH_EXTENSION_NAME=chamfer_3D -D_GLIBCXX_USE_CXX11_ABI=0 -gencode=arch=compute_75,code=sm_75 -std=c++14
FAILED: /home/20020006/geometric_adv/transfer/atlasnet/build/temp.linux-x86_64-3.6/auxiliary/ChamferDistancePytorch/chamfer3D/chamfer3D.o
/usr/local/cuda-10.1/bin/nvcc -I/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/include -I/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/include/torch/csrc/api/include -I/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/include/TH -I/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/include/THC -I/usr/local/cuda-10.1/include -I/home/20020006/.conda/envs/geo_adv/include/python3.6m -c -c /home/20020006/geometric_adv/transfer/atlasnet/auxiliary/ChamferDistancePytorch/chamfer3D/chamfer3D.cu -o /home/20020006/geometric_adv/transfer/atlasnet/build/temp.linux-x86_64-3.6/auxiliary/ChamferDistancePytorch/chamfer3D/chamfer3D.o -D__CUDA_NO_HALF_OPERATORS__ -D__CUDA_NO_HALF_CONVERSIONS__ -D__CUDA_NO_HALF2_OPERATORS__ --expt-relaxed-constexpr --compiler-options ''"'"'-fPIC'"'"'' -DTORCH_API_INCLUDE_EXTENSION_H -DTORCH_EXTENSION_NAME=chamfer_3D -D_GLIBCXX_USE_CXX11_ABI=0 -gencode=arch=compute_75,code=sm_75 -std=c++14
/bin/sh: 1: /usr/local/cuda-10.1/bin/nvcc: not found
ninja: build stopped: subcommand failed.
Traceback (most recent call last):
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/utils/cpp_extension.py", line 1515, in _run_ninja_build
env=env)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/subprocess.py", line 438, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['ninja', '-v']' returned non-zero exit status 1.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "auxiliary/ChamferDistancePytorch/chamfer3D/setup.py", line 13, in
'build_ext': BuildExtension
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/setuptools/init.py", line 153, in setup
return distutils.core.setup(**attrs)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/core.py", line 148, in setup
dist.run_commands()
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/dist.py", line 955, in run_commands
self.run_command(cmd)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/dist.py", line 974, in run_command
cmd_obj.run()
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/setuptools/command/install.py", line 67, in run
self.do_egg_install()
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/setuptools/command/install.py", line 109, in do_egg_install
self.run_command('bdist_egg')
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/cmd.py", line 313, in run_command
self.distribution.run_command(command)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/dist.py", line 974, in run_command
cmd_obj.run()
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/setuptools/command/bdist_egg.py", line 164, in run
cmd = self.call_command('install_lib', warn_dir=0)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/setuptools/command/bdist_egg.py", line 150, in call_command
self.run_command(cmdname)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/cmd.py", line 313, in run_command
self.distribution.run_command(command)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/dist.py", line 974, in run_command
cmd_obj.run()
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/setuptools/command/install_lib.py", line 11, in run
self.build()
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/command/install_lib.py", line 107, in build
self.run_command('build_ext')
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/cmd.py", line 313, in run_command
self.distribution.run_command(command)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/dist.py", line 974, in run_command
cmd_obj.run()
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/setuptools/command/build_ext.py", line 79, in run
_build_ext.run(self)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/command/build_ext.py", line 339, in run
self.build_extensions()
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/utils/cpp_extension.py", line 649, in build_extensions
build_ext.build_extensions(self)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/command/build_ext.py", line 448, in build_extensions
self._build_extensions_serial()
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/command/build_ext.py", line 473, in _build_extensions_serial
self.build_extension(ext)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/setuptools/command/build_ext.py", line 196, in build_extension
_build_ext.build_extension(self, ext)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/distutils/command/build_ext.py", line 533, in build_extension
depends=ext.depends)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/utils/cpp_extension.py", line 478, in unix_wrap_ninja_compile
with_cuda=with_cuda)
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/utils/cpp_extension.py", line 1233, in _write_ninja_file_and_compile_objects
error_prefix='Error compiling objects for extension')
File "/home/20020006/.conda/envs/geo_adv/lib/python3.6/site-packages/torch/utils/cpp_extension.py", line 1529, in _run_ninja_build
raise RuntimeError(message)
RuntimeError: Error compiling objects for extension

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.