From f5bb425a3500602e5ba3c5bbf7865b2f58837a50 Mon Sep 17 00:00:00 2001 From: zimmerrol Date: Wed, 30 Nov 2022 08:53:43 -0600 Subject: [PATCH] Public release --- README.md | 29 + active_tests/__init__.py | 14 + .../decision_boundary_binarization.py | 1402 ++++++++++++ argparse_utils.py | 164 ++ attacks/__init__.py | 14 + attacks/adaptive_kwta_attack.py | 156 ++ attacks/autopgd.py | 131 ++ attacks/fab.py | 66 + attacks/pgd.py | 124 ++ attacks/thermometer_ls_pgd.py | 196 ++ case_studies/__init__.py | 14 + case_studies/bat/README.md | 34 + case_studies/bat/adversarial_evaluation.py | 249 +++ case_studies/bat/adversarial_evaluation.sh | 14 + case_studies/bat/bat_utils.py | 222 ++ case_studies/bat/binarization_test.py | 294 +++ case_studies/bat/binarization_test.sh | 24 + case_studies/bat/eval.py | 209 ++ case_studies/bat/eval.sh | 14 + case_studies/bat/train.py | 356 +++ case_studies/bat/train.sh | 22 + case_studies/bat/wide_resnet.py | 185 ++ case_studies/curriculum_at/PGD_attack.py | 173 ++ case_studies/curriculum_at/README.md | 37 + .../curriculum_at/adversarial_evaluation.py | 237 ++ .../curriculum_at/adversarial_evaluation.sh | 51 + .../adversarial_evaluation_0.5.sh | 57 + .../curriculum_at/binarization_test.py | 356 +++ .../curriculum_at/binarization_test.sh | 42 + case_studies/curriculum_at/cifar10_input.py | 204 ++ case_studies/curriculum_at/config_attack.py | 68 + case_studies/curriculum_at/eval_attack.py | 25 + case_studies/curriculum_at/model_new.py | 1427 ++++++++++++ case_studies/curriculum_at/requirements.txt | 6 + case_studies/curriculum_at/run_attack.py | 463 ++++ case_studies/diffpure/LICENSE | 64 + case_studies/diffpure/README.md | 213 ++ case_studies/diffpure/assets/teaser_v7.jpeg | Bin 0 -> 520516 bytes case_studies/diffpure/bpda_eot/LICENSE_BPDA | 73 + .../diffpure/bpda_eot/bpda_eot_attack.py | 185 ++ .../classifiers/attribute_classifier.py | 65 + .../diffpure/classifiers/attribute_net.py | 227 ++ .../diffpure/classifiers/cifar10_resnet.py | 199 ++ case_studies/diffpure/configs/celeba.yml | 35 + case_studies/diffpure/configs/cifar10.yml | 65 + case_studies/diffpure/configs/imagenet.yml | 23 + case_studies/diffpure/data/__init__.py | 25 + case_studies/diffpure/data/datasets.py | 335 +++ case_studies/diffpure/ddpm/LICENSE_UNET_DDPM | 21 + case_studies/diffpure/ddpm/unet_ddpm.py | 345 +++ case_studies/diffpure/diffpure.Dockerfile | 97 + case_studies/diffpure/dp_utils.py | 301 +++ case_studies/diffpure/eval_sde_adv.py | 570 +++++ case_studies/diffpure/eval_sde_adv_bpda.py | 278 +++ .../guided_diffusion/LICENSE_GUIDED_DIFFUSION | 21 + .../diffpure/guided_diffusion/__init__.py | 11 + .../diffpure/guided_diffusion/dist_util.py | 101 + .../diffpure/guided_diffusion/fp16_util.py | 244 ++ .../guided_diffusion/gaussian_diffusion.py | 916 ++++++++ .../guided_diffusion/image_datasets.py | 175 ++ .../diffpure/guided_diffusion/logger.py | 503 +++++ .../diffpure/guided_diffusion/losses.py | 85 + case_studies/diffpure/guided_diffusion/nn.py | 178 ++ .../diffpure/guided_diffusion/resample.py | 162 ++ .../diffpure/guided_diffusion/respace.py | 136 ++ .../diffpure/guided_diffusion/script_util.py | 460 ++++ .../diffpure/guided_diffusion/train_util.py | 309 +++ .../diffpure/guided_diffusion/unet.py | 902 ++++++++ .../celebahq/run_celebahq_bpda_glasses.sh | 30 + .../celebahq/run_celebahq_bpda_smiling.sh | 30 + .../run_scripts/cifar10/run_cifar_bpda_eot.sh | 28 + .../run_scripts/cifar10/run_cifar_rand_L2.sh | 31 + .../cifar10/run_cifar_rand_L2_70-16-dp.sh | 31 + .../cifar10/run_cifar_rand_L2_rn50_eps1.sh | 31 + .../run_scripts/cifar10/run_cifar_rand_inf.sh | 32 + .../cifar10/run_cifar_rand_inf_70-16-dp.sh | 30 + .../run_cifar_rand_inf_binarization_test.sh | 27 + .../cifar10/run_cifar_rand_inf_rn50.sh | 29 + .../cifar10/run_cifar_stadv_rn50.sh | 30 + .../run_scripts/cifar10/run_cifar_stand_L2.sh | 30 + .../cifar10/run_cifar_stand_L2_70-16-dp.sh | 30 + .../cifar10/run_cifar_stand_L2_rn50_eps1.sh | 30 + .../cifar10/run_cifar_stand_inf.sh | 29 + .../cifar10/run_cifar_stand_inf_70-16-dp.sh | 29 + .../cifar10/run_cifar_stand_inf_rn50.sh | 29 + .../run_scripts/imagenet/run_in_rand_inf.sh | 29 + .../imagenet/run_in_rand_inf_50-2.sh | 29 + .../imagenet/run_in_rand_inf_deits.sh | 29 + .../run_scripts/imagenet/run_in_stand_inf.sh | 28 + .../imagenet/run_in_stand_inf_50-2.sh | 28 + .../imagenet/run_in_stand_inf_deits.sh | 28 + .../diffpure/runners/diffpure_ddpm.py | 142 ++ .../diffpure/runners/diffpure_guided.py | 89 + .../diffpure/runners/diffpure_ldsde.py | 252 +++ case_studies/diffpure/runners/diffpure_ode.py | 249 +++ case_studies/diffpure/runners/diffpure_sde.py | 247 ++ .../diffpure/score_sde/LICENSE_SCORE_SDE | 201 ++ case_studies/diffpure/score_sde/losses.py | 210 ++ .../diffpure/score_sde/models/__init__.py | 15 + .../diffpure/score_sde/models/ddpm.py | 181 ++ case_studies/diffpure/score_sde/models/ema.py | 106 + .../diffpure/score_sde/models/layers.py | 662 ++++++ .../diffpure/score_sde/models/layerspp.py | 274 +++ .../diffpure/score_sde/models/ncsnpp.py | 381 ++++ .../diffpure/score_sde/models/ncsnv2.py | 416 ++++ .../score_sde/models/normalization.py | 215 ++ .../score_sde/models/up_or_down_sampling.py | 265 +++ .../diffpure/score_sde/models/utils.py | 187 ++ .../diffpure/score_sde/op/__init__.py | 10 + .../diffpure/score_sde/op/fused_act.py | 105 + .../diffpure/score_sde/op/fused_bias_act.cpp | 29 + .../score_sde/op/fused_bias_act_kernel.cu | 99 + .../diffpure/score_sde/op/upfirdn2d.cpp | 31 + .../diffpure/score_sde/op/upfirdn2d.py | 208 ++ .../diffpure/score_sde/op/upfirdn2d_kernel.cu | 369 +++ case_studies/diffpure/score_sde/sampling.py | 485 ++++ case_studies/diffpure/score_sde/sde_lib.py | 262 +++ case_studies/diffpure/slurm/analyze_logs.py | 74 + .../diffpure/slurm/binarization_test.sh | 22 + .../slurm/binarization_test_single.sh | 45 + case_studies/diffpure/stadv_eot/attacks.py | 136 ++ .../stadv_eot/recoloradv/LICENSE_RECOLORADV | 17 + .../diffpure/stadv_eot/recoloradv/__init__.py | 12 + .../stadv_eot/recoloradv/color_spaces.py | 272 +++ .../recoloradv/color_transformers.py | 379 ++++ .../stadv_eot/recoloradv/mister_ed/README.md | 1 + .../recoloradv/mister_ed/__init__.py | 12 + .../mister_ed/adversarial_attacks.py | 710 ++++++ .../mister_ed/adversarial_perturbations.py | 813 +++++++ .../mister_ed/adversarial_training.py | 550 +++++ .../stadv_eot/recoloradv/mister_ed/config.py | 40 + .../recoloradv/mister_ed/loss_functions.py | 562 +++++ .../mister_ed/spatial_transformers.py | 528 +++++ .../recoloradv/mister_ed/utils/__init__.py | 12 + .../recoloradv/mister_ed/utils/checkpoints.py | 311 +++ .../mister_ed/utils/discretization.py | 224 ++ .../recoloradv/mister_ed/utils/image_utils.py | 193 ++ .../mister_ed/utils/pytorch_ssim.py | 89 + .../mister_ed/utils/pytorch_utils.py | 637 ++++++ .../diffpure/stadv_eot/recoloradv/norms.py | 51 + .../stadv_eot/recoloradv/perturbations.py | 129 ++ .../diffpure/stadv_eot/recoloradv/utils.py | 108 + case_studies/dla/adversarial_evaluation.py | 133 ++ case_studies/dla/adversarial_evaluation.sh | 27 + case_studies/dla/binarization_test.py | 241 ++ case_studies/dla/binarization_test.sh | 94 + case_studies/dla/cifar.py | 51 + case_studies/dla/defense.py | 187 ++ case_studies/dla/defense_v2.py | 257 +++ case_studies/dla/defense_v3.py | 263 +++ case_studies/dla/dla.py | 39 + case_studies/dla/pgd_attack.py | 69 + case_studies/empir/README.md | 145 ++ .../empir/cleverhans_tutorials/__init__.py | 14 + .../cleverhans_tutorials/tutorial_models.py | 1984 +++++++++++++++++ case_studies/empir/examples/__init__.py | 14 + case_studies/empir/examples/alexnet_attack.py | 753 +++++++ .../empir/examples/binarization_test.sh | 40 + case_studies/empir/examples/cifar10_attack.py | 540 +++++ .../examples/cifar10_binarization_test.py | 561 +++++ .../empir/examples/imagenet_preprocessing.py | 407 ++++ case_studies/empir/examples/mnist_attack.py | 681 ++++++ .../empir/modified_cleverhans/__init__.py | 19 + .../empir/modified_cleverhans/attacks.py | 1304 +++++++++++ .../empir/modified_cleverhans/attacks_tf.py | 1198 ++++++++++ .../empir/modified_cleverhans/attacks_th.py | 114 + .../modified_cleverhans/devtools/LICENSE.txt | 30 + .../modified_cleverhans/devtools/__init__.py | 14 + .../modified_cleverhans/devtools/checks.py | 43 + .../devtools/list_files.py | 100 + .../modified_cleverhans/devtools/mocks.py | 40 + .../devtools/tests/__init__.py | 14 + .../devtools/tests/docscrape.py | 853 +++++++ .../devtools/tests/test_format.py | 130 ++ .../modified_cleverhans/devtools/version.py | 36 + .../empir/modified_cleverhans/model.py | 181 ++ .../empir/modified_cleverhans/utils.py | 397 ++++ .../empir/modified_cleverhans/utils_keras.py | 213 ++ .../empir/modified_cleverhans/utils_mnist.py | 87 + .../empir/modified_cleverhans/utils_tf.py | 1578 +++++++++++++ .../empir/modified_cleverhans/utils_th.py | 340 +++ .../error_correcting_codes/AttackModel.py | 219 ++ .../error_correcting_codes/ClassBlender.py | 68 + .../error_correcting_codes/Clipper.py | 56 + .../error_correcting_codes/DataAugmenter.py | 69 + .../error_correcting_codes/Grayscaler.py | 56 + case_studies/error_correcting_codes/LICENSE | 674 ++++++ case_studies/error_correcting_codes/Model.py | 407 ++++ .../Model_Implementations.py | 250 +++ case_studies/error_correcting_codes/README.md | 13 + .../error_correcting_codes/TrainModel.py | 206 ++ .../adversarial_evaluation.py | 285 +++ .../binarization_test.py | 219 ++ .../binarization_test.sh | 28 + .../error_correcting_codes/utils_keras.py | 257 +++ case_studies/evaluate_classifier.py | 734 ++++++ case_studies/evaluate_detection_defense.py | 223 ++ case_studies/feature_scatter/README.md | 55 + case_studies/feature_scatter/__init__.py | 14 + .../feature_scatter/attack_methods.py | 358 +++ .../feature_scatter/binarization_test.sh | 48 + case_studies/feature_scatter/fs_eval.py | 547 +++++ case_studies/feature_scatter/fs_eval.sh | 15 + case_studies/feature_scatter/fs_eval_test.sh | 47 + case_studies/feature_scatter/fs_main.py | 338 +++ case_studies/feature_scatter/fs_train.sh | 16 + case_studies/feature_scatter/ftsc_utils.py | 97 + .../feature_scatter/models/__init__.py | 15 + .../feature_scatter/models/wideresnet.py | 143 ++ case_studies/feature_scatter/ot.py | 140 ++ case_studies/inputtransformations/README.md | 27 + .../adversarial_evaluation.py | 98 + .../adversarial_evaluation.sh | 11 + case_studies/inputtransformations/defense.py | 334 +++ .../inputtransformations/imagenet_labels.py | 1020 +++++++++ .../inputtransformations/inceptionv3.py | 61 + .../inputtransformations/quilt_preprocess.py | 74 + .../inputtransformations/robustml_attack.py | 83 + .../inputtransformations/robustml_model.py | 87 + case_studies/inputtransformations/setup.sh | 44 + case_studies/inputtransformations/utils.py | 67 + .../interpolation_training/__init__.py | 14 + .../interpolation_training/adv_interp.py | 65 + .../adv_interp_train.sh | 16 + .../binarization_test.sh | 65 + case_studies/interpolation_training/eval.py | 419 ++++ case_studies/interpolation_training/eval.sh | 12 + .../interpolation_training/eval_pretrain.sh | 9 + .../eval_test_pretrain.sh | 8 + .../interpolation_training/it_utils.py | 315 +++ .../interpolation_training/models/__init__.py | 15 + .../models/wideresnet.py | 145 ++ .../train_adv_interp.py | 239 ++ case_studies/jarn/README.md | 47 + case_studies/jarn/adversarial_evaluation.py | 140 ++ case_studies/jarn/adversarial_evaluation.sh | 11 + case_studies/jarn/autoattack_adapter.py | 129 ++ case_studies/jarn/binarization_test.py | 249 +++ case_studies/jarn/binarization_test.sh | 46 + case_studies/jarn/cifar10_input.py | 204 ++ case_studies/jarn/config.py | 101 + case_studies/jarn/config_attack.py | 60 + case_studies/jarn/model_jarn.py | 582 +++++ case_studies/jarn/pgd_attack.py | 199 ++ case_studies/jarn/requirements.txt | 5 + case_studies/jarn/run_attack.py | 242 ++ case_studies/jarn/run_train_jarn.sh | 3 + case_studies/jarn/train_jarn.py | 286 +++ case_studies/kwta/__init__.py | 14 + case_studies/kwta/all.sh | 5 + case_studies/kwta/binarization_test.sh | 61 + case_studies/kwta/models.py | 201 ++ case_studies/kwta/original/__init__.py | 14 + case_studies/kwta/original/kWTA/.gitignore | 1 + case_studies/kwta/original/kWTA/__init__.py | 14 + case_studies/kwta/original/kWTA/activation.py | 275 +++ case_studies/kwta/original/kWTA/models.py | 201 ++ case_studies/kwta/original/kWTA/resnet.py | 329 +++ case_studies/kwta/original/kWTA/training.py | 612 +++++ case_studies/kwta/original/train-cifar.py | 80 + case_studies/kwta/resnet.py | 406 ++++ case_studies/kwta/single_kwta.sh | 58 + case_studies/mixup/adversarial_evaluation.py | 291 +++ case_studies/mixup/binarization_test.py | 132 ++ case_studies/mixup/binarization_test.sh | 37 + case_studies/mixup/resnet_3layer.py | 336 +++ case_studies/mixup/transforms.py | 111 + case_studies/ml_loo/README.md | 50 + case_studies/ml_loo/adversarial_evaluation.py | 215 ++ case_studies/ml_loo/adversarial_evaluation.sh | 51 + case_studies/ml_loo/attack_model.py | 246 ++ case_studies/ml_loo/binarization_test.py | 415 ++++ case_studies/ml_loo/binarization_test.sh | 60 + case_studies/ml_loo/build_model.py | 570 +++++ .../ml_loo/cifar10resnet/models/original.hdf5 | Bin 0 -> 4816920 bytes case_studies/ml_loo/features_extract.py | 134 ++ case_studies/ml_loo/generate_attack.py | 215 ++ case_studies/ml_loo/load_data.py | 166 ++ case_studies/ml_loo/ml_loo.py | 334 +++ case_studies/ml_loo/resnet.py | 294 +++ case_studies/ml_loo/supp.pdf | Bin 0 -> 1139529 bytes case_studies/ml_loo/train_and_evaluate.py | 206 ++ case_studies/mmt/LICENSE | 201 ++ case_studies/mmt/README.md | 116 + case_studies/mmt/adaptive_attack.py | 378 ++++ case_studies/mmt/adversarial_evaluation.sh | 21 + case_studies/mmt/advtest_iterative.py | 402 ++++ .../mmt/advtest_iterative_blackbox.py | 404 ++++ case_studies/mmt/advtest_others.py | 422 ++++ case_studies/mmt/advtest_simple_transform.py | 280 +++ case_studies/mmt/advtrain.py | 303 +++ case_studies/mmt/binarization_test.sh | 43 + .../mmt/binarization_test_iterative.py | 566 +++++ case_studies/mmt/fgm_patched.py | 102 + .../mmt/kernel_paras/craft_MMcenters.m | 18 + .../meanvar1_featuredim256_class10.mat | Bin 0 -> 463 bytes .../meanvar1_featuredim256_class100.mat | Bin 0 -> 3409 bytes .../meanvar1_featuredim64_class10.mat | Bin 0 -> 390 bytes .../meanvar1_featuredim64_class100.mat | Bin 0 -> 2948 bytes case_studies/mmt/mmt_utils/__init__.py | 14 + .../craft_MMLDA_means_whenDlessthanL.py | 40 + .../mmt/mmt_utils/keras_wraper_ensemble.py | 181 ++ case_studies/mmt/mmt_utils/model.py | 245 ++ .../mmt/mmt_utils/utils_model_eval.py | 334 +++ case_studies/mmt/requirements.txt | 153 ++ case_studies/mmt/train.py | 255 +++ case_studies/odds/original/README.txt | 7 + case_studies/odds/original/__init__.py | 14 + .../odds/original/adversarial_evaluation.py | 359 +++ .../odds/original/adversarial_evaluation.sh | 19 + .../odds/original/binarization_test.py | 550 +++++ .../odds/original/binarization_test.sh | 95 + .../odds/original/carlini_wagner_attack.py | 250 +++ .../odds/original/carlini_wagner_helpers.py | 89 + case_studies/odds/original/cifar_model.py | 140 ++ .../odds/original/fetch_Madry_ResNet.py | 60 + .../odds/original/logit_matching_attack.py | 325 +++ .../odds/original/tensorflow_example.py | 499 +++++ .../odds/original/tf_robustify/__init__.py | 522 +++++ case_studies/odds/original/torch_example.py | 789 +++++++ case_studies/odds/original/vgg.py | 177 ++ case_studies/odds/setup_venv.sh | 11 + case_studies/pcl_defense/README.md | 68 + case_studies/pcl_defense/binarization_test.sh | 20 + .../binarization_test_increased_hardness.sh | 42 + .../pcl_defense/contrastive_proximity.py | 60 + case_studies/pcl_defense/eval.sh | 25 + case_studies/pcl_defense/pcl_training.py | 297 +++ .../pcl_training_adversarial_fgsm.py | 335 +++ .../pcl_training_adversarial_pgd.py | 367 +++ case_studies/pcl_defense/pcl_utils.py | 93 + case_studies/pcl_defense/proximity.py | 51 + case_studies/pcl_defense/resnet_model.py | 181 ++ case_studies/pcl_defense/robustness.py | 321 +++ case_studies/pcl_defense/softmax_training.py | 217 ++ .../gowal_adversarial_evaluation.sh | 65 + .../robust_models/gowal_binarization_test.sh | 61 + .../rade_badversarial_evaluation.sh | 65 + .../robust_models/rade_binarization_test.sh | 61 + .../rebuffi_adversarial_evaluation.sh | 66 + .../rebuffi_binarization_test.sh | 62 + case_studies/thermometer/eval.sh | 63 + case_studies/thermometer/original/README.md | 25 + .../original/adversarial_evaluation.sh | 19 + .../thermometer/original/binarization_test.py | 186 ++ .../thermometer/original/binarization_test.sh | 49 + .../binarization_test_increased_hardness.sh | 39 + .../thermometer/original/cifar10_input.py | 174 ++ .../thermometer/original/cifar_model.py | 244 ++ .../original/discretization_attacks.py | 266 +++ .../original/discretization_utils.py | 309 +++ .../thermometer/original/robustml_attack.py | 148 ++ .../thermometer/original/robustml_model.py | 84 + .../original/robustness_evaluation.py | 116 + case_studies/thermometer/original/setup.sh | 41 + .../thermometer/original/thermometer.ipynb | 234 ++ case_studies/thermometer/original/train.py | 173 ++ case_studies/thermometer/start_docker.sh | 5 + case_studies/thermometer/train.sh | 4 + case_studies/thermometer/train_at.sh | 19 + .../trapdoor/adversarial_evaluation.py | 173 ++ .../trapdoor/adversarial_evaluation.sh | 69 + case_studies/trapdoor/binarization_test.py | 265 +++ case_studies/trapdoor/binarization_test.sh | 111 + case_studies/trapdoor/defense.py | 214 ++ case_studies/trapdoor/generate_signatures.py | 85 + .../trapdoor/generate_signatures_tf.py | 110 + case_studies/trapdoor/original/__init__.py | 14 + .../trapdoor/original/eval_detection.py | 208 ++ .../trapdoor/original/inject_trapdoors.py | 185 ++ case_studies/trapdoor/original/trap_utils.py | 564 +++++ case_studies/trapdoor/orthogonal_pgd.py | 241 ++ case_studies/vanilla_classifier/all.sh | 7 + .../vanilla_classifier/at_inefficient_pgd.sh | 131 ++ case_studies/vanilla_classifier/baseline.sh | 49 + .../baseline_binarization_inner_boundary.sh | 24 + .../vanilla_classifier/gradient_masking.sh | 58 + .../vanilla_classifier/inefficient_pgd.sh | 44 + case_studies/vanilla_classifier/noisy_pgd.sh | 90 + .../non_differentiable_input.sh | 35 + .../pgd_num_steps_dependency.sh | 26 + .../pgd_step_size_dependency.sh | 37 + case_studies/vonenet/LICENSE | 674 ++++++ case_studies/vonenet/README.md | 105 + .../vonenet/adversarial_evaluation.py | 163 ++ .../vonenet/adversarial_evaluation.sh | 121 + case_studies/vonenet/binarization_test.py | 176 ++ case_studies/vonenet/binarization_test.sh | 131 ++ case_studies/vonenet/run.py | 150 ++ case_studies/vonenet/setup.py | 55 + case_studies/vonenet/train.py | 397 ++++ case_studies/vonenet/vonenet/__init__.py | 85 + case_studies/vonenet/vonenet/back_ends.py | 352 +++ case_studies/vonenet/vonenet/modules.py | 149 ++ case_studies/vonenet/vonenet/params.py | 114 + case_studies/vonenet/vonenet/utils.py | 46 + case_studies/vonenet/vonenet/vonenet.py | 91 + .../vonenet_tutorial-activations.ipynb | 352 +++ dm_networks.py | 288 +++ jpeg/__init__.py | 20 + jpeg/compression.py | 228 ++ jpeg/decompression.py | 217 ++ jpeg/jpeg_module.py | 71 + jpeg/utils.py | 81 + networks.py | 671 ++++++ tqdm_utils.py | 71 + utils.py | 339 +++ 407 files changed, 78077 insertions(+) create mode 100644 README.md create mode 100644 active_tests/__init__.py create mode 100644 active_tests/decision_boundary_binarization.py create mode 100644 argparse_utils.py create mode 100644 attacks/__init__.py create mode 100644 attacks/adaptive_kwta_attack.py create mode 100644 attacks/autopgd.py create mode 100644 attacks/fab.py create mode 100644 attacks/pgd.py create mode 100644 attacks/thermometer_ls_pgd.py create mode 100644 case_studies/__init__.py create mode 100644 case_studies/bat/README.md create mode 100644 case_studies/bat/adversarial_evaluation.py create mode 100644 case_studies/bat/adversarial_evaluation.sh create mode 100644 case_studies/bat/bat_utils.py create mode 100644 case_studies/bat/binarization_test.py create mode 100644 case_studies/bat/binarization_test.sh create mode 100644 case_studies/bat/eval.py create mode 100644 case_studies/bat/eval.sh create mode 100644 case_studies/bat/train.py create mode 100644 case_studies/bat/train.sh create mode 100644 case_studies/bat/wide_resnet.py create mode 100644 case_studies/curriculum_at/PGD_attack.py create mode 100644 case_studies/curriculum_at/README.md create mode 100644 case_studies/curriculum_at/adversarial_evaluation.py create mode 100644 case_studies/curriculum_at/adversarial_evaluation.sh create mode 100644 case_studies/curriculum_at/adversarial_evaluation_0.5.sh create mode 100644 case_studies/curriculum_at/binarization_test.py create mode 100644 case_studies/curriculum_at/binarization_test.sh create mode 100644 case_studies/curriculum_at/cifar10_input.py create mode 100644 case_studies/curriculum_at/config_attack.py create mode 100644 case_studies/curriculum_at/eval_attack.py create mode 100644 case_studies/curriculum_at/model_new.py create mode 100644 case_studies/curriculum_at/requirements.txt create mode 100644 case_studies/curriculum_at/run_attack.py create mode 100644 case_studies/diffpure/LICENSE create mode 100644 case_studies/diffpure/README.md create mode 100644 case_studies/diffpure/assets/teaser_v7.jpeg create mode 100644 case_studies/diffpure/bpda_eot/LICENSE_BPDA create mode 100644 case_studies/diffpure/bpda_eot/bpda_eot_attack.py create mode 100644 case_studies/diffpure/classifiers/attribute_classifier.py create mode 100644 case_studies/diffpure/classifiers/attribute_net.py create mode 100644 case_studies/diffpure/classifiers/cifar10_resnet.py create mode 100644 case_studies/diffpure/configs/celeba.yml create mode 100644 case_studies/diffpure/configs/cifar10.yml create mode 100644 case_studies/diffpure/configs/imagenet.yml create mode 100644 case_studies/diffpure/data/__init__.py create mode 100644 case_studies/diffpure/data/datasets.py create mode 100644 case_studies/diffpure/ddpm/LICENSE_UNET_DDPM create mode 100644 case_studies/diffpure/ddpm/unet_ddpm.py create mode 100644 case_studies/diffpure/diffpure.Dockerfile create mode 100644 case_studies/diffpure/dp_utils.py create mode 100644 case_studies/diffpure/eval_sde_adv.py create mode 100644 case_studies/diffpure/eval_sde_adv_bpda.py create mode 100644 case_studies/diffpure/guided_diffusion/LICENSE_GUIDED_DIFFUSION create mode 100644 case_studies/diffpure/guided_diffusion/__init__.py create mode 100644 case_studies/diffpure/guided_diffusion/dist_util.py create mode 100644 case_studies/diffpure/guided_diffusion/fp16_util.py create mode 100644 case_studies/diffpure/guided_diffusion/gaussian_diffusion.py create mode 100644 case_studies/diffpure/guided_diffusion/image_datasets.py create mode 100644 case_studies/diffpure/guided_diffusion/logger.py create mode 100644 case_studies/diffpure/guided_diffusion/losses.py create mode 100644 case_studies/diffpure/guided_diffusion/nn.py create mode 100644 case_studies/diffpure/guided_diffusion/resample.py create mode 100644 case_studies/diffpure/guided_diffusion/respace.py create mode 100644 case_studies/diffpure/guided_diffusion/script_util.py create mode 100644 case_studies/diffpure/guided_diffusion/train_util.py create mode 100644 case_studies/diffpure/guided_diffusion/unet.py create mode 100644 case_studies/diffpure/run_scripts/celebahq/run_celebahq_bpda_glasses.sh create mode 100644 case_studies/diffpure/run_scripts/celebahq/run_celebahq_bpda_smiling.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_bpda_eot.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2_70-16-dp.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2_rn50_eps1.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_70-16-dp.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_binarization_test.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_rn50.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_stadv_rn50.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2_70-16-dp.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2_rn50_eps1.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf_70-16-dp.sh create mode 100644 case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf_rn50.sh create mode 100644 case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf.sh create mode 100644 case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf_50-2.sh create mode 100644 case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf_deits.sh create mode 100644 case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf.sh create mode 100644 case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf_50-2.sh create mode 100644 case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf_deits.sh create mode 100644 case_studies/diffpure/runners/diffpure_ddpm.py create mode 100644 case_studies/diffpure/runners/diffpure_guided.py create mode 100644 case_studies/diffpure/runners/diffpure_ldsde.py create mode 100644 case_studies/diffpure/runners/diffpure_ode.py create mode 100644 case_studies/diffpure/runners/diffpure_sde.py create mode 100644 case_studies/diffpure/score_sde/LICENSE_SCORE_SDE create mode 100644 case_studies/diffpure/score_sde/losses.py create mode 100644 case_studies/diffpure/score_sde/models/__init__.py create mode 100644 case_studies/diffpure/score_sde/models/ddpm.py create mode 100644 case_studies/diffpure/score_sde/models/ema.py create mode 100644 case_studies/diffpure/score_sde/models/layers.py create mode 100644 case_studies/diffpure/score_sde/models/layerspp.py create mode 100644 case_studies/diffpure/score_sde/models/ncsnpp.py create mode 100644 case_studies/diffpure/score_sde/models/ncsnv2.py create mode 100644 case_studies/diffpure/score_sde/models/normalization.py create mode 100644 case_studies/diffpure/score_sde/models/up_or_down_sampling.py create mode 100644 case_studies/diffpure/score_sde/models/utils.py create mode 100644 case_studies/diffpure/score_sde/op/__init__.py create mode 100644 case_studies/diffpure/score_sde/op/fused_act.py create mode 100644 case_studies/diffpure/score_sde/op/fused_bias_act.cpp create mode 100644 case_studies/diffpure/score_sde/op/fused_bias_act_kernel.cu create mode 100644 case_studies/diffpure/score_sde/op/upfirdn2d.cpp create mode 100644 case_studies/diffpure/score_sde/op/upfirdn2d.py create mode 100644 case_studies/diffpure/score_sde/op/upfirdn2d_kernel.cu create mode 100644 case_studies/diffpure/score_sde/sampling.py create mode 100644 case_studies/diffpure/score_sde/sde_lib.py create mode 100644 case_studies/diffpure/slurm/analyze_logs.py create mode 100644 case_studies/diffpure/slurm/binarization_test.sh create mode 100644 case_studies/diffpure/slurm/binarization_test_single.sh create mode 100644 case_studies/diffpure/stadv_eot/attacks.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/LICENSE_RECOLORADV create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/__init__.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/color_spaces.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/color_transformers.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/README.md create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/__init__.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_attacks.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_perturbations.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_training.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/config.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/loss_functions.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/spatial_transformers.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/__init__.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/checkpoints.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/discretization.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/image_utils.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/pytorch_ssim.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/pytorch_utils.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/norms.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/perturbations.py create mode 100644 case_studies/diffpure/stadv_eot/recoloradv/utils.py create mode 100644 case_studies/dla/adversarial_evaluation.py create mode 100644 case_studies/dla/adversarial_evaluation.sh create mode 100644 case_studies/dla/binarization_test.py create mode 100644 case_studies/dla/binarization_test.sh create mode 100644 case_studies/dla/cifar.py create mode 100644 case_studies/dla/defense.py create mode 100644 case_studies/dla/defense_v2.py create mode 100644 case_studies/dla/defense_v3.py create mode 100644 case_studies/dla/dla.py create mode 100644 case_studies/dla/pgd_attack.py create mode 100644 case_studies/empir/README.md create mode 100644 case_studies/empir/cleverhans_tutorials/__init__.py create mode 100644 case_studies/empir/cleverhans_tutorials/tutorial_models.py create mode 100644 case_studies/empir/examples/__init__.py create mode 100644 case_studies/empir/examples/alexnet_attack.py create mode 100644 case_studies/empir/examples/binarization_test.sh create mode 100644 case_studies/empir/examples/cifar10_attack.py create mode 100644 case_studies/empir/examples/cifar10_binarization_test.py create mode 100644 case_studies/empir/examples/imagenet_preprocessing.py create mode 100644 case_studies/empir/examples/mnist_attack.py create mode 100644 case_studies/empir/modified_cleverhans/__init__.py create mode 100644 case_studies/empir/modified_cleverhans/attacks.py create mode 100644 case_studies/empir/modified_cleverhans/attacks_tf.py create mode 100644 case_studies/empir/modified_cleverhans/attacks_th.py create mode 100644 case_studies/empir/modified_cleverhans/devtools/LICENSE.txt create mode 100644 case_studies/empir/modified_cleverhans/devtools/__init__.py create mode 100644 case_studies/empir/modified_cleverhans/devtools/checks.py create mode 100644 case_studies/empir/modified_cleverhans/devtools/list_files.py create mode 100644 case_studies/empir/modified_cleverhans/devtools/mocks.py create mode 100644 case_studies/empir/modified_cleverhans/devtools/tests/__init__.py create mode 100644 case_studies/empir/modified_cleverhans/devtools/tests/docscrape.py create mode 100644 case_studies/empir/modified_cleverhans/devtools/tests/test_format.py create mode 100644 case_studies/empir/modified_cleverhans/devtools/version.py create mode 100644 case_studies/empir/modified_cleverhans/model.py create mode 100644 case_studies/empir/modified_cleverhans/utils.py create mode 100644 case_studies/empir/modified_cleverhans/utils_keras.py create mode 100644 case_studies/empir/modified_cleverhans/utils_mnist.py create mode 100644 case_studies/empir/modified_cleverhans/utils_tf.py create mode 100644 case_studies/empir/modified_cleverhans/utils_th.py create mode 100644 case_studies/error_correcting_codes/AttackModel.py create mode 100644 case_studies/error_correcting_codes/ClassBlender.py create mode 100644 case_studies/error_correcting_codes/Clipper.py create mode 100644 case_studies/error_correcting_codes/DataAugmenter.py create mode 100644 case_studies/error_correcting_codes/Grayscaler.py create mode 100644 case_studies/error_correcting_codes/LICENSE create mode 100644 case_studies/error_correcting_codes/Model.py create mode 100644 case_studies/error_correcting_codes/Model_Implementations.py create mode 100644 case_studies/error_correcting_codes/README.md create mode 100644 case_studies/error_correcting_codes/TrainModel.py create mode 100644 case_studies/error_correcting_codes/adversarial_evaluation.py create mode 100644 case_studies/error_correcting_codes/binarization_test.py create mode 100644 case_studies/error_correcting_codes/binarization_test.sh create mode 100644 case_studies/error_correcting_codes/utils_keras.py create mode 100644 case_studies/evaluate_classifier.py create mode 100644 case_studies/evaluate_detection_defense.py create mode 100644 case_studies/feature_scatter/README.md create mode 100644 case_studies/feature_scatter/__init__.py create mode 100644 case_studies/feature_scatter/attack_methods.py create mode 100644 case_studies/feature_scatter/binarization_test.sh create mode 100644 case_studies/feature_scatter/fs_eval.py create mode 100644 case_studies/feature_scatter/fs_eval.sh create mode 100644 case_studies/feature_scatter/fs_eval_test.sh create mode 100644 case_studies/feature_scatter/fs_main.py create mode 100644 case_studies/feature_scatter/fs_train.sh create mode 100644 case_studies/feature_scatter/ftsc_utils.py create mode 100644 case_studies/feature_scatter/models/__init__.py create mode 100644 case_studies/feature_scatter/models/wideresnet.py create mode 100644 case_studies/feature_scatter/ot.py create mode 100644 case_studies/inputtransformations/README.md create mode 100644 case_studies/inputtransformations/adversarial_evaluation.py create mode 100644 case_studies/inputtransformations/adversarial_evaluation.sh create mode 100644 case_studies/inputtransformations/defense.py create mode 100644 case_studies/inputtransformations/imagenet_labels.py create mode 100644 case_studies/inputtransformations/inceptionv3.py create mode 100644 case_studies/inputtransformations/quilt_preprocess.py create mode 100644 case_studies/inputtransformations/robustml_attack.py create mode 100644 case_studies/inputtransformations/robustml_model.py create mode 100644 case_studies/inputtransformations/setup.sh create mode 100644 case_studies/inputtransformations/utils.py create mode 100644 case_studies/interpolation_training/__init__.py create mode 100644 case_studies/interpolation_training/adv_interp.py create mode 100644 case_studies/interpolation_training/adv_interp_train.sh create mode 100644 case_studies/interpolation_training/binarization_test.sh create mode 100644 case_studies/interpolation_training/eval.py create mode 100644 case_studies/interpolation_training/eval.sh create mode 100644 case_studies/interpolation_training/eval_pretrain.sh create mode 100644 case_studies/interpolation_training/eval_test_pretrain.sh create mode 100644 case_studies/interpolation_training/it_utils.py create mode 100644 case_studies/interpolation_training/models/__init__.py create mode 100644 case_studies/interpolation_training/models/wideresnet.py create mode 100644 case_studies/interpolation_training/train_adv_interp.py create mode 100644 case_studies/jarn/README.md create mode 100644 case_studies/jarn/adversarial_evaluation.py create mode 100644 case_studies/jarn/adversarial_evaluation.sh create mode 100644 case_studies/jarn/autoattack_adapter.py create mode 100644 case_studies/jarn/binarization_test.py create mode 100644 case_studies/jarn/binarization_test.sh create mode 100644 case_studies/jarn/cifar10_input.py create mode 100644 case_studies/jarn/config.py create mode 100644 case_studies/jarn/config_attack.py create mode 100644 case_studies/jarn/model_jarn.py create mode 100644 case_studies/jarn/pgd_attack.py create mode 100644 case_studies/jarn/requirements.txt create mode 100644 case_studies/jarn/run_attack.py create mode 100644 case_studies/jarn/run_train_jarn.sh create mode 100644 case_studies/jarn/train_jarn.py create mode 100644 case_studies/kwta/__init__.py create mode 100644 case_studies/kwta/all.sh create mode 100644 case_studies/kwta/binarization_test.sh create mode 100644 case_studies/kwta/models.py create mode 100644 case_studies/kwta/original/__init__.py create mode 100644 case_studies/kwta/original/kWTA/.gitignore create mode 100644 case_studies/kwta/original/kWTA/__init__.py create mode 100644 case_studies/kwta/original/kWTA/activation.py create mode 100644 case_studies/kwta/original/kWTA/models.py create mode 100644 case_studies/kwta/original/kWTA/resnet.py create mode 100644 case_studies/kwta/original/kWTA/training.py create mode 100644 case_studies/kwta/original/train-cifar.py create mode 100644 case_studies/kwta/resnet.py create mode 100644 case_studies/kwta/single_kwta.sh create mode 100644 case_studies/mixup/adversarial_evaluation.py create mode 100644 case_studies/mixup/binarization_test.py create mode 100644 case_studies/mixup/binarization_test.sh create mode 100644 case_studies/mixup/resnet_3layer.py create mode 100644 case_studies/mixup/transforms.py create mode 100644 case_studies/ml_loo/README.md create mode 100644 case_studies/ml_loo/adversarial_evaluation.py create mode 100644 case_studies/ml_loo/adversarial_evaluation.sh create mode 100644 case_studies/ml_loo/attack_model.py create mode 100644 case_studies/ml_loo/binarization_test.py create mode 100644 case_studies/ml_loo/binarization_test.sh create mode 100644 case_studies/ml_loo/build_model.py create mode 100644 case_studies/ml_loo/cifar10resnet/models/original.hdf5 create mode 100644 case_studies/ml_loo/features_extract.py create mode 100644 case_studies/ml_loo/generate_attack.py create mode 100644 case_studies/ml_loo/load_data.py create mode 100644 case_studies/ml_loo/ml_loo.py create mode 100644 case_studies/ml_loo/resnet.py create mode 100644 case_studies/ml_loo/supp.pdf create mode 100644 case_studies/ml_loo/train_and_evaluate.py create mode 100644 case_studies/mmt/LICENSE create mode 100644 case_studies/mmt/README.md create mode 100644 case_studies/mmt/adaptive_attack.py create mode 100644 case_studies/mmt/adversarial_evaluation.sh create mode 100644 case_studies/mmt/advtest_iterative.py create mode 100644 case_studies/mmt/advtest_iterative_blackbox.py create mode 100644 case_studies/mmt/advtest_others.py create mode 100644 case_studies/mmt/advtest_simple_transform.py create mode 100644 case_studies/mmt/advtrain.py create mode 100644 case_studies/mmt/binarization_test.sh create mode 100644 case_studies/mmt/binarization_test_iterative.py create mode 100644 case_studies/mmt/fgm_patched.py create mode 100644 case_studies/mmt/kernel_paras/craft_MMcenters.m create mode 100644 case_studies/mmt/kernel_paras/meanvar1_featuredim256_class10.mat create mode 100644 case_studies/mmt/kernel_paras/meanvar1_featuredim256_class100.mat create mode 100644 case_studies/mmt/kernel_paras/meanvar1_featuredim64_class10.mat create mode 100644 case_studies/mmt/kernel_paras/meanvar1_featuredim64_class100.mat create mode 100644 case_studies/mmt/mmt_utils/__init__.py create mode 100644 case_studies/mmt/mmt_utils/craft_MMLDA_means_whenDlessthanL.py create mode 100644 case_studies/mmt/mmt_utils/keras_wraper_ensemble.py create mode 100644 case_studies/mmt/mmt_utils/model.py create mode 100644 case_studies/mmt/mmt_utils/utils_model_eval.py create mode 100644 case_studies/mmt/requirements.txt create mode 100644 case_studies/mmt/train.py create mode 100644 case_studies/odds/original/README.txt create mode 100644 case_studies/odds/original/__init__.py create mode 100644 case_studies/odds/original/adversarial_evaluation.py create mode 100644 case_studies/odds/original/adversarial_evaluation.sh create mode 100644 case_studies/odds/original/binarization_test.py create mode 100644 case_studies/odds/original/binarization_test.sh create mode 100644 case_studies/odds/original/carlini_wagner_attack.py create mode 100644 case_studies/odds/original/carlini_wagner_helpers.py create mode 100644 case_studies/odds/original/cifar_model.py create mode 100644 case_studies/odds/original/fetch_Madry_ResNet.py create mode 100644 case_studies/odds/original/logit_matching_attack.py create mode 100644 case_studies/odds/original/tensorflow_example.py create mode 100644 case_studies/odds/original/tf_robustify/__init__.py create mode 100644 case_studies/odds/original/torch_example.py create mode 100644 case_studies/odds/original/vgg.py create mode 100644 case_studies/odds/setup_venv.sh create mode 100644 case_studies/pcl_defense/README.md create mode 100644 case_studies/pcl_defense/binarization_test.sh create mode 100644 case_studies/pcl_defense/binarization_test_increased_hardness.sh create mode 100644 case_studies/pcl_defense/contrastive_proximity.py create mode 100644 case_studies/pcl_defense/eval.sh create mode 100644 case_studies/pcl_defense/pcl_training.py create mode 100644 case_studies/pcl_defense/pcl_training_adversarial_fgsm.py create mode 100644 case_studies/pcl_defense/pcl_training_adversarial_pgd.py create mode 100644 case_studies/pcl_defense/pcl_utils.py create mode 100644 case_studies/pcl_defense/proximity.py create mode 100644 case_studies/pcl_defense/resnet_model.py create mode 100644 case_studies/pcl_defense/robustness.py create mode 100644 case_studies/pcl_defense/softmax_training.py create mode 100644 case_studies/robust_models/gowal_adversarial_evaluation.sh create mode 100644 case_studies/robust_models/gowal_binarization_test.sh create mode 100644 case_studies/robust_models/rade_badversarial_evaluation.sh create mode 100644 case_studies/robust_models/rade_binarization_test.sh create mode 100644 case_studies/robust_models/rebuffi_adversarial_evaluation.sh create mode 100644 case_studies/robust_models/rebuffi_binarization_test.sh create mode 100644 case_studies/thermometer/eval.sh create mode 100644 case_studies/thermometer/original/README.md create mode 100644 case_studies/thermometer/original/adversarial_evaluation.sh create mode 100644 case_studies/thermometer/original/binarization_test.py create mode 100644 case_studies/thermometer/original/binarization_test.sh create mode 100644 case_studies/thermometer/original/binarization_test_increased_hardness.sh create mode 100644 case_studies/thermometer/original/cifar10_input.py create mode 100644 case_studies/thermometer/original/cifar_model.py create mode 100644 case_studies/thermometer/original/discretization_attacks.py create mode 100644 case_studies/thermometer/original/discretization_utils.py create mode 100644 case_studies/thermometer/original/robustml_attack.py create mode 100644 case_studies/thermometer/original/robustml_model.py create mode 100644 case_studies/thermometer/original/robustness_evaluation.py create mode 100644 case_studies/thermometer/original/setup.sh create mode 100644 case_studies/thermometer/original/thermometer.ipynb create mode 100644 case_studies/thermometer/original/train.py create mode 100644 case_studies/thermometer/start_docker.sh create mode 100644 case_studies/thermometer/train.sh create mode 100644 case_studies/thermometer/train_at.sh create mode 100644 case_studies/trapdoor/adversarial_evaluation.py create mode 100644 case_studies/trapdoor/adversarial_evaluation.sh create mode 100644 case_studies/trapdoor/binarization_test.py create mode 100644 case_studies/trapdoor/binarization_test.sh create mode 100644 case_studies/trapdoor/defense.py create mode 100644 case_studies/trapdoor/generate_signatures.py create mode 100644 case_studies/trapdoor/generate_signatures_tf.py create mode 100644 case_studies/trapdoor/original/__init__.py create mode 100644 case_studies/trapdoor/original/eval_detection.py create mode 100644 case_studies/trapdoor/original/inject_trapdoors.py create mode 100644 case_studies/trapdoor/original/trap_utils.py create mode 100644 case_studies/trapdoor/orthogonal_pgd.py create mode 100644 case_studies/vanilla_classifier/all.sh create mode 100644 case_studies/vanilla_classifier/at_inefficient_pgd.sh create mode 100644 case_studies/vanilla_classifier/baseline.sh create mode 100644 case_studies/vanilla_classifier/baseline_binarization_inner_boundary.sh create mode 100644 case_studies/vanilla_classifier/gradient_masking.sh create mode 100644 case_studies/vanilla_classifier/inefficient_pgd.sh create mode 100644 case_studies/vanilla_classifier/noisy_pgd.sh create mode 100644 case_studies/vanilla_classifier/non_differentiable_input.sh create mode 100644 case_studies/vanilla_classifier/pgd_num_steps_dependency.sh create mode 100644 case_studies/vanilla_classifier/pgd_step_size_dependency.sh create mode 100644 case_studies/vonenet/LICENSE create mode 100644 case_studies/vonenet/README.md create mode 100644 case_studies/vonenet/adversarial_evaluation.py create mode 100644 case_studies/vonenet/adversarial_evaluation.sh create mode 100644 case_studies/vonenet/binarization_test.py create mode 100644 case_studies/vonenet/binarization_test.sh create mode 100644 case_studies/vonenet/run.py create mode 100644 case_studies/vonenet/setup.py create mode 100644 case_studies/vonenet/train.py create mode 100644 case_studies/vonenet/vonenet/__init__.py create mode 100644 case_studies/vonenet/vonenet/back_ends.py create mode 100644 case_studies/vonenet/vonenet/modules.py create mode 100644 case_studies/vonenet/vonenet/params.py create mode 100644 case_studies/vonenet/vonenet/utils.py create mode 100644 case_studies/vonenet/vonenet/vonenet.py create mode 100644 case_studies/vonenet/vonenet_tutorial-activations.ipynb create mode 100644 dm_networks.py create mode 100644 jpeg/__init__.py create mode 100644 jpeg/compression.py create mode 100644 jpeg/decompression.py create mode 100644 jpeg/jpeg_module.py create mode 100644 jpeg/utils.py create mode 100644 networks.py create mode 100644 tqdm_utils.py create mode 100644 utils.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..6e2b9a0 --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# Increasing Confidence in Adversarial Robustness Evaluations + +This is the official repository of the paper _Increasing Confidence in Adversarial Robustness Evaluations_ +by Zimmermann et al. 2022. + +The reference implementation of our proposed active test is in +[active_tests/decision_boundary_binarization.py](active_tests/decision_boundary_binarization.py), +and the code to reproduce our experimental findings is in [case_studies](case_studies). Note, that when evaluating +the defense of our authors we always used their reference implementation and only performed the _minimal_ modification +to integrate our test in their respective code base. +## +![](https://zimmerrol.github.io/active-tests/img/Figure_1.svg) + +## Citing +If you use this library, you can cite our [paper](https://openreview.net/forum?id=NkK4i91VWp). +Here is an example BibTeX entry: + +```bibtex +@inproceedings{zimmermann2022increasing, + title={Increasing Confidence in Adversarial Robustness Evaluations}, + author={Roland S. Zimmermann and Wieland Brendel and Florian Tramer and Nicholas Carlini}, + booktitle={Advances in Neural Information Processing Systems}, + editor={Alice H. Oh and Alekh Agarwal and Danielle Belgrave and Kyunghyun Cho}, + year={2022}, + url={https://openreview.net/forum?id=NkK4i91VWp} +} +``` + +_Disclaimer: This is not an official Google product._ \ No newline at end of file diff --git a/active_tests/__init__.py b/active_tests/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/active_tests/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/active_tests/decision_boundary_binarization.py b/active_tests/decision_boundary_binarization.py new file mode 100644 index 0000000..12b8c19 --- /dev/null +++ b/active_tests/decision_boundary_binarization.py @@ -0,0 +1,1402 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import functools +import traceback +import sys +import warnings +from typing import Callable +from typing import List + +from torch.utils.data import SequentialSampler +from typing_extensions import Literal +from typing import Optional +from typing import Tuple +from typing import Union + +import numpy as np +from sklearn.linear_model import LogisticRegression +from sklearn.svm import LinearSVC, SVC +import torch +import torch.utils.data +from torch.utils.data import DataLoader +import tqdm + +import argparse_utils as aut +import networks +import utils as ut + +__all__ = ["interior_boundary_discrimination_attack"] + + +LogitRescalingType = Optional[ + Union[Literal["fixed"], Literal["adaptive"], Literal["tight"]] +] +SolutionGoodnessType = Union[Literal["perfect"], Literal["good"], None] +OptimizerType = Union[ + Literal["sklearn"], Literal["sklearn-svm"], Literal["sgd"], Literal["adam"] +] + + +class __KwargsSequential(torch.nn.Sequential): + """ + Modification of a torch.nn.Sequential model that allows kwargs in the + forward pass. These will be passed to the first module of the network. + """ + + def forward(self, x, **kwargs): + for idx, module in enumerate(self): + if idx == 0: + x = module(x, **kwargs) + else: + x = module(x) + return x + + +def _create_raw_data( + x: torch.Tensor, + y: torch.Tensor, + n_inner_points: int, + n_boundary_points: int, + n_boundary_adversarial_points: int, + n_far_off_boundary_points: int, + n_far_off_adversarial_points: int, + batch_size: int, + fill_batches_for_verification: bool, + verify_valid_inner_input_data_fn: Optional[Callable], + verify_valid_boundary_input_data_fn: Optional[Callable], + get_boundary_adversarials_fn: Optional[ + Callable[[torch.Tensor, torch.Tensor, int, float], torch.Tensor] + ], + device: str, + epsilon: float, + norm: ut.NormType, + n_boundary_classes: int = 1, + eta: float = 0.95, + xi: float = 1.50, + include_original: bool = True, + rejection_resampling_max_repetitions: int = 10, + sample_boundary_from_corners: bool = False, +) -> Tuple[DataLoader, DataLoader, DataLoader, int]: + """Creates the raw training data in image space. Label 0 corresponds to + inner points and label 1 to boundary points.""" + + def _sample_inner_points(n_samples): + # We want to keep the original data point -> only generate n-1 new points + x_inner = torch.repeat_interleave(torch.unsqueeze(x, 0), n_samples, 0) + + if norm == "linf": + # Random noise in [-1, 1]. + delta_inner = 2 * torch.rand_like(x_inner) - 1.0 + # Random noise in [-eps*eta, eps*eta] + delta_inner = delta_inner * eta * epsilon + elif norm == "l2": + # sample uniformly in ball with max radius eta*epsilon + delta_inner = torch.randn_like(x_inner) + delta_inner /= torch.norm(delta_inner, p=2, dim=[1, 2, 3], keepdim=True) + delta_inner *= torch.pow( + torch.rand( + (len(delta_inner), 1, 1, 1), + dtype=delta_inner.dtype, + device=delta_inner.device, + ), + 1 / np.prod(x.shape[1:]), + ) + delta_inner *= epsilon * eta + else: + raise ValueError + + if norm != "linf": + _, delta_inner = ut.clipping_aware_rescaling( + x_inner, + delta_inner, + target_distance=epsilon * eta, + norm=norm, + shrinking=True, + return_delta=True, + ) + + x_inner = torch.clamp(x_inner + delta_inner, 0, 1) + y_inner = torch.zeros(len(x_inner), dtype=torch.long, device=device) + + return x_inner, y_inner + + def _sample_boundary_points(n_samples, distance=epsilon): + x_boundary = torch.unsqueeze(x, 0).repeat( + tuple([n_samples] + [1] * len(x.shape)) + ) + + if norm == "linf": + if sample_boundary_from_corners: + delta_boundary = torch.randint( + 0, + 2, + size=x_boundary.shape, + device=x_boundary.device, + dtype=x_boundary.dtype, + ) + delta_boundary = (delta_boundary * 2.0 - 1.0) * distance + else: + delta_boundary = (torch.rand_like(x_boundary) * 2.0 - 1.0) * distance + elif norm == "l2": + # sample uniformly on sphere with radius epsilon + delta_boundary = torch.randn_like(x_boundary) + delta_boundary /= torch.norm( + delta_boundary, p=2, dim=[1, 2, 3], keepdim=True + ) + delta_boundary *= distance + else: + raise ValueError + + if not sample_boundary_from_corners: + _, delta_boundary = ut.clipping_aware_rescaling( + x_boundary, + delta_boundary, + target_distance=distance, + norm=norm, + growing=True, + shrinking=True, + return_delta=True, + ) + + x_boundary = torch.clamp(x_boundary + delta_boundary, 0, 1) + y_boundary = torch.ones(len(x_boundary), dtype=torch.long, device=device) + + return x_boundary, y_boundary + + def _create_boundary_data(): + # TODO(zimmerrol): Extend this logic for multiple boundary classes + n_random_boundary_samples = n_boundary_points - n_boundary_adversarial_points + if n_random_boundary_samples == 0: + x_random, y_random = None, None + else: + if verify_valid_boundary_input_data_fn is None: + x_random, y_random = _sample_boundary_points(n_random_boundary_samples) + else: + x_random, y_random = _rejection_resampling( + _sample_boundary_points, + n_random_boundary_samples, + verify_valid_boundary_input_data_fn, + n_repetitions=rejection_resampling_max_repetitions, + ) + + if n_random_boundary_samples == n_boundary_points: + # do not have to add any special adversarial points anymore + x_total, y_total = x_random, y_random + else: + x_adv = get_boundary_adversarials_fn( + x.clone(), y, n_boundary_adversarial_points, epsilon + ) + y_adv = torch.ones(len(x_adv), dtype=y.dtype, device=y.device) + if x_random is not None: + x_total = torch.cat((x_random, x_adv)) + y_total = torch.cat((y_random, y_adv)) + else: + x_total, y_total = x_adv, y_adv + + if n_boundary_classes > 1: + raise NotImplementedError("n_boundary_classes > 1 is not yet implemented.") + + if n_far_off_boundary_points > 0: + # add examples that have magnitude larger than epsilon but can be used + # e.g., by logit matching attacks as a reference point + n_random_far_off_samples = ( + n_far_off_boundary_points - n_far_off_adversarial_points + ) + if n_random_boundary_samples == 0: + x_faroff_random, y_faroff_random = None, None + else: + if verify_valid_boundary_input_data_fn is None: + x_faroff_random, y_faroff_random = _sample_boundary_points( + n_random_far_off_samples * n_boundary_classes, + distance=xi * epsilon, + ) + else: + x_faroff_random, y_faroff_random = _rejection_resampling( + functools.partial( + _sample_boundary_points, distance=xi * epsilon + ), + n_random_far_off_samples * n_boundary_classes, + verify_valid_boundary_input_data_fn, + n_repetitions=rejection_resampling_max_repetitions, + ) + if n_boundary_classes > 1: + raise NotImplementedError( + "n_boundary_classes > 1 is not yet implemented." + ) + + if n_far_off_adversarial_points > 0: + x_faroff_adv = get_boundary_adversarials_fn( + x.clone(), y, n_far_off_adversarial_points, epsilon + ) + y_faroff_adv = torch.ones( + len(x_faroff_adv), dtype=y.dtype, device=y.device + ) + if x_faroff_random is not None: + x_faroff = torch.cat((x_faroff_random, x_faroff_adv)) + y_faroff = torch.cat((y_faroff_random, y_faroff_adv)) + else: + x_faroff, y_faroff = x_faroff_adv, y_faroff_adv + else: + x_faroff, y_faroff = x_faroff_random, y_faroff_random + + x_total = torch.cat((x_total, x_faroff)) + y_total = torch.cat((y_total, y_faroff)) + + return x_total, y_total + + def _create_inner_data(): + if include_original: + n_random_points = n_inner_points - 1 + else: + n_random_points = n_inner_points + + if n_random_points > 0: + if verify_valid_inner_input_data_fn is None: + x_random, y_random = _sample_inner_points(n_inner_points) + else: + x_random, y_random = _rejection_resampling( + _sample_inner_points, + n_inner_points, + verify_valid_inner_input_data_fn, + n_repetitions=rejection_resampling_max_repetitions, + ) + + if include_original: + x_total = torch.cat((torch.unsqueeze(x, 0), x_random)) + y_total = torch.zeros( + len(y_random) + 1, dtype=y_random.dtype, device=y_random.device + ) + else: + x_total, y_total = x_random, y_random + else: + x_total = torch.unsqueeze(x, 0) + y_total = torch.zeros(1, dtype=y_boundary.dtype, device=y_boundary.device) + + return x_total, y_total + + def _rejection_resampling( + sampling_fn, n_samples, verify_valid_input_data_fn, n_repetitions=10 + ): + """Resample & replace until all samples returned by the sampling_fn are + valid according to verify_valid_input_data_fn.""" + # do not waste time but running a non-full batch + if fill_batches_for_verification: + n_sampling_samples = max(n_samples, batch_size) + else: + n_sampling_samples = n_samples + + x, y = sampling_fn(n_sampling_samples) + x_valid_mask = verify_valid_input_data_fn(x) + for i in range(n_repetitions + 1): + if np.sum(x_valid_mask) >= n_samples: + # found enough samples + # now restrict x to the valid samples + # and x and y such that their length matches n_samples + x = x[x_valid_mask] + x = x[:n_samples] + y = y[:n_samples] + return x, y + + if i == n_repetitions: + raise RuntimeError( + f"Rejection resampling failed after {n_repetitions} " f"rounds." + ) + + # check how many samples to be replaced + n_x_invalid = len(x_valid_mask) - np.sum(x_valid_mask) + # generate new samples + c = sampling_fn(n_sampling_samples)[0] + # check how many of them are valid and are needed + c_valid_mask = verify_valid_input_data_fn(c) + c = c[c_valid_mask][:n_x_invalid] + c_valid_mask = c_valid_mask[c_valid_mask][:n_x_invalid] + n_x_invalid_c_valid = min(n_x_invalid, len(c)) + # replace samples and update the mask + x[~x_valid_mask][:n_x_invalid_c_valid] = c + x_valid_mask[~x_valid_mask][:n_x_invalid_c_valid] = c_valid_mask + + if not n_inner_points > 0: + raise ValueError("n_inner_points must be > 0.") + if not n_boundary_points > 0: + raise ValueError("n_boundary_points must be > 0.") + if not n_boundary_classes == 1: + raise NotImplementedError("More than 1 boundary class is not yet supported.") + if not n_far_off_adversarial_points >= 0: + raise ValueError("n_far_off_adversarial_points must not be negative.") + if not n_far_off_boundary_points >= 0: + raise ValueError("n_far_off_boundary_points must not be negative.") + if not n_boundary_adversarial_points >= 0: + raise ValueError("n_boundary_adversarial_points must not be negative.") + + x = x.to(device) + y = y.to(device) + (x_boundary, y_boundary) = _create_boundary_data() + (x_inner, y_inner) = _create_inner_data() + + x = torch.cat((x_inner, x_boundary)) + y = torch.cat((y_inner, y_boundary)) + + dataset = torch.utils.data.TensorDataset(x, y) + dataset_boundary = torch.utils.data.TensorDataset(x_boundary, y_boundary) + dataset_inner = torch.utils.data.TensorDataset(x_inner, y_inner) + + dataloader = torch.utils.data.DataLoader( + dataset, shuffle=False, batch_size=batch_size + ) + dataloader_boundary = torch.utils.data.DataLoader( + dataset_boundary, shuffle=False, batch_size=batch_size + ) + dataloader_inner = torch.utils.data.DataLoader( + dataset_inner, shuffle=False, batch_size=batch_size + ) + + return dataloader, dataloader_boundary, dataloader_inner, len(x) + + +def _get_data_features_and_maybe_logits( + classifier: Callable, + raw_data_loader: torch.utils.data.DataLoader, + get_logits: bool, + device: str, + include_raw_data: bool = False, + raw_data_loader_boundary: Optional[torch.utils.data.DataLoader] = None, + raw_data_loader_inner: Optional[torch.utils.data.DataLoader] = None, + n_repetitions_boundary: Optional[int] = None, + n_repetitions_inner: Optional[int] = None, +) -> Tuple[torch.utils.data.DataLoader, torch.Tensor, int, int]: + """ + Collects the intermediate features for a classifier and creates a new data + loader consisting only of these features. + + Args: + classifier: Classifier to use as a feature extractor. + raw_data_loader: Data loader that contains images which + shall be mapped to intermediate features. + get_logits: Extract not only features but also logits + device: torch device. + include_raw_data: Include raw images in the data loader. + Returns: + Data loader mapping intermediate features to class labels. + """ + all_features = [] + all_logits = [] if get_logits else None + all_labels = [] + all_images = [] + + def _process_dataloader(dataloader: DataLoader): + with torch.no_grad(): + for x, y in dataloader: + x_ = x.to(device) + if get_logits: + features, logits = classifier(x_, features_and_logits=True) + all_logits.append(logits) + else: + features = classifier(x_, features_only=True) + + all_features.append(features.detach()) + all_labels.append(y) + if include_raw_data: + all_images.append(x) + + _process_dataloader(raw_data_loader) + + if n_repetitions_boundary is not None: + raw_data_loader_boundary = torch.utils.data.DataLoader( + torch.utils.data.TensorDataset( + torch.repeat_interleave( + raw_data_loader_boundary.dataset.tensors[0], + n_repetitions_boundary, + 0, + ), + torch.repeat_interleave( + raw_data_loader_boundary.dataset.tensors[1], + n_repetitions_boundary, + 0, + ), + ), + batch_size=raw_data_loader_boundary.batch_size, + ) + _process_dataloader(raw_data_loader_boundary) + if n_repetitions_inner is not None: + raw_data_loader_inner = torch.utils.data.DataLoader( + torch.utils.data.TensorDataset( + torch.repeat_interleave( + raw_data_loader_inner.dataset.tensors[0], n_repetitions_inner, 0 + ), + torch.repeat_interleave( + raw_data_loader_inner.dataset.tensors[1], n_repetitions_inner, 0 + ), + ), + batch_size=raw_data_loader_inner.batch_size, + ) + _process_dataloader(raw_data_loader_inner) + + all_features = torch.cat(all_features, 0) + + if get_logits: + all_logits = torch.cat(all_logits, 0) + all_labels = torch.cat(all_labels, 0) + if include_raw_data: + all_images = torch.cat(all_images) + + if len(all_features.shape) > 2: + warnings.warn( + f"Features are not vectors but higher dimensional " + f"({len(all_features.shape) - 1})" + ) + + if include_raw_data: + dataset = torch.utils.data.TensorDataset(all_features, all_labels, all_images) + else: + dataset = torch.utils.data.TensorDataset(all_features, all_labels) + dataloader = torch.utils.data.DataLoader( + dataset, + shuffle=not isinstance(raw_data_loader.sampler, SequentialSampler), + batch_size=raw_data_loader.batch_size, + ) + + return dataloader, all_logits, all_features.shape[-1], all_features.shape[0] + + +def _train_logistic_regression_classifier( + n_features: int, + train_loader: DataLoader, + classifier_logits: Optional[torch.Tensor], + optimizer: OptimizerType, + lr: float, + device: str, + n_classes: int = 2, + rescale_logits: LogitRescalingType = "fixed", + decision_boundary_closeness: Optional[float] = None, + solution_goodness: SolutionGoodnessType = "perfect", + class_weight: Optional[Union[Literal["balanced"], dict]] = None, +) -> torch.nn.Module: + """ + Trains a logistic regression model. + + Args: + n_features: Feature dimensionality. + train_loader: Data loader containing the data to fit model on. + classifier_logits: Logits of the underlying classifier; will be used for logit + rescaling. + optimizer: Type of optimizer to use. + lr: Learning rate (only applies to explicit gradient-descent optimizer). + device: torch device. + rescale_logits: Rescale weights of model such that the logits have + at most unit absolute magnitude. + decision_boundary_closeness: (optional) The larger this value, the will + the decision boundary be placed to the boundary sample(s). + Returns: + Logistic regression model. + """ + + if rescale_logits == "adaptive" and classifier_logits is None: + raise ValueError("classifier_logits must be supplied for adaptive rescaling") + + def get_accuracy() -> Tuple[float, float, float]: + """ + + :return: (total accuracy, accuracy for inner samples, for outer samples) + """ + # calculate accuracy + n_correct = {0: 0, 1: 0} + n_total = {0: 0, 1: 0} + with torch.no_grad(): + for x, y in train_loader: + x = x.to(device) + logits = binary_classifier(x) + for k in n_total.keys(): + n_correct[k] += ( + (logits.argmax(-1).cpu() == y.cpu()) + .float()[y == k] + .sum() + .item() + ) + n_total[k] += len(x[y == k]) + + accuracy = (n_correct[0] + n_correct[1]) / (n_total[0] + n_total[1]) + accuracy_inner = n_correct[0] / n_total[0] + accuracy_outer = n_correct[1] / n_total[1] + + return accuracy, accuracy_inner, accuracy_outer + + if not n_classes == 2: + raise NotImplementedError("Currently only supports 1 boundary class") + + if optimizer.startswith("sklearn"): + if optimizer == "sklearn": + # Use logistic regression of sklearn to speed up fitting. + regression = LogisticRegression( + penalty="none", + max_iter=max(1000, int(lr)), + multi_class="multinomial", + class_weight=class_weight, + ) + elif optimizer == "sklearn-svm": + # Since the problem should be perfectly possible to solve, C should not + # have any effect. + regression = LinearSVC( + penalty="l2", C=10e5, max_iter=max(1000, int(lr)), multi_class="ovr" + ) + else: + raise ValueError("Invalid optimizer choice.") + + regression.fit( + train_loader.dataset.tensors[0].cpu().numpy(), + train_loader.dataset.tensors[1].cpu().numpy(), + ) + + binary_classifier = torch.nn.Linear(n_features, n_classes) + + binary_classifier.weight.data = torch.Tensor( + np.concatenate((-regression.coef_, regression.coef_), 0) + ) + binary_classifier.bias.data = torch.Tensor( + np.concatenate((-regression.intercept_, regression.intercept_), 0) + ) + + binary_classifier = binary_classifier.to(device) + + accuracy, accuracy_inner, accuracy_outer = get_accuracy() + + if solution_goodness is not None and accuracy < 1.0: + raise_error = solution_goodness == "perfect" + raise_error |= ( + solution_goodness == "good" + and accuracy_inner == 0 + or accuracy_outer == 0 + ) + + message = ( + f"sklearn solver failed to find perfect solution, " + f"Accuracy = {accuracy:.4f} instead of 1.0; " + f"{accuracy_inner:.4f} and {accuracy_outer:.4f} for " + f"inner and boundary points." + ) + + if raise_error: + raise RuntimeError(message) + else: + warnings.warn(message) + else: + binary_classifier = torch.nn.Linear(n_features, n_classes).to(device) + criterion = torch.nn.CrossEntropyLoss() + optimizer = {"sgd": torch.optim.SGD, "adam": torch.optim.Adam}[optimizer]( + lr=lr, params=binary_classifier.parameters() + ) + epoch = 0 + while True: + epoch += 1 + for x, y in train_loader: + optimizer.zero_grad() + x = x.to(device) + y = y.to(device) + logits = binary_classifier(x) + loss = criterion(logits, y) + loss.backward() + optimizer.step() + + if epoch > 50000: + raise RuntimeError( + f"Could not fit binary discriminator in 50k iterations " + f"(Loss = {loss.item()}." + "Consider using different settings for the optimizer." + ) + + accuracy = get_accuracy() + # stop training once perfect accuracy is achieved + if accuracy == 1.0: + break + + if rescale_logits is not None or decision_boundary_closeness is not None: + # Get value range of binarized logits. + with torch.no_grad(): + logits = binary_classifier( + train_loader.dataset.tensors[0].to(device) + ).detach() + + if decision_boundary_closeness is not None: + logit_differences = logits[:, 0] - logits[:, 1] + lowest_difference = np.min(logit_differences.cpu().numpy()) + binary_classifier.bias.data[0] -= ( + decision_boundary_closeness * lowest_difference / 2 + ) + binary_classifier.bias.data[1] += ( + decision_boundary_closeness * lowest_difference / 2 + ) + + if rescale_logits is not None: + binarized_logit_range = ( + logits.detach().cpu().numpy().max() + - logits.detach().cpu().numpy().min() + ) + + if rescale_logits == "fixed": + target_logit_range = 1.0 + logit_offset = 0.0 + logit_rescaling_factor = binarized_logit_range / target_logit_range + elif rescale_logits == "adaptive": + # Rescale the binarized logits such that they have the same value range + # i.e., min and max value match. + target_logit_range = ( + classifier_logits.detach().cpu().numpy().max() + - classifier_logits.detach().cpu().numpy().min() + ) + logit_rescaling_factor = binarized_logit_range / target_logit_range + logit_offset = ( + classifier_logits.detach().cpu().numpy().min() + - logits.detach().cpu().numpy().min() / logit_rescaling_factor + ) + elif rescale_logits == "tight": + # Rescale/shift weights such that the distance between the decision + # boundary and the boundary data is small. + + # Calculate distance of boundary points to decision boundary. + distances = binary_classifier( + train_loader.dataset.tensors[0].to(device)[ + train_loader.dataset.tensors[1].to(device) != 0 + ] + )[:, 1:].cpu() + min_distance = distances.min() + # Move decision boundary close to true boundary points + logit_rescaling_factor = 1.0 + logit_offset = torch.tensor( + [+0.999 * min_distance.item(), -0.999 * min_distance.item()], + device=device, + ) + else: + raise ValueError(f"Invalid value for rescale_logits: {rescale_logits}") + + binary_classifier.bias.data /= logit_rescaling_factor + binary_classifier.bias.data += logit_offset + binary_classifier.weight.data /= logit_rescaling_factor + + return binary_classifier + + +def _get_interior_boundary_discriminator_and_dataloaders( + classifier: torch.nn.Module, + x: torch.Tensor, + y: torch.Tensor, + linearization_settings: aut.DecisionBoundaryBinarizationSettings, + device: str, + batch_size: int = 512, + rescale_logits: LogitRescalingType = "fixed", + n_samples_evaluation: int = 0, + n_samples_asr_evaluation: int = 0, + verify_valid_inner_training_data_fn: Optional[ + Callable[[torch.Tensor], np.ndarray] + ] = None, + verify_valid_boundary_training_data_fn: Optional[ + Callable[[torch.Tensor], np.ndarray] + ] = None, + verify_valid_inner_validation_data_fn: Optional[ + Callable[[torch.Tensor], np.ndarray] + ] = None, + verify_valid_boundary_validation_data_fn: Optional[ + Callable[[torch.Tensor], np.ndarray] + ] = None, + get_boundary_adversarials_fn: Optional[ + Callable[[torch.Tensor, torch.Tensor, float], np.ndarray] + ] = None, + fill_batches_for_verification: bool = False, + far_off_distance: float = 1.25, + rejection_resampling_max_repetitions: int = 10, + train_classifier_fn: Callable[ + [int, DataLoader, DataLoader, torch.Tensor, str, LogitRescalingType], + torch.nn.Module, + ] = None, + decision_boundary_closeness: Optional[float] = None, + n_inference_repetitions_boundary: Optional[int] = None, + n_inference_repetitions_inner: Optional[int] = None, + relative_inner_boundary_gap: Optional[float] = 0.05, + sample_training_data_from_corners: bool = False, +) -> Tuple[ + Tuple[torch.nn.Module, torch.nn.Module], + Tuple[DataLoader, DataLoader], + Tuple[float, float, float, float, bool, bool], +]: + """ + Creates a number of perturbed images, obtains the features for these images + and trains a linear, binary discriminator of these samples. + + Args: + classifier: The classifier that will be used as a feature encoder. + x: The single clean image to apply apply the method on. + y: The ground-truth classification label of x. + linearization_settings: How to construct the binary classifier. + device: torch device + batch_size: Max batch size allowed to use + rescale_logits: Rescale weights of linear classifier such that logits + have a max scale of 1 + n_samples_evaluation: Number of random samples to use for evaluation + verify_valid_inner_training_data_fn: Can be used for e.g. detector-based defenses. + Check whether all input points used for training/testing are actually valid + and won't get filtered out be the model/detector. + verify_valid_boundary_training_data_fn: See verify_valid_inner_training_data_fn but for boundary samples. + verify_valid_inner_validation_data_fn: See + verify_valid_inner_training_data_fn but for calculating the validation + scores, i.e. the random ASR. + verify_valid_boundary_validation_data_fn: See + verify_valid_boundary_training_data_fn but for calculating the validation + scores, i.e. the random ASR. + get_boundary_adversarials_fn: If given, use this function to + generate all but one of the boundary samples. This can be used for + evaluating detector-based evaluation functions. + fill_batches_for_verification: If computational cost of verification_fn + does not depend on the batch size, set this to True. + far_off_distance: Relative multiplier (in terms of epsilon) controlling + the distance between clean and far off training samples. + decision_boundary_closeness: (optional) The larger this value, the will + the decision boundary be placed to the boundary sample(s). + n_inference_repetitions_boundary: (optional) How often to repeat + inference for boundary samples for obtaining their features. + n_inference_repetitions_inner: (optional) How often to repeat + inference for inner samples for obtaining their features. + relative_inner_boundary_gap: (optional) Gap between interior and + boundary data relative to epsilon (i.e. a value of 0 means boundary points + can lie directly next to inner points) + sample_training_data_from_corners: Sample training data from the corners + of the epsilon ball; this setting is only possible when using linf norm. + Returns: + Tuple containing ((binary discriminator between interior and boundary points, + binary readout only), + (dataset of perturbed images, dataset of features of perturbed images), + (validation accuracies of inner/boundary/boundary surface/boundary corner points, + random attack success rate of surface/corner points)) + """ + + if sample_training_data_from_corners and linearization_settings.norm != "linf": + raise ValueError("Corners are only defined for linf norm.") + + # Check if model is compatible with this check. + try: + with torch.no_grad(): + if rescale_logits == "adaptive": + classifier( + torch.ones((1, 1, 1, 1), device=device), features_and_logits=True + ) + else: + classifier(torch.ones((1, 1, 1, 1), device=device), features_only=True) + except TypeError as e: + message = str(e) + if "unexpected keyword argument 'features_only'" in message: + raise ValueError( + "model does not support `features_only` flag in forward pass." + ) + if "unexpected keyword argument 'features_and_logits'" in message: + raise ValueError( + "model does not support `features_and_logits` flag in forward pass." + ) + except Exception: + pass + + ( + raw_train_loader, + raw_train_loader_boundary, + raw_train_loader_inner, + n_raw_training_samples, + ) = _create_raw_data( + x, + y, + linearization_settings.n_inner_points, + linearization_settings.n_boundary_points, + linearization_settings.n_boundary_adversarial_points, + linearization_settings.n_far_off_boundary_points, + linearization_settings.n_far_off_adversarial_points, + batch_size=batch_size, + fill_batches_for_verification=fill_batches_for_verification, + verify_valid_inner_input_data_fn=verify_valid_inner_training_data_fn, + verify_valid_boundary_input_data_fn=verify_valid_boundary_training_data_fn, + get_boundary_adversarials_fn=get_boundary_adversarials_fn, + device=device, + epsilon=linearization_settings.epsilon, + norm=linearization_settings.norm, + n_boundary_classes=1, + include_original=True, + xi=far_off_distance, + eta=1.0 - relative_inner_boundary_gap, + rejection_resampling_max_repetitions=rejection_resampling_max_repetitions, + sample_boundary_from_corners=sample_training_data_from_corners, + ) + + # Get features to train binary classifier on. + ( + train_loader, + logits, + n_features, + n_training_samples, + ) = _get_data_features_and_maybe_logits( + classifier, + raw_train_loader, + rescale_logits == "adaptive", + device, + include_raw_data=False, + n_repetitions_boundary=n_inference_repetitions_boundary, + n_repetitions_inner=n_inference_repetitions_inner, + raw_data_loader_boundary=raw_train_loader_boundary, + raw_data_loader_inner=raw_train_loader_inner, + ) + + if not (n_features > n_training_samples): + warnings.warn( + f"Feature dimension ({n_features}) should not be smaller than the " + f"number of training samples ({n_training_samples})", + RuntimeWarning, + ) + + # finally train new binary classifier on features + if train_classifier_fn is None: + binary_classifier = _train_logistic_regression_classifier( + n_features, + train_loader, + logits, + linearization_settings.optimizer, + linearization_settings.lr, + device, + class_weight=linearization_settings.class_weight, + rescale_logits=rescale_logits, + decision_boundary_closeness=decision_boundary_closeness, + ) + linearized_model = __KwargsSequential( + networks.Lambda( + lambda x, **kwargs: classifier(x, features_only=True, **kwargs) + ), + binary_classifier, + ) + + else: + binary_classifier = None + linearized_model = train_classifier_fn( + n_features, + train_loader, + raw_train_loader, + logits, + device, + rescale_logits=rescale_logits, + ) + + # evaluate on another set of random samples (we are only interested in the + # performance of points inside the epsilon ball) + if n_samples_evaluation > 0: + raw_validation_loader, _, _, _ = _create_raw_data( + x, + y, + n_samples_evaluation, + n_samples_evaluation, + 0, + 0, + 0, + batch_size=batch_size, + fill_batches_for_verification=fill_batches_for_verification, + # TODO(zimmerrol): check if this makes sense. The motivation to remove this here + # was that the moved the check down to when the accuracy is calculated + verify_valid_boundary_input_data_fn=None, + verify_valid_inner_input_data_fn=None, + # verify_valid_input_data_fn=verify_valid_input_validation_data_fn, + get_boundary_adversarials_fn=get_boundary_adversarials_fn, + device=device, + epsilon=linearization_settings.epsilon, + norm=linearization_settings.norm, + n_boundary_classes=1, + include_original=False, + xi=far_off_distance, + rejection_resampling_max_repetitions=rejection_resampling_max_repetitions, + eta=1.0, + sample_boundary_from_corners=False, + ) + + _, raw_validation_loader_corners, _, _ = _create_raw_data( + x, + y, + 1, + n_samples_evaluation, + 0, + 0, + 0, + batch_size=batch_size, + fill_batches_for_verification=fill_batches_for_verification, + verify_valid_boundary_input_data_fn=None, + verify_valid_inner_input_data_fn=None, + get_boundary_adversarials_fn=get_boundary_adversarials_fn, + device=device, + epsilon=linearization_settings.epsilon, + norm=linearization_settings.norm, + n_boundary_classes=1, + include_original=False, + xi=far_off_distance, + rejection_resampling_max_repetitions=rejection_resampling_max_repetitions, + eta=1.0, + sample_boundary_from_corners=True, + ) + + raw_validation_loader = torch.utils.data.DataLoader( + torch.utils.data.TensorDataset( + torch.cat( + ( + raw_validation_loader.dataset.tensors[0], + raw_validation_loader_corners.dataset.tensors[0], + ), + 0, + ), + torch.cat( + ( + raw_validation_loader.dataset.tensors[1], + raw_validation_loader_corners.dataset.tensors[1], + ), + 0, + ), + ), + batch_size=raw_validation_loader.batch_size, + shuffle=False, + ) + + # Get features to test binary classifier on. + validation_loader, _, _, _ = _get_data_features_and_maybe_logits( + classifier, raw_validation_loader, False, device, include_raw_data=True + ) + + inner_correctly_classified = [] + boundary_correctly_classified = [] + for it, (x_features, y, x_images) in enumerate(validation_loader): + x_features = x_features.to(device) + x_images = x_images.to(device) + + # If we use a custom train method use the raw images for validation as + # it is possible that the classifier has no simple linear readout. + + # TODO(zimmerrol): also allow detector-like models here + # if the verify_valid_input_data_fn is used, this shouldn't be a + # concern anymore since all samples generated here have already passed + # the detector + with torch.no_grad(): + if binary_classifier is not None: + y_pred = binary_classifier(x_features).argmax(-1).to("cpu") + else: + y_pred = linearized_model(x_images).argmax(-1).to("cpu") + # flag predictions for invalid data points such they are not + # counted as correctly classified samples + if verify_valid_inner_validation_data_fn is not None: + is_valid_input = verify_valid_inner_validation_data_fn( + x_images[y == 0] + ) + y_pred[y == 0][~is_valid_input] = -1 + if verify_valid_boundary_validation_data_fn is not None: + is_valid_input = verify_valid_boundary_validation_data_fn( + x_images[y == 1] + ) + y_pred[y == 1][~is_valid_input] = -1 + + inner_correctly_classified += (y_pred[y == 0] == 0).numpy().tolist() + boundary_correctly_classified += (y_pred[y == 1] == 1).numpy().tolist() + + inner_correctly_classified = np.array(inner_correctly_classified) + boundary_correctly_classified = np.array(boundary_correctly_classified) + + validation_accuracy_inner = float(np.mean(inner_correctly_classified)) + validation_accuracy_boundary = float(np.mean(boundary_correctly_classified)) + + validation_accuracy_boundary_surface = float( + np.mean(boundary_correctly_classified[:n_samples_evaluation]) + ) + validation_accuracy_boundary_corners = float( + np.mean(boundary_correctly_classified[n_samples_evaluation:]) + ) + random_attack_success_inner = ( + np.mean(inner_correctly_classified[:n_samples_asr_evaluation]) < 1.0 + ) + random_attack_success_boundary_surface = ( + np.mean( + boundary_correctly_classified[:n_samples_evaluation][ + :n_samples_asr_evaluation + ] + ) + > 0.0 + ) + random_attack_success_boundary_corners = ( + np.mean( + boundary_correctly_classified[n_samples_evaluation:][ + :n_samples_asr_evaluation + ] + ) + > 0.0 + ) + random_attack_success_boundary_corners = np.logical_or( + random_attack_success_inner, random_attack_success_boundary_corners + ) + random_attack_success_boundary_surface = np.logical_or( + random_attack_success_inner, random_attack_success_boundary_surface + ) + validation_accuracies_and_asr = ( + validation_accuracy_inner, + validation_accuracy_boundary, + validation_accuracy_boundary_surface, + validation_accuracy_boundary_corners, + random_attack_success_boundary_surface, + random_attack_success_boundary_corners, + ) + else: + validation_accuracies_and_asr = None + + return ( + (linearized_model, binary_classifier), + (raw_train_loader, train_loader), + validation_accuracies_and_asr, + ) + + +def __wrap_assert_get_boundary_adversarials_fn( + fn: Callable[[torch.Tensor, torch.Tensor, int, float], np.ndarray], + norm: ut.NormType, +) -> Callable[[torch.Tensor, torch.Tensor, int, float], np.ndarray]: + """Make sure adversarial examples really lie on the epsilon ball boundary + (or are within a relative distance of 1%).""" + + def inner(x: torch.Tensor, y: torch.Tensor, n: int, epsilon: float): + x_ = fn(x, y, n, epsilon) + delta = (x_ - x).cpu() + if norm == "linf": + distance = torch.abs(delta).flatten(1).max(1)[0].numpy() + elif norm in ("l2", "l1"): + distance = torch.norm( + delta, p=1 if norm == "l1" else 2, keepdim=False, dim=[1, 2, 3] + ).numpy() + else: + raise ValueError(f"Unknown norm: {norm}") + # TODO(zimmerrol): Verify whether 1% tolerance is sensible. + assert np.isclose(distance, epsilon, atol=0.01 * epsilon), ( + f"Magnitude of boundary adversarial examples ({distance}) " + f"does not match target distance ({epsilon}" + ) + return x_ + + return inner + + +def interior_boundary_discrimination_attack( + classifier: torch.nn.Module, + test_loader: torch.utils.data.DataLoader, + attack_fn: Callable[ + [torch.nn.Module, torch.utils.data.DataLoader, dict], + Tuple[np.ndarray, Tuple[torch.Tensor, torch.Tensor]], + ], + linearization_settings: aut.DecisionBoundaryBinarizationSettings, + n_samples: int, + device: str, + batch_size: int = 512, + rescale_logits: LogitRescalingType = "fixed", + n_samples_evaluation: int = 0, + n_samples_asr_evaluation: int = 0, + verify_valid_inner_training_data_fn: Optional[ + Callable[[torch.Tensor], np.ndarray] + ] = None, + verify_valid_boundary_training_data_fn: Optional[ + Callable[[torch.Tensor], np.ndarray] + ] = None, + verify_valid_inner_validation_data_fn: Optional[ + Callable[[torch.Tensor], np.ndarray] + ] = None, + verify_valid_boundary_validation_data_fn: Optional[ + Callable[[torch.Tensor], np.ndarray] + ] = None, + get_boundary_adversarials_fn: Optional[ + Callable[[torch.Tensor, torch.Tensor, int, float], np.ndarray] + ] = None, + fill_batches_for_verification: bool = True, + far_off_distance: float = 1.50, + rejection_resampling_max_repetitions: int = 10, + train_classifier_fn: Callable[ + [int, DataLoader, torch.Tensor, str, LogitRescalingType], torch.nn.Module + ] = None, + fail_on_exception: bool = False, + decision_boundary_closeness: Optional[float] = None, + n_inference_repetitions_boundary: Optional[int] = None, + n_inference_repetitions_inner: Optional[int] = None, + relative_inner_boundary_gap: Optional[float] = 0.05, + sample_training_data_from_corners: bool = False, +) -> List[Tuple[bool, float, float, Tuple[float, float, float, float, bool, bool]]]: + + """ + Performs the binarization test. This means, replacing the last linear layer + of the classifier with a binary classifier distinguishing between images + of different perturbation magnitude. + + Args: + classifier: The classifier that will be used as a feature encoder. + test_loader: Data loader of the data to run the test on. + attack_fn: Function performing an adversarial attack on a classifier and + dataset passed as arguments. + linearization_settings: How to construct the binarized classifier. + n_samples: Number of samples to perform this test on. + device: torch device + batch_size: Max batch size allowed to use + rescale_logits: Rescale weights of linear classifier such that logits + have a max scale of 1 + n_samples_evaluation: Number of random samples to use for evaluation + n_samples_asr_evaluation: Number of random samples used to calculate + the ASR of a random attacker + verify_valid_inner_training_data_fn: Can be used for e.g. + detector-based defenses. + Check whether all input points used for training/testing are actually valid + and won't get filtered out be the model/detector. + verify_valid_boundary_training_data_fn: See + verify_valid_inner_training_data_fn but for boundary samples. + verify_valid_inner_validation_data_fn: See + verify_valid_inner_training_data_fn but for calculating the validation + scores, i.e. the random ASR. + verify_valid_boundary_validation_data_fn: See + verify_valid_boundary_training_data_fn but for calculating the validation + scores, i.e. the random ASR. + get_boundary_adversarials_fn: If given, use this function to + generate all but one of the boundary samples. This can be used for + evaluating detector-based evaluation functions. + fill_batches_for_verification: If computational cost of verification_fn + does not depend on the batch size, set this to True. + far_off_distance: Relative multiplier (in terms of epsilon) controlling + the distance between clean and far off training samples. + rejection_resampling_max_repetitions: How often to resample to satisfy + constraints on training samples. + train_classifier_fn: Callback that trains a readout classifier on a set of + features. + fail_on_exception: Raise exception if a single samples fails or keep + running and report about this later. + decision_boundary_closeness: (optional) The larger this value, the closer + the decision boundary will be placed to the boundary sample(s). + n_inference_repetitions_boundary: (optional) How often to repeat + inference for boundary samples for obtaining their features. + n_inference_repetitions_inner: (optional) How often to repeat + inference for inner samples for obtaining their features. + relative_inner_boundary_gap: (optional) Gap between interior and + boundary data (in pixel space) relative to epsilon (i.e. a value of 0 means + boundary points can lie directly next to inner points) + sample_training_data_from_corners: Sample training data from the corners + of the epsilon ball; this setting is only possible when using + Returns: + List containing tuples of (attack successful, logit diff of results of attack_fn, + logit diff of best training sample, (validation accuracy inner, + validation accuracy boundary, random ASR))) + """ + + if get_boundary_adversarials_fn is not None and ( + linearization_settings.n_boundary_adversarial_points == 0 + and linearization_settings.n_far_off_adversarial_points == 0 + ): + warnings.warn( + "get_boundary_adversarials_fn is set but number of boundary " + "and far-off adversarial examples is set to 0", + UserWarning, + ) + + results = [] + data_iterator = iter(test_loader) + current_batch_x = None + current_batch_y = None + current_batch_index = 0 + + if get_boundary_adversarials_fn is not None: + # Make sure this function really returns boundary adversarials. + get_boundary_adversarials_fn = __wrap_assert_get_boundary_adversarials_fn( + get_boundary_adversarials_fn, linearization_settings.norm + ) + + # Show warnings only once + warnings_shown_for_messages = [] + for i in tqdm.tqdm(range(n_samples)): + if current_batch_x is None or current_batch_index == len(current_batch_x) - 1: + try: + # Only use input and label. + current_batch_x, current_batch_y = next(data_iterator) + except StopIteration: + warnings.warn( + f"Could only gather {i} and not the " + f"{n_samples} requested samples." + ) + break + current_batch_index = 0 + else: + current_batch_index += 1 + + # Get current item/input data. + x = current_batch_x[current_batch_index] + y = current_batch_y[current_batch_index] + + setup_successful = False + with warnings.catch_warnings(record=True) as ws: + try: + ( + (binary_discriminator, binary_linear_layer), + (image_loader, feature_loader), + validation_accuracies, + ) = _get_interior_boundary_discriminator_and_dataloaders( + classifier, + x, + y, + linearization_settings, + device, + rescale_logits=rescale_logits, + n_samples_evaluation=n_samples_evaluation, + n_samples_asr_evaluation=n_samples_asr_evaluation, + batch_size=batch_size, + verify_valid_inner_training_data_fn=verify_valid_inner_training_data_fn, + verify_valid_boundary_training_data_fn=verify_valid_boundary_training_data_fn, + verify_valid_inner_validation_data_fn=verify_valid_inner_validation_data_fn, + verify_valid_boundary_validation_data_fn=verify_valid_boundary_validation_data_fn, + get_boundary_adversarials_fn=get_boundary_adversarials_fn, + fill_batches_for_verification=fill_batches_for_verification, + far_off_distance=far_off_distance, + rejection_resampling_max_repetitions=rejection_resampling_max_repetitions, + train_classifier_fn=train_classifier_fn, + decision_boundary_closeness=decision_boundary_closeness, + n_inference_repetitions_boundary=n_inference_repetitions_boundary, + n_inference_repetitions_inner=n_inference_repetitions_inner, + relative_inner_boundary_gap=relative_inner_boundary_gap, + sample_training_data_from_corners=sample_training_data_from_corners, + ) + setup_successful = True + except RuntimeError as ex: + exc_type, exc_obj, exc_tb = sys.exc_info() + fname, lineno, fnname, code = traceback.extract_tb(exc_tb)[-1] + if fail_on_exception: + raise ex + else: + warnings.warn(f"Exception caught: {fname}:{lineno}({fnname}): {ex}") + + for w in ws: + if str(w.message) not in warnings_shown_for_messages: + warnings_shown_for_messages.append(str(w.message)) + warnings.warn(str(w.message), w.category) + + if not setup_successful: + continue + + attack_loader = torch.utils.data.DataLoader( + torch.utils.data.TensorDataset( + torch.unsqueeze(x, 0), torch.zeros(1, dtype=torch.long) + ), + shuffle=False, + batch_size=1, + ) + + if linearization_settings.n_far_off_boundary_points == 0: + attack_kwargs = {} + else: + attack_kwargs = dict( + reference_points_x=image_loader.dataset.tensors[0][ + -linearization_settings.n_far_off_boundary_points * 1 : + ], + reference_points_y=image_loader.dataset.tensors[1][ + -linearization_settings.n_far_off_boundary_points * 1 : + ], + ) + + with warnings.catch_warnings(record=True) as ws: + attack_successful, (x_adv, logits_adv) = attack_fn( + binary_discriminator, attack_loader, attack_kwargs + ) + for w in ws: + if str(w.message) not in warnings_shown_for_messages: + warnings_shown_for_messages.append(str(w.message)) + warnings.warn(f"{w.filename}:{w.lineno}:{w.message}", w.category) + + logit_diff_adv = (logits_adv[:, 1] - logits_adv[:, 0]).item() + + # Now compare the result of the attack (x_adv) with the training samples + # in terms of their confidence. + # For this, first get logits of binary discriminator for data it was + # trained on, but only do this for samples of the adversarial class (y = 1). + logits_training = [] + if train_classifier_fn is None: + for x, y in feature_loader: + with torch.no_grad(): + x = x[y == 1] + if len(x) == 0: + continue + logits_training.append(binary_linear_layer(x.to(device)).cpu()) + else: + for x, y in image_loader: + with torch.no_grad(): + x = x[y == 1] + if len(x) == 0: + continue + logits_training.append(binary_discriminator(x.to(device)).cpu()) + logits_training = torch.cat(logits_training, 0) + + # Now get training sample with max confidence (alternatively we could also + # just compute the distance to the linear boundary for all sample and pick + # the one with max distance). + logit_diff_training = torch.max( + logits_training[:, 1] - logits_training[:, 0] + ).item() + + result = ( + attack_successful, + logit_diff_adv, + logit_diff_training, + validation_accuracies, + ) + + results.append(result) + + return results + + +def format_result( + scores_logit_differences_and_validation_accuracies, + n_samples, + indent=0, + title="interior-vs-boundary discrimination", +): + """Formats the result of the interior-vs-boundary discriminator test""" + if len(scores_logit_differences_and_validation_accuracies) == 0: + test_result = (np.nan, np.nan, np.nan, np.nan) + else: + scores = [it[0] for it in scores_logit_differences_and_validation_accuracies] + validation_scores = [ + it[3] for it in scores_logit_differences_and_validation_accuracies + ] + if validation_scores[0] is None: + validation_scores = (np.nan, np.nan, np.nan) + else: + validation_scores = np.array(validation_scores) + validation_scores = tuple(np.mean(validation_scores, 0)) + logit_differences = [ + (it[1], it[2]) for it in scores_logit_differences_and_validation_accuracies + ] + logit_differences = np.array(logit_differences) + relative_performance = (logit_differences[:, 0] - logit_differences[:, 1]) / ( + logit_differences[:, 1] + 1e-12 + ) + + test_result = ( + np.mean(scores), + np.mean(relative_performance), + np.std(relative_performance), + validation_scores, + ) + + indent = "\t" * indent + + return ( + "{0}{1}, ASR: {2}\n”, " + "{0}\tNormalized Logit-Difference-Improvement: {3} +- {4}\n" + "{0}\tValidation Accuracy (I, B, BS, BC, R. ASR S, R. ASR C): {5}\n" + "{0}\tSetup failed for {6}/{7} samples".format( + indent, + title, + *test_result, + n_samples - len(scores_logit_differences_and_validation_accuracies), + n_samples, + ) + ) diff --git a/argparse_utils.py b/argparse_utils.py new file mode 100644 index 0000000..7668519 --- /dev/null +++ b/argparse_utils.py @@ -0,0 +1,164 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import argparse +import importlib +import re +from dataclasses import dataclass +from typing import Any +from typing import Callable +from typing import Dict +from typing import Optional +from typing import Tuple +from typing import Union + +from typing_extensions import Literal + +import utils as ut + + +@dataclass +class AdversarialAttackSettings: + epsilon: float + norm: ut.NormType + step_size: float + n_steps: int = 20 + n_averages: int = 1 + attack: Tuple[Literal["pgd", "kwta"]] = "pgd" + random_start: bool = True + + def __repr__(self): + return ( + f"{self.attack}_{self.norm}_{self.epsilon}_{self.step_size}_" + f"{self.n_steps}_{self.n_averages}_{self.random_start}" + ) + + +@dataclass +class DecisionBoundaryBinarizationSettings: + epsilon: float + norm: ut.NormType + n_inner_points: int + n_boundary_points: int + adversarial_attack_settings: Optional[AdversarialAttackSettings] + n_boundary_adversarial_points: int = 0 + n_far_off_boundary_points: int = 0 + n_far_off_adversarial_points: int = 0 + optimizer: str = "adam" + lr: float = 5e-2 + class_weight: Optional[Union[Literal["balanced"], dict]] = None + + def __repr__(self): + return ( + f"{self.norm}_{self.epsilon}_{self.n_inner_points}_" + f"{self.n_boundary_points}_{self.n_far_off_boundary_points}_" + f"{self.adversarial_attack_settings}_{self.optimizer}_{self.lr}" + ) + + +def __parse_structure_argument( + value, + argument_type: Union[Callable[[str], Any], type], + known_flags: Dict[str, Tuple[str, bool]], + argument_types: Dict[str, Callable], +): + """ + Recursively parses structured arguments encoded as a string. + + Args: + argument_type: Class to store values in. + known_flags: Map between name and default value of flags. + argument_types: Map between argument names and argument constructors + for variables. + + Returns: + Object created based on string. + """ + arguments = re.findall(r'(?:[^\s,"]|"(?:\\.|[^"])*")+', value) + kwargs = {} + for argument in arguments: + parts = argument.split("=") + if len(parts) > 2: + parts = [parts[0], "=".join(parts[1:])] + if len(parts) != 2: + # argument is a flag + if argument not in known_flags: + raise argparse.ArgumentTypeError( + "invalid argument/unknown flag:", argument + ) + else: + kwargs[known_flags[argument][0]] = known_flags[argument][1] + else: + key, value = parts + value = value.replace(r"\"", '"') + if value.startswith('"') and value.endswith('"'): + value = value[1:-1] + if key in argument_types: + kwargs[key] = argument_types[key](value) + else: + raise argparse.ArgumentTypeError( + f"invalid argument `{argument}` for type `{argument_type}`" + ) + + try: + return argument_type(**kwargs) + except Exception as ex: + raise argparse.ArgumentTypeError("Could not create type:", ex) + + +def parse_adversarial_attack_argument(value): + """Parse a string defining a AdversarialAttackSettings object.""" + return __parse_structure_argument( + value, + AdversarialAttackSettings, + {}, + { + "norm": str, + "n_steps": int, + "epsilon": float, + "step_size": float, + "attack": str, + "n_averages": int, + "random_start": lambda x: x.lower() == "true", + }, + ) + + +def parse_classifier_argument(value): + """Parse a string describing a classifier object.""" + class_name = value.split(".")[-1] + module_path = ".".join(value.split(".")[:-1]) + module = importlib.import_module(module_path) + return getattr(module, class_name) + + +def parse_decision_boundary_binarization_argument(value): + """Parse a string defining a DecisionBoundaryBinarizationSettings object.""" + return __parse_structure_argument( + value, + DecisionBoundaryBinarizationSettings, + {}, + { + "norm": str, + "epsilon": float, + "n_boundary_points": int, + "n_inner_points": int, + "adversarial_attack_settings": lambda x: parse_adversarial_attack_argument( + x + ), + "optimizer": str, + "lr": float, + "class_weight": str, + }, + ) diff --git a/attacks/__init__.py b/attacks/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/attacks/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/attacks/adaptive_kwta_attack.py b/attacks/adaptive_kwta_attack.py new file mode 100644 index 0000000..a909a7b --- /dev/null +++ b/attacks/adaptive_kwta_attack.py @@ -0,0 +1,156 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Adapted and heavily modified from +https://github.com/wielandbrendel/adaptive_attacks_paper/blob/master/01_kwta/kwta_attack.ipynb +""" + +from typing import Callable +from typing import Optional + +import numpy as np +import torch +import torch.nn.functional +from tqdm import tqdm + +import utils as ut + + +def __best_other_classes(logits: torch.Tensor, + exclude: torch.Tensor) -> torch.Tensor: + other_logits = logits - torch.nn.functional.one_hot(exclude, + num_classes=logits.shape[ + -1]) * np.inf + + return other_logits.argmax(axis=-1) + + +def __logit_diff_loss_fn(model: Callable, x: torch.Tensor, + classes: torch.Tensor, + targeted: bool): + with torch.no_grad(): + logits = model(x) + + if targeted: + c_minimize = classes + c_maximize = __best_other_classes(logits, classes) + else: + c_minimize = __best_other_classes(logits, classes) + c_maximize = classes + + N = len(x) + rows = range(N) + + logits_diffs = logits[rows, c_minimize] - logits[rows, c_maximize] + assert logits_diffs.shape == (N,) + + return logits_diffs + + +def __es_gradient_estimator(loss_fn: Callable, x: torch.Tensor, y: torch.Tensor, + n_samples: int, sigma: float, clip=False, bounds=(0, 1)): + assert len(x) == len(y) + assert n_samples > 0 + + gradient = torch.zeros_like(x) + with torch.no_grad(): + for k in range(n_samples // 2): + noise = torch.randn_like(x) + + pos_theta = x + sigma * noise + neg_theta = x - sigma * noise + + if clip: + pos_theta = pos_theta.clip(*bounds) + neg_theta = neg_theta.clip(*bounds) + + pos_loss = loss_fn(pos_theta, y) + neg_loss = loss_fn(neg_theta, y) + + gradient += (pos_loss - neg_loss)[:, None, None, None] * noise + + gradient /= 2 * sigma * 2 * n_samples + + return gradient + + +def gradient_estimator_pgd(model: Callable, + x: torch.Tensor, y: torch.Tensor, + n_steps: int, + step_size: float, epsilon: float, norm: ut.NormType, + loss_fn: Optional[Callable] = None, + random_start: bool = True, + early_stopping: bool = False, targeted: bool = False): + if loss_fn is None: + loss_fn = lambda x, y: __logit_diff_loss_fn(model, x, y, targeted) + + assert len(x) == len(y) + + if random_start: + delta = torch.rand_like(x) + delta = ut.normalize(delta, norm) + x_adv, delta = ut.clipping_aware_rescaling(x, delta, epsilon, norm=norm, + growing=False, return_delta=True) + else: + x_adv = x + delta = torch.zeros_like(x) + + if targeted: + is_adversarial_fn = lambda x: model(x).argmax(-1) == y + else: + is_adversarial_fn = lambda x: model(x).argmax(-1) != y + + mask = ~is_adversarial_fn(x_adv) + if not early_stopping: + mask = torch.ones_like(mask) + else: + if mask.sum() == 0: + return x_adv.detach(), ~mask.detach() + + if len(x) > 1: + iterator = tqdm(range(n_steps)) + else: + iterator = range(n_steps) + for it in iterator: + if it < 0.6 * n_steps: + n_samples = 100 + elif it < 0.8 * n_steps: + n_samples = 1000 + elif it >= 0.8 * n_steps: + n_samples = 20000 + + pert_x = (x + delta).clip(0, 1) + grad_x = __es_gradient_estimator(loss_fn, pert_x[mask], y[mask], n_samples, + epsilon) + + grad_x = ut.normalize(grad_x, norm) + + # update only subportion of deltas + delta[mask] = delta[mask] - step_size * grad_x + + # project back to feasible set + x_adv, delta = ut.clipping_aware_rescaling(x, delta, epsilon, norm=norm, + growing=False, return_delta=True) + + mask = ~is_adversarial_fn(x_adv) + # new_logit_diffs = loss_fn(x_adv, y) + # mask = new_logit_diffs >= 0 + if not early_stopping: + mask = torch.ones_like(mask) + + if early_stopping and mask.sum() == 0: + break + + return x_adv.detach(), ~mask.detach() diff --git a/attacks/autopgd.py b/attacks/autopgd.py new file mode 100644 index 0000000..0cb14c5 --- /dev/null +++ b/attacks/autopgd.py @@ -0,0 +1,131 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from typing_extensions import Literal +from typing import Tuple + +import torch +from typing import Callable +import utils as ut +from autoattack import autopgd_base + + +class __PatchedAPGDAttack(autopgd_base.APGDAttack): + def dlr_loss(self, x, y): + """Patched DLR loss that works with less than 3 classes. Taken and modified + from: https://github.com/fra31/auto-attack/blob/master/autoattack/ + autopgd_base.py#L567""" + + x_sorted, ind_sorted = x.sort(dim=1) + ind = (ind_sorted[:, -1] == y).float() + u = torch.arange(x.shape[0]) + + if x_sorted.shape[-1] > 2: + # normal dlr loss + return -(x[u, y] - x_sorted[:, -2] * ind - x_sorted[:, -1] * ( + 1. - ind)) / (x_sorted[:, -1] - x_sorted[:, -3] + 1e-12) + else: + # modified dlr loss (w/o the normalizer) + return -(x[u, y] - x_sorted[:, -2] * ind - x_sorted[:, -1] * ( + 1. - ind)) + + +class __PatchedAPGDAttack_targeted(autopgd_base.APGDAttack_targeted): + def dlr_loss_targeted(self, x, y): + """Patched DLR loss that works with less than 3 classes. Taken and modified + from: https://github.com/fra31/auto-attack/blob/master/autoattack/ + autopgd_base.py#L606""" + + x_sorted, ind_sorted = x.sort(dim=1) + u = torch.arange(x.shape[0]) + + if x_sorted.shape[-1] > 2: + # normal dlr loss + return -(x[u, y] - x[u, self.y_target]) / (x_sorted[:, -1] - .5 * ( + x_sorted[:, -3] + x_sorted[:, -4]) + 1e-12) + else: + # modified dlr loss (w/o the normalizer) + return -(x[u, y] - x[u, self.y_target]) + + +def auto_pgd(model: Callable, x: torch.Tensor, y: torch.Tensor, + n_steps: int, + epsilon: float, norm: ut.NormType, + loss: Tuple[Literal["ce"], Literal["logit-diff"]] = "ce", + targeted: bool = False, + n_restarts: int = 1, + n_averaging_steps: int = 1, + n_classes: int = 10): + """Performs a standard projected gradient descent (PGD) with a cross-entropy + objective. + + :param model: Inference function of the model yielding logits. + :param x: Input images. + :param y: Ground-truth labels. + :param n_steps: Number of steps. + :param epsilon: Maximum size of the perturbation measured by the norm. + :param norm: Norm to use for measuring the size of the perturbation. + examples have been found. + :param targeted: Perform a targeted adversarial attack. + :param n_restarts: How often to restart attack. + :param n_averaging_steps: Number over repetitions for every gradient + calculation. + :return: (Adversarial examples, attack success for each sample, + target labels (optional)) + """ + assert norm in ("linf", "l2", "l1") + + norm = {"linf": "Linf", "l2": "L2", "l1": "L1"}[norm] + + attack_cls = __PatchedAPGDAttack_targeted if targeted \ + else __PatchedAPGDAttack + + n_restarts += 1 + + optional_kwargs = {} + if targeted: + optional_kwargs["n_target_classes"] = n_classes - 1 + attack = attack_cls(predict=model, n_iter=n_steps, norm=norm, + n_restarts=n_restarts, eps=epsilon, + eot_iter=n_averaging_steps, device=x.device, + seed=None, **optional_kwargs) + attack.loss = "ce" if loss == "ce" else "dlr" + if targeted: + attack.loss += "-targeted" + + x_adv = attack.perturb(x, y) + y_pred = model(x_adv).argmax(-1) + + if targeted: + is_adv = y_pred == y + else: + is_adv = y_pred != y + + if targeted: + return x_adv.detach(), is_adv.detach(), attack.y_target.detach() + else: + return x_adv.detach(), is_adv.detach() + + +def fix_autoattack(attack): + attack.apgd_targeted = __PatchedAPGDAttack_targeted( + attack.model, n_restarts=attack.apgd_targeted.n_restarts, n_iter=attack.apgd_targeted.n_iter, + verbose=attack.apgd_targeted.verbose, eps=attack.apgd_targeted.eps, norm=attack.apgd_targeted.norm, + eot_iter=attack.apgd_targeted.eot_iter, rho=attack.apgd_targeted.thr_decr, seed=attack.apgd_targeted.seed, + device=attack.apgd_targeted.device, is_tf_model=attack.apgd_targeted.is_tf_model, + logger=attack.apgd_targeted.logger) + attack.apgd = __PatchedAPGDAttack( + attack.model, n_restarts=attack.apgd.n_restarts, n_iter=attack.apgd.n_iter, verbose=attack.apgd.verbose, + eps=attack.apgd.eps, norm=attack.apgd.norm, eot_iter=attack.apgd.eot_iter, rho=attack.apgd.thr_decr, + seed=attack.apgd.seed, device=attack.apgd.device, is_tf_model=attack.apgd.is_tf_model, logger=attack.apgd.logger) diff --git a/attacks/fab.py b/attacks/fab.py new file mode 100644 index 0000000..fc04f7a --- /dev/null +++ b/attacks/fab.py @@ -0,0 +1,66 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import torch +from typing import Callable +import utils as ut +from autoattack import fab_pt + + +def fab(model: Callable, x: torch.Tensor, y: torch.Tensor, + n_steps: int, + epsilon: float, norm: ut.NormType, + targeted: bool = False, + n_restarts: int = 1, + n_classes: int = 10): + """Runs the Fast Adaptive Boundary Attack (Linf, L2, L1). + + :param model: Inference function of the model yielding logits. + :param x: Input images. + :param y: Ground-truth labels. + :param n_steps: Number of steps. + :param epsilon: Maximum size of the perturbation measured by the norm. + :param norm: Norm to use for measuring the size of the perturbation. + examples have been found. + :param targeted: Perform a targeted adversarial attack. + :param n_restarts: How often to restart attack. + :return: (Adversarial examples, attack success for each sample, + target labels (optional)) + """ + assert norm in ("linf", "l2", "l1") + + norm = {"linf": "Linf", "l2": "L2", "l1": "L1"}[norm] + + n_restarts += 1 + + optional_kwargs = {} + if targeted: + optional_kwargs["n_target_classes"] = n_classes - 1 + attack = fab_pt.FABAttack_PT( + predict=model, n_iter=n_steps, norm=norm, + n_restarts=n_restarts, eps=epsilon, + device=x.device, targeted=targeted, + **optional_kwargs) + x_adv = attack.perturb(x, y) + y_pred = model(x_adv).argmax(-1) + + if targeted: + is_adv = y_pred == y + else: + is_adv = y_pred != y + + if targeted: + return x_adv.detach(), is_adv.detach(), attack.y_target.detach() + else: + return x_adv.detach(), is_adv.detach() diff --git a/attacks/pgd.py b/attacks/pgd.py new file mode 100644 index 0000000..b50f80c --- /dev/null +++ b/attacks/pgd.py @@ -0,0 +1,124 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from typing import Callable + +import torch + +import utils as ut + + +def general_pgd(loss_fn: Callable, is_adversarial_fn: Callable, x: torch.Tensor, + y: torch.Tensor, n_steps: int, + step_size: float, epsilon: float, norm: ut.NormType, + random_start: bool = True, + early_stopping: bool = False, + n_averaging_steps: int = 1): + """Performs a projected gradient descent (PGD) for an arbitrary loss function + and success criterion. + + :param loss_fn: Loss function to minimize. + :param is_adversarial_fn: Check if examples are adversarial + :param x: Input images. + :param y: Ground-truth labels. + :param n_steps: Number of steps. + :param step_size: Size of the steps/learning rate. + :param epsilon: Maximum size of the perturbation measured by the norm. + :param norm: Norm to use for measuring the size of the perturbation. + :param random_start: Randomly start within the epsilon ball. + :param early_stopping: Stop once an adversarial perturbation for all + examples have been found. + :param n_averaging_steps: Number over repetitions for every gradient + calculation. + :return: (Adversarial examples, attack success for each sample) + """ + assert norm in ("linf", "l2", "l1") + + x_orig = x + x = x.clone() + + if random_start: + delta = torch.rand_like(x) + delta = ut.normalize(delta, norm) + x = ut.clipping_aware_rescaling(x_orig, delta, epsilon, norm=norm, + growing=False) + + for step in range(n_steps): + x = x.requires_grad_() + + # check early stopping + with torch.no_grad(): + is_adv = is_adversarial_fn(x, y) + if early_stopping and torch.all(is_adv): # + return x.detach(), is_adv.detach() + + grad_x = torch.zeros_like(x) + for _ in range(n_averaging_steps): + # get gradient of cross-entropy wrt to input + loss = loss_fn(x, y) + grad_x += torch.autograd.grad(loss, x)[0].detach() / n_averaging_steps + + # normalize gradient + grad_x = ut.normalize(grad_x, norm) + + # perform step + delta = (x - x_orig).detach() - step_size * grad_x.detach() + + # project back to feasible set + x = ut.clipping_aware_rescaling(x_orig, delta, epsilon, norm=norm, + growing=False) + del loss, grad_x + + with torch.no_grad(): + is_adv = is_adversarial_fn(x, y) + + return x.detach(), is_adv.detach() + + +def pgd(model: Callable, x: torch.Tensor, y: torch.Tensor, n_steps: int, + step_size: float, epsilon: float, norm: ut.NormType, + random_start: bool = True, + early_stopping: bool = False, + targeted: bool = False, + n_averaging_steps: int = 1): + """Performs a standard projected gradient descent (PGD) with a cross-entropy + objective. + + :param x: Input images. + :param y: Ground-truth labels. + :param n_steps: Number of steps. + :param step_size: Size of the steps/learning rate. + :param epsilon: Maximum size of the perturbation measured by the norm. + :param norm: Norm to use for measuring the size of the perturbation. + :param random_start: Randomly start within the epsilon ball. + :param early_stopping: Stop once an adversarial perturbation for all + examples have been found. + :param targeted: Perform a targeted adversarial attack. + :param n_averaging_steps: Number over repetitions for every gradient + calculation. + :return: (Adversarial examples, attack success for each sample) + """ + assert norm in ("linf", "l2", "l1") + + criterion = torch.nn.CrossEntropyLoss() + + sign = 1 if targeted else -1 + + return general_pgd(loss_fn=lambda x, y: sign * criterion(model(x), y), + is_adversarial_fn=lambda x, y: model(x).argmax( + -1) == y if targeted else model(x).argmax(-1) != y, + x=x, y=y, n_steps=n_steps, step_size=step_size, + epsilon=epsilon, norm=norm, random_start=random_start, + n_averaging_steps=n_averaging_steps, + early_stopping=early_stopping) \ No newline at end of file diff --git a/attacks/thermometer_ls_pgd.py b/attacks/thermometer_ls_pgd.py new file mode 100644 index 0000000..422e3de --- /dev/null +++ b/attacks/thermometer_ls_pgd.py @@ -0,0 +1,196 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from typing import Callable + +import numpy as np +import torch + +import utils as ut + + +def general_thermometer_ls_pgd( + loss_fn: Callable, is_adversarial_fn: Callable, + x: torch.Tensor, + y: torch.Tensor, n_steps: int, + step_size: float, epsilon: float, norm: ut.NormType, + l: int, temperature: float = 1.0, annealing_factor=1.0 / 1.2, + random_start: bool = True, + n_restarts=0, + early_stopping: bool = False, + n_averaging_steps: int = 1): + """Performs a logit-space projected gradient descent (PGD) for an arbitrary loss function + and success criterion for a thermometer-encoded model. + + :param loss_fn: Loss function to minimize. + :param is_adversarial_fn: Check if examples are adversarial + :param x: Input images. + :param y: Ground-truth labels. + :param n_steps: Number of steps. + :param step_size: Size of the steps/learning rate. + :param epsilon: Maximum size of the perturbation measured by the norm. + :param norm: Norm to use for measuring the size of the perturbation. + :param l: + :param temperature: + :param annealing_factor: + :param random_start: Randomly start within the epsilon ball. + :param early_stopping: Stop once an adversarial perturbation for all + examples have been found. + :param n_averaging_steps: Number over repetitions for every gradient + calculation. + :return: (Adversarial examples, attack success for each sample) + """ + assert norm in ("linf",), "LS-PGD only supports linf norm" + assert random_start, "LS-PGD only works with random starts" + #assert epsilon < 1.0 / l, f"Epsilon ({epsilon}) must be smaller " \ + # f"than 1.0/l ({1.0 / l})" + + def one_hot(y): + L = torch.arange(l, dtype=x.dtype, device=x.device) + L = L.view((1, 1, l, 1, 1)) / l + y = torch.unsqueeze(y, 2) + y = torch.logical_and( + y >= L, + y <= L + 1 / l).float() + return y + + def init_mask(x): + # Compute the mask over the bits that we are allowed to attack + mask = torch.zeros((len(x), 3, l, x.shape[-2], x.shape[-1]), dtype=x.dtype, + device=x.device) + for alpha in np.linspace(0, 1, l): + mask += one_hot(torch.maximum(torch.zeros_like(x), x - alpha * epsilon)) + mask += one_hot(torch.minimum(torch.ones_like(x), x + alpha * epsilon)) + mask = (mask > 0).float() + return mask + + def get_final_x(u): + x = torch.argmax(u, 2) / l + + # now move x as close as possible to x_orig without changing + # the argmax of the logits + delta = x - x_orig + delta[delta > 0] = torch.floor(delta[delta > 0] * l) / l + delta[delta < 0] = torch.ceil(delta[delta < 0] * l) / l + + # only relevant for debugging: + # assert torch.all(torch.abs(delta) <= 1.0/l) + + delta = torch.minimum(torch.ones_like(delta) * epsilon, delta) + delta = torch.maximum(-torch.ones_like(delta) * epsilon, delta) + x = x_orig + delta + + # only relevant for debugging: + # project back to feasible set (if everything was correct before, + # this shouldn't change anything) + # x2 = ut.clipping_aware_rescaling(x_orig, delta, epsilon, norm=norm, + # growing=False) + # assert torch.all(torch.abs(x - x2) < 1e-8) + + return x + + x_final = x.clone() + x_orig = x + mask = init_mask(x_orig) + + for _ in range(n_restarts + 1): + x_logits = torch.randn_like(mask) + for step in range(n_steps): + # mask u so that x(u) is within the epsilon ball + x_logits = x_logits * mask - (1.0 - mask) * 1e12 + # check early stopping + x = get_final_x(x_logits) + is_adv = is_adversarial_fn(x, y) + # print(is_adv[:32].long()) + if early_stopping and torch.all(is_adv): # + return x.detach(), is_adv.detach() + + x_logits = x_logits.requires_grad_() + x_thermometer = torch.softmax(x_logits / temperature, 2) + # convert something like [0, 0, 1, 0, .., 0] to [1, 1, 1, 0, ..., 0] + x_thermometer = torch.flip( + torch.cumsum(torch.flip(x_thermometer, (2,)), 2), (2,)) + x_thermometer = x_thermometer.view(( + x_thermometer.shape[0], -1, x_thermometer.shape[-2], + x_thermometer.shape[-1])) + + grad_x_logits = torch.zeros_like(x_logits) + for _ in range(n_averaging_steps): + # get gradient of cross-entropy wrt to the thermometer encoded input + loss = loss_fn(x_thermometer, y) + # print(step, loss.item(), is_adv.sum().item()) + grad_x_logits += torch.autograd.grad(loss, x_logits)[0] / n_averaging_steps + + # perform step + x_logits = (x_logits - step_size * torch.sign(grad_x_logits)).detach() + + temperature *= annealing_factor + + x = get_final_x(x_logits) + is_adv = is_adversarial_fn(x, y) + + x_final[is_adv] = x[is_adv] + + is_adv = is_adversarial_fn(x, y) + + return x.detach(), is_adv.detach() + + +def thermometer_ls_pgd(model: Callable, x: torch.Tensor, y: torch.Tensor, + n_steps: int, + step_size: float, epsilon: float, norm: ut.NormType, + l: int, + temperature: float = 1.0, + annealing_factor=1.0 / 1.2, + random_start: bool = True, + early_stopping: bool = False, + targeted: bool = False, + n_averaging_steps: int = 1): + """Performs a logit-space projected gradient descent (PGD) with a cross-entropy + objective for a thermometer-encoded model. + + :param x: Input images. + :param y: Ground-truth labels. + :param n_steps: Number of steps. + :param step_size: Size of the steps/learning rate. + :param epsilon: Maximum size of the perturbation measured by the norm. + :param norm: Norm to use for measuring the size of the perturbation. + :param l: + :param temperature: + :param annealing_factor: + :param random_start: Randomly start within the epsilon ball. + :param early_stopping: Stop once an adversarial perturbation for all + examples have been found. + :param targeted: Perform a targeted adversarial attack. + :param n_averaging_steps: Number over repetitions for every gradient + calculation. + :return: (Adversarial examples, attack success for each sample) + """ + assert norm in ("linf", "l2", "l1") + + criterion = torch.nn.CrossEntropyLoss() + + sign = 1 if targeted else -1 + + return general_thermometer_ls_pgd( + loss_fn=lambda x, y: sign * criterion(model(x), y), + is_adversarial_fn=lambda x, y: model(x).argmax( + -1) == y if targeted else model(x).argmax(-1) != y, + x=x, y=y, n_steps=n_steps, step_size=step_size, + epsilon=epsilon, norm=norm, + l=l, temperature=temperature, + annealing_factor=annealing_factor, + random_start=random_start, + n_averaging_steps=n_averaging_steps, + early_stopping=early_stopping) diff --git a/case_studies/__init__.py b/case_studies/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/case_studies/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/case_studies/bat/README.md b/case_studies/bat/README.md new file mode 100644 index 0000000..01e5d87 --- /dev/null +++ b/case_studies/bat/README.md @@ -0,0 +1,34 @@ +# Bilateral Adversarial Training: Towards Fast Training of More Robust Models Against Adversarial Attacks + +Code and models for the ICCV 2019 [paper](https://arxiv.org/abs/1811.10716). + +The code is based on this [repo](https://github.com/MadryLab/cifar10_challenge) from MadryLab. + +We use one-step adversarial training with targeted attack and random start, which significantly improves both the speed and accuracy. + +# CIFAR10 +The training time is about 12 hours on one V100 GPU with 200 epochs + CIFAR10 + WRN28-10. The models can be downloaded [here](https://drive.google.com/file/d/11uUH1iV6xENARYWnzFnEZkKLb2y_8vHJ/view?usp=sharing). + +In the table below, the rows are various robust models (differ by how to choose the target label in targeted attack and the perturbation budget used in training), and the columns are two commonly used attacks for evaluation. Specifically, PGD100-2-8 means 100 iterations of PGD with step size 2 and perturbation budget 8. + +Note that the two robust models, R-MOSA-LA and R-RAND-LA, are not included in the original paper, due to space limit and possible distraction from main theme. R-MOSA-LA means Most One-Step Adversarial and R-RAND-LA means random target among non-groundtruth classes. I may upload a report providing details if time allows in future but for now you can check the corresponding [code block](https://github.com/wjyouch/bilateral-adversarial-training/blob/master/train.py#L157). The takeaway is that using a proper targeted attack in one-step adversarial training makes a huge difference. + +Besides, we also use PGD100-2-8 with 100 random starts (the last column of the table below). Specifically, if any of the 100 trials causes the model to fail then we say the attack succeeds. It turns out that our models perform reasonably well against this super strong and time-consuming (100 iterations + 100 random starts) attack. + +|Accuracy (%)| Clean | PGD100-2-8 | CW100-2-8 | PGD1000-2-8 | CW1000-2-8|100xPGD100-2-8| +|--------|--------|--------|--------|--------|--------|----------| +|R-MC-LA (eps=8)|91.2|55.3|53.9|54.8|53.4|52.5| +|R-MC-LA (eps=4)|92.8|62.4|60.5|61.4|59.3|58.6| +|R-MOSA-LA (eps=8)|90.7|61.3|58.3|NA|NA|57.3| +|R-MOSA-LA (eps=4)|**92.8**|**71.0**|**67.9**|NA|NA|**66.9**| +|R-RAND-LA (eps=8)|89.7|59.3|56.8|NA|NA|NA| +|R-RAND-LA (eps=4)|92.8|65.7|62.9|NA|NA|NA| +|Our implementation of [Madry's method](https://arxiv.org/abs/1706.06083)|88.0|47.2|48.1|NA|NA|NA| + + +FYI: CIFAR100 dataset can be downloaded [here](https://drive.google.com/file/d/1Lo32gut3G9Sg4pz-ACFdsVzsxMRmCe-1/view?usp=sharing) and SVHN dataset can be downloaded [here](https://drive.google.com/file/d/1gd3-p2_9NN6k9UshmER0fyRG3UL_D2ug/view?usp=sharing). + +# Environment +Python 3.6.7 + +TensorFlow 1.12.0 diff --git a/case_studies/bat/adversarial_evaluation.py b/case_studies/bat/adversarial_evaluation.py new file mode 100644 index 0000000..46987e5 --- /dev/null +++ b/case_studies/bat/adversarial_evaluation.py @@ -0,0 +1,249 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + + +import logging +logging.getLogger('tensorflow').setLevel(logging.FATAL) +import tensorflow as tf +tf.logging.set_verbosity(tf.logging.ERROR) + + +import time +import sys + +import numpy as np + +from bat_utils import * +from wide_resnet import Model + + +def load_data(FLAGS): + # load data + if FLAGS.dataset == 'SVHN': + raise ValueError("not supported") + elif FLAGS.dataset == 'CIFAR': + if FLAGS.num_classes == 10: + dataset = load_cifar10_data('data/cifar-10-batches-py/') + elif FLAGS.num_classes == 20: + dataset = load_cifar100_data('cifar100_data', is_fine=False) + elif FLAGS.num_classes == 100: + dataset = load_cifar100_data('cifar100_data', is_fine=True) + else: + raise ValueError('Number of classes not valid!') + train_images = dataset['train_images'] + train_labels = dataset['train_labels'] + test_images = dataset['test_images'] + test_labels = dataset['test_labels'] + else: + raise ValueError('Dataset not valid!') + + return train_images, train_labels, test_images, test_labels + + +def load_model(FLAGS): + x_pl = tf.placeholder(tf.float32, shape=[None, 32, 32, 3], name='x') + y_pl = tf.placeholder(tf.int64, shape=[None], name='y') + is_train = tf.placeholder(tf.bool, name='is_train') + + model = Model(is_train) + x_transformed = x_pl * 2.0 - 1.0 + logits, _ = model.build_model(images=x_transformed, num_classes=FLAGS.num_classes) + + prob = tf.nn.softmax(logits) + correct = tf.cast(tf.equal(tf.argmax(logits, axis=1), y_pl), tf.float32) + accuracy = tf.reduce_mean(correct) + + saver = tf.train.Saver(max_to_keep=100) + + config = tf.ConfigProto() + config.gpu_options.allow_growth = True + sess = tf.Session(config=config) + + saver.restore(sess, FLAGS.ckpt_path) + print('restored checkpoint from %s' % FLAGS.ckpt_path) + + return sess, (x_pl, y_pl, is_train, logits, accuracy) + + +def setup_attack(logits, x_pl, y_pl, FLAGS): + xent = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, + labels=y_pl) + # loss for adversarial attack + if FLAGS.loss_type == 'xent': + if FLAGS.targeted: + loss_att = tf.reduce_sum(xent) + else: + loss_att = -tf.reduce_sum(xent) + elif FLAGS.loss_type == 'CW': + y_loss = tf.one_hot(y_pl, FLAGS.num_classes) + self = tf.reduce_sum(y_loss * logits, axis=1) + other = tf.reduce_max((1 - y_loss) * logits - y_loss * 1e4, axis=1) + if FLAGS.targeted: + raise ValueError("not supported") + else: + loss_att = tf.reduce_sum(tf.maximum(self - other + FLAGS.margin, 0)) + else: + raise ValueError('loss type not supported!') + + grad, = tf.gradients(loss_att, x_pl) + + return grad + + +def adv_attack(sess, grad, x_pl, y_pl, is_train, x_batch, y_batch, FLAGS): + epsilon = FLAGS.epsilon / 255.0 + step_size = FLAGS.step_size / 255.0 + + if not FLAGS.targeted: + y_att = np.copy(y_batch) + else: + raise ValueError("targeted mode not supported") + + # randomly perturb the original images + if FLAGS.random_start: + x = x_batch + np.random.uniform(-epsilon, epsilon, x_batch.shape) + else: + x = np.copy(x_batch) + + for i in range(FLAGS.num_steps): + logits, grad_val = sess.run(grad, + feed_dict={ + x_pl: x, + y_pl: y_att, + is_train: False + }) + + x = x - step_size * np.sign(grad_val) + + x = np.clip(x, x_batch - epsilon, x_batch + epsilon) + + x = np.clip(x, 0, 1.0) + + return x + + +def run_eval(sess, grad, x_pl, y_pl, is_train, logits, FLAGS, + test_images, test_labels, num_classes=10): + test_size = test_images.shape[0] + epoch_steps = np.ceil(test_size / FLAGS.batch_size).astype(np.int32) + nat_total = 0.0 + adv_total = 0.0 + class_nat_total = np.zeros([num_classes]) + class_adv_total = np.zeros([num_classes]) + nat_cnt_list = np.zeros([test_size]) + adv_cnt_list = np.zeros([test_size]) + idx = np.random.permutation(test_size) + for step_idx in range(epoch_steps): + start = step_idx * FLAGS.batch_size + end = np.minimum((step_idx + 1) * FLAGS.batch_size, + test_size).astype(np.int32) + x_batch = test_images[idx[start:end]] + y_batch = test_labels[idx[start:end]] + + start_time = time.time() + + nat_logits = sess.run(logits, + feed_dict={ + x_pl: x_batch, + is_train: False + }) + nat_cnt = nat_logits.argmax(-1) == y_batch + + x_batch_adv = adv_attack(sess, grad, x_pl, y_pl, is_train, x_batch, y_batch, FLAGS) + + adv_logits = sess.run(logits, + feed_dict={ + x_pl: x_batch_adv, + y_pl: y_batch, + is_train: False + }) + adv_cnt = adv_logits.argmax(-1) == y_batch + + nat_cnt_list[start:end] = nat_cnt + adv_cnt_list[start:end] = adv_cnt + + for ii in range(FLAGS.num_classes): + class_nat_total[ii] += np.sum(nat_cnt[y_batch == ii]) + class_adv_total[ii] += np.sum(adv_cnt[y_batch == ii]) + + nat_total += np.sum(nat_cnt) + adv_total += np.sum(adv_cnt) + + duration = time.time() - start_time + print('finished batch %d/%d, duration %.2f, nat acc %.2f, adv acc %.2f' % + (step_idx, epoch_steps, duration, 100 * np.mean(nat_cnt), + 100 * np.mean(adv_cnt))) + sys.stdout.flush() + + nat_acc = nat_total / test_size + adv_acc = adv_total / test_size + class_nat_total /= (test_size / FLAGS.num_classes) + class_adv_total /= (test_size / FLAGS.num_classes) + print('clean accuracy: %.2f, adv accuracy: %.2f' % + (100 * nat_acc, 100 * adv_acc)) + for ii in range(FLAGS.num_classes): + print('class %d, clean %.2f, adv %.2f' % + (ii, 100 * class_nat_total[ii], 100 * class_adv_total[ii])) + + +def parse_args(): + tf.flags.DEFINE_string('ckpt_path', '', '') + tf.flags.DEFINE_string('dataset', 'CIFAR', '') + tf.flags.DEFINE_integer('num_classes', 10, '') + tf.flags.DEFINE_integer('batch_size', 100, '') + tf.flags.DEFINE_string('loss_type', 'xent', '') + tf.flags.DEFINE_float('margin', 50.0, '') + tf.flags.DEFINE_float('epsilon', 8.0, '') + tf.flags.DEFINE_integer('num_steps', 10, '') + tf.flags.DEFINE_float('step_size', 2.0, '') + tf.flags.DEFINE_boolean('random_start', False, '') + tf.flags.DEFINE_boolean('targeted', False, '') + tf.flags.DEFINE_integer('n_samples', 2048, '') + + FLAGS = tf.flags.FLAGS + + print(FLAGS.flag_values_dict()) + + return FLAGS + + +def main(): + FLAGS = parse_args() + _, _, test_images, test_labels = load_data(FLAGS) + + # normalize to [0,1] value range from [-1, 1] since we put normalization + # inside of the model + test_images = (test_images + 1.0) / 2.0 + + # subsample test data + if FLAGS.n_samples == -1: + FLAGS.n_samples = len(test_images) + idxs = np.arange(len(test_images)) + np.random.shuffle(idxs) + idxs = idxs[:FLAGS.n_samples] + + test_images, test_labels = test_images[idxs], test_labels[idxs] + + sess, (x_pl, y_pl, is_train, logits, accuracy) = load_model(FLAGS) + attack_grad = setup_attack(logits, x_pl, y_pl, FLAGS) + run_eval(sess, attack_grad, x_pl, y_pl, is_train, logits, FLAGS, + test_images, test_labels) + + +if __name__ == "__main__": + main() diff --git a/case_studies/bat/adversarial_evaluation.sh b/case_studies/bat/adversarial_evaluation.sh new file mode 100644 index 0000000..7ad65ed --- /dev/null +++ b/case_studies/bat/adversarial_evaluation.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +TF_CPP_MIN_LOG_LEVEL=3 ./venv3.8tf/bin/python case_studies/bat/adversarial_evaluation.py \ + --num_classes=10 \ + --ckpt_path=checkpoints/bat/mosa_eps4/checkpoint-200 \ + --dataset=CIFAR \ + --loss_type=xent \ + --margin=50.0 \ + --epsilon=8.0 \ + --num_steps=100 \ + --step_size=2.0 \ + --random_start=True \ + --batch_size=256 \ + --n_samples=2048 diff --git a/case_studies/bat/bat_utils.py b/case_studies/bat/bat_utils.py new file mode 100644 index 0000000..78d0cee --- /dev/null +++ b/case_studies/bat/bat_utils.py @@ -0,0 +1,222 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import gzip +import os + +import numpy as np + + +def extract_images(file_path): + '''Extract the images into a 4D uint8 numpy array [index, y, x, depth].''' + def _read32(bytestream): + dt = np.dtype(np.uint32).newbyteorder('>') + return np.frombuffer(bytestream.read(4), dtype=dt)[0] + + f = open(file_path, 'rb') + with gzip.GzipFile(fileobj=f) as bytestream: + magic = _read32(bytestream) + if magic != 2051: + raise ValueError( + 'Invalid magic number %d in MNIST image file: %s' % + (magic, f.name)) + num_images = _read32(bytestream) + rows = _read32(bytestream) + cols = _read32(bytestream) + buf = bytestream.read(rows * cols * num_images) + data = np.frombuffer(buf, dtype=np.uint8) + data = data.reshape(num_images, rows, cols, 1) + return data + + +def extract_labels(file_path): + '''Extract the labels into a 1D uint8 numpy array [index].''' + def _read32(bytestream): + dt = np.dtype(np.uint32).newbyteorder('>') + return np.frombuffer(bytestream.read(4), dtype=dt)[0] + + f = open(file_path, 'rb') + with gzip.GzipFile(fileobj=f) as bytestream: + magic = _read32(bytestream) + if magic != 2049: + raise ValueError( + 'Invalid magic number %d in MNIST label file: %s' % + (magic, f.name)) + num_items = _read32(bytestream) + buf = bytestream.read(num_items) + labels = np.frombuffer(buf, dtype=np.uint8) + return labels + + +def load_mnist_data(data_path, is_uint8=False): + TRAIN_IMAGES = 'train-images-idx3-ubyte.gz' + TRAIN_LABELS = 'train-labels-idx1-ubyte.gz' + TEST_IMAGES = 't10k-images-idx3-ubyte.gz' + TEST_LABELS = 't10k-labels-idx1-ubyte.gz' + + train_images = extract_images(os.path.join(data_path, TRAIN_IMAGES)) + if not is_uint8: + train_images = 2 * (train_images / 255.0 - 0.5) + train_labels = extract_labels(os.path.join(data_path, TRAIN_LABELS)) + test_images = extract_images(os.path.join(data_path, TEST_IMAGES)) + if not is_uint8: + test_images = 2 * (test_images / 255.0 - 0.5) + test_labels = extract_labels(os.path.join(data_path, TEST_LABELS)) + + train_data = order_data(train_images, train_labels, 10) + test_data = order_data(test_images, test_labels, 10) + + return dict(train_images=train_data['images'], + train_labels=train_data['labels'], + train_count=train_data['count'], + test_images=test_data['images'], + test_labels=test_data['labels'], + test_count=test_data['count']) + + +# python2 +#def unpickle(file): +# import cPickle +# fo = open(file, 'rb') +# dict = cPickle.load(fo) +# fo.close() +# return dict + + +# python3 +def unpickle(file): + import pickle + fo = open(file, 'rb') + dict = pickle.load(fo, encoding='bytes') + fo.close() + return dict + + +def load_cifar100_data(data_path, is_fine=True, is_uint8=False): + # train + train_set = unpickle(os.path.join(data_path, 'train')) + train_images = train_set[b'data'] + train_images = np.dstack([ + train_images[:, :1024], train_images[:, 1024:2048], + train_images[:, 2048:] + ]) + train_images = train_images.reshape([train_images.shape[0], 32, 32, 3]) + if not is_uint8: + train_images = train_images / 255.0 + train_images = 2.0 * (train_images - 0.5) + if is_fine: + train_labels = np.array(train_set[b'fine_labels']) + else: + train_labels = np.array(train_set[b'coarse_labels']) + + # test + test_set = unpickle(os.path.join(data_path, 'test')) + test_images = test_set[b'data'] + test_images = np.dstack([ + test_images[:, :1024], test_images[:, 1024:2048], test_images[:, 2048:] + ]) + test_images = test_images.reshape([test_images.shape[0], 32, 32, 3]) + if not is_uint8: + test_images = test_images / 255.0 + test_images = 2.0 * (test_images - 0.5) + if is_fine: + test_labels = np.array(test_set[b'fine_labels']) + else: + test_labels = np.array(test_set[b'coarse_labels']) + + return dict(train_images=train_images, + train_labels=train_labels, + test_images=test_images, + test_labels=test_labels) + + +def load_cifar10_data(data_path, is_uint8=False): + # train + train_names = [ + 'data_batch_1', 'data_batch_2', 'data_batch_3', 'data_batch_4', + 'data_batch_5' + ] + all_images = [] + all_labels = [] + for filename in train_names: + train_set = unpickle(os.path.join(data_path, filename)) + all_images.append(train_set[b'data']) + all_labels.append(train_set[b'labels']) + train_images = np.concatenate(all_images, axis=0) + train_images = np.dstack([ + train_images[:, :1024], train_images[:, 1024:2048], + train_images[:, 2048:] + ]) + train_images = train_images.reshape([train_images.shape[0], 32, 32, 3]) + if not is_uint8: + train_images = train_images / 255.0 + train_images = 2.0 * (train_images - 0.5) + train_labels = np.concatenate(all_labels, axis=0) + + # test + test_set = unpickle(os.path.join(data_path, 'test_batch')) + test_images = test_set[b'data'] + test_images = np.dstack([ + test_images[:, :1024], test_images[:, 1024:2048], test_images[:, 2048:] + ]) + test_images = test_images.reshape([test_images.shape[0], 32, 32, 3]) + if not is_uint8: + test_images = test_images / 255.0 + test_images = 2.0 * (test_images - 0.5) + test_labels = np.array(test_set[b'labels']) + + return dict(train_images=train_images, + train_labels=train_labels, + test_images=test_images, + test_labels=test_labels) + + +def preprocess_py(images, pad_size, target_size): + '''Preprocess images in python. + Args: + images: 4-D numpy array. + Returns: + preprocessed images, 4-D numpy array. + ''' + assert images.shape[1] == images.shape[2], 'can only handle square images!' + image_number = images.shape[0] + image_size = images.shape[1] + # padding, with equal pad size on both sides. + padded_images = np.pad(images, [(0, 0), (pad_size, pad_size), + (pad_size, pad_size), (0, 0)], + mode='constant', + constant_values=0) + # random crop + idx = np.random.random_integers(low=0, + high=2 * pad_size, + size=[image_number, 2]) + cropped_images = np.zeros([image_number, target_size, target_size, 3]) + for i in np.arange(image_number): + cropped_images[i] = padded_images[i, idx[i, 0]:idx[i, 0] + + target_size, idx[i, 1]:idx[i, 1] + + target_size] + # random flip + if np.random.rand() > 0.5: + cropped_images = cropped_images[:, :, ::-1] + return cropped_images + + +def one_hot(y, dim): + y_dense = np.zeros([len(y), dim]) + y_dense[np.arange(len(y)), y] = 1.0 + return y_dense diff --git a/case_studies/bat/binarization_test.py b/case_studies/bat/binarization_test.py new file mode 100644 index 0000000..98101bc --- /dev/null +++ b/case_studies/bat/binarization_test.py @@ -0,0 +1,294 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import logging +from functools import partial +from typing import Tuple + +import torch + +from tensorflow_wrapper import TensorFlow1ToPyTorchWrapper + +logging.getLogger('tensorflow').setLevel(logging.FATAL) +import tensorflow as tf + +tf.logging.set_verbosity(tf.logging.ERROR) + +import time +import sys + +import numpy as np + +from bat_utils import * +from wide_resnet import Model + +from utils import build_dataloader_from_arrays +from active_tests import decision_boundary_binarization as dbb +from argparse_utils import DecisionBoundaryBinarizationSettings + + +def load_data(FLAGS): + # load data + if FLAGS.dataset == 'SVHN': + raise ValueError("not supported") + elif FLAGS.dataset == 'CIFAR': + if FLAGS.num_classes == 10: + dataset = load_cifar10_data('data/cifar-10-batches-py/') + elif FLAGS.num_classes == 20: + dataset = load_cifar100_data('cifar100_data', is_fine=False) + elif FLAGS.num_classes == 100: + dataset = load_cifar100_data('cifar100_data', is_fine=True) + else: + raise ValueError('Number of classes not valid!') + train_images = dataset['train_images'] + train_labels = dataset['train_labels'] + test_images = dataset['test_images'] + test_labels = dataset['test_labels'] + else: + raise ValueError('Dataset not valid!') + + return train_images, train_labels, test_images, test_labels + + +def load_model(FLAGS): + x_pl = tf.placeholder(tf.float32, shape=[None, 32, 32, 3], name='x') + y_pl = tf.placeholder(tf.int64, shape=[None], name='y') + is_train = tf.placeholder(tf.bool, name='is_train') + + model = Model(is_train) + x_transformed = x_pl * 2.0 - 1.0 + fe_logits, features = model.build_model(images=x_transformed, + num_classes=FLAGS.num_classes) + + saver = tf.train.Saver(max_to_keep=100) + + config = tf.ConfigProto() + config.gpu_options.allow_growth = True + sess = tf.Session(config=config) + + saver.restore(sess, FLAGS.ckpt_path) + print('restored checkpoint from %s' % FLAGS.ckpt_path) + + # create binary classifier + bro_w = tf.get_variable( + 'DW', [features.shape[-1], 2], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + bro_b = tf.get_variable('biases', [2], initializer=tf.constant_initializer()) + bro_w_pl = tf.placeholder(tf.float32, shape=[features.shape[-1], 2]) + bro_b_pl = tf.placeholder(tf.float32, shape=[2]) + bro_w_set_weight = bro_w.assign(bro_w_pl) + bro_b_set_weight = bro_b.assign(bro_b_pl) + logits = tf.nn.xw_plus_b(features, bro_w, bro_b) + + prob = tf.nn.softmax(logits) + correct = tf.cast(tf.equal(tf.argmax(logits, axis=1), y_pl), tf.float32) + accuracy = tf.reduce_mean(correct) + + return sess, (x_pl, y_pl, is_train, logits, fe_logits, features, accuracy), \ + (bro_w_pl, bro_b_pl, bro_w_set_weight, bro_b_set_weight) + + +def setup_attack(logits, x_pl, y_pl, FLAGS): + xent = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, + labels=y_pl) + # loss for adversarial attack + if FLAGS.loss_type == 'xent': + if FLAGS.targeted: + loss_att = tf.reduce_sum(xent) + else: + loss_att = -tf.reduce_sum(xent) + elif FLAGS.loss_type == 'CW': + y_loss = tf.one_hot(y_pl, FLAGS.num_classes) + self = tf.reduce_sum(y_loss * logits, axis=1) + other = tf.reduce_max((1 - y_loss) * logits - y_loss * 1e4, axis=1) + if FLAGS.targeted: + raise ValueError("not supported") + else: + loss_att = tf.reduce_sum(tf.maximum(self - other + FLAGS.margin, 0)) + else: + raise ValueError('loss type not supported!') + + grad, = tf.gradients(loss_att, x_pl) + + return grad + + +def adv_attack(sess, grad, x_pl, y_pl, is_train, x_batch, y_batch, FLAGS): + epsilon = FLAGS.epsilon / 255.0 + step_size = FLAGS.step_size / 255.0 + + if not FLAGS.targeted: + y_att = np.copy(y_batch) + else: + raise ValueError("targeted mode not supported") + + # randomly perturb the original images + if FLAGS.random_start: + x = x_batch + np.random.uniform(-epsilon, epsilon, x_batch.shape) + else: + x = np.copy(x_batch) + + for i in range(FLAGS.num_steps): + grad_val = sess.run(grad, + feed_dict={ + x_pl: x, + y_pl: y_att, + is_train: False + }) + + x = x - step_size * np.sign(grad_val) + x = np.clip(x, x_batch - epsilon, x_batch + epsilon) + x = np.clip(x, 0, 1.0) + + return x + + +def parse_args(): + tf.flags.DEFINE_string('ckpt_path', '', '') + tf.flags.DEFINE_string('dataset', 'CIFAR', '') + tf.flags.DEFINE_integer('num_classes', 10, '') + tf.flags.DEFINE_integer('batch_size', 100, '') + tf.flags.DEFINE_string('loss_type', 'xent', '') + tf.flags.DEFINE_float('margin', 50.0, '') + tf.flags.DEFINE_float('epsilon', 8.0, '') + tf.flags.DEFINE_integer('num_steps', 10, '') + tf.flags.DEFINE_float('step_size', 2.0, '') + tf.flags.DEFINE_boolean('random_start', False, '') + tf.flags.DEFINE_boolean('targeted', False, '') + tf.flags.DEFINE_integer('n_samples', 2048, '') + + tf.flags.DEFINE_integer('n_boundary_points', 1, '') + tf.flags.DEFINE_integer('n_inner_points', 999, '') + tf.flags.DEFINE_boolean('sample_from_corners', False, '') + + FLAGS = tf.flags.FLAGS + + # print(FLAGS.flag_values_dict()) + + return FLAGS + + +def run_attack(m, l, sess, logits, x_pl, is_train, bro_w_pl, bro_b_pl, + bro_w_assign, bro_b_assign, attack_fn): + linear_layer = m[-1] + del m + + sess.run(bro_w_assign, {bro_w_pl: linear_layer.weight.data.numpy().T}) + sess.run(bro_b_assign, {bro_b_pl: linear_layer.bias.data.numpy()}) + + for x, y in l: + x, y = x.numpy(), y.numpy() + x = x.transpose((0, 2, 3, 1)) + x_batch_adv = attack_fn(x, y) + + adv_logits: np.ndarray = sess.run(logits, + feed_dict={ + x_pl: x_batch_adv, + is_train: False + }) + is_adv: np.ndarray = adv_logits.argmax(-1) != y + + return is_adv, (torch.tensor(x_batch_adv.transpose((0, 3, 1, 2))), + torch.tensor(adv_logits)) + + +def main(): + FLAGS = parse_args() + _, _, test_images, test_labels = load_data(FLAGS) + + print(FLAGS.flag_values_dict()) + + # normalize to [0,1] value range from [-1, 1] since we put normalization + # inside of the model + test_images = (test_images + 1.0) / 2.0 + + # subsample test data + if FLAGS.n_samples == -1: + FLAGS.n_samples = len(test_images) + idxs = np.arange(len(test_images)) + np.random.shuffle(idxs) + test_images, test_labels = test_images[idxs], test_labels[idxs] + test_images = test_images.transpose((0, 3, 1, 2)) + + test_loader = build_dataloader_from_arrays(test_images, test_labels, + FLAGS.batch_size) + + sess, (x_pl, y_pl, is_train, logits, fe_logits, features, accuracy), \ + (bro_w_pl, bro_b_pl, bro_w_set_weight, bro_b_set_weight) = load_model(FLAGS) + attack_grad = setup_attack(logits, x_pl, y_pl, FLAGS) + attack_fn = lambda x, y: adv_attack(sess, attack_grad, x_pl, y_pl, is_train, + x, y, FLAGS) + + def feature_extractor_forward_pass(x, features_and_logits: bool = False, + features_only: bool = False): + if features_and_logits: + assert not features_only, "Only one of the flags must be set." + if features_and_logits: + f, l = sess.run( + (features, fe_logits), + feed_dict={x_pl: x.transpose(0, 2, 3, 1), is_train: False}) + return f, l + elif features_only: + return sess.run( + features, + feed_dict={x_pl: x.transpose(0, 2, 3, 1), is_train: False}) + else: + return sess.run( + fe_logits, + feed_dict={x_pl: x.transpose(0, 2, 3, 1), is_train: False}) + + feature_extractor = TensorFlow1ToPyTorchWrapper( + logit_forward_pass=feature_extractor_forward_pass, + logit_forward_and_backward_pass=None, + ) + + scores_logit_differences_and_validation_accuracies = \ + dbb.interior_boundary_discrimination_attack( + feature_extractor, + test_loader, + # m, l, sess, logits, x_pl, is_train, bro_w_pl, bro_b_pl, + # bro_w_assign, bro_b_assign, attack_fn) + attack_fn=lambda m, l, kwargs: partial(run_attack, + sess=sess, logits=logits, x_pl=x_pl, is_train=is_train, + bro_w_pl=bro_w_pl, bro_b_pl=bro_b_pl, bro_w_assign=bro_w_set_weight, + bro_b_assign=bro_b_set_weight, + attack_fn=attack_fn)(m, l), + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=FLAGS.epsilon / 255.0, + norm="linf", + lr=10000, + n_boundary_points=FLAGS.n_boundary_points, + n_inner_points=FLAGS.n_inner_points, + adversarial_attack_settings=None, + optimizer="sklearn" + ), + n_samples=FLAGS.n_samples, + device="cpu", + n_samples_evaluation=200, + n_samples_asr_evaluation=200, + # rescale_logits="adaptive", + sample_training_data_from_corners=FLAGS.sample_from_corners, + decision_boundary_closeness=0.9999, + # args.num_samples_test * 10 + ) + + print(dbb.format_result(scores_logit_differences_and_validation_accuracies, + FLAGS.n_samples)) + +if __name__ == "__main__": + main() diff --git a/case_studies/bat/binarization_test.sh b/case_studies/bat/binarization_test.sh new file mode 100644 index 0000000..5134706 --- /dev/null +++ b/case_studies/bat/binarization_test.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +nsamples=${1:-512} + +echo "#samples: $nsamples" + +kwargs="" +# kwargs="--sample_from_corners=True" + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/bat/binarization_test.py \ + --num_classes=10 \ + --ckpt_path=checkpoints/bat/mosa_eps4/checkpoint-200 \ + --dataset=CIFAR \ + --loss_type=xent \ + --margin=50.0 \ + --epsilon=8.0 \ + --num_steps=100 \ + --step_size=2.0 \ + --random_start=True \ + --batch_size=256 \ + --n_samples=$nsamples \ + --n_inner_points=999 \ + $kwargs diff --git a/case_studies/bat/eval.py b/case_studies/bat/eval.py new file mode 100644 index 0000000..8494736 --- /dev/null +++ b/case_studies/bat/eval.py @@ -0,0 +1,209 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time +import os +import sys + +import numpy as np +import tensorflow as tf + +from utils import * +from wide_resnet import Model + +tf.flags.DEFINE_string('ckpt_path', '', '') +tf.flags.DEFINE_string('dataset', 'CIFAR', '') +tf.flags.DEFINE_integer('num_classes', 10, '') +tf.flags.DEFINE_integer('batch_size', 100, '') +tf.flags.DEFINE_string('loss_type', 'xent', '') +tf.flags.DEFINE_float('margin', 50.0, '') +tf.flags.DEFINE_float('epsilon', 8.0, '') +tf.flags.DEFINE_integer('num_steps', 10, '') +tf.flags.DEFINE_float('step_size', 2.0, '') +tf.flags.DEFINE_boolean('random_start', False, '') +tf.flags.DEFINE_boolean('targeted', False, '') + +tf.flags.DEFINE_string('cuda_device', '3', '') + +FLAGS = tf.flags.FLAGS + +os.environ['CUDA_VISIBLE_DEVICES'] = FLAGS.cuda_device + +print(FLAGS.flag_values_dict()) + +# load data +if FLAGS.dataset == 'SVHN': + train_data = np.load('svhn_data/train_32x32.npz') + train_images = train_data['arr_0'] + train_images = 2.0 * (train_images / 255.0 - 0.5) + train_labels = train_data['arr_1'] + test_data = np.load('svhn_data/test_32x32.npz') + test_images = test_data['arr_0'] + test_images = 2 * (test_images / 255.0 - 0.5) + test_labels = test_data['arr_1'] +elif FLAGS.dataset == 'CIFAR': + if FLAGS.num_classes == 10: + dataset = load_cifar10_data('cifar10_data') + elif FLAGS.num_classes == 20: + dataset = load_cifar100_data('cifar100_data', is_fine=False) + elif FLAGS.num_classes == 100: + dataset = load_cifar100_data('cifar100_data', is_fine=True) + else: + raise ValueError('Number of classes not valid!') + train_images = dataset['train_images'] + train_labels = dataset['train_labels'] + test_images = dataset['test_images'] + test_labels = dataset['test_labels'] +else: + raise ValueError('Dataset not valid!') + +x_pl = tf.placeholder(tf.float32, shape=[None, 32, 32, 3], name='x') +y_pl = tf.placeholder(tf.int64, shape=[None], name='y') +is_train = tf.placeholder(tf.bool, name='is_train') + +model = Model(is_train) +logits, _ = model.build_model(images=x_pl, num_classes=FLAGS.num_classes) +prob = tf.nn.softmax(logits) +xent = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, + labels=y_pl) + +correct = tf.cast(tf.equal(tf.argmax(logits, axis=1), y_pl), tf.float32) +accuracy = tf.reduce_mean(correct) + +# loss for adversarial attack +if FLAGS.loss_type == 'xent': + if FLAGS.targeted: + loss_att = tf.reduce_sum(xent) + else: + loss_att = -tf.reduce_sum(xent) +elif FLAGS.loss_type == 'CW': + y_loss = tf.one_hot(y_pl, FLAGS.num_classes) + self = tf.reduce_sum(y_loss * logits, axis=1) + other = tf.reduce_max((1 - y_loss) * logits - y_loss * 1e4, axis=1) + if FLAGS.targeted: + loss_att = tf.reduce_sum(tf.maximum(other - self + FLAGS.margin, 0)) + else: + loss_att = tf.reduce_sum(tf.maximum(self - other + FLAGS.margin, 0)) +else: + raise ValueError('loss type not supported!') + +grad, = tf.gradients(loss_att, x_pl) + +saver = tf.train.Saver(max_to_keep=100) + +config = tf.ConfigProto() +config.gpu_options.allow_growth = True +sess = tf.Session(config=config) + +saver.restore(sess, FLAGS.ckpt_path) +print('restored checkpoint from %s' % FLAGS.ckpt_path) + + +def adv_attack(nat_prob, x_batch, y_batch): + epsilon = FLAGS.epsilon / 255.0 * 2 + step_size = FLAGS.step_size / 255.0 * 2 + + if not FLAGS.targeted: + y_att = np.copy(y_batch) + else: + # most confusing targeted attack + nat_prob[np.arange(y_batch.shape[0]), y_batch] = 0.0 + y_att = np.argmax(nat_prob, axis=1) + + # randomly perturb the original images + if FLAGS.random_start: + x = x_batch + np.random.uniform(-epsilon, epsilon, x_batch.shape) + else: + x = np.copy(x_batch) + + for i in range(FLAGS.num_steps): + grad_val = sess.run(grad, + feed_dict={ + x_pl: x, + y_pl: y_att, + is_train: False + }) + + x = x - step_size * np.sign(grad_val) + + x = np.clip(x, x_batch - epsilon, x_batch + epsilon) + + x = np.clip(x, -1.0, 1.0) + + return x + + +test_size = test_images.shape[0] +epoch_steps = np.ceil(test_size / FLAGS.batch_size).astype(np.int32) +nat_total = 0.0 +adv_total = 0.0 +class_nat_total = np.zeros([FLAGS.num_classes]) +class_adv_total = np.zeros([FLAGS.num_classes]) +nat_cnt_list = np.zeros([test_size]) +adv_cnt_list = np.zeros([test_size]) +idx = np.random.permutation(test_size) +for step_idx in range(epoch_steps): + start = step_idx * FLAGS.batch_size + end = np.minimum((step_idx + 1) * FLAGS.batch_size, + test_size).astype(np.int32) + x_batch = test_images[idx[start:end]] + y_batch = test_labels[idx[start:end]] + + start_time = time.time() + + nat_cnt, nat_prob = sess.run([correct, prob], + feed_dict={ + x_pl: x_batch, + y_pl: y_batch, + is_train: False + }) + + x_batch_adv = adv_attack(nat_prob, x_batch, y_batch) + + adv_cnt = sess.run(correct, + feed_dict={ + x_pl: x_batch_adv, + y_pl: y_batch, + is_train: False + }) + + nat_cnt_list[start:end] = nat_cnt + adv_cnt_list[start:end] = adv_cnt + + for ii in range(FLAGS.num_classes): + class_nat_total[ii] += np.sum(nat_cnt[y_batch == ii]) + class_adv_total[ii] += np.sum(adv_cnt[y_batch == ii]) + + nat_total += np.sum(nat_cnt) + adv_total += np.sum(adv_cnt) + + duration = time.time() - start_time + print('finished batch %d/%d, duration %.2f, nat acc %.2f, adv acc %.2f' % + (step_idx, epoch_steps, duration, 100 * np.mean(nat_cnt), + 100 * np.mean(adv_cnt))) + sys.stdout.flush() + +nat_acc = nat_total / test_size +adv_acc = adv_total / test_size +class_nat_total /= (test_size / FLAGS.num_classes) +class_adv_total /= (test_size / FLAGS.num_classes) +print('clean accuracy: %.2f, adv accuracy: %.2f' % + (100 * nat_acc, 100 * adv_acc)) +for ii in range(FLAGS.num_classes): + print('class %d, clean %.2f, adv %.2f' % + (ii, 100 * class_nat_total[ii], 100 * class_adv_total[ii])) diff --git a/case_studies/bat/eval.sh b/case_studies/bat/eval.sh new file mode 100644 index 0000000..e9145b7 --- /dev/null +++ b/case_studies/bat/eval.sh @@ -0,0 +1,14 @@ +#! /bin/bash + +python eval.py --cuda_device=3 \ +--num_classes=10 \ +--ckpt_path=models/mc_eps4/checkpoint-200 \ +--dataset=CIFAR \ +--loss_type=xent \ +--margin=50.0 \ +--epsilon=8.0 \ +--num_steps=100 \ +--step_size=2.0 \ +--random_start=True \ +--targeted=False \ +--batch_size=100 \ diff --git a/case_studies/bat/train.py b/case_studies/bat/train.py new file mode 100644 index 0000000..5a50363 --- /dev/null +++ b/case_studies/bat/train.py @@ -0,0 +1,356 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time +import os +import sys + +import numpy as np +import tensorflow as tf + +from utils import * +from wide_resnet import Model + +tf.flags.DEFINE_string('model_dir', '/tmp/adv_train/', '') +tf.flags.DEFINE_string('dataset', '', '') +tf.flags.DEFINE_integer('num_classes', 10, '') + +tf.flags.DEFINE_string('restore_ckpt_path', '', '') +tf.flags.DEFINE_integer('start_epoch', 0, '') +tf.flags.DEFINE_integer('max_epoch', 201, '') +tf.flags.DEFINE_integer('decay_epoch1', 100, '') +tf.flags.DEFINE_integer('decay_epoch2', 150, '') +tf.flags.DEFINE_float('decay_rate', 0.1, '') +tf.flags.DEFINE_float('learning_rate', 0.1, '') +tf.flags.DEFINE_float('momentum', 0.9, '') +tf.flags.DEFINE_integer('batch_size', 128, '') +tf.flags.DEFINE_float('weight_decay', 2e-4, '') + +tf.flags.DEFINE_float('margin', 50.0, '') +tf.flags.DEFINE_string('loss_type', 'xent', '') +tf.flags.DEFINE_float('epsilon', 8.0, '') +tf.flags.DEFINE_integer('num_steps', 7, '') +tf.flags.DEFINE_float('step_size', 2.0, '') +tf.flags.DEFINE_boolean('random_start', True, '') +tf.flags.DEFINE_boolean('targeted', True, '') +tf.flags.DEFINE_string('target_type', 'MC', '') + +tf.flags.DEFINE_boolean('label_adversary', True, '') +tf.flags.DEFINE_float('multi', 9, '') + +tf.flags.DEFINE_integer('log_steps', 10, '') +tf.flags.DEFINE_integer('save_epochs', 20, '') +tf.flags.DEFINE_integer('eval_epochs', 10, '') + +tf.flags.DEFINE_string('cuda_device', '3', '') + +FLAGS = tf.flags.FLAGS + +os.environ['CUDA_VISIBLE_DEVICES'] = FLAGS.cuda_device + +print(FLAGS.flag_values_dict()) + +# load data +if FLAGS.dataset == 'SVHN': + train_data = np.load('svhn_data/train_32x32.npz') + train_images = train_data['arr_0'] + train_images = 2.0 * (train_images / 255.0 - 0.5) + train_labels = train_data['arr_1'] + test_data = np.load('svhn_data/test_32x32.npz') + test_images = test_data['arr_0'] + test_images = 2 * (test_images / 255.0 - 0.5) + test_labels = test_data['arr_1'] +elif FLAGS.dataset == 'CIFAR': + if FLAGS.num_classes == 10: + dataset = load_cifar10_data('cifar10_data') + elif FLAGS.num_classes == 20: + dataset = load_cifar100_data('cifar100_data', is_fine=False) + elif FLAGS.num_classes == 100: + dataset = load_cifar100_data('cifar100_data', is_fine=True) + else: + raise ValueError('Number of classes not valid!') + train_images = dataset['train_images'] + train_labels = dataset['train_labels'] + test_images = dataset['test_images'] + test_labels = dataset['test_labels'] +else: + raise ValueError('Dataset not valid!') + +x_pl = tf.placeholder(tf.float32, shape=[None, 32, 32, 3], name='x') +y_pl = tf.placeholder(tf.int64, shape=[None], name='y') +y_loss = tf.placeholder(tf.float32, + shape=[None, FLAGS.num_classes], + name='y_loss') +lr = tf.placeholder(tf.float32, name='lr') +is_train = tf.placeholder(tf.bool, name='is_train') +global_step = tf.Variable(0, trainable=False, name='global_step') + +model = Model(is_train) +logits, _ = model.build_model(images=x_pl, num_classes=FLAGS.num_classes) +prob = tf.nn.softmax(logits) +xent = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_loss) +mean_xent = tf.reduce_mean(xent) +total_loss = mean_xent + FLAGS.weight_decay * model.weight_decay_loss + +correct = tf.cast(tf.equal(tf.argmax(logits, axis=1), y_pl), tf.float32) +accuracy = tf.reduce_mean(correct) + +# loss for adversarial attack +if FLAGS.loss_type == 'xent': + if FLAGS.targeted: + loss_att = tf.reduce_sum(xent) + else: + loss_att = -tf.reduce_sum(xent) +elif FLAGS.loss_type == 'CW': + self = tf.reduce_sum(y_loss * logits, axis=1) + other = tf.reduce_max((1 - y_loss) * logits - y_loss * 1000.0, axis=1) + if FLAGS.targeted: + loss_att = tf.reduce_sum(tf.maximum(other - self + FLAGS.margin, 0)) + else: + loss_att = tf.reduce_sum(tf.maximum(self - other + FLAGS.margin, 0)) +else: + raise ValueError('loss type not supported!') + +grad, = tf.gradients(loss_att, x_pl) + +update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) +opt = tf.train.MomentumOptimizer(lr, FLAGS.momentum) +grads_and_vars = opt.compute_gradients(total_loss, tf.trainable_variables()) +with tf.control_dependencies(update_ops): + train_step = opt.apply_gradients(grads_and_vars, global_step=global_step) + +saver = tf.train.Saver(max_to_keep=100) + +init_op = tf.global_variables_initializer() + +config = tf.ConfigProto() +config.gpu_options.allow_growth = True +sess = tf.Session(config=config) +sess.run(init_op) + +if FLAGS.restore_ckpt_path: + saver.restore(sess, os.path.abspath(FLAGS.restore_ckpt_path)) + print('Restored checkpoints from %s' % FLAGS.restore_ckpt_path) + + +def adv_attack(nat_logits, + x_batch, + y_batch, + epsilon=FLAGS.epsilon, + step_size=FLAGS.step_size, + num_steps=FLAGS.num_steps): + epsilon = epsilon / 255.0 * 2.0 + step_size = step_size / 255.0 * 2.0 + y_batch_dense = one_hot(y_batch, FLAGS.num_classes) + if not FLAGS.targeted: # non-targeted + y_att = np.copy(y_batch) + elif FLAGS.target_type == 'MC': # most confusing target label + nat_logits[np.arange(y_batch.shape[0]), y_batch] = -1e4 + y_att = np.argmax(nat_logits, axis=1) + elif FLAGS.target_type == 'RAND': # random target label + y_att = np.zeros_like(y_batch) + for ii in np.arange(y_batch.shape[0]): + tmp = np.ones([FLAGS.num_classes]) / (FLAGS.num_classes - 1) + tmp[y_batch[ii]] = 0.0 + y_att[ii] = np.random.choice(FLAGS.num_classes, p=tmp) + elif FLAGS.target_type == 'MOSA': # most one-step adversarial one-step target label + weight = sess.run(tf.get_default_graph().get_tensor_by_name( + 'logit/DW:0')).T # num_classes * num_features + dist = euclidean_distances( + weight[y_batch], + weight) + y_batch_dense # batch_size * num_classes + gt_logits = np.sum(nat_logits * y_batch_dense, axis=1) + diff_logits = np.reshape(gt_logits, [-1, 1]) - nat_logits + truncated = np.where(diff_logits > 1e-4, diff_logits, 1e4) + y_att = np.argmin(truncated / dist, axis=1) + elif FLAGS.target_type == 'MIX': # mix of MC and MOSA + weight = sess.run(tf.get_default_graph().get_tensor_by_name( + 'logit/DW:0')).T # num_classes * num_features + dist = euclidean_distances( + weight[y_batch], + weight) + y_batch_dense # batch_size * num_classes + gt_logits = np.sum(nat_logits * y_batch_dense, axis=1) + diff_logits = np.reshape(gt_logits, [-1, 1]) - nat_logits + truncated = np.where(diff_logits > 1e-4, diff_logits, 1e4) + y_att_MOSA = np.argmin(truncated / dist, axis=1) + y_att_MC = np.argmax((1.0 - y_batch_dense) * nat_logits, axis=1) + y_att = np.where( + np.argmax(nat_logits, axis=1) == y_batch, y_att_MOSA, y_att_MC) + else: + raise ValueError('Target type not valid!') + y_att_dense = one_hot(y_att, FLAGS.num_classes) + + # randomly perturb as initialization + if FLAGS.random_start: + noise = np.random.uniform(-epsilon, epsilon, x_batch.shape) + x = x_batch + noise + else: + x = np.copy(x_batch) + + for i in range(num_steps): + grad_val = sess.run(grad, + feed_dict={ + x_pl: x, + y_loss: y_att_dense, + is_train: False + }) + + x = x - step_size * np.sign(grad_val) + + x = np.clip(x, x_batch - epsilon, x_batch + epsilon) + + x = np.clip(x, -1.0, 1.0) + + return x + + +def adv_labels(nat_prob, y_batch, gamma=0.01): + L = -np.log(nat_prob + 1e-8) # log-likelihood + LL = np.copy(L) + LL[np.arange(y_batch.shape[0]), y_batch] = 1e4 + minval = np.min(LL, axis=1) + LL[np.arange(y_batch.shape[0]), y_batch] = -1e4 + maxval = np.max(LL, axis=1) + + denom = np.sum(L, axis=1) - L[np.arange(y_batch.shape[0]), y_batch] - ( + FLAGS.num_classes - 1) * (minval - gamma) + delta = 1 / (1 + FLAGS.multi * (maxval - minval + gamma) / denom) + alpha = delta / denom + + y_batch_adv = np.reshape( + alpha, [-1, 1]) * (L - np.reshape(minval, [-1, 1]) + gamma) + y_batch_adv[np.arange(y_batch.shape[0]), y_batch] = 1.0 - delta + + return y_batch_adv + + +# training loop +train_size = train_images.shape[0] +epoch_steps = np.ceil(train_size / FLAGS.batch_size).astype(np.int32) +for epoch_idx in np.arange(FLAGS.start_epoch, FLAGS.max_epoch): + if epoch_idx < FLAGS.decay_epoch1: + lr_val = FLAGS.learning_rate + elif epoch_idx < FLAGS.decay_epoch2: + lr_val = FLAGS.learning_rate * FLAGS.decay_rate + else: + lr_val = FLAGS.learning_rate * FLAGS.decay_rate * FLAGS.decay_rate + + # each epoch random shuffle of training images + idx = np.random.permutation(train_size) + for step_idx in np.arange(epoch_steps): + start = step_idx * FLAGS.batch_size + end = np.minimum((step_idx + 1) * FLAGS.batch_size, + train_size).astype(np.int32) + x_batch = preprocess_py(train_images[idx[start:end]], 4, 32) + y_batch = train_labels[idx[start:end]] + y_batch_dense = one_hot(y_batch, FLAGS.num_classes) + + start_time = time.time() + + nat_prob, nat_logits = sess.run([prob, logits], + feed_dict={ + x_pl: x_batch, + is_train: False + }) + + # generate adversarial images + x_batch_adv = adv_attack(nat_logits, x_batch, y_batch) + + # generate adversarial labels + y_batch_adv = adv_labels(nat_prob, y_batch) + + # eval accuracy + if step_idx % FLAGS.log_steps == 0: + nat_acc = sess.run(accuracy, + feed_dict={ + x_pl: x_batch, + y_pl: y_batch, + is_train: False + }) + adv_acc = sess.run(accuracy, + feed_dict={ + x_pl: x_batch_adv, + y_pl: y_batch, + is_train: False + }) + + # training step + if FLAGS.label_adversary: + _, loss_val = sess.run([train_step, total_loss], + feed_dict={ + x_pl: x_batch_adv, + y_loss: y_batch_adv, + is_train: True, + lr: lr_val + }) + else: + _, loss_val = sess.run( + [train_step, total_loss], + feed_dict={ + x_pl: x_batch_adv, + y_loss: y_batch_dense, + is_train: True, + lr: lr_val + }) + + duration = time.time() - start_time + + # print to stdout + if step_idx % FLAGS.log_steps == 0: + print( + "epoch %d, step %d, lr %.4f, duration %.2f, training nat acc %.2f, training adv acc %.2f, training adv loss %.4f" + % (epoch_idx, step_idx, lr_val, duration, 100 * nat_acc, + 100 * adv_acc, loss_val)) + sys.stdout.flush() + + # save checkpoint + if epoch_idx % FLAGS.save_epochs == 0: + saver.save(sess, os.path.join(FLAGS.model_dir, 'checkpoint'), + epoch_idx) + + # evaluate + def eval_once(): + eval_size = test_images.shape[0] + epoch_steps = np.ceil(eval_size / FLAGS.batch_size).astype(np.int32) + # random shuffle of test images does not affect the result + idx = np.random.permutation(eval_size) + count = 0.0 + for step_idx in np.arange(epoch_steps): + start = step_idx * FLAGS.batch_size + end = np.minimum((step_idx + 1) * FLAGS.batch_size, + eval_size).astype(np.int32) + x_batch = test_images[idx[start:end]] + y_batch = test_labels[idx[start:end]] + nat_logits = sess.run(logits, + feed_dict={ + x_pl: x_batch, + is_train: False + }) + x_batch_adv = adv_attack(nat_logits, x_batch, y_batch) + count += np.sum( + sess.run(correct, + feed_dict={ + x_pl: x_batch_adv, + y_pl: y_batch, + is_train: False + })) + acc = count / eval_size + return acc + + if epoch_idx % FLAGS.eval_epochs == 0: + print('epoch %d, adv acc %.2f' % (epoch_idx, 100 * eval_once())) diff --git a/case_studies/bat/train.sh b/case_studies/bat/train.sh new file mode 100644 index 0000000..fd60ef3 --- /dev/null +++ b/case_studies/bat/train.sh @@ -0,0 +1,22 @@ +#! /bin/bash + +python train.py --cuda_device=0 \ +--model_dir=/tmp \ +--dataset=CIFAR \ +--num_classes=10 \ +--max_epoch=201 \ +--decay_epoch1=100 \ +--decay_epoch2=150 \ +--start_epoch=0 \ +--restore_ckpt_path='' \ +--loss_type=xent \ +--margin=50.0 \ +--epsilon=8.0 \ +--num_steps=1 \ +--step_size=8.0 \ +--random_start=True \ +--targeted=True \ +--target_type=MC \ +--save_epochs=20 \ +--eval_epochs=10 \ +--multi=9.0 \ diff --git a/case_studies/bat/wide_resnet.py b/case_studies/bat/wide_resnet.py new file mode 100644 index 0000000..6459a2f --- /dev/null +++ b/case_studies/bat/wide_resnet.py @@ -0,0 +1,185 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +# based on https://github.com/tensorflow/models/tree/master/resnet +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np +import tensorflow as tf + + +class Model(object): + """ResNet model.""" + def __init__(self, is_train): + """ResNet constructor.""" + self.is_train = is_train + + def add_internal_summaries(self): + pass + + def build_model(self, images, num_classes): + """Build the core model within the graph.""" + with tf.variable_scope('input'): + x = self._conv('init_conv', images, 3, 3, 16, self._stride_arr(1)) + + strides = [1, 2, 2] + activate_before_residual = [True, False, False] + res_func = self._residual + + # Uncomment the following codes to use w28-10 wide residual network. + # It is more memory efficient than very deep residual network and has + # comparably good performance. + # https://arxiv.org/pdf/1605.07146v1.pdf + #filters = [16, 16, 32, 64] # WRN-28-1 + #filters = [16, 80, 160, 320] # WRN-28-5 + filters = [16, 160, 320, 640] # WRN-28-10 + #filters = [16, 256, 512, 1024] # WRN-28-16 + + # Update hps.num_residual_units to 9 + + with tf.variable_scope('unit_1_0'): + x = res_func(x, filters[0], filters[1], + self._stride_arr(strides[0]), + activate_before_residual[0]) + for i in range(1, 5): + with tf.variable_scope('unit_1_%d' % i): + x = res_func(x, filters[1], filters[1], self._stride_arr(1), + False) + + with tf.variable_scope('unit_2_0'): + x = res_func(x, filters[1], filters[2], + self._stride_arr(strides[1]), + activate_before_residual[1]) + for i in range(1, 5): + with tf.variable_scope('unit_2_%d' % i): + x = res_func(x, filters[2], filters[2], self._stride_arr(1), + False) + + with tf.variable_scope('unit_3_0'): + x = res_func(x, filters[2], filters[3], + self._stride_arr(strides[2]), + activate_before_residual[2]) + for i in range(1, 5): + with tf.variable_scope('unit_3_%d' % i): + x = res_func(x, filters[3], filters[3], self._stride_arr(1), + False) + + with tf.variable_scope('unit_last'): + x = self._batch_norm('final_bn', x) + x = self._relu(x, 0.1) + x = self._global_avg_pool(x) + + with tf.variable_scope('logit'): + self.pre_softmax = self._fully_connected(x, num_classes) + + self.weight_decay_loss = self._decay() + + return self.pre_softmax, x + + def _stride_arr(self, stride): + """Map a stride scalar to the stride array for tf.nn.conv2d.""" + return [1, stride, stride, 1] + + def _batch_norm(self, name, x): + """Batch normalization.""" + with tf.name_scope(name): + return tf.contrib.layers.batch_norm( + inputs=x, + decay=.9, + center=True, + scale=True, + activation_fn=None, + updates_collections=tf.GraphKeys.UPDATE_OPS, + is_training=self.is_train) + + def _residual(self, + x, + in_filter, + out_filter, + stride, + activate_before_residual=False): + """Residual unit with 2 sub layers.""" + if activate_before_residual: + with tf.variable_scope('shared_activation'): + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + orig_x = x + else: + with tf.variable_scope('residual_only_activation'): + orig_x = x + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + + with tf.variable_scope('sub1'): + x = self._conv('conv1', x, 3, in_filter, out_filter, stride) + + with tf.variable_scope('sub2'): + x = self._batch_norm('bn2', x) + x = self._relu(x, 0.1) + x = self._conv('conv2', x, 3, out_filter, out_filter, [1, 1, 1, 1]) + + with tf.variable_scope('sub_add'): + if in_filter != out_filter: + orig_x = tf.nn.avg_pool(orig_x, stride, stride, 'VALID') + orig_x = tf.pad(orig_x, [[0, 0], [0, 0], [0, 0], + [(out_filter - in_filter) // 2, + (out_filter - in_filter) // 2]]) + + x += orig_x + + tf.logging.debug('image after unit %s', x.get_shape()) + return x + + def _decay(self): + """L2 weight decay loss.""" + costs = [] + for var in tf.trainable_variables(): + if var.op.name.find('DW') > 0: + costs.append(tf.nn.l2_loss(var)) + return tf.add_n(costs) + + def _conv(self, name, x, filter_size, in_filters, out_filters, strides): + """Convolution.""" + with tf.variable_scope(name): + n = filter_size * filter_size * out_filters + kernel = tf.get_variable( + 'DW', [filter_size, filter_size, in_filters, out_filters], + tf.float32, + initializer=tf.random_normal_initializer(stddev=np.sqrt(2.0 / + n))) + return tf.nn.conv2d(x, kernel, strides, padding='SAME') + + def _relu(self, x, leakiness=0.0): + """Relu, with optional leaky support.""" + return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu') + + def _fully_connected(self, x, out_dim): + """FullyConnected layer for final output.""" + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + + def _global_avg_pool(self, x): + assert x.get_shape().ndims == 4 + return tf.reduce_mean(x, [1, 2]) diff --git a/case_studies/curriculum_at/PGD_attack.py b/case_studies/curriculum_at/PGD_attack.py new file mode 100644 index 0000000..ea39bd2 --- /dev/null +++ b/case_studies/curriculum_at/PGD_attack.py @@ -0,0 +1,173 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Implementation of attack methods. Running this file as a program will +apply the attack to the model specified by the config file and store +the examples in an .npy file. +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from datetime import datetime +import os +import tensorflow as tf +import numpy as np + +import cifar10_input + +import config_attack + +class LinfPGDAttack: + def __init__(self, model, epsilon, num_steps, step_size, random_start, loss_func, dataset='cifar10'): + """Attack parameter initialization. The attack performs k steps of + size a, while always staying within epsilon from the initial + point.""" + self.model = model + self.epsilon = epsilon + self.num_steps = num_steps + self.step_size = step_size + self.rand = random_start + self.dataset = dataset + + if loss_func == 'xent': + loss = model.xent + elif loss_func == "logit-diff": + loss = model.top2_logit_diff_loss + elif loss_func == 'target_task_xent': + raise ValueError("Not implemented") + loss = model.target_task_mean_xent + correct_logit = tf.reduce_sum(label_mask * model.pre_softmax, axis=1) + wrong_logit = tf.reduce_max((1-label_mask) * model.pre_softmax - 1e4*label_mask, axis=1) + loss = -tf.nn.relu(correct_logit - wrong_logit + 50) + else: + print('Unknown loss function. Defaulting to cross-entropy') + loss = model.xent + + self.grad = tf.gradients(loss, model.x_input)[0] + self.loss = loss + # self.logit = tf.placeholder(tf.float32, shape=[None, 100]) + # self.grad2 = tf.gradients(loss + tf.reduce_mean(tf.reduce_sum(tf.pow(tf.subtract(self.logit, model.pre_softmax), 2.0), keepdims=True)), model.x_input)[0] + + def perturb(self, x_nat, y, sess, feed_dict={}): + """Given a set of examples (x_nat, y), returns a set of adversarial + examples within epsilon of x_nat in l_infinity norm.""" + if self.rand: + x = x_nat + np.random.uniform(-self.epsilon, self.epsilon, x_nat.shape) + x = np.clip(x, 0, 255) # ensure valid pixel range + else: + x = np.copy(x_nat) + + for i in range(self.num_steps): + loss, grad = sess.run((self.loss, self.grad), feed_dict={self.model.x_input: x, + self.model.y_input: y, + **feed_dict}) + + x = np.add(x, self.step_size * np.sign(grad), out=x, casting='unsafe') + + x = np.clip(x, x_nat - self.epsilon, x_nat + self.epsilon) + x = np.clip(x, 0, 255) # ensure valid pixel range + + return x + + def perturb_l2(self, x_nat, y, sess, feed_dict={}): + """Given a set of examples (x_nat, y), returns a set of adversarial + examples within epsilon of x_nat in l_2 norm.""" + if self.rand: + pert = np.random.uniform(-self.epsilon, self.epsilon, x_nat.shape) + pert_norm = np.linalg.norm(pert) + pert = pert / max(1, pert_norm) + else: + pert = np.zeros(x_nat.shape) + + for i in range(self.num_steps): + x = x_nat + pert + # x = np.clip(x, 0, 255) + grad = sess.run(self.grad, feed_dict={self.model.x_input: x, + self.model.y_input: y, + **feed_dict}) + + normalized_grad = grad / np.linalg.norm(grad) + pert = np.add(pert, self.step_size * normalized_grad, out=pert, casting='unsafe') + + # project pert to norm ball + pert_norm = np.linalg.norm(pert) + rescale_factor = pert_norm / self.epsilon + pert = pert / max(1, rescale_factor) + + x = x_nat + pert + x = np.clip(x, 0, 255) + + return x + + # def perturb_TRADES(self, x_nat, y, sess): + # """Given a set of examples (x_nat, y), returns a set of adversarial + # examples within epsilon of x_nat in l_2 norm of TRADES Loss.""" + # if self.rand: + # pert = np.random.uniform(-self.epsilon, self.epsilon, x_nat.shape) + # pert_norm = np.linalg.norm(pert) + # pert = pert / max(1, pert_norm) + # else: + # pert = np.zeros(x_nat.shape) + + # nat_logit = sess.run(model.pre_softmax, feed_dict={self.model.x_input: x_nat, + # self.model.y_input: y}) + # for i in range(self.num_steps): + # x = x_nat + pert + # grad = sess.run(self.grad2, feed_dict={self.model.x_input: x, + # self.model.y_input: y, self.logit: nat_logit}) + # normalized_grad = grad / np.linalg.norm(grad) + # pert = np.add(pert, self.step_size * normalized_grad, out=pert, casting='unsafe') + # pert_norm = np.linalg.norm(pert) + # rescale_factor = pert_norm / self.epsilon + # pert = pert / max(1, rescale_factor) + + # #x = x_nat + pert + # x = np.clip(x, 0, 255) + + # return x + + + def modified_perturb_l2(self, x_nat, y, feed_dict={}): + if self.rand: + pert = np.random.uniform(-self.epsilon, self.epsilon, x_nat.shape) + pert_norm = np.linalg.norm(pert) + pert = pert / max(1, pert_norm) + else: + pert = np.zeros(x_nat.shape) + + for i in range(self.num_steps): + x = x_nat + pert + # x = np.clip(x, 0, 255) + with tf.Session() as sess: + sess.run(tf.global_variables_initializer()) + grad = sess.run(self.grad, feed_dict={self.model.x_input: x, + self.model.y_input: y, + **feed_dict}) + + normalized_grad = grad / np.linalg.norm(grad) + pert = np.add(pert, self.step_size * normalized_grad, out=pert, casting='unsafe') + + # project pert to norm ball + pert_norm = np.linalg.norm(pert) + rescale_factor = pert_norm / self.epsilon + pert = pert / max(1, rescale_factor) + + x = x_nat + pert + x = np.clip(x, 0, 255) + + return (x - x_nat) + + diff --git a/case_studies/curriculum_at/README.md b/case_studies/curriculum_at/README.md new file mode 100644 index 0000000..de23be6 --- /dev/null +++ b/case_studies/curriculum_at/README.md @@ -0,0 +1,37 @@ +# Get Fooled for the Right Reason +Official repository for the NeurIPS 2021 paper Get Fooled for the Right Reason: Improving Adversarial Robustness through a Teacher-guided Curriculum Learning Approach + +## Dependencies +1. Tensorflow 1.14.0 +2. Python 3.7 + +## Datasets +CIFAR10: https://www.cs.toronto.edu/~kriz/cifar.html + +## Models +`modelGTP_cifar10`: https://www.dropbox.com/sh/29n2lt08ypjdw67/AABSZlD8nTM08E-bcZv1mdkOa?dl=0 + +## Usage +1. Install dependencies with `pip install -r requirements.txt`. Prefarably, create an anaconda environment. +2. Download and save datasets in `datasets/` folder. +3. Download and save model in `models/` folder. +4. Run the `python eval_attack.py` +5. The evaluation results will be stored in `attack_log` directory. + +### Note +Using a GPU is highly recommended. + + +## Code overview +- `model_new.py`: contains code for IGAM model architectures. +- `cifar10_input.py` provides utility functions and classes for loading the CIFAR10 dataset. +- `PGD_attack.py`: generates adversarial examples and save them in `attacks/`. +- `run_attack.py`: evaluates model on adversarial examples from `attacks/`. +- `config_attack.py`: parameters for adversarial example evaluation. +- `eval_attack.py`: runs **FGSM, PGD-5, PGD-10, PGD-20** attacks and logs the results in `attack_log` directory. However, you can get results for any attack by modifying the `num_steps` flag in the code. + +## Acknowledgements + +Useful code bases we used in our work: +- https://github.com/MadryLab/cifar10_challenge (for adversarial example generation and evaluation) +- https://github.com/ashafahi/free_adv_train (for model code) diff --git a/case_studies/curriculum_at/adversarial_evaluation.py b/case_studies/curriculum_at/adversarial_evaluation.py new file mode 100644 index 0000000..09cde63 --- /dev/null +++ b/case_studies/curriculum_at/adversarial_evaluation.py @@ -0,0 +1,237 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import logging +logging.getLogger('tensorflow').setLevel(logging.FATAL) +import tensorflow as tf + +tf.logging.set_verbosity(tf.logging.ERROR) + +import tensorflow as tf +import numpy as np + +import cifar10_input + +import config_attack + +import sys +import math +from tqdm import tqdm + +from case_studies.curriculum_at.PGD_attack import LinfPGDAttack + +if __name__ == '__main__': + config = vars(config_attack.get_args()) + + tf.set_random_seed(config['tf_seed']) + np.random.seed(config['np_seed']) + + model_file = tf.train.latest_checkpoint(config['model_dir']) + # print("config['model_dir']: ", config['model_dir']) + if model_file is None: + print('No model found') + sys.exit() + + if 'GTP' in config['model_dir']: + from model_new import Model, ModelTinyImagnet + + if config['dataset'] == 'cifar10' or config['dataset'] == 'cifar100': + # TODO: verify this with the authors + # ATTENTION: mode was "train" before + model = Model(mode=config["inference_mode"], dataset=config['dataset'], + train_batch_size=config['eval_batch_size'], + normalize_zero_mean=True) + else: + model = ModelTinyImagnet(mode='train', dataset=config['dataset'], + train_batch_size=config['eval_batch_size'], + normalize_zero_mean=True) + + elif 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config[ + 'model_dir']: + print("finetuned tinyimagenet MODEL") + from model_new import ModelTinyImagenetSourceExtendedLogits + + full_source_model_x_input = tf.placeholder(tf.float32, + shape=[None, 32, 32, 3]) + upresized_full_source_model_x_input = tf.image.resize_images( + full_source_model_x_input, size=[64, 64]) + if config['dataset'] == 'cifar10': + model = ModelTinyImagenetSourceExtendedLogits(mode='train', + dataset='tinyimagenet', + target_task_class_num=10, + train_batch_size=config[ + 'eval_batch_size'], + input_tensor=upresized_full_source_model_x_input) + elif config['dataset'] == 'cifar100': + model = ModelTinyImagenetSourceExtendedLogits(mode='train', + dataset='tinyimagenet', + target_task_class_num=100, + train_batch_size=config[ + 'eval_batch_size'], + input_tensor=upresized_full_source_model_x_input) + + model.x_input = full_source_model_x_input + + t_vars = tf.trainable_variables() + source_model_vars = [var for var in t_vars if ( + 'discriminator' not in var.name and 'classifier' not in var.name and 'target_task_logit' not in var.name)] + source_model_target_logit_vars = [var for var in t_vars if + 'target_task_logit' in var.name] + source_model_saver = tf.train.Saver(var_list=source_model_vars) + finetuned_source_model_vars = source_model_vars + source_model_target_logit_vars + finetuned_source_model_saver = tf.train.Saver( + var_list=finetuned_source_model_vars) + elif 'finetuned_on_cifar100' in config['model_dir']: + raise NotImplementedError + print("finetuned MODEL") + from model_original_cifar_challenge import ModelExtendedLogits + + model = ModelExtendedLogits(mode='train', target_task_class_num=100, + train_batch_size=config['eval_batch_size']) + + t_vars = tf.trainable_variables() + source_model_vars = [var for var in t_vars if ( + 'discriminator' not in var.name and 'classifier' not in var.name and 'target_task_logit' not in var.name)] + source_model_target_logit_vars = [var for var in t_vars if + 'target_task_logit' in var.name] + source_model_saver = tf.train.Saver(var_list=source_model_vars) + finetuned_source_model_vars = source_model_vars + source_model_target_logit_vars + finetuned_source_model_saver = tf.train.Saver( + var_list=finetuned_source_model_vars) + elif ('adv_trained' in config['model_dir'] or 'naturally_trained' in config[ + 'model_dir'] or 'a_very_robust_model' in config['model_dir']): + raise NotImplementedError + print("original challenge MODEL") + from free_model_original import Model + + model = Model(mode='eval', dataset=config['dataset'], + train_batch_size=config['eval_batch_size']) + elif 'IGAM' in config['model_dir']: + print("IGAM MODEL") + from model_new import Model + + model = Model(mode='train', dataset=config['dataset'], + train_batch_size=config['eval_batch_size'], + normalize_zero_mean=True) + else: + raise NotImplementedError + print("other MODEL") + from free_model import Model + + model = Model(mode='eval', dataset=config['dataset'], + train_batch_size=config['eval_batch_size']) + + attack = LinfPGDAttack(model, + config['epsilon'], + config['num_steps'], + config['step_size'], + config['random_start'], + config['loss_func'], + dataset=config['dataset']) + saver = tf.train.Saver() + + data_path = config['data_path'] + # print(data_path) + # x = input() + + if config['dataset'] == 'cifar10': + # print("load cifar10 dataset") + cifar = cifar10_input.CIFAR10Data(data_path) + elif config['dataset'] == 'cifar100': + raise NotImplementedError + print("load cifar100 dataset") + cifar = cifar100_input.CIFAR100Data(data_path) + else: + raise NotImplementedError + print("load tinyimagenet dataset") + cifar = tinyimagenet_input.TinyImagenetData() + + with tf.Session() as sess: + # Restore the checkpoint + if 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config[ + 'model_dir']: + sess.run(tf.global_variables_initializer()) + source_model_file = tf.train.latest_checkpoint( + "models/model_AdvTrain-igamsource-IGAM-tinyimagenet_b16") + source_model_saver.restore(sess, source_model_file) + finetuned_source_model_file = tf.train.latest_checkpoint( + config['model_dir']) + finetuned_source_model_saver.restore(sess, finetuned_source_model_file) + elif 'finetuned_on_cifar100' in config['model_dir']: + sess.run(tf.global_variables_initializer()) + source_model_file = tf.train.latest_checkpoint("models/adv_trained") + source_model_saver.restore(sess, source_model_file) + finetuned_source_model_file = tf.train.latest_checkpoint( + config['model_dir']) + finetuned_source_model_saver.restore(sess, finetuned_source_model_file) + else: + saver.restore(sess, model_file) + + # Iterate over the samples batch-by-batch + num_eval_examples = config['num_eval_examples'] + eval_batch_size = config['eval_batch_size'] + num_batches = int(math.ceil(num_eval_examples / eval_batch_size)) + + x_adv = [] # adv accumulator + x = [] + y = [] + y_p = [] + y_adv = [] + is_correct = [] + # print('Iterating over {} batches'.format(num_batches)) + + for ibatch in tqdm(range(num_batches)): + bstart = ibatch * eval_batch_size + bend = min(bstart + eval_batch_size, num_eval_examples) + + x_batch = cifar.eval_data.xs[bstart:bend, :] + y_batch = cifar.eval_data.ys[bstart:bend] + + if config['attack_norm'] == 'inf': + x_batch_adv = attack.perturb(x_batch, y_batch, sess) + elif config['attack_norm'] == '2': + x_batch_adv = attack.perturb_l2(x_batch, y_batch, sess) + elif config['attack_norm'] == 'TRADES': + x_batch_adv = attack.perturb_TRADES(x_batch, y_batch, sess) + elif config['attack_norm'] == "": + x_batch_adv = x_batch + + y_pred = sess.run(model.predictions, feed_dict={model.x_input: x_batch_adv}) + + y_pred_clean = sess.run(model.predictions, feed_dict={model.x_input: x_batch}) + + x_adv.append(x_batch_adv) + x.append(x_batch) + y.append(y_batch) + y_p.append(y_pred_clean) + y_adv.append(y_pred) + + is_correct.append(y_pred == y_batch) + is_correct = np.concatenate(is_correct) + x_adv = np.concatenate(x_adv) + x = np.concatenate(x) + y = np.concatenate(y) + y_p = np.concatenate(y_p) + y_adv = np.concatenate(y_adv) + if config["save_data_path"] is not None: + x = x.astype(int) + x_adv = x_adv.astype(int) + np.savez(config["save_data_path"], x_a=x, x_b=x_adv, y_a=y_p, y_b=y_adv) + print(f"Robust accuracy: {np.mean(is_correct)}") + + diff --git a/case_studies/curriculum_at/adversarial_evaluation.sh b/case_studies/curriculum_at/adversarial_evaluation.sh new file mode 100644 index 0000000..707d10c --- /dev/null +++ b/case_studies/curriculum_at/adversarial_evaluation.sh @@ -0,0 +1,51 @@ +nsamples=10000 + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using their attack parameters and train mode (default)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/curriculum_at/adversarial_evaluation.py \ + --step_size=2 \ + --num_steps=20 \ + --loss_func=xent \ + --inference_mode=train \ + --num_eval_examples=$nsamples + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using adapted attack parameters and train mode (default)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/curriculum_at/adversarial_evaluation.py \ + --random_start \ + --step_size=0.5 \ + --num_steps=75 \ + --loss_func=logit-diff \ + --inference_mode=train \ + --num_eval_examples=$nsamples + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using their attack parameters and eval mode (modified)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/curriculum_at/adversarial_evaluation.py \ + --step_size=2 \ + --num_steps=20 \ + --loss_func=xent \ + --inference_mode=eval \ + --num_eval_examples=$nsamples + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using adapted attack parameters and eval mode (modified)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/curriculum_at/adversarial_evaluation.py \ + --random_start \ + --step_size=0.5 \ + --num_steps=75 \ + --loss_func=logit-diff \ + --inference_mode=eval \ + --num_eval_examples=$nsamples \ No newline at end of file diff --git a/case_studies/curriculum_at/adversarial_evaluation_0.5.sh b/case_studies/curriculum_at/adversarial_evaluation_0.5.sh new file mode 100644 index 0000000..960420e --- /dev/null +++ b/case_studies/curriculum_at/adversarial_evaluation_0.5.sh @@ -0,0 +1,57 @@ +nsamples=10000 + +echo "Running attacks with epsilon=128/255" + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using their attack parameters and train mode (default)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/curriculum_at/adversarial_evaluation.py \ + --step_size=2 \ + --num_steps=20 \ + --loss_func=xent \ + --inference_mode=train \ + --epsilon=128 \ + --num_eval_examples=$nsamples + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using adapted attack parameters and train mode (default)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/curriculum_at/adversarial_evaluation.py \ + --random_start \ + --step_size=0.5 \ + --num_steps=75 \ + --loss_func=logit-diff \ + --inference_mode=train \ + --epsilon=128 \ + --num_eval_examples=$nsamples + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using their attack parameters and eval mode (modified)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/curriculum_at/adversarial_evaluation.py \ + --step_size=2 \ + --num_steps=20 \ + --loss_func=xent \ + --inference_mode=eval \ + --epsilon=128 \ + --num_eval_examples=$nsamples + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using adapted attack parameters and eval mode (modified)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/curriculum_at/adversarial_evaluation.py \ + --random_start \ + --step_size=0.5 \ + --num_steps=75 \ + --loss_func=logit-diff \ + --inference_mode=eval \ + --epsilon=128 \ + --num_eval_examples=$nsamples \ No newline at end of file diff --git a/case_studies/curriculum_at/binarization_test.py b/case_studies/curriculum_at/binarization_test.py new file mode 100644 index 0000000..66fbab9 --- /dev/null +++ b/case_studies/curriculum_at/binarization_test.py @@ -0,0 +1,356 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import logging + +import torch + +logging.getLogger('tensorflow').setLevel(logging.FATAL) +import tensorflow as tf + +tf.logging.set_verbosity(tf.logging.ERROR) + +import tensorflow as tf +import numpy as np + +import cifar10_input + +import config_attack + +import sys +import math +from tqdm import tqdm +import tqdm_utils + +from PGD_attack import LinfPGDAttack +from active_tests.decision_boundary_binarization import interior_boundary_discrimination_attack + +if __name__ == '__main__': + config = vars(config_attack.get_args()) + + tf.set_random_seed(config['tf_seed']) + np.random.seed(config['np_seed']) + + model_file = tf.train.latest_checkpoint(config['model_dir']) + # print("config['model_dir']: ", config['model_dir']) + if model_file is None: + print('No model found') + sys.exit() + + if 'GTP' in config['model_dir']: + from model_new import Model, ModelTinyImagnet + + if config['dataset'] == 'cifar10' or config['dataset'] == 'cifar100': + # TODO: verify this with the authors + # ATTENTION: mode was "train" before + model = Model(mode=config["inference_mode"], dataset=config['dataset'], + train_batch_size=config['eval_batch_size'], + normalize_zero_mean=True) + else: + model = ModelTinyImagnet(mode='train', dataset=config['dataset'], + train_batch_size=config['eval_batch_size'], + normalize_zero_mean=True) + + elif 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config[ + 'model_dir']: + print("finetuned tinyimagenet MODEL") + from model_new import ModelTinyImagenetSourceExtendedLogits + + full_source_model_x_input = tf.placeholder(tf.float32, + shape=[None, 32, 32, 3]) + upresized_full_source_model_x_input = tf.image.resize_images( + full_source_model_x_input, size=[64, 64]) + if config['dataset'] == 'cifar10': + model = ModelTinyImagenetSourceExtendedLogits(mode='train', + dataset='tinyimagenet', + target_task_class_num=10, + train_batch_size=config[ + 'eval_batch_size'], + input_tensor=upresized_full_source_model_x_input) + elif config['dataset'] == 'cifar100': + model = ModelTinyImagenetSourceExtendedLogits(mode='train', + dataset='tinyimagenet', + target_task_class_num=100, + train_batch_size=config[ + 'eval_batch_size'], + input_tensor=upresized_full_source_model_x_input) + + model.x_input = full_source_model_x_input + + t_vars = tf.trainable_variables() + source_model_vars = [var for var in t_vars if ( + 'discriminator' not in var.name and 'classifier' not in var.name and 'target_task_logit' not in var.name)] + source_model_target_logit_vars = [var for var in t_vars if + 'target_task_logit' in var.name] + source_model_saver = tf.train.Saver(var_list=source_model_vars) + finetuned_source_model_vars = source_model_vars + source_model_target_logit_vars + finetuned_source_model_saver = tf.train.Saver( + var_list=finetuned_source_model_vars) + elif 'finetuned_on_cifar100' in config['model_dir']: + raise NotImplementedError + print("finetuned MODEL") + from model_original_cifar_challenge import ModelExtendedLogits + + model = ModelExtendedLogits(mode='train', target_task_class_num=100, + train_batch_size=config['eval_batch_size']) + + t_vars = tf.trainable_variables() + source_model_vars = [var for var in t_vars if ( + 'discriminator' not in var.name and 'classifier' not in var.name and 'target_task_logit' not in var.name)] + source_model_target_logit_vars = [var for var in t_vars if + 'target_task_logit' in var.name] + source_model_saver = tf.train.Saver(var_list=source_model_vars) + finetuned_source_model_vars = source_model_vars + source_model_target_logit_vars + finetuned_source_model_saver = tf.train.Saver( + var_list=finetuned_source_model_vars) + elif ('adv_trained' in config['model_dir'] or 'naturally_trained' in config[ + 'model_dir'] or 'a_very_robust_model' in config['model_dir']): + raise NotImplementedError + print("original challenge MODEL") + from free_model_original import Model + + model = Model(mode='eval', dataset=config['dataset'], + train_batch_size=config['eval_batch_size']) + elif 'IGAM' in config['model_dir']: + print("IGAM MODEL") + from model_new import Model + + model = Model(mode='train', dataset=config['dataset'], + train_batch_size=config['eval_batch_size'], + normalize_zero_mean=True) + else: + raise NotImplementedError + print("other MODEL") + from free_model import Model + + model = Model(mode='eval', dataset=config['dataset'], + train_batch_size=config['eval_batch_size']) + + saver = tf.train.Saver() + + data_path = config['data_path'] + # print(data_path) + # x = input() + + if config['dataset'] == 'cifar10': + # print("load cifar10 dataset") + cifar = cifar10_input.CIFAR10Data(data_path) + elif config['dataset'] == 'cifar100': + raise NotImplementedError + print("load cifar100 dataset") + cifar = cifar100_input.CIFAR100Data(data_path) + else: + raise NotImplementedError + print("load tinyimagenet dataset") + cifar = tinyimagenet_input.TinyImagenetData() + + with tf.Session() as sess: + # Restore the checkpoint + if 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config[ + 'model_dir']: + sess.run(tf.global_variables_initializer()) + source_model_file = tf.train.latest_checkpoint( + "models/model_AdvTrain-igamsource-IGAM-tinyimagenet_b16") + source_model_saver.restore(sess, source_model_file) + finetuned_source_model_file = tf.train.latest_checkpoint( + config['model_dir']) + finetuned_source_model_saver.restore(sess, finetuned_source_model_file) + elif 'finetuned_on_cifar100' in config['model_dir']: + sess.run(tf.global_variables_initializer()) + source_model_file = tf.train.latest_checkpoint("models/adv_trained") + source_model_saver.restore(sess, source_model_file) + finetuned_source_model_file = tf.train.latest_checkpoint( + config['model_dir']) + finetuned_source_model_saver.restore(sess, finetuned_source_model_file) + else: + saver.restore(sess, model_file) + + # Iterate over the samples batch-by-batch + num_eval_examples = config['num_eval_examples'] + eval_batch_size = config['eval_batch_size'] + num_batches = int(math.ceil(num_eval_examples / eval_batch_size)) + + class ModelWrapper: + def __init__(self, model, weight_shape, bias_shape, num_classes=2): + self.weight = tf.placeholder(dtype=tf.float32, shape=weight_shape) + self.bias = tf.placeholder(dtype=tf.float32, shape=bias_shape) + + y = model.neck + + # TODO: check whether we need a separate placeholder for the binary label + self.y_input = model.y_input + self.x_input = model.x_input + + self.logits = y @ tf.transpose(self.weight) + tf.reshape(self.bias, (1, -1)) + self.predictions = tf.argmax(self.logits, 1) + + self.pre_softmax = self.logits + + # define losses + self.y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent = tf.reduce_sum(self.y_xent, name='y_xent') + + # for top-2 logit diff loss + self.label_mask = tf.one_hot(self.y_input, + num_classes, + on_value=1.0, + off_value=0.0, + dtype=tf.float32) + self.correct_logit = tf.reduce_sum(self.label_mask * self.pre_softmax, axis=1) + self.wrong_logit = tf.reduce_max((1-self.label_mask) * self.pre_softmax - 1e4*self.label_mask, axis=1) + # TODO: why the plus 50? + # self.top2_logit_diff_loss = -tf.nn.relu(self.correct_logit - self.wrong_logit + 50) + self.top2_logit_diff_loss = -self.correct_logit + self.wrong_logit + + + wrapped_model = ModelWrapper(model, (2, 640), (2,)) + + attack = LinfPGDAttack(wrapped_model, + config['epsilon'], + config['num_steps'], + config['step_size'], + config['random_start'], + config['loss_func'], + dataset=config['dataset']) + + def run_attack(m, l): + linear_layer = m[-1] + del m + + # initialize an attack (it's a white box attack, and it's allowed to look + # at the internals of the model in any way it wants) + # attack = BPDA(sess, model, epsilon=model.threat_model.epsilon, debug=args.debug) + # m = PyTorchToTensorFlow1Wrapper(m, "cpu") + + weights_feed_dict = { + wrapped_model.weight: linear_layer.weight.data.numpy(), + wrapped_model.bias: linear_layer.bias.data.numpy() + } + + assert len(l) == 1, len(l) + for x, y in l: + x_batch = x.numpy().transpose((0, 2, 3, 1)) * 255.0 + y_batch = y.numpy() + + if config['attack_norm'] == 'inf': + x_batch_adv = attack.perturb(x_batch, y_batch, sess, weights_feed_dict) + elif config['attack_norm'] == '2': + x_batch_adv = attack.perturb_l2(x_batch, y_batch, sess, weights_feed_dict) + elif config['attack_norm'] == 'TRADES': + x_batch_adv = attack.perturb_TRADES(x_batch, y_batch, sess, weights_feed_dict) + + logits, y_pred = sess.run((wrapped_model.logits, wrapped_model.predictions), + feed_dict={model.x_input: x_batch_adv, + **weights_feed_dict}) + is_adv = y_pred != y_batch + + return is_adv, (torch.Tensor(x_batch_adv) / 255.0, torch.Tensor(logits)) + + random_indices = list(range(len(cifar.eval_data.xs))) + np.random.shuffle(random_indices) + + x_batch = [] + y_batch = [] + for j in range(config['num_eval_examples']): + x_ = cifar.eval_data.xs[random_indices[j]] + y_ = cifar.eval_data.ys[random_indices[j]] + x_batch.append(x_) + y_batch.append(y_) + x_batch = np.array(x_batch).transpose((0, 3, 1, 2)) / 255.0 + y_batch = np.array(y_batch) + + from tensorflow_wrapper import TensorFlow1ToPyTorchWrapper, PyTorchToTensorFlow1Wrapper + from utils import build_dataloader_from_arrays + + test_loader = build_dataloader_from_arrays(x_batch, y_batch, batch_size=32) + + def _model_forward_pass(x, features_and_logits: bool = False, features_only: bool = False): + if features_and_logits: + assert not features_only, "Only one of the flags must be set." + if features_and_logits: + return sess.run( + (model.neck, model.pre_softmax), + feed_dict={model.x_input: x.transpose(0, 2, 3, 1) * 255.0}) + elif features_only: + return sess.run( + model.neck, + feed_dict={model.x_input: x.transpose(0, 2, 3, 1) * 255.0}) + else: + raise ValueError + + feature_extractor = TensorFlow1ToPyTorchWrapper( + logit_forward_pass=_model_forward_pass, + logit_forward_and_backward_pass=lambda x, **kwargs: sess.run( + model.feature_grad, + feed_dict={model.x_input: x.transpose(0, 2, 3, 1) * 255.0}) / 255.0 + ) + + assert config["n_boundary_points"] is not None + assert config["n_inner_points"] is not None + + from argparse_utils import DecisionBoundaryBinarizationSettings + + with tqdm_utils.tqdm_print(): + scores_logit_differences_and_validation_accuracies = \ + interior_boundary_discrimination_attack( + feature_extractor, + test_loader, + attack_fn=lambda m, l, kwargs: run_attack(m, l), + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=config["epsilon"]/255.0, + norm="linf", + lr=10000, + n_boundary_points=config["n_boundary_points"], + n_inner_points=config["n_inner_points"], + adversarial_attack_settings=None, + optimizer="sklearn" + ), + n_samples=config['num_eval_examples'], + device="cpu", + n_samples_evaluation=200, + n_samples_asr_evaluation=200, + rescale_logits="adaptive", + sample_training_data_from_corners=config["sample_from_corners"], + decision_boundary_closeness=0.99999 + #args.num_samples_test * 10 + ) + + scores = [it[0] for it in scores_logit_differences_and_validation_accuracies] + validation_scores = [it[3] for it in scores_logit_differences_and_validation_accuracies] + if validation_scores[0] is None: + validation_scores = (np.nan, np.nan) + else: + validation_scores = np.array(validation_scores) + validation_scores = tuple(np.mean(validation_scores, 0)) + logit_differences = [(it[1], it[2]) for it in + scores_logit_differences_and_validation_accuracies] + logit_differences = np.array(logit_differences) + relative_performance = (logit_differences[:, 0] - logit_differences[:, + 1]) / logit_differences[:, + 1] + + test_result = (np.mean(scores), np.mean(relative_performance), + np.std(relative_performance), validation_scores) + + print("\tinterior-vs-boundary discrimination (ce loss), ASR: {0}\n”, " + "\t\tNormalized Logit-Difference-Improvement: {1} +- {2}\n" + "\t\tValidation Accuracy (inner, boundary): {3}".format( + *test_result)) + + diff --git a/case_studies/curriculum_at/binarization_test.sh b/case_studies/curriculum_at/binarization_test.sh new file mode 100644 index 0000000..6feac6e --- /dev/null +++ b/case_studies/curriculum_at/binarization_test.sh @@ -0,0 +1,42 @@ +nsamples=${1:-512} +epsilon=${2:-8} +mode=${3:-train} + +kwargs="" +kwargs="--sample-from-corners" + +echo "Attacking $nsamples with epsilon = $epsilon and model inference = $mode" +echo "kwargs: $kwargs" + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "1 boundary point, 999 inner (their attack parameters)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/curriculum_at/binarization_test.py \ + --step_size=2 \ + --num_steps=20 \ + --loss_func=xent \ + --n_boundary_points=1 \ + --n_inner_points=999 \ + --epsilon=$epsilon \ + --inference_mode=$mode \ + --num_eval_examples=$nsamples \ + $kwargs + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "1 boundary point, 999 inner (modified attack parameters)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + case_studies/curriculum_at/binarization_test.py \ + --random_start \ + --step_size=0.5 \ + --num_steps=50 \ + --loss_func=logit-diff \ + --n_boundary_points=1 \ + --n_inner_points=999 \ + --epsilon=$epsilon \ + --inference_mode=$mode \ + --num_eval_examples=$nsamples\ + $kwargs \ No newline at end of file diff --git a/case_studies/curriculum_at/cifar10_input.py b/case_studies/curriculum_at/cifar10_input.py new file mode 100644 index 0000000..74505cf --- /dev/null +++ b/case_studies/curriculum_at/cifar10_input.py @@ -0,0 +1,204 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Utilities for importing the CIFAR10 dataset. +Each image in the dataset is a numpy array of shape (32, 32, 3), with the values +being unsigned integers (i.e., in the range 0,1,...,255). +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import os +import pickle +import sys +import tensorflow as tf +import numpy as np +import re + +version = sys.version_info + + +class CIFAR10Data(object): + """ + Unpickles the CIFAR10 dataset from a specified folder containing a pickled + version following the format of Krizhevsky which can be found + [here](https://www.cs.toronto.edu/~kriz/cifar.html). + Inputs to constructor + ===================== + - path: path to the pickled dataset. The training data must be pickled + into five files named data_batch_i for i = 1, ..., 5, containing 10,000 + examples each, the test data + must be pickled into a single file called test_batch containing 10,000 + examples, and the 10 class names must be + pickled into a file called batches.meta. The pickled examples should + be stored as a tuple of two objects: an array of 10,000 32x32x3-shaped + arrays, and an array of their 10,000 true labels. + """ + + def __init__(self, path, batch_start = 0, init_shuffle=True, train_size_ratio=1): + num_classes = 10 + path = CIFAR10Data.rec_search(path) + train_filenames = ['data_batch_{}'.format(ii + 1) for ii in range(5)] + eval_filename = 'test_batch' + metadata_filename = 'batches.meta' + + train_images = np.zeros((50000, 32, 32, 3), dtype='uint8') + train_labels = np.zeros(50000, dtype='int32') + for ii, fname in enumerate(train_filenames): + cur_images, cur_labels = self._load_datafile(os.path.join(path, fname)) + train_images[ii * 10000: (ii + 1) * 10000, ...] = cur_images + train_labels[ii * 10000: (ii + 1) * 10000, ...] = cur_labels + eval_images, eval_labels = self._load_datafile( + os.path.join(path, eval_filename)) + + with open(os.path.join(path, metadata_filename), 'rb') as fo: + if version.major == 3: + data_dict = pickle.load(fo, encoding='bytes') + else: + data_dict = pickle.load(fo) + + self.label_names = data_dict[b'label_names'] + for ii in range(len(self.label_names)): + self.label_names[ii] = self.label_names[ii].decode('utf-8') + + if train_size_ratio < 1: + new_train_images = [] + new_train_labels = [] + for class_ind in range(num_classes): + current_class_train_images = train_images[train_labels == class_ind] + num_train_per_class = int(current_class_train_images.shape[0] * train_size_ratio) + new_train_images.append(current_class_train_images[:num_train_per_class]) + new_train_labels.append(np.full(num_train_per_class, class_ind, dtype='int32')) + train_images = np.concatenate(new_train_images, axis=0) + train_labels = np.concatenate(new_train_labels) + + self.train_data = DataSubset(train_images, train_labels, batch_start = batch_start, init_shuffle=init_shuffle) + self.eval_data = DataSubset(eval_images, eval_labels, batch_start = batch_start, init_shuffle=init_shuffle) + + @staticmethod + def rec_search(original_path): + rx = re.compile(r'data_batch_[0-9]+') + r = [] + for path, _, file_names in os.walk(original_path): + r.extend([os.path.join(path, x) for x in file_names if rx.search(x)]) + if len(r) is 0: # Is this the best way? + return original_path + return os.path.dirname(r[0]) + + @staticmethod + def _load_datafile(filename): + with open(filename, 'rb') as fo: + if version.major == 3: + data_dict = pickle.load(fo, encoding='bytes') + else: + data_dict = pickle.load(fo) + + assert data_dict[b'data'].dtype == np.uint8 + image_data = data_dict[b'data'] + image_data = image_data.reshape((10000, 3, 32, 32)).transpose(0, 2, 3, 1) + return image_data, np.array(data_dict[b'labels']) + + +class AugmentedCIFAR10Data(object): + """ + Data augmentation wrapper over a loaded dataset. + Inputs to constructor + ===================== + - raw_cifar10data: the loaded CIFAR10 dataset, via the CIFAR10Data class + - sess: current tensorflow session + - model: current model (needed for input tensor) + """ + + def __init__(self, raw_cifar10data, sess, model): + assert isinstance(raw_cifar10data, CIFAR10Data) + self.image_size = 32 + + # create augmentation computational graph + self.x_input_placeholder = tf.placeholder(tf.float32, shape=[None, 32, 32, 3]) + padded = tf.map_fn(lambda img: tf.image.resize_image_with_crop_or_pad( + img, self.image_size + 4, self.image_size + 4), + self.x_input_placeholder) + cropped = tf.map_fn(lambda img: tf.random_crop(img, [self.image_size, + self.image_size, + 3]), padded) + flipped = tf.map_fn(lambda img: tf.image.random_flip_left_right(img), cropped) + self.augmented = flipped + + self.train_data = AugmentedDataSubset(raw_cifar10data.train_data, sess, + self.x_input_placeholder, + self.augmented) + self.eval_data = AugmentedDataSubset(raw_cifar10data.eval_data, sess, + self.x_input_placeholder, + self.augmented) + self.label_names = raw_cifar10data.label_names + + +class DataSubset(object): + def __init__(self, xs, ys, batch_start = 0, init_shuffle=True): + self.xs = xs + self.n = xs.shape[0] + self.ys = ys + self.batch_start = batch_start + if init_shuffle: + self.cur_order = np.random.permutation(self.n) + else: + self.cur_order = np.arange(self.n) + + def get_next_batch(self, batch_size, multiple_passes=False, reshuffle_after_pass=True): + if self.n < batch_size: + raise ValueError('Batch size can be at most the dataset size') + if not multiple_passes: + actual_batch_size = min(batch_size, self.n - self.batch_start) + if actual_batch_size <= 0: + raise ValueError('Pass through the dataset is complete.') + batch_end = self.batch_start + actual_batch_size + batch_xs = self.xs[self.cur_order[self.batch_start: batch_end], ...] + batch_ys = self.ys[self.cur_order[self.batch_start: batch_end], ...] + self.batch_start += actual_batch_size + if actual_batch_size < batch_size: + print('actual_batch_size < batch_size, padding with zeros') + batch_xs_pad = np.zeros(shape=(batch_size - actual_batch_size, batch_xs.shape[1], batch_xs.shape[2], batch_xs.shape[3]), dtype=batch_xs.dtype) + batch_ys_pad = np.zeros(batch_size - actual_batch_size, dtype=batch_ys.dtype) + batch_xs = np.concatenate([batch_xs, batch_xs_pad], axis=0) + batch_ys = np.concatenate([batch_ys, batch_ys_pad], axis=0) + return batch_xs, batch_ys + actual_batch_size = min(batch_size, self.n - self.batch_start) + if actual_batch_size < batch_size: + if reshuffle_after_pass: + self.cur_order = np.random.permutation(self.n) + self.batch_start = 0 + batch_end = self.batch_start + batch_size + batch_xs = self.xs[self.cur_order[self.batch_start: batch_end], ...] + batch_ys = self.ys[self.cur_order[self.batch_start: batch_end], ...] + self.batch_start += actual_batch_size + return batch_xs, batch_ys + + +class AugmentedDataSubset(object): + def __init__(self, raw_datasubset, sess, x_input_placeholder, + augmented): + self.sess = sess + self.raw_datasubset = raw_datasubset + self.x_input_placeholder = x_input_placeholder + self.augmented = augmented + + def get_next_batch(self, batch_size, multiple_passes=False, reshuffle_after_pass=True): + raw_batch = self.raw_datasubset.get_next_batch(batch_size, multiple_passes, + reshuffle_after_pass) + images = raw_batch[0].astype(np.float32) + return self.sess.run(self.augmented, feed_dict={self.x_input_placeholder: + raw_batch[0]}), raw_batch[1] diff --git a/case_studies/curriculum_at/config_attack.py b/case_studies/curriculum_at/config_attack.py new file mode 100644 index 0000000..2c87665 --- /dev/null +++ b/case_studies/curriculum_at/config_attack.py @@ -0,0 +1,68 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import configargparse +import pdb + +def pair(arg): + return [float(x) for x in arg.split(',')] + +def get_args(): + parser = configargparse.ArgParser(default_config_files=[]) + parser.add("--model_dir", type=str, default="checkpoints/tf_curriculum_at/modelGTP_cifar10/", help="Path to save/load the checkpoints, default=models/model") + parser.add("--data_path", type=str, default="data/cifar-10-batches-py/", help="Path to dataset, default=datasets/cifar10") + parser.add("--tf_seed", type=int, default=451760341, help="Random seed for initializing tensor-flow variables to rule out the effect of randomness in experiments, default=45160341") + parser.add("--np_seed", type=int, default=216105420, help="Random seed for initializing numpy variables to rule out the effect of randomness in experiments, default=216105420") + parser.add("--num_eval_examples", type=int, default=10000, help="Number of eval samples, default=10000") + parser.add("--eval_batch_size", type=int, default=512, help="Eval batch size, default=100") + parser.add("--epsilon", "-e", type=float, default=8.0, help="Epsilon (Lp Norm distance from the original image) for generating adversarial examples, default=8.0") + parser.add("--num_steps", type=int, default=10, help="Number of steps to PGD attack, default=10") + parser.add("--ckpt", type=int, default = 0, help = "Checkpoint number for midway evaluation, default = 0") + parser.add("--step_size", "-s", type=float, default=2.0, help="Step size in PGD attack for generating adversarial examples in each step, default=2.0") + parser.add("--random_start", dest="random_start", action="store_true", help="Random start for PGD attack default=True") + parser.add("--no-random_start", dest="random_start", action="store_false", help="No random start for PGD attack default=True") + parser.set_defaults(random_start=True) + parser.add("--loss_func", "-f", type=str, default="xent", choices=["logit-diff", "xent", "target_task_xent"], help="Loss function for the model, choices are [xent, target_task_xent], default=xent") + parser.add("--attack_norm", type=str, default="inf", choices=["", "inf", "2", "TRADES"], help="Lp norm type for attacks, choices are [inf, 2], default=inf") + parser.add("--dataset", "-d", type=str, default="cifar10", choices=["cifar10", "cifar100", "tinyimagenet"], help="Path to load dataset, default=cifar10") + parser.add("--store_adv_path", type=str, default=None, help="Path to save adversarial examples, default=None") + parser.add("--attack_name", type=str, default=None, help="Path to save adversarial examples, default=''") + parser.add("--save_eval_log", dest="save_eval_log", action="store_true", help="Save txt file for attack eval") + parser.add("--no-save_eval_log", dest="save_eval_log", action="store_false", help="Save txt file for attack eval") + parser.set_defaults(save_eval_log=False) + + parser.add("--xfer_attack", dest="xfer_attack", action="store_true", help="Adversarial transfer attack") + parser.add("--no-xfer_attack", dest="xfer_attack", action="store_false", help="not adversarial transfer attack") + parser.set_defaults(xfer_attack=False) + parser.add("--custom_output_model_name", type=str, default=None, help="Custom model name, default=None") + + # for binarization test + parser.add("--n_boundary_points", default=None, type=int) + parser.add("--n_inner_points", default=None, type=int) + parser.add("--sample-from-corners", action="store_true") + + parser.add("--save_data_path", default=None, type=str) + + parser.add("--inference_mode", default="train", choices=("train", "eval"), type=str) + + args = parser.parse_args() + return args + + +if __name__ == "__main__": + print(get_args()) + pdb.set_trace() + +# TODO Default for model_dir +# TODO Need to update the helps diff --git a/case_studies/curriculum_at/eval_attack.py b/case_studies/curriculum_at/eval_attack.py new file mode 100644 index 0000000..343ff01 --- /dev/null +++ b/case_studies/curriculum_at/eval_attack.py @@ -0,0 +1,25 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from datetime import datetime +import subprocess + +directory = "models/modelGTP_cifar10" +subprocess.run("python PGD_attack.py -d cifar10 --data_path datasets/cifar10 --attack_name fgsm --save_eval_log --num_steps 1 --no-random_start --step_size 8 --model_dir {} ; python run_attack.py -d cifar10 --data_path datasets/cifar10 --attack_name fgsm --save_eval_log --model_dir {} ; python PGD_attack.py -d cifar10 --data_path datasets/cifar10 --attack_name pgds5 --save_eval_log --num_steps 5 --model_dir {} ; python run_attack.py -d cifar10 --data_path datasets/cifar10 --attack_name pgds5 --save_eval_log --num_steps 5 --model_dir {} ; python PGD_attack.py -d cifar10 --data_path datasets/cifar10 --attack_name pgds10 --save_eval_log --num_steps 10 --model_dir {} ; python run_attack.py -d cifar10 --data_path datasets/cifar10 --attack_name pgds10 --save_eval_log --num_steps 10 --model_dir {} ; python PGD_attack.py -d cifar10 --data_path datasets/cifar10 --attack_name pgds20 --save_eval_log --num_steps 20 --model_dir {} ; python run_attack.py -d cifar10 --data_path datasets/cifar10 --attack_name pgds20 --save_eval_log --num_steps 20 --model_dir {}".format(directory, directory, directory, directory, directory, directory, directory, directory, directory, directory), shell=True) +print("{}: Ended evaluation on fgsm and pgd attacks".format(datetime.now())) + diff --git a/case_studies/curriculum_at/model_new.py b/case_studies/curriculum_at/model_new.py new file mode 100644 index 0000000..c98fd24 --- /dev/null +++ b/case_studies/curriculum_at/model_new.py @@ -0,0 +1,1427 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +# based on https://github.com/tensorflow/models/tree/master/resnet +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np +import tensorflow as tf +import json +from collections import OrderedDict + + +class Model(object): + """ResNet model.""" + + def __init__(self, mode, dataset, train_batch_size=None, normalize_zero_mean=True, use_pert=False): + """ResNet constructor. + + Args: + mode: One of 'train' and 'eval'. + """ + self.neck = None + self.y_pred = None + self.mode = mode + self.dataset = dataset + self.pert = True if (mode == 'train' and use_pert) else False + if dataset == "cifar10": + self.num_classes = 10 + elif dataset == "cifar100": + self.num_classes = 100 + elif dataset == "GTSRB": + self.num_classes = 43 + else: + self.num_classes = 200 + self.train_batch_size = train_batch_size + self.activations = [] + self.normalize_zero_mean = normalize_zero_mean + self._build_model() + + def add_internal_summaries(self): + pass + + def _stride_arr(self, stride): + """Map a stride scalar to the stride array for tf.nn.conv2d.""" + return [1, stride, stride, 1] + + def _build_model(self): + assert self.mode == 'train' or self.mode == 'eval' + """Build the core model within the graph.""" + with tf.variable_scope('classifier'): + with tf.variable_scope('input'): + + if self.dataset == 'cifar10' or self.dataset == 'cifar100' or self.dataset == 'GTSRB': + self.x_input = tf.placeholder( + tf.float32, + shape=[None, 32, 32, 3]) + else: + self.x_input = tf.placeholder( + tf.float32, + shape=[None, 64, 64, 3]) + + self.y_input = tf.placeholder(tf.int64, shape=None) + + if self.pert: + self.pert = tf.get_variable(name='instance_perturbation', initializer=tf.zeros_initializer, + shape=[self.train_batch_size, 32, 32, 3], dtype=tf.float32, + trainable=True) + self.final_input = self.x_input + self.pert + self.final_input = tf.clip_by_value(self.final_input, 0., 255.) + else: + self.final_input = self.x_input + + if self.normalize_zero_mean: + final_input_mean = tf.reduce_mean(self.final_input, axis=[1,2,3]) + for i in range(3): + final_input_mean = tf.expand_dims(final_input_mean, axis=-1) + final_input_mean = tf.tile(final_input_mean, [1,32,32,3]) + zero_mean_final_input = self.final_input - final_input_mean + self.input_standardized = tf.math.l2_normalize(zero_mean_final_input, axis=[1,2,3]) + else: + self.input_standardized = tf.math.l2_normalize(self.final_input, axis=[1,2,3]) + + x = self._conv('init_conv', self.input_standardized, 3, 3, 16, self._stride_arr(1)) + self.activations.append(x) + + strides = [1, 2, 2] + activate_before_residual = [True, False, False] + res_func = self._residual + + # Uncomment the following codes to use w28-10 wide residual network. + # It is more memory efficient than very deep residual network and has + # comparably good performance. + # https://arxiv.org/pdf/1605.07146v1.pdf + # filters = [16, 16, 32, 64] # for debugging + filters = [16, 160, 320, 640] + + # Update hps.num_residual_units to 9 + + with tf.variable_scope('unit_1_0'): + x = res_func(x, filters[0], filters[1], self._stride_arr(strides[0]), + activate_before_residual[0]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_1_%d' % i): + x = res_func(x, filters[1], filters[1], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_2_0'): + x = res_func(x, filters[1], filters[2], self._stride_arr(strides[1]), + activate_before_residual[1]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_2_%d' % i): + x = res_func(x, filters[2], filters[2], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_3_0'): + x = res_func(x, filters[2], filters[3], self._stride_arr(strides[2]), + activate_before_residual[2]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_3_%d' % i): + x = res_func(x, filters[3], filters[3], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_last'): + x = self._batch_norm('final_bn', x) + x = self._relu(x, 0.1) + x = self._global_avg_pool(x) + self.neck = x + + with tf.variable_scope('logit'): + self.pre_softmax = self._fully_connected(x, self.num_classes) + self.activations.append(self.pre_softmax) + self.softmax = tf.nn.softmax(self.pre_softmax) + + sample_indices = tf.range(self.train_batch_size, dtype=tf.int64) + sample_indices = tf.expand_dims(sample_indices, axis=-1) + target_indices = tf.expand_dims(self.y_input, axis=-1) + self.gather_indices = tf.concat([sample_indices, target_indices], axis=-1) + self.target_softmax = tf.gather_nd(self.softmax, self.gather_indices, name="targetsoftmax") + # target logit is independent of other class logits while target softmax value is + self.target_logit = tf.gather_nd(self.pre_softmax, self.gather_indices, name="targetlogit") + + self.predictions = tf.argmax(self.pre_softmax, 1) + self.y_pred = self.predictions + self.correct_prediction = tf.equal(self.predictions, self.y_input) + self.num_correct = tf.reduce_sum(tf.cast(self.correct_prediction, tf.int64)) + self.accuracy = tf.reduce_mean(tf.cast(self.correct_prediction, tf.float32)) + + self.feature_grad = tf.gradients(self.neck, self.x_input)[0] + + with tf.variable_scope('costs'): + self.y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent = tf.reduce_sum(self.y_xent, name='y_xent') + self.mean_xent = tf.reduce_mean(self.y_xent) + self.y_xent_dbp = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent_dbp = tf.reduce_sum(self.y_xent_dbp, name='y_xent_dbp') + self.mean_xent_dbp = tf.reduce_mean(self.y_xent_dbp) + self.weight_decay_loss = self._decay() + self.temploss = tf.reduce_sum(-tf.multiply(tf.one_hot(self.y_input, self.num_classes), tf.log(tf.clip_by_value(self.softmax, 1e-10, 1.0))), axis = 1) + + # for top-2 logit diff loss + self.label_mask = tf.one_hot(self.y_input, + self.num_classes, + on_value=1.0, + off_value=0.0, + dtype=tf.float32) + self.correct_logit = tf.reduce_sum(self.label_mask * self.pre_softmax, axis=1) + self.wrong_logit = tf.reduce_max((1-self.label_mask) * self.pre_softmax - 1e4*self.label_mask, axis=1) + self.top2_logit_diff_loss = -tf.nn.relu(self.correct_logit - self.wrong_logit + 50) + + def _batch_norm(self, name, x): + """Batch normalization.""" + with tf.name_scope(name): + return tf.contrib.layers.batch_norm(inputs=x, decay=.9, center=True, scale=True, activation_fn=None, + updates_collections=None, is_training=(self.mode == 'train')) + + def _residual(self, x, in_filter, out_filter, stride, activate_before_residual=False): + """Residual unit with 2 sub layers.""" + if activate_before_residual: + with tf.variable_scope('shared_activation'): + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + orig_x = x + else: + with tf.variable_scope('residual_only_activation'): + orig_x = x + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + + with tf.variable_scope('sub1'): + x = self._conv('conv1', x, 3, in_filter, out_filter, stride) + + with tf.variable_scope('sub2'): + x = self._batch_norm('bn2', x) + x = self._relu(x, 0.1) + x = self._conv('conv2', x, 3, out_filter, out_filter, [1, 1, 1, 1]) + + with tf.variable_scope('sub_add'): + if in_filter != out_filter: + orig_x = tf.nn.avg_pool(orig_x, stride, stride, 'VALID') + orig_x = tf.pad( + orig_x, [[0, 0], [0, 0], [0, 0], + [(out_filter - in_filter) // 2, (out_filter - in_filter) // 2]]) + x += orig_x + + tf.logging.debug('image after unit %s', x.get_shape()) + return x + + def _decay(self): + """L2 weight decay loss.""" + costs = [] + for var in tf.trainable_variables(): + if var.op.name.find('DW') > 0: + costs.append(tf.nn.l2_loss(var)) + return tf.add_n(costs) + + def _conv(self, name, x, filter_size, in_filters, out_filters, strides): + """Convolution.""" + with tf.variable_scope(name): + n = filter_size * filter_size * out_filters + kernel = tf.get_variable( + 'DW', [filter_size, filter_size, in_filters, out_filters], + tf.float32, initializer=tf.random_normal_initializer( + stddev=np.sqrt(2.0 / n))) + return tf.nn.conv2d(x, kernel, strides, padding='SAME') + + def _relu(self, x, leakiness=0.0): + """Relu, with optional leaky support.""" + return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu') + + def _fully_connected(self, x, out_dim): + """FullyConnected layer for final output.""" + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + + def _global_avg_pool(self, x): + assert x.get_shape().ndims == 4 + return tf.reduce_mean(x, [1, 2]) + + +class ModelTinyImagnet(object): + """ResNet model.""" + + def __init__(self, mode, dataset, train_batch_size=None, normalize_zero_mean=False, use_pert=False): + """ResNet constructor. + + Args: + mode: One of 'train' and 'eval'. + """ + self.neck = None + self.y_pred = None + self.mode = mode + self.pert = True if (mode == 'train' and use_pert) else False + if dataset == 'tinyimagenet': + self.num_classes = 200 + self.input_size = 64 + elif dataset == 'cifar100': + self.num_classes = 100 + self.input_size = 32 + else: + self.num_classes = 10 + self.input_size = 32 + self.train_batch_size = train_batch_size + self.activations = [] + self.normalize_zero_mean = normalize_zero_mean + self._build_model() + + def add_internal_summaries(self): + pass + + def _stride_arr(self, stride): + """Map a stride scalar to the stride array for tf.nn.conv2d.""" + return [1, stride, stride, 1] + + def _build_model(self): + assert self.mode == 'train' or self.mode == 'eval' + """Build the core model within the graph.""" + with tf.variable_scope('classifier'): + with tf.variable_scope('input'): + + self.x_input = tf.placeholder( + tf.float32, + shape=[None, self.input_size, self.input_size, 3]) + + self.y_input = tf.placeholder(tf.int64, shape=None) + + if self.pert: + self.pert = tf.get_variable(name='instance_perturbation', initializer=tf.zeros_initializer, + shape=[self.train_batch_size, self.input_size, self.input_size, 3], dtype=tf.float32, + trainable=True) + self.final_input = self.x_input + self.pert + self.final_input = tf.clip_by_value(self.final_input, 0., 255.) + else: + self.final_input = self.x_input + + if self.normalize_zero_mean: + final_input_mean = tf.reduce_mean(self.final_input, axis=[1,2,3]) + for i in range(3): + final_input_mean = tf.expand_dims(final_input_mean, axis=-1) + final_input_mean = tf.tile(final_input_mean, [1,self.input_size,self.input_size,3]) + zero_mean_final_input = self.final_input - final_input_mean + self.input_standardized = tf.math.l2_normalize(zero_mean_final_input, axis=[1,2,3]) + else: + self.input_standardized = tf.math.l2_normalize(self.final_input, axis=[1,2,3]) + + x = self._conv('init_conv', self.input_standardized, 3, 3, 16, self._stride_arr(1)) + self.activations.append(x) + + strides = [1, 2, 2] + activate_before_residual = [True, False, False] + res_func = self._residual + + # Uncomment the following codes to use w28-10 wide residual network. + # It is more memory efficient than very deep residual network and has + # comparably good performance. + # https://arxiv.org/pdf/1605.07146v1.pdf + # filters = [16, 16, 32, 64] # for debugging + filters = [16, 160, 320, 640] + + # Update hps.num_residual_units to 9 + + with tf.variable_scope('unit_1_0'): + x = res_func(x, filters[0], filters[1], self._stride_arr(strides[0]), + activate_before_residual[0]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_1_%d' % i): + x = res_func(x, filters[1], filters[1], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_2_0'): + x = res_func(x, filters[1], filters[2], self._stride_arr(strides[1]), + activate_before_residual[1]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_2_%d' % i): + x = res_func(x, filters[2], filters[2], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_3_0'): + x = res_func(x, filters[2], filters[3], self._stride_arr(strides[2]), + activate_before_residual[2]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_3_%d' % i): + x = res_func(x, filters[3], filters[3], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_last'): + x = self._batch_norm('final_bn', x) + x = self._relu(x, 0.1) + x = self._global_avg_pool(x) + self.neck = x + + with tf.variable_scope('logit'): + self.pre_softmax = self._fully_connected(x, self.num_classes) + self.activations.append(self.pre_softmax) + self.softmax = tf.nn.softmax(self.pre_softmax) + # y_one_hot = tf.one_hot(self.y_input, self.num_classes) + # self.target_softmax = self.softmax * y_one_hot + + sample_indices = tf.range(self.train_batch_size, dtype=tf.int64) + sample_indices = tf.expand_dims(sample_indices, axis=-1) + target_indices = tf.expand_dims(self.y_input, axis=-1) + self.gather_indices = tf.concat([sample_indices, target_indices], axis=-1) + self.target_softmax = tf.gather_nd(self.softmax, self.gather_indices, name="targetsoftmax") + # target logit is independent of other class logits while target softmax value is + self.target_logit = tf.gather_nd(self.pre_softmax, self.gather_indices, name="targetlogit") + + self.predictions = tf.argmax(self.pre_softmax, 1) + self.y_pred = self.predictions + self.correct_prediction = tf.equal(self.predictions, self.y_input) + self.num_correct = tf.reduce_sum(tf.cast(self.correct_prediction, tf.int64)) + self.accuracy = tf.reduce_mean(tf.cast(self.correct_prediction, tf.float32)) + + with tf.variable_scope('costs'): + self.y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent = tf.reduce_sum(self.y_xent, name='y_xent') + self.mean_xent = tf.reduce_mean(self.y_xent) + self.weight_decay_loss = self._decay() + self.temploss = tf.reduce_sum(-tf.multiply(tf.one_hot(self.y_input, self.num_classes), tf.log(tf.clip_by_value(self.softmax, 1e-10, 1.0))), axis = 1) + + # for top-2 logit diff loss + self.label_mask = tf.one_hot(self.y_input, + self.num_classes, + on_value=1.0, + off_value=0.0, + dtype=tf.float32) + self.correct_logit = tf.reduce_sum(self.label_mask * self.pre_softmax, axis=1) + self.wrong_logit = tf.reduce_max((1-self.label_mask) * self.pre_softmax - 1e4*self.label_mask, axis=1) + self.top2_logit_diff_loss = -tf.nn.relu(self.correct_logit - self.wrong_logit + 50) + + def _batch_norm(self, name, x): + """Batch normalization.""" + with tf.name_scope(name): + return tf.contrib.layers.batch_norm(inputs=x, decay=.9, center=True, scale=True, activation_fn=None, + updates_collections=None, is_training=(self.mode == 'train')) + + def _residual(self, x, in_filter, out_filter, stride, activate_before_residual=False): + """Residual unit with 2 sub layers.""" + if activate_before_residual: + with tf.variable_scope('shared_activation'): + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + orig_x = x + else: + with tf.variable_scope('residual_only_activation'): + orig_x = x + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + + with tf.variable_scope('sub1'): + x = self._conv('conv1', x, 3, in_filter, out_filter, stride) + + with tf.variable_scope('sub2'): + x = self._batch_norm('bn2', x) + x = self._relu(x, 0.1) + x = self._conv('conv2', x, 3, out_filter, out_filter, [1, 1, 1, 1]) + + with tf.variable_scope('sub_add'): + if in_filter != out_filter: + orig_x = tf.nn.avg_pool(orig_x, stride, stride, 'VALID') + orig_x = tf.pad( + orig_x, [[0, 0], [0, 0], [0, 0], + [(out_filter - in_filter) // 2, (out_filter - in_filter) // 2]]) + x += orig_x + + tf.logging.debug('image after unit %s', x.get_shape()) + return x + + def _decay(self): + """L2 weight decay loss.""" + costs = [] + for var in tf.trainable_variables(): + if var.op.name.find('DW') > 0: + costs.append(tf.nn.l2_loss(var)) + return tf.add_n(costs) + + def _conv(self, name, x, filter_size, in_filters, out_filters, strides): + """Convolution.""" + with tf.variable_scope(name): + n = filter_size * filter_size * out_filters + kernel = tf.get_variable( + 'DW', [filter_size, filter_size, in_filters, out_filters], + tf.float32, initializer=tf.random_normal_initializer( + stddev=np.sqrt(2.0 / n))) + return tf.nn.conv2d(x, kernel, strides, padding='SAME') + + def _relu(self, x, leakiness=0.0): + """Relu, with optional leaky support.""" + return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu') + + def _fully_connected(self, x, out_dim): + """FullyConnected layer for final output.""" + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + + def _global_avg_pool(self, x): + assert x.get_shape().ndims == 4 + return tf.reduce_mean(x, [1, 2]) + +class ModelTinyImagenetSource(object): + """ResNet model.""" + + def __init__(self, mode, dataset, train_batch_size=None, normalize_zero_mean=False, use_pert=False): + """ResNet constructor. + + Args: + mode: One of 'train' and 'eval'. + """ + self.neck = None + self.y_pred = None + self.mode = mode + self.pert = True if (mode == 'train' and use_pert) else False + if dataset == 'tinyimagenet': + self.num_classes = 200 + self.input_size = 64 + elif dataset == 'cifar100': + self.num_classes = 100 + self.input_size = 32 + else: + self.num_classes = 10 + self.input_size = 32 + self.train_batch_size = train_batch_size + self.activations = [] + self.normalize_zero_mean = normalize_zero_mean + self._build_model() + + def add_internal_summaries(self): + pass + + def _stride_arr(self, stride): + """Map a stride scalar to the stride array for tf.nn.conv2d.""" + return [1, stride, stride, 1] + + def _build_model(self): + assert self.mode == 'train' or self.mode == 'eval' + """Build the core model within the graph.""" + with tf.variable_scope('input'): + + self.x_input = tf.placeholder( + tf.float32, + shape=[None, self.input_size, self.input_size, 3]) + + self.y_input = tf.placeholder(tf.int64, shape=None) + + if self.pert: + self.pert = tf.get_variable(name='instance_perturbation', initializer=tf.zeros_initializer, + shape=[self.train_batch_size, self.input_size, self.input_size, 3], dtype=tf.float32, + trainable=True) + self.final_input = self.x_input + self.pert + self.final_input = tf.clip_by_value(self.final_input, 0., 255.) + else: + self.final_input = self.x_input + + if self.normalize_zero_mean: + final_input_mean = tf.reduce_mean(self.final_input, axis=[1,2,3]) + for i in range(3): + final_input_mean = tf.expand_dims(final_input_mean, axis=-1) + final_input_mean = tf.tile(final_input_mean, [1,self.input_size,self.input_size,3]) + zero_mean_final_input = self.final_input - final_input_mean + self.input_standardized = tf.math.l2_normalize(zero_mean_final_input, axis=[1,2,3]) + else: + self.input_standardized = tf.math.l2_normalize(self.final_input, axis=[1,2,3]) + + x = self._conv('init_conv', self.input_standardized, 3, 3, 16, self._stride_arr(1)) + self.activations.append(x) + + strides = [1, 2, 2] + activate_before_residual = [True, False, False] + res_func = self._residual + + # Uncomment the following codes to use w28-10 wide residual network. + # It is more memory efficient than very deep residual network and has + # comparably good performance. + # https://arxiv.org/pdf/1605.07146v1.pdf + # filters = [16, 16, 32, 64] # for debugging + filters = [16, 160, 320, 640] + + # Update hps.num_residual_units to 9 + + with tf.variable_scope('unit_1_0'): + x = res_func(x, filters[0], filters[1], self._stride_arr(strides[0]), + activate_before_residual[0]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_1_%d' % i): + x = res_func(x, filters[1], filters[1], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_2_0'): + x = res_func(x, filters[1], filters[2], self._stride_arr(strides[1]), + activate_before_residual[1]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_2_%d' % i): + x = res_func(x, filters[2], filters[2], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_3_0'): + x = res_func(x, filters[2], filters[3], self._stride_arr(strides[2]), + activate_before_residual[2]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_3_%d' % i): + x = res_func(x, filters[3], filters[3], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_last'): + x = self._batch_norm('final_bn', x) + x = self._relu(x, 0.1) + x = self._global_avg_pool(x) + self.neck = x + + with tf.variable_scope('logit'): + self.pre_softmax = self._fully_connected(x, self.num_classes) + self.activations.append(self.pre_softmax) + self.softmax = tf.nn.softmax(self.pre_softmax) + + sample_indices = tf.range(self.train_batch_size, dtype=tf.int64) + sample_indices = tf.expand_dims(sample_indices, axis=-1) + target_indices = tf.expand_dims(self.y_input, axis=-1) + self.gather_indices = tf.concat([sample_indices, target_indices], axis=-1) + self.target_softmax = tf.gather_nd(self.softmax, self.gather_indices, name="targetsoftmax") + # target logit is independent of other class logits while target softmax value is + self.target_logit = tf.gather_nd(self.pre_softmax, self.gather_indices, name="targetlogit") + + self.predictions = tf.argmax(self.pre_softmax, 1) + self.y_pred = self.predictions + self.correct_prediction = tf.equal(self.predictions, self.y_input) + self.num_correct = tf.reduce_sum(tf.cast(self.correct_prediction, tf.int64)) + self.accuracy = tf.reduce_mean(tf.cast(self.correct_prediction, tf.float32)) + + with tf.variable_scope('costs'): + self.y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent = tf.reduce_sum(self.y_xent, name='y_xent') + self.mean_xent = tf.reduce_mean(self.y_xent) + self.weight_decay_loss = self._decay() + + # for top-2 logit diff loss + self.label_mask = tf.one_hot(self.y_input, + self.num_classes, + on_value=1.0, + off_value=0.0, + dtype=tf.float32) + self.correct_logit = tf.reduce_sum(self.label_mask * self.pre_softmax, axis=1) + self.wrong_logit = tf.reduce_max((1-self.label_mask) * self.pre_softmax - 1e4*self.label_mask, axis=1) + self.top2_logit_diff_loss = -tf.nn.relu(self.correct_logit - self.wrong_logit + 50) + + def _batch_norm(self, name, x): + """Batch normalization.""" + with tf.name_scope(name): + return tf.contrib.layers.batch_norm(inputs=x, decay=.9, center=True, scale=True, activation_fn=None, + updates_collections=None, is_training=(self.mode == 'train')) + + def _residual(self, x, in_filter, out_filter, stride, activate_before_residual=False): + """Residual unit with 2 sub layers.""" + if activate_before_residual: + with tf.variable_scope('shared_activation'): + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + orig_x = x + else: + with tf.variable_scope('residual_only_activation'): + orig_x = x + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + + with tf.variable_scope('sub1'): + x = self._conv('conv1', x, 3, in_filter, out_filter, stride) + + with tf.variable_scope('sub2'): + x = self._batch_norm('bn2', x) + x = self._relu(x, 0.1) + x = self._conv('conv2', x, 3, out_filter, out_filter, [1, 1, 1, 1]) + + with tf.variable_scope('sub_add'): + if in_filter != out_filter: + orig_x = tf.nn.avg_pool(orig_x, stride, stride, 'VALID') + orig_x = tf.pad( + orig_x, [[0, 0], [0, 0], [0, 0], + [(out_filter - in_filter) // 2, (out_filter - in_filter) // 2]]) + x += orig_x + + tf.logging.debug('image after unit %s', x.get_shape()) + return x + + def _decay(self): + """L2 weight decay loss.""" + costs = [] + for var in tf.trainable_variables(): + if var.op.name.find('DW') > 0: + costs.append(tf.nn.l2_loss(var)) + return tf.add_n(costs) + + def _conv(self, name, x, filter_size, in_filters, out_filters, strides): + """Convolution.""" + with tf.variable_scope(name): + n = filter_size * filter_size * out_filters + kernel = tf.get_variable( + 'DW', [filter_size, filter_size, in_filters, out_filters], + tf.float32, initializer=tf.random_normal_initializer( + stddev=np.sqrt(2.0 / n))) + return tf.nn.conv2d(x, kernel, strides, padding='SAME') + + def _relu(self, x, leakiness=0.0): + """Relu, with optional leaky support.""" + return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu') + + def _fully_connected(self, x, out_dim): + """FullyConnected layer for final output.""" + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + + def _global_avg_pool(self, x): + assert x.get_shape().ndims == 4 + return tf.reduce_mean(x, [1, 2]) + +class ModelTinyImagenetSourceExtendedLogits(object): + """ResNet model.""" + + def __init__(self, mode, dataset, train_batch_size=None, normalize_zero_mean=False, use_pert=False, target_task_class_num=10, input_tensor=None): + """ResNet constructor. + + Args: + mode: One of 'train' and 'eval'. + """ + self.neck = None + self.y_pred = None + self.mode = mode + self.pert = True if (mode == 'train' and use_pert) else False + if dataset == 'tinyimagenet': + self.num_classes = 200 + self.input_size = 64 + elif dataset == 'cifar100': + self.num_classes = 100 + self.input_size = 32 + else: + self.num_classes = 10 + self.input_size = 32 + self.train_batch_size = train_batch_size + self.activations = [] + self.normalize_zero_mean = normalize_zero_mean + self.input_tensor = input_tensor + self.target_task_class_num = target_task_class_num + self._build_model() + + def add_internal_summaries(self): + pass + + def _stride_arr(self, stride): + """Map a stride scalar to the stride array for tf.nn.conv2d.""" + return [1, stride, stride, 1] + + def _build_model(self): + assert self.mode == 'train' or self.mode == 'eval' + """Build the core model within the graph.""" + with tf.variable_scope('input'): + if self.input_tensor == None: + self.x_input = tf.placeholder( + tf.float32, + shape=[None, self.input_size, self.input_size, 3]) + else: + self.x_input = self.input_tensor + + self.y_input = tf.placeholder(tf.int64, shape=None) + + if self.pert: + self.pert = tf.get_variable(name='instance_perturbation', initializer=tf.zeros_initializer, + shape=[self.train_batch_size, self.input_size, self.input_size, 3], dtype=tf.float32, + trainable=True) + self.final_input = self.x_input + self.pert + self.final_input = tf.clip_by_value(self.final_input, 0., 255.) + else: + self.final_input = self.x_input + + if self.normalize_zero_mean: + final_input_mean = tf.reduce_mean(self.final_input, axis=[1,2,3]) + for i in range(3): + final_input_mean = tf.expand_dims(final_input_mean, axis=-1) + final_input_mean = tf.tile(final_input_mean, [1,self.input_size,self.input_size,3]) + zero_mean_final_input = self.final_input - final_input_mean + self.input_standardized = tf.math.l2_normalize(zero_mean_final_input, axis=[1,2,3]) + else: + self.input_standardized = tf.math.l2_normalize(self.final_input, axis=[1,2,3]) + + x = self._conv('init_conv', self.input_standardized, 3, 3, 16, self._stride_arr(1)) + self.activations.append(x) + + strides = [1, 2, 2] + activate_before_residual = [True, False, False] + res_func = self._residual + + # Uncomment the following codes to use w28-10 wide residual network. + # It is more memory efficient than very deep residual network and has + # comparably good performance. + # https://arxiv.org/pdf/1605.07146v1.pdf + # filters = [16, 16, 32, 64] # for debugging + filters = [16, 160, 320, 640] + + # Update hps.num_residual_units to 9 + + with tf.variable_scope('unit_1_0'): + x = res_func(x, filters[0], filters[1], self._stride_arr(strides[0]), + activate_before_residual[0]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_1_%d' % i): + x = res_func(x, filters[1], filters[1], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_2_0'): + x = res_func(x, filters[1], filters[2], self._stride_arr(strides[1]), + activate_before_residual[1]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_2_%d' % i): + x = res_func(x, filters[2], filters[2], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_3_0'): + x = res_func(x, filters[2], filters[3], self._stride_arr(strides[2]), + activate_before_residual[2]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_3_%d' % i): + x = res_func(x, filters[3], filters[3], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_last'): + x = self._batch_norm('final_bn', x) + x = self._relu(x, 0.1) + x = self._global_avg_pool(x) + self.neck = x + + with tf.variable_scope('logit'): + self.pre_softmax = self._fully_connected(x, self.num_classes) + self.activations.append(self.pre_softmax) + self.softmax = tf.nn.softmax(self.pre_softmax) + + sample_indices = tf.range(self.train_batch_size, dtype=tf.int64) + sample_indices = tf.expand_dims(sample_indices, axis=-1) + target_indices = tf.expand_dims(self.y_input, axis=-1) + self.gather_indices = tf.concat([sample_indices, target_indices], axis=-1) + self.target_softmax = tf.gather_nd(self.softmax, self.gather_indices, name="targetsoftmax") + # target logit is independent of other class logits while target softmax value is + self.target_logit = tf.gather_nd(self.pre_softmax, self.gather_indices, name="targetlogit") + + self.predictions = tf.argmax(self.pre_softmax, 1) + self.y_pred = self.predictions + self.correct_prediction = tf.equal(self.predictions, self.y_input) + self.num_correct = tf.reduce_sum(tf.cast(self.correct_prediction, tf.int64)) + self.accuracy = tf.reduce_mean(tf.cast(self.correct_prediction, tf.float32)) + + with tf.variable_scope('costs'): + self.y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent = tf.reduce_sum(self.y_xent, name='y_xent') + self.mean_xent = tf.reduce_mean(self.y_xent) + self.weight_decay_loss = self._decay() + + # for top-2 logit diff loss + self.label_mask = tf.one_hot(self.y_input, + self.num_classes, + on_value=1.0, + off_value=0.0, + dtype=tf.float32) + self.correct_logit = tf.reduce_sum(self.label_mask * self.pre_softmax, axis=1) + self.wrong_logit = tf.reduce_max((1-self.label_mask) * self.pre_softmax - 1e4*self.label_mask, axis=1) + self.top2_logit_diff_loss = -tf.nn.relu(self.correct_logit - self.wrong_logit + 50) + + with tf.variable_scope('target_task_logit'): + self.target_task_pre_softmax = self._fully_connected(x, self.target_task_class_num) + + self.target_task_softmax = tf.nn.softmax(self.target_task_pre_softmax) + sample_indices = tf.range(self.train_batch_size, dtype=tf.int64) + sample_indices = tf.expand_dims(sample_indices, axis=-1) + target_indices = tf.expand_dims(self.y_input, axis=-1) + self.gather_indices = tf.concat([sample_indices, target_indices], axis=-1) + self.target_softmax = tf.gather_nd(self.target_task_softmax, self.gather_indices, name="targetsoftmax") + + self.target_task_predictions = tf.argmax(self.target_task_pre_softmax, 1) + self.target_task_correct_prediction = tf.equal(self.target_task_predictions, self.y_input) + self.target_task_num_correct = tf.reduce_sum( + tf.cast(self.target_task_correct_prediction, tf.int64)) + self.target_task_accuracy = tf.reduce_mean( + tf.cast(self.target_task_correct_prediction, tf.float32)) + + with tf.variable_scope('target_task_costs'): + self.target_task_y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.target_task_pre_softmax, labels=self.y_input) + self.target_task_xent = tf.reduce_sum(self.target_task_y_xent, name='target_task_y_xent') + self.target_task_mean_xent = tf.reduce_mean(self.target_task_y_xent) + + def _batch_norm(self, name, x): + """Batch normalization.""" + with tf.name_scope(name): + return tf.contrib.layers.batch_norm(inputs=x, decay=.9, center=True, scale=True, activation_fn=None, + updates_collections=None, is_training=(self.mode == 'train')) + + def _residual(self, x, in_filter, out_filter, stride, activate_before_residual=False): + """Residual unit with 2 sub layers.""" + if activate_before_residual: + with tf.variable_scope('shared_activation'): + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + orig_x = x + else: + with tf.variable_scope('residual_only_activation'): + orig_x = x + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + + with tf.variable_scope('sub1'): + x = self._conv('conv1', x, 3, in_filter, out_filter, stride) + + with tf.variable_scope('sub2'): + x = self._batch_norm('bn2', x) + x = self._relu(x, 0.1) + x = self._conv('conv2', x, 3, out_filter, out_filter, [1, 1, 1, 1]) + + with tf.variable_scope('sub_add'): + if in_filter != out_filter: + orig_x = tf.nn.avg_pool(orig_x, stride, stride, 'VALID') + orig_x = tf.pad( + orig_x, [[0, 0], [0, 0], [0, 0], + [(out_filter - in_filter) // 2, (out_filter - in_filter) // 2]]) + x += orig_x + + tf.logging.debug('image after unit %s', x.get_shape()) + return x + + def _decay(self): + """L2 weight decay loss.""" + costs = [] + for var in tf.trainable_variables(): + if var.op.name.find('DW') > 0: + costs.append(tf.nn.l2_loss(var)) + return tf.add_n(costs) + + def _conv(self, name, x, filter_size, in_filters, out_filters, strides): + """Convolution.""" + with tf.variable_scope(name): + n = filter_size * filter_size * out_filters + kernel = tf.get_variable( + 'DW', [filter_size, filter_size, in_filters, out_filters], + tf.float32, initializer=tf.random_normal_initializer( + stddev=np.sqrt(2.0 / n))) + return tf.nn.conv2d(x, kernel, strides, padding='SAME') + + def _relu(self, x, leakiness=0.0): + """Relu, with optional leaky support.""" + return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu') + + def _fully_connected(self, x, out_dim): + """FullyConnected layer for final output.""" + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + + def _global_avg_pool(self, x): + assert x.get_shape().ndims == 4 + return tf.reduce_mean(x, [1, 2]) + +class ModelExtendedLogitsC2I(object): + """ResNet model.""" + def __init__(self, mode, target_task_class_num=200, train_batch_size=None, input_tensor=None, source_task="cifar10"): + """ResNet constructor. + + Args: + mode: One of 'train' and 'eval'. + """ + self.mode = mode + self.activations = [] + self.target_task_class_num = target_task_class_num + self.train_batch_size = train_batch_size + self.input_tensor = input_tensor + self.source_task = source_task + self._build_model() + + def add_internal_summaries(self): + pass + + def _stride_arr(self, stride): + """Map a stride scalar to the stride array for tf.nn.conv2d.""" + return [1, stride, stride, 1] + + def _build_model(self): + assert self.mode == 'train' or self.mode == 'eval' + """Build the core model within the graph.""" + with tf.variable_scope('input'): + + if self.input_tensor == None: + self.x_input = tf.placeholder( + tf.float32, + shape=[None, 32, 32, 3]) + else: + self.x_input = self.input_tensor + + self.y_input = tf.placeholder(tf.int64, shape=None) + + + input_standardized = tf.map_fn(lambda img: tf.image.per_image_standardization(img), + self.x_input) + x = self._conv('init_conv', input_standardized, 3, 3, 16, self._stride_arr(1)) + self.activations.append(x) + + strides = [1, 2, 2] + activate_before_residual = [True, False, False] + res_func = self._residual + # Uncomment the following codes to use w28-10 wide residual network. + # It is more memory efficient than very deep residual network and has + # comparably good performance. + # https://arxiv.org/pdf/1605.07146v1.pdf + filters = [16, 160, 320, 640] + + + # Update hps.num_residual_units to 9 + + with tf.variable_scope('unit_1_0'): + x = res_func(x, filters[0], filters[1], self._stride_arr(strides[0]), + activate_before_residual[0]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_1_%d' % i): + x = res_func(x, filters[1], filters[1], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_2_0'): + x = res_func(x, filters[1], filters[2], self._stride_arr(strides[1]), + activate_before_residual[1]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_2_%d' % i): + x = res_func(x, filters[2], filters[2], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_3_0'): + x = res_func(x, filters[2], filters[3], self._stride_arr(strides[2]), + activate_before_residual[2]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_3_%d' % i): + x = res_func(x, filters[3], filters[3], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_last'): + x = self._batch_norm('final_bn', x) + x = self._relu(x, 0.1) + x = self._global_avg_pool(x) + + with tf.variable_scope('logit'): + if self.source_task == "cifar10": + self.pre_softmax = self._fully_connected(x, 10) + elif self.source_task == "cifar100": + self.pre_softmax = self._fully_connected(x, 100) + self.activations.append(self.pre_softmax) + + self.predictions = tf.argmax(self.pre_softmax, 1) + self.correct_prediction = tf.equal(self.predictions, self.y_input) + self.num_correct = tf.reduce_sum( + tf.cast(self.correct_prediction, tf.int64)) + self.accuracy = tf.reduce_mean( + tf.cast(self.correct_prediction, tf.float32)) + + with tf.variable_scope('costs'): + self.y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent = tf.reduce_sum(self.y_xent, name='y_xent') + self.mean_xent = tf.reduce_mean(self.y_xent) + self.weight_decay_loss = self._decay() + + with tf.variable_scope('target_task_logit'): + self.target_task_pre_softmax = self._fully_connected(x, self.target_task_class_num) + + self.target_task_softmax = tf.nn.softmax(self.target_task_pre_softmax) + sample_indices = tf.range(self.train_batch_size, dtype=tf.int64) + sample_indices = tf.expand_dims(sample_indices, axis=-1) + target_indices = tf.expand_dims(self.y_input, axis=-1) + self.gather_indices = tf.concat([sample_indices, target_indices], axis=-1) + self.target_softmax = tf.gather_nd(self.target_task_softmax, self.gather_indices, name="targetsoftmax") + + # self.target_task_pre_softmax = self._named_fully_connected('target_task_logit', x, self.target_task_class_num) + + self.target_task_predictions = tf.argmax(self.target_task_pre_softmax, 1) + self.target_task_correct_prediction = tf.equal(self.target_task_predictions, self.y_input) + self.target_task_num_correct = tf.reduce_sum( + tf.cast(self.target_task_correct_prediction, tf.int64)) + self.target_task_accuracy = tf.reduce_mean( + tf.cast(self.target_task_correct_prediction, tf.float32)) + + with tf.variable_scope('target_task_costs'): + self.target_task_y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.target_task_pre_softmax, labels=self.y_input) + self.target_task_xent = tf.reduce_sum(self.target_task_y_xent, name='target_task_y_xent') + self.target_task_mean_xent = tf.reduce_mean(self.target_task_y_xent) + # self.weight_decay_loss = self._decay() + + def _batch_norm(self, name, x): + """Batch normalization.""" + with tf.name_scope(name): + return tf.contrib.layers.batch_norm( + inputs=x, + decay=.9, + center=True, + scale=True, + activation_fn=None, + updates_collections=None, + is_training=(self.mode == 'train')) + + def _residual(self, x, in_filter, out_filter, stride, + activate_before_residual=False): + """Residual unit with 2 sub layers.""" + if activate_before_residual: + with tf.variable_scope('shared_activation'): + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + orig_x = x + else: + with tf.variable_scope('residual_only_activation'): + orig_x = x + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + + with tf.variable_scope('sub1'): + x = self._conv('conv1', x, 3, in_filter, out_filter, stride) + + with tf.variable_scope('sub2'): + x = self._batch_norm('bn2', x) + x = self._relu(x, 0.1) + x = self._conv('conv2', x, 3, out_filter, out_filter, [1, 1, 1, 1]) + + with tf.variable_scope('sub_add'): + if in_filter != out_filter: + orig_x = tf.nn.avg_pool(orig_x, stride, stride, 'VALID') + orig_x = tf.pad( + orig_x, [[0, 0], [0, 0], [0, 0], + [(out_filter-in_filter)//2, (out_filter-in_filter)//2]]) + x += orig_x + + tf.logging.debug('image after unit %s', x.get_shape()) + return x + + def _decay(self): + """L2 weight decay loss.""" + costs = [] + for var in tf.trainable_variables(): + if var.op.name.find('DW') > 0: + costs.append(tf.nn.l2_loss(var)) + return tf.add_n(costs) + + def _conv(self, name, x, filter_size, in_filters, out_filters, strides): + """Convolution.""" + with tf.variable_scope(name): + n = filter_size * filter_size * out_filters + kernel = tf.get_variable( + 'DW', [filter_size, filter_size, in_filters, out_filters], + tf.float32, initializer=tf.random_normal_initializer( + stddev=np.sqrt(2.0/n))) + return tf.nn.conv2d(x, kernel, strides, padding='SAME') + + def _relu(self, x, leakiness=0.0): + """Relu, with optional leaky support.""" + return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu') + + def _fully_connected(self, x, out_dim): + """FullyConnected layer for final output.""" + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + + def _named_fully_connected(self, name, x, out_dim): + """FullyConnected layer for final output.""" + with tf.variable_scope(name): + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + + def _global_avg_pool(self, x): + assert x.get_shape().ndims == 4 + return tf.reduce_mean(x, [1, 2]) + + + +class IgamConvDiscriminatorModel(object): + """Simple conv discriminator model.""" + # based on https://github.com/tensorflow/models/blob/d361076952b73706c5c7ddf9c940bf42c27a3213/research/slim/nets/dcgan.py#L41 + + def __init__(self, mode, dataset, train_batch_size=None, num_conv_layers=5, base_num_channels=16, x_modelgrad_input_tensor=None, y_modelgrad_input_tensor=None, x_source_modelgrad_input_tensor=None, + y_source_modelgrad_input_tensor=None, normalize_zero_mean=False, only_fully_connected=False, num_fc_layers=3, image_size=32, cropped_input_size=None, crop_pad_x_tensor=None, crop_pad_y_tensor=None, avg_pool_hw=False): + """conv disc constructor. + + Args: + mode: One of 'train' and 'eval'. + """ + self.neck = None + self.y_pred = None + self.mode = mode + self.pert = False + self.num_classes = 2 # grad from model or rand init grad + self.train_batch_size = train_batch_size + self.num_conv_layers = num_conv_layers + self.num_fc_layers = num_fc_layers + self.base_num_channels = base_num_channels + self.x_modelgrad_input_tensor = x_modelgrad_input_tensor + self.y_modelgrad_input_tensor = y_modelgrad_input_tensor + self.x_source_modelgrad_input_tensor = x_source_modelgrad_input_tensor + self.y_source_modelgrad_input_tensor = y_source_modelgrad_input_tensor + self.normalize_zero_mean = normalize_zero_mean + self.only_fully_connected = only_fully_connected + self.image_size = image_size + self.cropped_input_size = cropped_input_size + self.crop_pad_x_tensor = crop_pad_x_tensor + self.crop_pad_y_tensor = crop_pad_y_tensor + self.avg_pool_hw = avg_pool_hw + self._build_model() + + def add_internal_summaries(self): + pass + + def _stride_arr(self, stride): + """Map a stride scalar to the stride array for tf.nn.conv2d.""" + return [1, stride, stride, 1] + + def _build_model(self): + assert self.mode == 'train' or self.mode == 'eval' + """Build the core model within the graph.""" + with tf.variable_scope('discriminator', reuse=tf.AUTO_REUSE): + with tf.variable_scope('input'): + + if self.x_modelgrad_input_tensor == None: + # for assign to work + self.x_modelgrad_input = tf.get_variable(name='x_modelgrad_input', initializer=tf.zeros_initializer, + shape=[self.train_batch_size, self.image_size, self.image_size, 3], dtype=tf.float32) + + self.x_source_modelgrad_input = tf.placeholder( + tf.float32, + shape=[None, self.image_size, self.image_size, 3]) + else: + self.x_modelgrad_input = self.x_modelgrad_input_tensor + self.x_source_modelgrad_input = self.x_source_modelgrad_input_tensor + + if self.cropped_input_size != None: + if self.crop_pad_x_tensor == None: + crop_pad = (self.image_size - self.cropped_input_size) // 2 + cropped_x_modelgrad_input = tf.slice(self.x_modelgrad_input, [0, crop_pad, crop_pad, 0], [-1, self.cropped_input_size, self.cropped_input_size, -1]) + cropped_x_source_modelgrad_input = tf.slice(self.x_source_modelgrad_input, [0, crop_pad, crop_pad, 0], [-1, self.cropped_input_size, self.cropped_input_size, -1]) + + self.x_input = tf.concat([cropped_x_modelgrad_input, cropped_x_source_modelgrad_input], axis=0) + else: + cropped_x_modelgrad_input = tf.slice(self.x_modelgrad_input, [0, self.crop_pad_x_tensor, self.crop_pad_y_tensor, 0], [-1, self.cropped_input_size, self.cropped_input_size, -1]) + cropped_x_source_modelgrad_input = tf.slice(self.x_source_modelgrad_input, [0, self.crop_pad_x_tensor, self.crop_pad_y_tensor, 0], [-1, self.cropped_input_size, self.cropped_input_size, -1]) + + self.x_input = tf.concat([cropped_x_modelgrad_input, cropped_x_source_modelgrad_input], axis=0) + else: + self.x_input = tf.concat([self.x_modelgrad_input, self.x_source_modelgrad_input], axis=0) + self.cropped_input_size = self.image_size + + if self.y_modelgrad_input_tensor == None: + # for assign to work + self.y_modelgrad_input = tf.get_variable(name='y_modelgrad_input', initializer=tf.zeros_initializer, + shape=self.train_batch_size, dtype=tf.int64) + + self.y_source_modelgrad_input = tf.placeholder(tf.int64, shape=None) + else: + self.y_modelgrad_input = self.y_modelgrad_input_tensor + self.y_source_modelgrad_input = self.y_source_modelgrad_input_tensor + + self.y_input = tf.concat([self.y_modelgrad_input, self.y_source_modelgrad_input], axis=0) + + + if self.pert: + self.pert = tf.get_variable(name='instance_perturbation', initializer=tf.zeros_initializer, + shape=[self.train_batch_size, self.cropped_input_size, self.cropped_input_size, 3], dtype=tf.float32, + trainable=True) + self.final_input = self.x_input + self.pert + self.final_input = tf.clip_by_value(self.final_input, 0., 255.) + else: + self.final_input = self.x_input + + if self.normalize_zero_mean: + final_input_mean = tf.reduce_mean(self.final_input, axis=[1,2,3]) + for i in range(3): + final_input_mean = tf.expand_dims(final_input_mean, axis=-1) + final_input_mean = tf.tile(final_input_mean, [1, self.cropped_input_size, self.cropped_input_size,3]) + zero_mean_final_input = self.final_input - final_input_mean + self.input_standardized = tf.math.l2_normalize(zero_mean_final_input, axis=[1,2,3]) + else: + self.input_standardized = tf.math.l2_normalize(self.final_input, axis=[1,2,3]) + + x = self.input_standardized + base_num_channels = self.base_num_channels + if self.only_fully_connected == False: + for i in range(self.num_conv_layers): + output_num_channels = base_num_channels * 2**i + if i == 0: + x = self._conv('conv{}'.format(i), x, 4, 3, output_num_channels, self._stride_arr(2), bias=True) + x = self._batch_norm('bn{}'.format(i), x) + x = self._relu(x, 0.1) + else: + x = self._conv('conv{}'.format(i), x, 4, output_num_channels // 2, output_num_channels, self._stride_arr(2), bias=True) + x = self._batch_norm('bn{}'.format(i), x) + x = self._relu(x, 0.1) + else: + for i in range(self.num_fc_layers): + if i == self.num_fc_layers -1: + x = self._fully_connected(x, base_num_channels//2, name='fc{}'.format(i)) + else: + x = self._fully_connected(x, base_num_channels, name='fc{}'.format(i)) + x = self._batch_norm('bn{}'.format(i), x) + x = self._relu(x, 0.1) + + with tf.variable_scope('logit'): + if self.avg_pool_hw: + x = self._global_avg_pool(x) + self.pre_softmax = self._fully_connected(x, self.num_classes) + + self.predictions = tf.argmax(self.pre_softmax, 1) + self.y_pred = self.predictions + self.correct_prediction = tf.equal(self.predictions, self.y_input) + self.num_correct = tf.reduce_sum(tf.cast(self.correct_prediction, tf.int64)) + self.accuracy = tf.reduce_mean(tf.cast(self.correct_prediction, tf.float32)) + + with tf.variable_scope('costs'): + self.y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent = tf.reduce_sum(self.y_xent, name='y_xent') + self.mean_xent = tf.reduce_mean(self.y_xent) + self.weight_decay_loss = self._decay() + + def _batch_norm(self, name, x): + """Batch normalization.""" + with tf.name_scope(name): + return tf.contrib.layers.batch_norm(inputs=x, decay=.9, center=True, scale=True, activation_fn=None, + updates_collections=None, is_training=(self.mode == 'train')) + def _decay(self): + """L2 weight decay loss.""" + costs = [] + for var in tf.trainable_variables(): + if var.op.name.find('DW') > 0: + costs.append(tf.nn.l2_loss(var)) + return tf.add_n(costs) + + def _conv(self, name, x, filter_size, in_filters, out_filters, strides, bias=False, padding='SAME'): + """Convolution.""" + with tf.variable_scope(name): + n = filter_size * filter_size * out_filters + kernel = tf.get_variable( + 'DW', [filter_size, filter_size, in_filters, out_filters], + tf.float32, initializer=tf.random_normal_initializer( + stddev=np.sqrt(2.0 / n))) + if bias == True: + b = tf.get_variable('biases', [out_filters], + initializer=tf.constant_initializer()) + conv_out = tf.nn.conv2d(x, kernel, strides, padding=padding) + conv_out_b = tf.nn.bias_add(conv_out, b) + return conv_out_b + else: + return tf.nn.conv2d(x, kernel, strides, padding=padding) + + def _relu(self, x, leakiness=0.0): + """Relu, with optional leaky support.""" + return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu') + + def _fully_connected(self, x, out_dim, name=None): + """FullyConnected layer for final output.""" + if name == None: + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + else: + with tf.variable_scope(name): + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + + def _global_avg_pool(self, x): + assert x.get_shape().ndims == 4 + return tf.reduce_mean(x, [1, 2]) + + diff --git a/case_studies/curriculum_at/requirements.txt b/case_studies/curriculum_at/requirements.txt new file mode 100644 index 0000000..41a4d0b --- /dev/null +++ b/case_studies/curriculum_at/requirements.txt @@ -0,0 +1,6 @@ +ConfigArgParse==0.14.0 +tqdm==4.31.1 +tensorflow-gpu==1.14.0 +numba>=0.43.1 +matplotlib>=3.0.3 +Pillow==5.4.1 \ No newline at end of file diff --git a/case_studies/curriculum_at/run_attack.py b/case_studies/curriculum_at/run_attack.py new file mode 100644 index 0000000..ebf24e3 --- /dev/null +++ b/case_studies/curriculum_at/run_attack.py @@ -0,0 +1,463 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +"""Evaluates a model against examples from a .npy file as specified + + in attack_config.json""" + +from __future__ import absolute_import + +from __future__ import division + +from __future__ import print_function + + + +from datetime import datetime + +import json + +import math + +import os + +import sys + +import time + + + +import tensorflow as tf + +import numpy as np + +from tqdm import tqdm + + + +import cifar10_input + +import config_attack + + + + + +config = vars(config_attack.get_args()) + + + +data_path = config['data_path'] + + + +def run_attack(checkpoint, x_adv, epsilon): + + if config['dataset'] == 'cifar10': + + cifar = cifar10_input.CIFAR10Data(data_path) + + elif config['dataset'] == 'cifar100': + + cifar = cifar100_input.CIFAR100Data(data_path) + else: + cifar = tinyimagenet_input.TinyImagenetData() + + + + if 'GTP' in config['model_dir']: + + print("GTP MODEL") + + from model_new import Model, ModelTinyImagnet + if config['dataset'] == 'cifar10' or config['dataset'] == 'cifar100': + model = Model(mode='train', dataset=config['dataset'], train_batch_size=config['eval_batch_size'], normalize_zero_mean=True) + else: + model = ModelTinyImagnet(mode='train', dataset=config['dataset'], train_batch_size=config['eval_batch_size'], normalize_zero_mean=True) + + elif 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config['model_dir']: + + print("finetuned tinyimagenet MODEL") + + from model_new import ModelTinyImagenetSourceExtendedLogits + + full_source_model_x_input = tf.placeholder(tf.float32, shape = [None, 32, 32, 3]) + + upresized_full_source_model_x_input = tf.image.resize_images(full_source_model_x_input, size=[64, 64]) + + if config['dataset'] == 'cifar10': + + model = ModelTinyImagenetSourceExtendedLogits(mode='train', dataset='tinyimagenet', target_task_class_num=10, train_batch_size=config['eval_batch_size'], input_tensor=upresized_full_source_model_x_input) + + elif config['dataset'] == 'cifar100': + + model = ModelTinyImagenetSourceExtendedLogits(mode='train', dataset='tinyimagenet', target_task_class_num=100, train_batch_size=config['eval_batch_size'], input_tensor=upresized_full_source_model_x_input) + + + + model.x_input = full_source_model_x_input + + + + t_vars = tf.trainable_variables() + + source_model_vars = [var for var in t_vars if ('discriminator' not in var.name and 'classifier' not in var.name and 'target_task_logit' not in var.name)] + + source_model_target_logit_vars = [var for var in t_vars if 'target_task_logit' in var.name] + + source_model_saver = tf.train.Saver(var_list=source_model_vars) + + finetuned_source_model_vars = source_model_vars + source_model_target_logit_vars + + finetuned_source_model_saver = tf.train.Saver(var_list=finetuned_source_model_vars) + + elif 'finetuned_on_cifar100' in config['model_dir']: + + print("finetuned MODEL") + + from model_original_cifar_challenge import ModelExtendedLogits + + model = ModelExtendedLogits(mode='train', target_task_class_num=100, train_batch_size=config['eval_batch_size']) + + + + t_vars = tf.trainable_variables() + + source_model_vars = [var for var in t_vars if ('discriminator' not in var.name and 'classifier' not in var.name and 'target_task_logit' not in var.name)] + + source_model_target_logit_vars = [var for var in t_vars if 'target_task_logit' in var.name] + + source_model_saver = tf.train.Saver(var_list=source_model_vars) + + finetuned_source_model_vars = source_model_vars + source_model_target_logit_vars + + finetuned_source_model_saver = tf.train.Saver(var_list=finetuned_source_model_vars) + + elif ('adv_trained' in config['model_dir'] or 'naturally_trained' in config['model_dir'] or 'a_very_robust_model' in config['model_dir']): + + print("original challenge MODEL") + + from free_model_original import Model + + model = Model(mode='eval', dataset=config['dataset'], train_batch_size=config['eval_batch_size']) + + elif 'IGAM' in config['model_dir']: + + print("IGAM MODEL") + + from model_new import Model + + model = Model(mode='train', dataset=config['dataset'], train_batch_size=config['eval_batch_size'], normalize_zero_mean=True) + + else: + + print("other MODEL") + + from free_model import Model + + model = Model(mode='eval', dataset=config['dataset'], train_batch_size=config['eval_batch_size']) + + + + saver = tf.train.Saver() + + + + num_eval_examples = 10000 + + eval_batch_size = 100 + + + + num_batches = int(math.ceil(num_eval_examples / eval_batch_size)) + + total_corr = 0 + + + + x_nat = cifar.eval_data.xs + + l_inf = np.amax(np.abs(x_nat - x_adv)) + + + + if l_inf > epsilon + 0.0001: + + print('maximum perturbation found: {}'.format(l_inf)) + + print('maximum perturbation allowed: {}'.format(epsilon)) + + return + + + + y_pred = [] # label accumulator + + + + with tf.Session() as sess: + + # Restore the checkpoint + + if 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config['model_dir']: + + sess.run(tf.global_variables_initializer()) + + source_model_file = tf.train.latest_checkpoint("models/model_AdvTrain-igamsource-IGAM-tinyimagenet_b16") + + source_model_saver.restore(sess, source_model_file) + + finetuned_source_model_file = tf.train.latest_checkpoint(config['model_dir']) + + finetuned_source_model_saver.restore(sess, finetuned_source_model_file) + + elif 'finetuned_on_cifar100' in config['model_dir']: + + sess.run(tf.global_variables_initializer()) + + source_model_file = tf.train.latest_checkpoint("models/adv_trained") + + source_model_saver.restore(sess, source_model_file) + + finetuned_source_model_file = tf.train.latest_checkpoint(config['model_dir']) + + finetuned_source_model_saver.restore(sess, finetuned_source_model_file) + + else: + + saver.restore(sess, checkpoint) + + + + # Iterate over the samples batch-by-batch + + for ibatch in range(num_batches): + + bstart = ibatch * eval_batch_size + + bend = min(bstart + eval_batch_size, num_eval_examples) + + + + x_batch = x_adv[bstart:bend, :] + + y_batch = cifar.eval_data.ys[bstart:bend] + + + + dict_adv = {model.x_input: x_batch, + + model.y_input: y_batch} + + + + if 'finetuned_on_cifar10' in config['model_dir'] or 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config['model_dir']: + + cur_corr, y_pred_batch = sess.run([model.target_task_num_correct, model.target_task_predictions], + + feed_dict=dict_adv) + + else: + + cur_corr, y_pred_batch = sess.run([model.num_correct, model.predictions], + + feed_dict=dict_adv) + + + + total_corr += cur_corr + + y_pred.append(y_pred_batch) + + + + accuracy = total_corr / num_eval_examples + + + + print('Adv Accuracy: {:.2f}%'.format(100.0 * accuracy)) + + y_pred = np.concatenate(y_pred, axis=0) + + + + store_adv_pred_path = "preds/" + adv_examples_path.split("/")[-1] + + if not os.path.exists("preds/"): + + os.makedirs("preds/") + + np.save(store_adv_pred_path, y_pred) + + print('Output saved at ', store_adv_pred_path) + + + + if config['save_eval_log']: + + date_str = datetime.now().strftime("%d_%b") + + log_dir = "attack_log/" + date_str + + if not os.path.exists(log_dir): + + os.makedirs(log_dir) + + log_filename = adv_examples_path.split("/")[-1].replace('.npy', '.txt') + + model_name = config['model_dir'].split('/')[1] + + log_file_path = os.path.join(log_dir, log_filename) + + with open(log_file_path, "w") as f: + + f.write('Model checkpoint: {} \n'.format(checkpoint)) + + f.write('Adv Accuracy: {:.2f}%'.format(100.0 * accuracy)) + + print('Results saved at ', log_file_path) + + + + # full test evaluation + + if config['dataset'] == 'cifar10': + raw_data = cifar10_input.CIFAR10Data(data_path) + elif config['dataset'] == 'cifar100': + raw_data = cifar100_input.CIFAR100Data(data_path) + else: + raw_data = tinyimagenet_input.TinyImagenetData() + + data_size = raw_data.eval_data.n + + if data_size % config['eval_batch_size'] == 0: + + eval_steps = data_size // config['eval_batch_size'] + + else: + + eval_steps = data_size // config['eval_batch_size'] + 1 + + total_num_correct = 0 + + for ii in tqdm(range(eval_steps)): + + x_eval_batch, y_eval_batch = raw_data.eval_data.get_next_batch(config['eval_batch_size'], multiple_passes=False) + + eval_dict = {model.x_input: x_eval_batch, model.y_input: y_eval_batch} + + if 'finetuned_on_cifar10' in config['model_dir'] or 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config['model_dir']: + + num_correct = sess.run(model.target_task_num_correct, feed_dict=eval_dict) + + else: + + num_correct = sess.run(model.num_correct, feed_dict=eval_dict) + + total_num_correct += num_correct + + eval_acc = total_num_correct / data_size + + with open(log_file_path, "a+") as f: + + f.write('\nClean Accuracy: {:.2f}%'.format(100.0 * eval_acc)) + + print('Clean Accuracy: {:.2f}%'.format(100.0 * eval_acc)) + + print('Results saved at ', log_file_path) + + + +if __name__ == '__main__': + + import json + + + + # with open('attack_config.json') as config_file: + + # config = json.load(config_file) + + + + model_dir = config['model_dir'] + + + + checkpoint = tf.train.latest_checkpoint(model_dir) + + + adv_examples_path = config['store_adv_path'] + + if adv_examples_path == None: + + model_name = config['model_dir'].split('/')[1] + + if config['attack_name'] == None: + if config['dataset'] == 'cifar10': + adv_examples_path = "attacks/{}_attack.npy".format(model_name) + elif config['dataset'] == 'cifar100': + adv_examples_path = "attacks/{}_c100attack.npy".format(model_name) + else: + adv_examples_path = "attacks/{}_tinyattack.npy".format(model_name) + + else: + if config['dataset'] == 'cifar10': + adv_examples_path = "attacks/{}_{}_attack.npy".format(model_name, config['attack_name']) + elif config['dataset'] == 'cifar100': + adv_examples_path = "attacks/{}_{}_c100attack.npy".format(model_name, config['attack_name']) + else: + adv_examples_path = "attacks/{}_{}_tinyattack.npy".format(model_name, config['attack_name']) + + + + if config['attack_norm'] == '2': + + adv_examples_path = adv_examples_path.replace("attack.npy", "l2attack.npy") + + + + x_adv = np.load(adv_examples_path) + + + + tf.set_random_seed(config['tf_seed']) + + np.random.seed(config['np_seed']) + + + + if checkpoint is None: + + print('No checkpoint found') + + elif x_adv.shape != (10000, 32, 32, 3): + + print('Invalid shape: expected (10000, 32, 32, 3), found {}'.format(x_adv.shape)) + + elif np.amax(x_adv) > 255.0001 or np.amin(x_adv) < -0.0001: + + print('Invalid pixel range. Expected [0, 255], found [{}, {}]'.format( + + np.amin(x_adv), + + np.amax(x_adv))) + + else: + + print("adv_examples_path: ", adv_examples_path) + + run_attack(checkpoint, x_adv, config['epsilon']) + + diff --git a/case_studies/diffpure/LICENSE b/case_studies/diffpure/LICENSE new file mode 100644 index 0000000..bda414b --- /dev/null +++ b/case_studies/diffpure/LICENSE @@ -0,0 +1,64 @@ +NVIDIA Source Code License for DiffPure + +1. Definitions + +“Licensor” means any person or entity that distributes its Work. + +“Software” means the original work of authorship made available under this License. + +“Work” means the Software and any additions to or derivative works of the Software that are made available under +this License. + +The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the meaning as provided under +U.S. copyright law; provided, however, that for the purposes of this License, derivative works shall not include +works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work. + +Works, including the Software, are “made available” under this License by including in or with the Work either +(a) a copyright notice referencing the applicability of this License to the Work, or (b) a copy of this License. + +2. License Grant + +2.1 Copyright Grant. Subject to the terms and conditions of this License, each Licensor grants to you a perpetual, +worldwide, non-exclusive, royalty-free, copyright license to reproduce, prepare derivative works of, publicly +display, publicly perform, sublicense and distribute its Work and any resulting derivative works in any form. + +3. Limitations + +3.1 Redistribution. You may reproduce or distribute the Work only if (a) you do so under this License, (b) you +include a complete copy of this License with your distribution, and (c) you retain without modification any +copyright, patent, trademark, or attribution notices that are present in the Work. + +3.2 Derivative Works. You may specify that additional or different terms apply to the use, reproduction, and +distribution of your derivative works of the Work (“Your Terms”) only if (a) Your Terms provide that the use +limitation in Section 3.3 applies to your derivative works, and (b) you identify the specific derivative works +that are subject to Your Terms. Notwithstanding Your Terms, this License (including the redistribution +requirements in Section 3.1) will continue to apply to the Work itself. + +3.3 Use Limitation. The Work and any derivative works thereof only may be used or intended for use +non-commercially. Notwithstanding the foregoing, NVIDIA and its affiliates may use the Work and any derivative +works commercially. As used herein, “non-commercially” means for research or evaluation purposes only. + +3.4 Patent Claims. If you bring or threaten to bring a patent claim against any Licensor (including any claim, +cross-claim or counterclaim in a lawsuit) to enforce any patents that you allege are infringed by any Work, then +your rights under this License from such Licensor (including the grant in Section 2.1) will terminate immediately. + +3.5 Trademarks. This License does not grant any rights to use any Licensor’s or its affiliates’ names, logos, +or trademarks, except as necessary to reproduce the notices described in this License. + +3.6 Termination. If you violate any term of this License, then your rights under this License (including the +grant in Section 2.1) will terminate immediately. + +4. Disclaimer of Warranty. + +THE WORK IS PROVIDED “AS IS” WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING +WARRANTIES OR CONDITIONS OF M ERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT. YOU +BEAR THE RISK OF UNDERTAKING ANY ACTIVITIES UNDER THIS LICENSE. + +5. Limitation of Liability. + +EXCEPT AS PROHIBITED BY APPLICABLE LAW, IN NO EVENT AND UNDER NO LEGAL THEORY, WHETHER IN TORT (INCLUDING +NEGLIGENCE), CONTRACT, OR OTHERWISE SHALL ANY LICENSOR BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, +INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATED TO THIS LICENSE, THE USE OR +INABILITY TO USE THE WORK (INCLUDING BUT NOT LIMITED TO LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS OR +DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY OTHER COMM ERCIAL DAMAGES OR LOSSES), EVEN IF THE LICENSOR HAS BEEN +ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. \ No newline at end of file diff --git a/case_studies/diffpure/README.md b/case_studies/diffpure/README.md new file mode 100644 index 0000000..3102365 --- /dev/null +++ b/case_studies/diffpure/README.md @@ -0,0 +1,213 @@ +# Diffusion Models for Adversarial Purification + +

+ +

+ +Official PyTorch implementation of the ICML 2022 paper:
+**[Diffusion Models for Adversarial Purification](https://arxiv.org/abs/2205.07460)** +
+Weili Nie, Brandon Guo, Yujia Huang, Chaowei Xiao, Arash Vahdat, Anima Anandkumar
+https://diffpure.github.io
+ +Abstract: *Adversarial purification refers to a class of defense methods that remove adversarial perturbations using a +generative model. These methods do not make assumptions on the form of attack and the classification model, and thus can +defend pre-existing classifiers against unseen threats. However, their performance currently falls behind adversarial +training methods. In this work, we propose DiffPure that uses diffusion models for adversarial purification: +Given an adversarial example, we first diffuse it with a small amount of noise following a forward diffusion process, +and then recover the clean image through a reverse generative process. To evaluate our method against strong adaptive +attacks in an efficient and scalable way, we propose to use the adjoint method to compute full gradients of the reverse +generative process. Extensive experiments on three image datasets including CIFAR-10, ImageNet and CelebA-HQ with three +classifier architectures including ResNet, WideResNet and ViT demonstrate that our method achieves the state-of-the-art +results, outperforming current adversarial training and adversarial purification methods, often by a large margin.* + +## Requirements + +- 1-4 high-end NVIDIA GPUs with 32 GB of memory. +- 64-bit Python 3.8. +- CUDA=11.0 and docker must be installed first. +- Installation of the required library dependencies with Docker: + ```bash + docker build -f diffpure.Dockerfile --tag=diffpure:0.0.1 . + docker run -it -d --gpus 0 --name diffpure --shm-size 8G -v $(pwd):/workspace -p 5001:6006 diffpure:0.0.1 + docker exec -it diffpure bash + ``` + +## Data and pre-trained models + +Before running our code on ImageNet and CelebA-HQ, you have to first download these two datasets. For example, you can +follow [the instructions to download CelebA-HQ](https://github.com/suvojit-0x55aa/celebA-HQ-dataset-download). Note that +we use the LMDB format for ImageNet, so you may need +to [convert the ImageNet dataset to LMDB](https://github.com/Lyken17/Efficient-PyTorch/tree/master/tools). There is no +need to download CIFAR-10 separately. + +Note that you have to put all the datasets in the `datasest` directory. + +For the pre-trained diffusion models, you need to first download them from the following links: + +- [Score SDE](https://github.com/yang-song/score_sde_pytorch) for + CIFAR-10: (`vp/cifar10_ddpmpp_deep_continuous`: [download link](https://drive.google.com/file/d/16_-Ahc6ImZV5ClUc0vM5Iivf8OJ1VSif/view?usp=sharing)) +- [Guided Diffusion](https://github.com/openai/guided-diffusion) for + ImageNet: (`256x256 diffusion unconditional`: [download link](https://openaipublic.blob.core.windows.net/diffusion/jul-2021/256x256_diffusion_uncond.pt)) +- [DDPM](https://github.com/ermongroup/SDEdit) for CelebA-HQ: (`CelebA-HQ`: [download link](https://image-editing-test-12345.s3-us-west-2.amazonaws.com/checkpoints/celeba_hq.ckpt)) + +For the pre-trained classifiers, most of them do not need to be downloaded separately, except for + +- `attribute classifiers` from [gan-ensembling](https://github.com/chail/gan-ensembling) on + CelebA-HQ: [download link](http://latent-composition.csail.mit.edu/other_projects/gan_ensembling/zips/pretrained_classifiers.zip) +- `wideresnet-70-16` on CIFAR-10: TBD +- `resnet-50` on CIFAR-10: TBD +- `wrn-70-16-dropout` on CIFAR-10: TBD + +Note that you have to put all the pretrained models in the `pretrained` directory. + +## Run experiments on CIFAR-10 + +### AutoAttack Linf + +- To get results of defending against AutoAttack Linf (the `Rand` version): + +```bash +cd run_scripts/cifar10 +bash run_cifar_rand_inf.sh [seed_id] [data_id] # WideResNet-28-10 +bash run_cifar_rand_inf_70-16-dp.sh [seed_id] [data_id] # WideResNet-70-16 +bash run_cifar_rand_inf_rn50.sh [seed_id] [data_id] # ResNet-50 +``` + +- To get results of defending against AutoAttack Linf (the `Standard` version): + +```bash +cd run_scripts/cifar10 +bash run_cifar_stand_inf.sh [seed_id] [data_id] # WideResNet-28-10 +bash run_cifar_stand_inf_70-16-dp.sh [seed_id] [data_id] # WideResNet-70-16 +bash run_cifar_stand_inf_rn50.sh [seed_id] [data_id] # ResNet-50 +``` + +Note that `[seed_id]` is used for getting error bars, and `[data_id]` is used for sampling a fixed set of images. + +To reproduce the numbers in the paper, we recommend using three seeds (e.g., 121..123) for `[seed_id]` and eight seeds +(e.g., 0..7) for `[data_id]`, and averaging all the results across `[seed_id]` and `[data_id]`, accordingly. +To measure the worse-case defense performance of our method, the reported robust accuracy is the minimum robust accuracy +of these two versions: `Rand` and `Standard`. + +### AutoAttack L2 + +- To get results of defending against AutoAttack L2 (the `Rand` version): + +```bash +cd run_scripts/cifar10 +bash run_cifar_rand_L2.sh [seed_id] [data_id] # WideResNet-28-10 +bash run_cifar_rand_L2_70-16-dp.sh [seed_id] [data_id] # WideResNet-70-16 +bash run_cifar_rand_L2_rn50.sh [seed_id] [data_id] # ResNet-50 +``` + +- To get results of defending against AutoAttack L2 (the `Standard` version): + +```bash +cd run_scripts/cifar10 +bash run_cifar_stand_L2.sh [seed_id] [data_id] # WideResNet-28-10 +bash run_cifar_stand_L2_70-16-dp.sh [seed_id] [data_id] # WideResNet-70-16 +bash run_cifar_stand_L2_rn50.sh [seed_id] [data_id] # ResNet-50 +``` + +Note that `[seed_id]` is used for getting error bars, and `[data_id]` is used for sampling a fixed set of images. + +To reproduce the numbers in the paper, we recommend using three seeds (e.g., 121..123) for `[seed_id]` and eight seeds +(e.g., 0..7) for `[data_id]`, and averaging all the results across `[seed_id]` and `[data_id]`, accordingly. +To measure the worse-case defense performance of our method, the reported robust accuracy is the minimum robust accuracy +of these two versions: `Rand` and `Standard`. + +### StAdv + +- To get results of defending against StAdv: + +```bash +cd run_scripts/cifar10 +bash run_cifar_stadv_rn50.sh [seed_id] [data_id] # ResNet-50 +``` + +Note that `[seed_id]` is used for getting error bars, and `[data_id]` is used for sampling a fixed set of images. + +To reproduce the numbers in the paper, we recommend using three seeds (e.g., 121..123) for `[seed_id]` and eight seeds +(e.g., 0..7) for `[data_id]`, and averaging all the results across `[seed_id]` and `[data_id]`, accordingly. + + +### BPDA+EOT + +- To get results of defending against BPDA+EOT: + +```bash +cd run_scripts/cifar10 +bash run_cifar_bpda_eot.sh [seed_id] [data_id] # WideResNet-28-10 +``` + +Note that `[seed_id]` is used for getting error bars, and `[data_id]` is used for sampling a fixed set of images. + +To reproduce the numbers in the paper, we recommend using three seeds (e.g., 121..123) for `[seed_id]` and five seeds +(e.g., 0..4) for `[data_id]`, and averaging all the results across `[seed_id]` and `[data_id]`, accordingly. + +## Run experiments on ImageNet + +### AutoAttack Linf + +- To get results of defending against AutoAttack Linf (the `Rand` version): + +```bash +cd run_scripts/imagenet +bash run_in_rand_inf.sh [seed_id] [data_id] # ResNet-50 +bash run_in_rand_inf_50-2.sh [seed_id] [data_id] # WideResNet-50-2 +bash run_in_rand_inf_deits.sh [seed_id] [data_id] # DeiT-S +``` + +- To get results of defending against AutoAttack Linf (the `Standard` version): + +```bash +cd run_scripts/imagenet +bash run_in_stand_inf.sh [seed_id] [data_id] # ResNet-50 +bash run_in_stand_inf_50-2.sh [seed_id] [data_id] # WideResNet-50-2 +bash run_in_stand_inf_deits.sh [seed_id] [data_id] # DeiT-S +``` + +Note that `[seed_id]` is used for getting error bars, and `[data_id]` is used for sampling a fixed set of images. + +To reproduce the numbers in the paper, we recommend using three seeds (e.g., 121..123) for `[seed_id]` and 16 seeds +(e.g., 0..15) for `[data_id]`, and averaging all the results across `[seed_id]` and `[data_id]`, accordingly. +To measure the worse-case defense performance of our method, the reported robust accuracy is the minimum robust accuracy +of these two versions: `Rand` and `Standard`. + +## Run experiments on CelebA-HQ + +### BPDA+EOT + +- To get results of defending against BPDA+EOT: + +```bash +cd run_scripts/celebahq +bash run_celebahq_bpda_glasses.sh [seed_id] [data_id] # the glasses attribute +bash run_celebahq_bpda_smiling.sh [seed_id] [data_id] # the smiling attribute +``` + +Note that `[seed_id]` is used for getting error bars, and `[data_id]` is used for sampling a fixed set of images. + +To reproduce the numbers in the paper, we recommend using three seeds (e.g., 121..123) for `[seed_id]` and 64 seeds +(e.g., 0..63) for `[data_id]`, and averaging all the results across `[seed_id]` and `[data_id]`, accordingly. + +## License + +Please check the [LICENSE](LICENSE) file. This work may be used non-commercially, meaning for research or evaluation +purposes only. For business inquiries, please contact +[researchinquiries@nvidia.com](mailto:researchinquiries@nvidia.com). + +## Citation + +Please cite our paper, if you happen to use this codebase: + +``` +@inproceedings{nie2022DiffPure, + title={Diffusion Models for Adversarial Purification}, + author={Nie, Weili and Guo, Brandon and Huang, Yujia and Xiao, Chaowei and Vahdat, Arash and Anandkumar, Anima}, + booktitle = {International Conference on Machine Learning (ICML)}, + year={2022} +} +``` + diff --git a/case_studies/diffpure/assets/teaser_v7.jpeg b/case_studies/diffpure/assets/teaser_v7.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..cd42f32e252dabb46013e3e77e393966655de6b2 GIT binary patch literal 520516 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 z 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 Od)wJtdE-yJj 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

l*vHSUV82eXf9qFF0RAoFOQarSHaI#ZTFUe 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 z

?YR4l){wBMg-*ohoVTY{^UJRXe;hfchZ_(oTHO^g%%T>4FO#OBKMNXX?ow@K~j zkG(jV=NXF=&=Y@;h^UK(Fm&GZSO36o%j*OpPY+e(h_IDSkVw4W&K0s^?k^yJtL6#+ zf_OyEzYHJCNH@%(Pd~0*MOiU(EoFIYx;U2*jm2{h%X5pGh>KV0C+!`YzSV0_)(ms% z_@&ijC_S=YVoQ+bG|xnpsAqxU8iIsoJK{~k(&{MpBJ|Gdp)gaW+BMY_P9{wzn;V`l ztyy{B_L+g8n>J>uQFiw8i_TZ8d!q$n;|bBS4DSNKvg3BO!v{-EQ_kl-UqcPQ7;Tjf z$e&5(B{ysL2qSIGk4;w}OkKKQe6#|}ZXfoy7m^;v-{aSm?OxmFzw2x{P;ajMO8mF7 zx=KueYcPl`jv+Kp?NI_&57Bu&i_I%p9Xdd(f$N^XzDqU6NL zoWl))faa?AnAbJ(HOg5^Gn~?T zNVnnJ;U!!0S)qDJaOMMOQQ$dyuJp2$&aUlLTK2C0VPN=Zxes{cE5uIY z%KXCVzZ<#Ao7UfSGFPgK>38kI2=gxaj zO&?iq(xOUDZ4vmgb&J@2F<|#Sb|d=n73LuN=Fz=JEdSjIaI`mh$zdHEHm_Y*C;F{L z1P|U9zbO$+$Kxkh&fhsg^bzaIgID($#FTs`{+t`OKmO7uRo&zL^>X}?Sr+kYc}8KE zy{^&`YcfGKssqp;^=SFNch8REmD^69c$%Ty#`Wmnx6s)Do;s7?(>hY2zwNT~dX|t8S-&7-*%<4R%KDsk33K@xOybM0(?!9K6fB)hJ zo8Ux3t&iHYv;es2mnmFW_1Ia&)dzu8*1;JQrKU)TCHvT~-06K(yu>C*70Z1&y!a)$ zRA3%0oS+;r;}3>aS;Vaa2=}u{+%Is6ac#<^1HSwW^ide#si33IPfqGSo9~}r_lU+R zUO$ROM-hNDiW%#SIeqL>tXAh${G~APPoAE!AAKKeSMO)#xb)~gHc#tx0j_c3on7;> za=Yg#SS~_Q zr6K&g6ird1Sj>2&*0nnH8x_u=0=Ln8gg2mAZ71?6Hl_yYwkO?n6=wNFEpDYx#wOQg z=K7o*HHF~Q)0Tfpf>dx(HsWNS4sdynmx1K4?$g-B>m~cR^hch;XCiAK;}%m-tB&pW z8?;p0(Zt{1 zDQ5vYb}=v6^*OW8Ugkb8_##5twoMz<0Ls}I7k`&qZz}Qj%B3pJ7~XbiJ42;95Jz#j zVRWfkKU=?hG&5>bb0E;WaBi^1j7eq>M6A!ZjdGAO(_GY33OnhM!E0G`dJPMYpK3}- zTwV+QcY}S$AXfeRuQ=ma*?1$ydSB$isVjD;L$H$mBU_T(zyb0+B5&Rxa9S*0Qb!M>UQlK}DzeLMhM?E4a@(Mlak_2fl zK#p0||L?idnWK45Twu^?Xf~Epha}%m-5GIV3T7!n@r8U#e4tW!Iu+2W`?GIC(ODRo z+3V;nrum6FAu{q^#vf!-Nbqan$tNk7nZ-?x{0cXP^F>iYQ;jJ@zqa=yzr9-8iBm0k_Sg9A9FCRkU~s2U?mX}Pow&zGUse+Tg#2zkHi^{{&(j#9sw zPYpUdV3CU_gL!I%7{k?2k8|R(wMq zcKq-7@S|;NbNQy|T1n~Tw_gtG6vj|7rq0qa?M^MS;{*+tj_Hh`;LB=r_Q7G7^WWG zkx-p%p|-lWKAl|te+_Id5W(fW7g}|!sTjjXtU7N9>@>P*Gb{b@%eBRgv0jdQV|rD$ zG)32M&}k>HGldT6r(9xurfvK?{C_&U_!^sv&Dy%|_BYT}e{U0O9I!epR!N|&o&J38R6}0v89VqQfEdT%h3xH6z$nA?JE8l*=B4HJLcJI8UW|a8-Gf-MQr-6Oi%B9 zd$irOD?PMeelOa011&ZxZP*QIVzARSdmEp#Lkn4cL$5ChaE-^KValL3@P}Nk>8n*a zwM`S0@N=6b;RNCTe*n|s8P+S{Qrin1^jhPj$Zop`xPx;|1i+};B9mhI)$F;F6~pi9 zm9Ayin=wMlq4AoZ8`I)M?`_Rlkx0~;0*VVm*H`x@qtmZ5OXk11&eiJplctTuT0tEL!0Fa#Bb{Y(bBgHX9LOP4Ctfbo(D)ei+q-H9pRy8Xi04R~Lra27a|Sb<62Ooe+-Nax~7i_`H~D^!VkL^n8jFgWy4f6p2`m|#-S zo>MF)HQSy^OiUKfuTjcjb3&ZEHlSHC}b$`6XMt26fWs>8t#FGSmvp7UNr{7fmS+dAezbV*RD^}=*Cb!n4 z%2YQDPK!uBos*=fNpe5W7vqW9<<$2h?9=XpOYEILXM>A?qMdk7u}{cI`PGUsn8BI+ zuz5Q`Jr|0Fj|hzqPiDyuMt=K1DpX2yJ~oT$K0WUM>r4|s%OvK3;kGB4FNS5I%00vK zn-W=X`}8oPH*U4vmTF~Utc5LeH;Bq~4{l}cjnZIh6wh@`A0SlP*X#8{L$q>W) zdmBF&1A!L6U&U|!=9yE(X==N=X?^m6$gu>3ZF0=!HE%*Kyj6L@(4U^+qmyD%nD|^k zHz2|Tg}krAjab!gK%^=^&vc>QSqAyOIQfA6CzdQEbCkn~^(u7F;Z_pKDR94k|0Nwa z+mcbEY6!nJtYta4PpSqqjd8{{BO@E)rNsD5atB7{ETP%iIpys?{Z)Czd>g9~yQ5U}EgZa@V`z#p z1xtY(-k|Cl|L?K8z0%2|AV)khBAvbtZvZL6L3}J*n^KU-TKjsuI(;ZOIIHsONV8*x zlBFdjS8N;t3aP9hXuaD4B=6qs*(pW72LIM#H6QxriMpNFtuvPLBb7<)$YcjdLxSAx z+OjAS{*pgezVgQ_JaxO<_}`7u2aa|5{I5O~=v)B2T#8a^n!IM)cLO_6c5pZdY&@tQ zPvEHRD#_m^t4o=EJD1%$Wbo&WYJ?<&F>|KRNN7j`lyEA^n4V?xOGM zt5l1rwlfl09$9KJSN?^(X)43*y7_dq?OI|GPOyaLa_k#x1wcZAun?6G-h(_O3;n{D83ipRrA4d(+V9(gEobHKJTHj9*Fo>0r2HN ziU#>=_@0PsM=deF9m})YyOF<`#%|0J3rnl*l)6)^8=RnuoeTPbn@#`a=wnq}Ef?s< z5}{uR6N~fKxTro?ITZg@@~h*)2OyB~WMcvo>BG7>g8xaIEg#h|!-Bu)3|BN~g#=%T z9|aza(#16S&|-T4Y8Xk87n*fs_9+0Q_imaEaBz9{C`W-a{sror z0J9b?woR~R6>~VLtuN!$Spt0J;Lpo>5)7=$S=}Y>XjJ1V#)BNwK`DgO@SMV;l+7&b z=+=T?>=&*(mPp^zoHJ}$Zy<9Ga4%PG*fRGo^v?gfxj%i;$xq^idEc2l4l#WEdr$hM zk;&DINdmI21~J{?-vfY^x+J7q$9q(WxxbqIzx{Wk+vUmD<`3l2gxMe@!r4=8Ju7{) zU$ei+(#Ci{LbRr$WSW@S-4jqyIDgIj>r6GI+&WNX==z4I6YsS2ob?%gLu1kOpvM33 zZAjDD+v)%Lm)~BTzu@kT?zvqMBxh`-a9&5=eGZhdN_j!S7)T{QZz>*A0XO0c#q)|C z?2en4?7aUxul`HqM|~Zi@Kaz@E4m_zE!u1@ZN&{6{VdkZ8Hh4};bQ@r4$1@N$$lvR zaM^RInQAnp^RU*Zz7mVUtd@szmFS+L`S};`yNF9azE4C_oH98_pWrsXLgn}j7oAtN zHOmCT6ps3=&bz9n2DdVD{aU(3=nRAKpxK~+A63w#hvgt-{wyA>j-vyc3CFMFx6bmC zNmgS)rryM%=@0q>7 zSBLx%pH8IzpcFTnh;{udO4*y2u;^^b3?!)EGX8_)3_i)H0;Bf@U&fHKrwsjfw$lY49ey0#eawU1xYK+l(bDRqbg5*(+3aUcvlY#f#<;Wde5rVr-h6a7L#vXN9*X8>l#vD9 zEpu*0*~sWs&Md_6Y(APz+vjAh6S^!O@LN=LeSpHGR>D+So11@(@WCquas zGoyMAwOlBlXG3d^0#2<7icb=sm?Yb)=Dv5oz?sWpbG5$GStkl1-2uXjlod|K`lWRk z0u<-aXFvrS?!-t>XIYB!%~+jL6tZi=+^w=Me-Naw_jff0rH~ZzQ+Hw zW=Vc-i9*5+`Wp-~#kJGBJ^XFxQby(&;;Uq+1-4gL}`QSwgmgDypM7sv(_jP?cR{t<`A-GwSAngk;~{ zSJ}*?t3EdBpO)>1z5T0)qr;v8T<(-pWvs)f8_oy74+QB>zVJt{M$vQW3w|Ss+JLU( zxWtj2YA$)M!N>#`+4FcrW`8vh;xA9?w?6N({Xi`@VOQswLCdN5(#p&%(cJ7B6JVIg zsGd@y0|X@$cGaye3<{H?Nt>`a>2OMt)2im)UtuIixeY_=q*QiV4{>_XoMIu=x7C>T zodMtA&rT6q39DGFslD{5w8_r%#JPW^We3tIm_nJ#sl&g%$v(?a>$F?|X?Eu8yjfhGUGM$GytmY`5Q%F4RHa@sJ!2EQ3>Q(lMZi zv}iSXJ|j!`^1i+MQ}{!Oue7g=S|31-@m|2BDGbY>nhl)v&gw3H9+z0Gsbxa>`-kW> z?~Dcg8h>gv02`|>0AeY9aemfiD2u)syuQki<>=8OT7m_SaC=*anzHQ_w4Hx*PIfeq zA`|p_BxF2Fq-Yy5?$P4+V9Ek7T%6-`9bakzo#grkY}#10tJej%9-B|Cj?#UKHDQy4 zj06^y&30=?8(a?+&X6c+6y>u#J>OK5vj8_))qbvV#%zSQs5&<@=g5x2a`Sil_(tM~ zmh}09AeC-iMC$caS)mbIz6W0VqpO#7AGx1qU*|yoHc<=1kUz4Q6$iYC#t4q8C}S8t zf2vCpM$o!7+PIg$%pxyKNGt>M0ss?~Fn4mgRzRY7r53B;>%KV*tEXgJOcZZI?}gOV z)yf?!*z%#^*Mvgs+fFmpp|`3e!O9}tywlX-=kj8o(NfJH>NB?c=UY)hE(U>EF;WFu z-|)X1$BIu<=5{-inTO=rM$r81q?2IVnjx+2k5;7h1`dUKv@k0`a2fKrJDP<{!O9rQ z1O0m$egbEFHytBHRfN;*&mTaZLI9#pmvoLF51uN|m{hR99(d~k(GkGRbwm(j$n}M& zhWa^yiZ8#Ql$5*p#)aQo`2x3Z>WP=~FA4i`3sXLUAuZMxizVhpA7*MiwL*Dy$uIu+ z&;n4Xvb+O@$Y~V9EZdsl#u!?jow>w)!Et_(3Z&BZ+|T@~Z5dQUeMXgYsy2~l(x^+e_hJpe>b3t2EUhLcc=FPL}4xYBL!p|Ka`Zub$}9zl{Fbz439QdR0+BKpF)0u zmK9p7MXn|^5-!4|g#m{*@c|X~rT+_xy1uW^q4LS)y1lt+U8z*7i)LSVrpW8J2TcIO zanwCmMU4WWxc}ViLJ}yScWcX!ZaR13sP~<7@TwOh;RuL}Q?%+;s;n#dN6{OCQ?D8} zoaW?z@VWVV{CezYbK;dp*r5`QW_-Jb9a?Ndl1 zUx^RVW5fB;%h=&-`sp9$$@5x+MU|ZjlxUe!Qn0hy&i|evvmc{rw-cXp+x+&TzSW!v z+$Tj)!iGh37u92w7Ndr-&A$9WWr{tb#_;epX_TjhNRhT?QQyGK4izq79QP{m+G#~4!1S=C*#<&FCykwO7EqlQl3-B@*iVctx2;bDhXtnA9@yHjPF>+g9t+ZBt=n9c}?7k+* zhjlRPZc$F;*0fsiZei`YK)n5x&K|Eh`vl6tfw91PGzfXAYl4E8aK9ZpUJNTs{5V^e zh47tAMM<#gE1#p4SsDWO&xba0socjB6dADt%s z<8+m6el$>vrJA`xK9pLbeFYyy&vCW3cebb3u&rU^wQ zoujOZTybv7KC}B94ZOKL9)K=wWRqJH4#%cpUJW38*SmmN98-rPK_D!F8V&S!8hWNP;Vc2!4kAOYZEwG#}Uc zFX=+2h2dWF=h@ZAN_FuBbJi4$Ax|j1yIm}|EFh)!d#LjSG$ftD&h9)(e-LarI72uQ zj;v7Bh&Dv7Ihqc z&u@3{%7HREu({)glu}i@iBYGo7$`Clk(+Y zv{D!-bdv5Z9s-vDvR*g}>H#<_*LW7M<5zxXq9dG^YMs(&7yT#--`}p=6io2Z<9B#I zcVaSqieh&$itr9E6_<4ieExdgs&$rt<#X!VZ2S;%B=+n(Q{Y^KW;gfk3=%wp?$%!! zP8lv1AJ^*_sv}zHZYI|iOqg)sEPJg`axGAdjNVX{Ndb@q%iak}bSQ#Oz!`{}}u`2qjK5HGHHHub}C1 zi#Kl?^BA7NDEK{QEA!fXz_ zK4(=$yJe0Y^;lrh?m!(~^9bXYk{d1OghB*0ORnz^0`j+Q83UaFwTh5Vt#Ss1F{*V( zIp64=;K5uFC_}B=DFOEyeNW{$JZPe#{KU~wNQC}P+QXdP36*{7aj7*Hk}lvx2ldvz zaC|)T__*ae>AbRzfb{KsS?Ek87#7yBoyDGeeeRs`=*YBgXqYKS%^z49RT@Vj;&98m zNA@m{#ky*yB4#4~HreR>-Llw&D7{rsUY57XBh#KP00Chlk;T}(wtVV$ndjaXr*cRT zQN)4q6EBIuz zi)I_*Xh8#t(P(pRIIhl>gD?)c@J8F!`b0iT_!6)>1M&CU19oQ>NZ45tT&>Z7#)kKv zGW$GSX%xte8Iy9&8|9c(^ypA>oL`ut3C#1qA=&(Q!xr(jF1c7~?7;xl(~3WZ6m-aE z8>yk5bQ-p4ek-llqpjGQpWnF))_`6Eh&*0XwvnBmNQl_heE3HI@8vVQkf&uol~`)7L#4iO$25lAqK<2X-oru-|0I{(&pm_CuI1H>xZ2j_nFasIgn5)3# zPs)rcsNkkYk8O+HO%0;8hb##IKg6m|gQ{%G$rtVfmip8O2!jIO>DhAoJq$ojJTe>F zD3K>cuBMiqWt!z#0TT@W>K$(MA1$;0D-1j(5JvUA85bOEhbkQx66;$Mr=u?Pl^2p; zd-db_>tX{FN69kQ?BaOmidFBN*>d}45n#!77Q*;VB!DKlo#t}jJ}@q)$A~g;UL!D2 z2Z!SR{Nd45^IS1Mtw|M!LR9O>$xDxl9Vny^s&v<-^~2CCt@9!W4R;5|4RhR>Og-tp zQNJE+FQ2)bJ|}m&1l0h!{yFRzRXnp7X^!z!vFuh`!Co6_< zyY#>AgvHDqaE6A^kqVkwhpvl z8bYv#$7I&y912S!iT59U>Us01i7)z5s$o;7;>uZ)$&3u7mU-ns%_egFl}r{aNBx6j`G+9CtoEIWcgcO^onN0Bs$ayZ;UxY?^H-+>Oe0@wHUqz_Si zmILeG?^tba5)!b7F$7yk0B+wBTj~bXnqL-eMHq_6gejgJg#%wub#51qr2*0{riW41 zeU^!Qpu1bnB)-vcpj{DmH{u5LbpePGe;yrG-%sCxwa)V;aW;+!(Woa-uG>$1OdIBllcs-(Jm=*A2;Y84I#_ZFV@!l-JST9Bdscz>$NpAJonAG60qp88~ z2t*NNp+JpDR8UO8!RbJ6RD9Vm$g2?b8YplL)SvES8Klj;jK5|3x z?!VueTA9IJQdIZUk2v%F#k{%3PFVpJNh#L`+XGMS@>`U?xIo}J^S%zkpj{O?-tQS$ zS2X?#0p>~y1XP_j(0>7*xjbu11@04C(9O{sQ7#m@p(?9BfKt=t$?T7$ix2l_J%|jN zmYD}5?H{WB>@z)2tf{1Yqs5q*l56DxKX;-{JbGq7+pa71hE_Q&W5s1Z=bOHeb5zap z_~4wt?< z8f{|2$+wuu>j6dsEV1Cl%(>8O%>`5T z;U>R{7VX>U^@f5BdFC8zl521{GB5FXkKkzFNMcL3bB|oCHO~i}+?ePmV%927rVn`$ zv+I-pklcCFIDD7*jetv@ZwDJ{M1`X@^GcUxbII9|rBAHeLc2&!A8j78k@RUQrWuXG#_YjjT4Jd~+y z%Gg>xuuYB~mHu<}KxtW)i3`-NtUl<@BU48YT3|8-h8VO4*f9s-fOZsT!M60dVgZ6Q zf)`qgNh{+qQ4V)|TP!B5%$Ss+RHB2G?3=^B?YF|c8E*pd*toE#=Nh|WQ*!F_*SsML zg*mQDaklz3SO6r5Y7JMRyGUw5?d@49jgmkH27MJP*cp46X3>y^=e zLbLOl+;&!Z*gB5|&tmo3aeo27PHs8h)OIGpd+lD?oD4CB-()(^X0}-ps=dbJ^l&hn z88ett(AdPKv}a${mI(JPl|Pua)m~11F&t78T~}6@QhRLo!Z%~0YWAa5uU_HE5m_O) zE*V>Z8=}|*_fpICZzt52$vEHzUZ{0*6^p$+4R!qf%g#+C0hj;$7fOC_U)Vl_TZ)8G z2pZp(UyX9{eT$OkyfYn|1?{&Wjld)^z-05E9I=Trn~j*kHxidJ=4>&ETgH~nqaE5- z{?91l?yvi9daBOK$_`@0^R`@;9tVBOmz$F+>xi#NmM6Jsc+^HP@EUT<_it$wS`B#Y zJ+e!~I9w+a}As;ULtH!yp<21S%7M4&=4# z*2&dzyj$Ci<( z=G0K$z-zC$&C48!Na}anwJZa*86=?XQa;j-7rbNa_ZSyzn2wrYM?{6$a*aWdP=;Cj zNCU_52Wv*@p^f^ieyhGo&H~yoQgR*>-{1cKC_2x0Huv|BpVMvE-kesg*n2ePS8b^v zY9#guHDix9_Bpk8i-ejdB_bkr>``JArM0&bjZKXjrJVo$&qI0QL0;ecdtcY*^L_^_ zWDc#{Wb-;O*tdhsC4q5z81QSJNa1)%P5zW(eD^rQlmgo?xe_SQ?F?LL zvVXYi^D^6XLdIsG<*?qMbYe$q^Y$<2TE9AdFG}K@E0k?c~0E(akCoCt`w(Qrhu#8eRSGvGq)uo7D5(8B`Krf9+jwVs%$~X{`&J# zuD$K=5ey%rYWIq%QA}sAoc&jAj9F0ZFDA(C4o_6U#a?1c7fJLu`^dYloO&cyv z8!Lg}R(2=`25k^#`McXGpe32Xj8muG_UV!Os!N=~m6KL(gWcb_Y^OR~A?N7K&jpOx zxAu7qA29;M9yLKtm6bPXnwdjorkID~{ZpnyP`&e)gkoLKyueGkeZ8)z_#&ojj~ThQ z%a*#F%ZI$dM&<5G21FyL=w9nU9ci|H_+(Ul5OVYumQSX=Ayqo6Gt35StDz;u+8d(9 z&T&Pu&iyP7=OtN6%gV-a%Z4m@IEba$?D(4%TE$?Ws0{j9J@D44bWZ(faZ(?G5E&$* z-K@0OXI+jZU4QyFr_#^9QUsI$v3+oSQq1;$e>l0Ke!se}aB_yC9m~%E`KA$^p^E2W zaYC^k=bh>EG`Tw)_Cot*tp_4onqoL*zE_<%BM+1}`5)p&sOPNBRx(x=7tC)pgj?Lw zf9-a&e=e9IL`^TKb6)MuP~H8(bpt_TtyBPWMC9&)9TFm3gWaKV4#|B^2O90*Me{Y3 z?SuV5LN;y2dIIr8n!qzjOg^c_gWB@>ZB)Yz4}VkW;=Z6>D`1~U72a0-h*-(GkaqQO z5QMY!Or*$X9W+_30FEG6AMl`Gu_?;;Bvd`*auG=PYm)0b0eD4lZY}@M^91>YU%#0ayq{zE(sLZ;rK?(wi^hA78ch=i zOhC{gW&V@EmTWnxcHH`S?@GXe!_kEY6k@SD&DC=O&@~%<`?H!N}EJ)yd$8a<{f+ znB(t1lc6_f_2lavimIvx z6qbGIEJ}>W{Zo}dv=9Y+cmObWn?nKh87eaOf+%U`Sux?Ce-@gLcHvXT)00^Wep~Gi zMlpY3nmCUmxVH=!TXiw2$=~C{#WnuX7^h#HW`&I(*X@`4J1x$@~KHnyVNw2*}fn%8ydfWc{mPPjXQ zjM?MRAp1dcc^+Fq!&^dWVjax3?|Rla+$W50Lol+1&h%&yV!sj;b6H0eFv=i~ZHETq zDwBN)v$e(obZ(`ysDLdgLAjx^s=OXQ+mM!>&=_vZH$P15;N8fFA>RMWh*IWt5(QX> z(9SjF?UnWSRHVy$6-XNDb1j#)|*LFWEw`TBtK8MW9n#d3ubvR} zJy}pjj`mJikOl&~qgcV-PFLbzD~{WpDRYt7;>ELoHFwz?@S+(^LnyhhIHc?s?(VE0 zoO-xz(402Q_Spb=&B|^?h~;ZQ^ZxLiky2Rn(3Ua7d$Z5?FbD#yDxtssCfe*n8SRK< zOc#&ZvvQQ5tcEmj#cZ081-x$?uv%BWbD%5K<9@>X9#KtJs22pk5`-uu;Z2;}61$z; z;!dmUvC=Fxy>N380L(~JvC|(bhAWHiGF<%64yg*a=C|Cqk{G{HvmqqmTdkZOZcw*N6;!w`SF+EguqVX#enbOrc#8 z&OS|1p(=-FN-!2X$tpgcvvQTT%8COFriH(XG+|Hi>%`Q)~a&T-(u{VJmsd!Yuon{c+6Nda>_oCG;T zjvXmj9pMeGzv+9KKU;Morpg1Fjd2Dm1yIbe|0H3ADwdq}2mN>QEm6gcfYlaInIQiO#XY2ym_L<*K(jmtVCvf^Ze#} zV5mDdGWE@Dw0>Lg{>YGF{dnZ07`k+bXZ$JK(t_ycskJE&S*dl9qrZHw%UQ*TQf`JA zeAf3f0U=mC-nt!hm$IVOoH$ZLRE+iYNbO!00Vu|yDx1zV9R4c6@%v1hsFO7%xNIdf38i}Pmxi7C5?BNF)d*B08&{@ z^o8j@199U0UI!&nQH#FUHHR+;`~b94$2S8G@*Dk7c>B+URNFlu>hPJ(5}(lP&js9L zqd)f3ff@HXs|n_KV|JYq%|Kg2e^h=Xi*m6AQ|?61vJ&H?s9kQb7XNK}OWSOP;OZIc zBccr}co5Vc4wHpN_e{h{!K$JQG}WWp!~eYaYvUwREZeT;AmX>R%U&Yh>dDGf+xsdx zIeg*i)8>|gJDHCyW$K4)l4p($T4OVJPh^4QKwhFt!6x;{c1VTvrik?gE`?$`qA=;N z_*wDG&OpU`M~T(_yPwJ(>jtQgQr%rlC|{&WrYO*azY1Y68NcHfxe@^I(G&~A zvd4hf&tdu5O-Sz0hni%b6|^xcs63#1^s~YqhsV^3im0Z#=TDb-V6=cc(eAFAJ<+~# zmTu@aUH?UBlUr3SQgGrPA4tR+X`#!&AVqA&(tahC(t@amvW2oFe9N`PDo14M69^Bw z7bs~3ET{tR8OlhS+$>n9ce!R3Ce7^qgq0q}od{5NK(!oSZx(Ngnn@`wGixub49UWqmOj{CyqJx#c1k^`p=09kuv zHD0vwdgo%r`ys`FM@wLsFo2smBbtx5nG*3fkSFuA>CE4NAc5=r<3t~|FW$l4{$&PX zexn0&@fJJp=01cdomnz-7RP^XDpL7~*dFU%K9W!|wakB3!xQ@ZjBdoU9%sz@WE;3S z#gqkHXijbiLaH9PNlT9K`siO~Guk7PNe*f~6>ue1o7+aKxOmFSy2&(UJcVY;6S{zw zoWLH3DiM=m3ot9H$IzkL6*KBUHg9ED>O}Htw6UerpxyW+C8*}_SsvVl)<64|Vuh}) zNiNZ!E}Wibo86yzDqCVOKq|Be8;Wds@2VthA8XB4ETF}vL`WjYzP3)mnz1BxPZUF$ z6-iLbd;!2aWz2Y==S3E6T*MU`WLzXxtnR2D9UC zwUZp2zT=_!>juA48q;+~9rs7jRQL7${^*hhOjwT0&l!;e-8wun6kbeJu2Gp%DqAS2 zi@?%y-NW;wLP$S;=lyJZqwxEg&CPeKXX$bTJ(ixF@MnfvcJbX|9^c7F+(|#GwEmavv$v=`Y`t^>h6pcOTab6&b~w~?>a!DpZM;ka(8Vbh#uD7BiUNn zl>-m>h&G%425t=Y59T78c-e zsH>43N}E2ld%g$jLq@4;op1<^eJ6 zN=r#@*x8s49cC*eF1P-%T&aW@79yHZz$nWX8-h#0rmWJ^ni_v9$l_!FqbIFCZ=NYq}d~FOD8}^HZ{rb5kABLpsx=+>qXxm=` zHwgXoocau+y3q#|)1T!-wf~GuB1Ge|$I_$(qf4sm5dyl3I4`Kw?I%nz;W--muydMc zR&gR_g*FUB_;W}N$@EcOqT?8D@03Fnhqm=@$My|2&^aL|@fLJxSxZWEadApaDgE6_ zxHy7o#j1*gd0im@H8yyVu~lp|Mye>j8f{LRGm!MDAiunzfBa!_q;XpHWcyK1!z;ff z2V0wvQQK6#U9-i7NBz1;zL?nKW%>zI0>$N65mi2MS$p-h-)TyX4sMyEMPGWa3)XFs z#?KmqUcY17y$mzdRfM2&&rm}wd-|o@s`PWkvo@tIjSa68rcVwdFq1yV2r!)QRpHzJ zCEqZ!^RRwdH}o9+Ea4oGVizvNzz)G6Q{Q|v!|Dc! zr}j!Zm5<>QQXxUxPWw%vKI#b+2ID!ZLv;}LZBG6D?(Vr$3pKSVIp@lmrJ7pJ!eZ~h zlla`}9?WURlD#FVRXH1Oao2hfVSo(`X3q2xM@8+R`k8E4|Hi+;C-wnNT*lg9skNrf zuOywKx*@>6KyOlPbN3*q+~qA1LUM4nE_nXTAtQ{6Ga4nN5K~@Qwhe)LUEfD&X8CI* zeT4N~SSxfnNkGvo2(YR!)3JqJOZpt}?BXL6;MsL3hm(H}vg2a_)-`vMau~n*{mz;L z^`;5eq$$6a;K>SZ?ix=y`pxlKEj;~zPov4)W}|AuQ8c@r+{wEVG%X>=TyWf8HPBmh-q!wUQOQ}@qWg36uco1tu| zwg_3Te*T2>C8q8MD{D@94g#W>PdR^k+>~Hs-sf~L;p89=6w4QUPuE6!zeU-m3CoUh zoqt|9WYaM9Z|f+QwLh3(NnuK*(NZs$SykeSk<8fAd7x!#HQDhoP3U}YZB(<|Ns0=@ zE%;yr*N`{|ur5Mc*#m&+ZLE|z0gm3ETOg~LRV$r*PFrt!j`D8ix-5W8M(>}-dqa}O z^Epy0&A>)bx87qU_j3&kE2FXkxXHl-%8IvOdK0U8EG|B5!5Y(Jiq{MRmA_bjXv`it zrlm0Ly{CMf<^Jk?WmB4PAY#raxXB8wX1DG`8R? z91B<@bf!Ae24ped z0sbj}XsL@Hds6S$DrieZwWT$Hnsby7NwcjTB>!8ZZY#(KfO)r3p@Xpuu>9?^@t#5E z_&VHl%n7f(OWbFt1N43%_D!#2b&g(g_GIDhSw#6tjXcqem7YU>((hgGRL>NJDnH3z z09G-4Sh8;Lqmwz@ymM4#JBo3Oo8(^W5#<3Sq1z2eGGdsq4RW0^vUJc_20Q7!ONzq< z^bdOIH@8TD>#2DA`li={nlqBFbQAcv?iHYEnmdaI9i_3~)~!?na(>u5fJGS9ufxCz znhcQ!>{Rdqv(Ya^^Iq7AWk|0H$xJp)oWbCxsV_%IJIBU&{}kFwsR#Uon1GXb!l_{r ztD(jxpEWY{zq7~GFG(G0SEC2gjqocz)wechTGT6jaqdP%ehHkKrb~)ylGo0h!!Cmr zwlOn^F3|sm8M$6T+POyM-usstuPm%99~;PZkE3Xq7Zk+3I3nMq{rv`6lU``WR`b_? z7gp0cq~^zp%~+u%_x~NW$7&PJ2nl^uNyj5E+IWGrx^{VGD94oe4V>m!N*Q8HR6xZI z-u7S%K}+~BDKWx&@dfCI?>t7}the~Y$W+WU*w`cRuA)avWDUX}kDtphQlCe%-M9TV zTjILuBZ|tRJYd9sdYG~BSxLahX}=kMn?D9Ez1h!GtxR_mw4#`&es!qW4yWgA2>QO9@PX0pq z(6((dC!84cVRO{{3;BvA{Lin!Mrv2A$)szm4t$=AQ69=p$S$sen*&yVwxgDMwz)HF z-1pecni52+(SI`6*BmS5@)(-C97}fqk7@Na6%bUN20gxz{VR ztn)iY_B$yFk^GULipWcujGB`v7TWY3;$N6ED;(xLwP!J-zf}*UU+vEVux^>T*;U6C z_}sVKDf+3$yd|C;e8WTo!1HEOmAS@_O`#x`*n-Ep%whKuyIY#lolR46OR>jEwKV;q zj4g#jR3>*!RhFxIs1eweTjsNP4zy5o8raZOs94t{beU6yov`}W{!pAov#viuO3Pt+ zsK=zORVq)Bj)an;$NkrJ?>!M_;sNs=f=PU+IPDMeP~_Ghoxr&`!$OsdnZe ze9AwITx?Z%6F+&c?T0xDhycX;4 z>2&9tJ8a*~-s`N*=ZAm8Emcabzxp|9Z>%?JfQgzKEFQOP^}-ApIs1kXLv_#bt|8vp z{r~;JaTZGH&1K3kD5Fr*nHM}H!DGt9zP_Rp%r{HC{$PvTc1%azU<;U;n;rk~tDvPl zRK|B0DT-_t#ISc(2kg-MA-ED|RKn|`I~Ee^T; z<(yqwv0H9ETM9rV$iCjn9rH^fjaupJufu-Uw)!@V*?5FKKyK#ZM)F0%3fMv&1{=rdCd8}FR`0o*z|ECd_N_rWn!_uKmX|{Pj zdF~WlKiZjeIIuFlQC0VCaXKvM+p7z)%4wAO_Ua9lklV0Q+h1I;gSgm$fVV{Ll}wA&HQ3 zm!`ax7sq7LJY5Zq(|WHXhrZYoHT16cET0|GbNNAQCu;x377% zG;CuaRr2%o<^xP>N!E9DDLYBxD=2*2bqxJ8vhv(v(f?HYAAmgru#=L#O86R+$PpsF z{&xKBPGQ6l?kmxcYnD#~IJEs=&gd?GUqQoaM+)!HBS)>bu5!2e7lFm();BfTtPdHX zT7%oT0+OtaYHmyF&#Ade=VP;#s2z_FC?rL{+(YvNGPU%1<6Rr&n{t&}LukY9z_+W> zLx1+|++>0VzoLz99nTNhWrnJJMmMfm=lMpcjfdIjO`SsarpZ%#=K;TsfR&Q|zU6-G z=|>G=qq?y@m2?JFAJtOE+5FXA&)f(8ydVGay{32lVWcSvJWUk>NjcTNJU#D_i#q@H z%z=1J-fd{qTZxndny)X5PMA_UuNbi#9kg}a>^b1ly0!7&9|M|~W!gKzXTJaaQ7Xq_ zF^Q78q7_BWz;6R^8z<%>y3WPGs*5{a|NXJqvi>vPp;5R}Smp|-cipH2NW@=e4OXkV zND6FrfqnKjfI~0FiI>+@^0(c}cCrJ1u6Vsz`_3HRUO_){KBeWd1B zT76@2oqfrt1#Jg;G?IU|Hya|fk3EIS;pSZ2zHaZ_XSpB|Q1 zW?7vtUFOGLk>q@M{o{O!%`hy-NG84_#E1ak8Meam}P`xWSDj z@jUo=n*t6M3TUl_=(|<|mbk7)2kW#1DE_)`nqSXH0#l25U1lU;1fV6YuUp?d7np8N#SiKzPb`DG&j`)lxmi0 zudgFd01Zr;rSb*gez{!)M)pT>gIPXo7u9F?3C}y6xL%h2cCJDd>5r)-`^JCcBO51t zW0QL@DbmVynpo<93NuWar{scF-%LF52)vn=>UjdkaIsofyy)FuFrm!+meFkPbMBcH zd!0y3z(YTDtp)b2zFaE+gb+Gh#Sn$>w3G=C@jKlhP=CKavtBA?oRGU(_nW9%WeU&? z&KopKr8s_#)3T)r&va8&gv^Wgy1_LmrY3r{b`p7bceuTvpzZYa>%d-b44~ zukP~py%9#kP(2Fn#c`NDsI4t=Y`s|(pW>pSdlzb&)okvRpO^UxA}M3zZ6(!M3mM8= zop2E==AcO`XQYuD>rM3=<~?Lj$a&gh23K^a`|K|+b2^=kXD^m38?ViyGP^r&CBHa` zD6egtX>(hBWc=cwKe_&g3WM}^DJs1ux3oa8yP)ogn?M4a>QjfE4%R`p48Juq%p{!j zgb{cHy%KLhiNeuNc8JM5cvo;_Hc-n~iM>J$d1mOMeN zEXmo`iEY9A=ZDn!=VOr%Y;AOEo>gw-qDSM6Mt>t8DD?W4^%IQUKAfeRN^R%u%2}nI ztlR$<>G?)SE1D)0?Nf2aYPoCuj^d)aY0eV5qg6V^rxL5Srm@dVUtkmT&9gSA%m7Z! zhVZDv=066Md}bC(6+6gTK|oNqIPP(exd$+aIddwoYBu;YodP6oQhc8A4hGAQQ*;_0 zN(W+uFv9Hr6wq6;(CVmi-9?E-cgPp%48KkGS&}=1w@=3O`8Nw?zXr=NQxW{$N>-OG zQyd-jK0^HSVoi0;i5W-_TI}ezUttOWk>^7z#Wjb~_4?gBC`OLSIwse_Q(!-dz^fe> z^b0Fm@pAQt@U}4H!E1&CjDxZ2iq^e>vt(HU&w$fmct2Ab{agoK%F^xq#)LNKswEBsZ~pFcS#0H2U7b9Pb;biTt!8|r z=5D1|^a=(tn0)em3j62 zA;tF&AgZwE*QU0-z?-qCTMQi{`$|@=^8#>*pS@9fv-)8W_2+}W1<$Cq5&8Q73qc_= z6FB1;8#M+4wV8hl_rZG*bs(6Zz_Y&5SVL)$qo?FpuS>oLv^-7Br0+=)OY#V43@c0= z#DN<)Bgo+H?4RN(0h(71>%Y&Ze}-H+N7*<2KK^;QNZ|PM7eJxAiU049OeNzBsmNRZ z{V^uYHoaP?5jAkPb0_d`0P%*ZyKvY5BrW2!|5vN@IGjg;w3DmSxzFPYmWjwzdEXAZ zC@AYw=9~TJk1oiqHLG4pv5|h*oIf zBv#4#3tyXT+>ogPxjrxElTIQ7Q>zI7VCA|a0{{ha0JO;`$_0|9#DuI3>!P|7zvRoU zVCTt})Nap`B2kT@*@mp*;VX$K=HddimmlV0ffv-=yD4iE*0v2T0Tw3y;RH$BU1f(q z&Qzs%yw_R{9_j8Kvg{hY=-34MIQ%7H^Ykw7-!iJ(UAZnScMO+xcmPRaDVAOSd>^c- zVxv+LTpu?i(RaA!(f^FYWw4zr4kd9ihhk#>+8vg(*BW`9m5GB?{8c=uJJ87AKYS%; z<*r$ynwvdO3Xafv{HKB*&1T7(!i~PMtm!Od{h;rEJJymfgtKT3DQIyEwqkK>1N6Y) z@%`rJ=7kTd+^7Mw?~QU=8RTiz{4q~XDKp#++z{QODy^f-b*Sjqe^seH;a<<8rJ3UicefDE9o?)6na{>BNDg!DzzsMQr zXJRzfVvk3p!8h&C8}}f4_3h_rqc7g1OPe;7o6lv})zzi=>=i2&7MdTOpo3C$r>{GC zWq&^W$U59fyJvH1%QQdDRQ;}X^n^LzX+>gCg=Pc|$jCB1X~=tXmKo!%#zk!wo3LM( z(P#;;sqzV$%YJlOcwebt5(1T4gbY?@gpZs;Pto^lD)2*@pX^$>9IenWPU!5N>vDhH zyL0avMqA-#s##iFTCAZ?s%2ljGoOEEd|R=0sO|5!SuP;I*MXtRB@@sDU`Ym5I<1lz z=!^1b4kNUOV7Z}+-c1*W4TQVx_0uL2|Kx}$ecB<_m)ge0iinFxXI+C1;t-@nKHVVC)(B)}AM`t@=cX z4RoT_tx=kukp3Yp<9{XG34}lXo_TR?ogw7|MtuY+AhU)une=$PsFU9;!oLVnQE6Mq zO;Kq{9rJcr`o5kjw%N^Wsy}P(iGLW{sOIvjFtu#^LlU{<< zvdMr?FWmeB8`nS@-tD#rRk1P7Dv$#oKl8ne)XPoSnzy-8fUcyhOEKI;WUhWIaxW}k z0G^L1hF`9}G9yGq*uZX2lGzupt~qRI?^lOEyhT>aWX#PHcE-HuFb5PNlKPO!sb>n9 z{~0)k=Pz?JeP7)uFPAUHs_a~zC&~t^cJPKx`)5E)#!oY%>%G|_@@VbI|2HE$EOvEx zJPWHTX`gTRX849tgPPd?`1uf+t^8eh|7_O9%~|jg6T9+|w<2SU>S~m`Q2qJirzF*o z)~wXDl4hn9VKlM3&tO}ns2U65aBtO#u1zTiDL~7M9A42wWvwA5{;ip&KLtfWN;r+N z;Bo)TO@c)C!RX`|)D+4Vlci!>YheP_E{VFP?bgW={$PUSO>!QWRi=AI02F1DRfwm$ zGLqh_0dCA;0?ZZ9LR4Pm^obiYjFDAsP4zbi<(=kGm)oV9YFz)Jw%KDN}Q8u zsFxI*eYr66O8SZHspK;Wc&dhWFof--JUOYp1gpji*~SC}6sVDl=~U<2%$o`3`7rf? z3G~DMS=C)$*eh?{y`^o4WZ9mEXTy<|Q`pc=QR4=i=x)=I18N+c$KTa1SAnqa^*Xn)-U^nCDlsjr{!|40O-% z_!{f5I<#sP=xu0IpP2{ndJ)pTD=N2UbFy=&x9f3Gyz^s?a@mdx@exKz0si*N=sv2x ziy7KJK>jvA^6W=Xs`~sR3!mfas`o!C9b&x)r%$U6Y^t8sTpeGsYtsaO%UeIBX=Ju| z5Ig=Fk^SM~L$Z^#t0;{B_O0Q@uJG@>YRjLm@q2XEgFTjq!O5+d`Z(?S@D~UFvggGP z_J7Y}b9Gp}i*xuh&+WJ><}5{v|L-Or%LI)v3_H6~(->^aEUV_MwA=(M)kl8bG$*gG zn&*9i|Hb>W5tVRxA8b;{SBKRMskG5BPvx^rD*STkFi#ivGA8dNBecj4S%PlPU z(&uGmW21+>m5dqlt@j#p)$QjjS1sJ=my}e#9IqPzbF6@8daAVMEya;wz)D|z zf=VK3OyMP}JnZv}<(zf0mfj@=ZppT3IE@=oZ5UcZf)*78HRqz3Hv{J99KOvyL)__{ z923`-BP`7itVLvT`QFR=^zq}~RcOV*%$7eXzV}7nszUI=&p?fh{RylYr&V9eX+~E$ zs^Y#`3QQf!^q|1%@M1yZ4bfidqoY5M@X~0H<93_QcgjeLzt*V9zgrS*u$sHUmn9qs zXhzIxB#eFCm(x9xe{!!99PAc|Jh7PCotheQV55lPYX1sfd}6H6dZY2hPQl)%*>&B& zpAIXEzBZ8Wr;U9mo9?Gp-|e2t+CO6y4NYfAs7ebWd@Z&%$)~-6#@E$m?#c?pEV<}`$@lS!sX$|b z9$!QqMVFh5^69MiHY&J0uFUeP?`@sE0mu{GTl#Ods560mA?}Bw=J^A@nr$uS@vZC&uCHr z1@XO{TAWx;6EzLQ&r|~FkIWvkz;{P z1Q9H>tcYaI3<#0pm$s^@0`Nx7+gop=Yc8|T4T}|A%M)6mZ zaVQvf_$L>@jAc{A@I)FXM|9fMn}RzkxgQv9u46hlBay^e^5LEjSZC96)5*(E^VkTE`{SM$Ggo1vBcfrN$Io1s=8k z*Zpdq&*KPaa!s8M1DW92?8drn*D++tD`ZwZ8n65GiG3hp$G_>*il4gs#T}O{|4ES3 zCE!c3E+@V>9oR-{Hd(72qCxL$tFd3;L0f9>JgaW;gm{v%bj+$ToqZZN3jpZF(kD*h z1qS8w0VT4bmasHYS4EuLV=#Yn1eNrH_K~67VL`ciiz_$y@@q|X+|`;zG$h^d>g$Ba zl#Fy0Zv(D(uk1mZP3-@$u|2Z)QYmUR>3z%l_5MxLLbqApPZiKBZ>`ks*}BzWcWP&s z50nugPki0bWOyTQJY@uYmSYn9VBJ3NpAH8-c0h_pL4;H{N4kL{)%Xp#?O;SkA0~54 zh#5g@3NH;QwkO}|yW1nK8@ski5XL&x8a2ERE<<+kwq@*5e^8bLnyAs!Kx3rR*6w%MB-V!X>fxIp%DG&jMOfj4DE}&3t=&Sq zX3>s;`G9)cGY|pnYWIW_8to&mw__aB>6(h{YblMVMg$zo{p<=O+H9PM4>oEEHI5z+ z8|@zRil75V<1kb~&jDJh{oWnlf=LI+5{^aQ-uaSP&X_Km0F_H=tV{h4(_Z5Wl zw1M{zJ|gyWJju35eMF&Ti+>hP$S|m6K|%Tb(BIv#-U!!HvAg)3%O~8s8&n{)2CPa* z$6E)(oHF7&T%b6%RESAib&yBbShn)!$4jX*rRC%wH&Jqi`y+VfbgF@jZ@0Ben=z|` zt;cprvLNL7uBl_KYH^@o12MGj*5MBfgJtPkhP=O*RHO~}d4~mL)fjT9EB{b)-}bMm zTRmaVT)`#$d)U?@j~#H+iR0s;w@i7Y@g>6#pMV`w;nk~??{yT(qxxF{Tya1kY$Kl) zP;RM-0yol`G3ha7LraJy)n_Ojl%Xt>Cc1nA4Zx9wdkR+e3R(Ase$Z2hmNuT&=&ahl z&GK!+$@>+x^AyaH`^og7y7{;?*>bq%pVOL#`gu^tch3vHoTkcqy^vBlvHtIqeyIF! zGI-2m3TrlE3qBIasESB5HwWo4?xQEx7A*&PQeXwD`#-bD{Rnwf{$a@hPfCRTGN4di z)yx8!6ljd$Y*^l48P!BJgXPb_a1pkW%M@`v`I2(=iDHn+DUly(b6l`Gao;a!{tM$4 zU)pC!X3M7E=SB z;P_s}7Q-hKW~jog0r80wXG$R4mN3o+aCR z=0@hmja$Cr)5JqwzT5LP-TPt6x>(1ZI~krWJ(XwC5JW^M*{brPA?g*(QX=?V;8~?p z;m_I+>v2^t2RxaY6AK>WUDBfJla~6FdBm0zduDpQKZbL28ui+`!6Uw>TVb$egE3AXw zQo^{>-42AQx)($%+o&kfaKpUSltjVV1Vi!9}<5~h}#k&_03nx>Uy zPDdzdqBIsBBhG7%w^2ENlQM7LkNFS{AzA6}H@yB2T%;M4T9o!ErS{6>Z&=B7l=9JN&XQHeq>|{$zh3Td(%&V>5Yww?|8?wLMk^ zNr=51cd$OoFcu3@&byEiw!-X9@n?$92^~IsZ!i?t9+}LNK|L^`N(JQRX6w8)H zG|Yzl&+@gHEe*NEuO|WHw>GRXH_OTIXL4@bHY_@Y!e|pBecRVGHXP5gLNmr8IXZ&? zMN3iylTRk9d8h8P4-tpQjT{B!CopU!_w>7CpP5_;yA5Gi!sM=>xlqT*sSI|V<59Ka zP|eUT6>(}WmJ%jIKdB51U zG$3@y0^sTy+t%C047rZgAwW1&7RLw`e$=(>TEpX6O8}v)*?Pb(Za2RK(~lM3rY8vB z-)c1bX1keN6;0+RX^vA`Qcr4?hvCnE95aCq#g|&t5}hIrzIpJyPHeZ3&y0|k=8O@_~Z*xs)SrupiwcJPNQ4A(A z*>aCoS^>y;_R~CywSCIDL)<-^0+cRS-;vD$R}uBnl%IjJ_DNdios7)O&NNqU2Eh-> z0ksbO{HU3>PWH4D-X-H4>XD}TQM3BXvlMGIt$p?eX zK1)WpkYmFO#T2OWBc%-TeN(uYp%u(>bJ%L<5lDD;Z6zU1GUGuI;?7j&S6WA4d2V@^%8K3HWl z0>YD`!qHB`4eO~~^-&F53gxc98O90>F;*|khR7p0hW9gX17`b^6f9x&%dKZ7n>8YcaW7nbk& z;+$kLteIspE%`;U7t(^u?q@Q1NNFJxfl2Lx7OPW4={28h6>p|PONaPMH;Z4&bgI?T9R?mmZg9!AIFcR6ry=@D#Xv! zGG2BPJp>v=PJDD#rX43`TIN;*+R)KnCx12!x6B)(z79V1=E;gheyB3YEbvuIURwH_ z-Sx)SuTDjVwKWEU!j_rl6IHCTm47wXwzjHT%;g8{GG@!GU`l1tH?qAs8t!X@xI;s( zRO5WR&)Q&yP;T~|F)J0f*y5N%=2Ch9>EkzBdi&3GoR(+cXIx4~#dmyMu%xL;7HIM` z%+I8My{VkXi&+t4$9L?9VjL{-mkmNX14T$~hudlYF0Y#!A!!}#MtR<)H8L_I|Xq@Iq9?pyKGuonW40B!uT)vdLhP!pmi zJPp*rrces}^l@@hGX1(}`v=2{bN;wO+H4;?%R8Dcor>hxh&)e)sy5ROOftg0oo@oD z#g^OFR|AcUt>i+p`pCKcZ#&3?>yT-%3w3*&#BJFz5qw0lF{1Lf!mfr!OVv)fEm*Dp zXWeb^y!#j3N!HV}mq{EiMHj=a$Pi0r{$WLFCPv+BvN71q$%^X3DnRE+cCDA}426=V z`wH(ja8-DIVFjy{maFj+UM=sN#(L$&9^{PJ(pDv0ekxemn&-x`-7T;ca@n0jdEjHK z;O$Y~;t4$$Fh0Nacjrngg52=wHqe}K0xsHks_JK|ICL!he}C0@i|aLy<@Sx74?&xs zUyrDkcC~@Q*+<^eZfE;ofAdwZ7`C#!bE+A-Fup$&sQJx|(q@*11nVlXfPL(e3dNwD z_~>H$nCyo90fS%S`DT9_={_9F%YGirFS+Z(ZrzH}f9)Dv z7l-=sy3JqypYF0(@Qp4FmmEWC;1|gu+1^#jHHTdv`uzQwFAD~AP=R;Zk0kq9b?PM_ z;3Q@PApx|uh;Vx))`UTK>V~uYU?DquA~auw&apEPj?#$NtQ+ycG6-5TOOxe+358}=|BCtLrV}K&@-N|wg@(CjLAF%NZ*`aB zG8&RMjllQIDAW%vUCEREHz}4z;6wSmDi)P~D!L0-&3C9pdm4?l=oh_?96ZT>RYXS; z>CD(N*bE+aMK-k3*U9wM>Kw{W{0V!keNXVots8r$OO?0jz)UwG!Bh7jIO_>F4z$E5 zL3LA)#dYk%hrE)^S1}D1Ua-xPyl4X7SG4B~qGuu~yz03Dor{o{5}qf(e9Ek-J}Ykx z>Ohg(<$ake3@ESk7VMtzZA1!OmS`y;JJ=?bc?YeojGglS3GpM0F6|#@a(u8ofa6a|WLDn)f{mcwPV!1u# zo@|KA(NIPKfUfJaoiX$YmcEcfF*2$2uvcLWSRY^TB5;{BjX1taqxV$Xl2tQK$(8B} zjbh;nJr;V)&{wg1BSO6Y{#H-#Y3a-R;K@B#S>r-nbhj6+ZJH3V6Jp}?hEAJ}d;Kgs zmg-a$ZAr38PEheB55hO=i*_Ym)4iH5ZK`9ii4`?g`c!=;0P~X3M;t)?Mu;ntqaRn? zY!dKUU6n3z-DR*Yoq$X%;~-ghQN1CQXJ@2?MYVhCqvQRWvpL=lHvwi<9FHDv>QJ2* z)EREu#Ly;Ylt7uv?fzO;2*Oum_;6S_+RXH#tB`yDxGL^n40XDv;l~GZb`m*fG?+&@ zIWNM$cud(_b4BaRNgm*-(#|u*a5Xe1Taw8IFOhJWqY##pN<^-6jX*O-NrmF7Qodiv z*PsF|R04gZkqN5@&18@90z*c5IXY_~@9b$FcwWDS7*EDupS0WpJLG`vxk}Y!3&k~t zJy!#8kbDJHf1WPJOhC9k*4?b?P0x$&UfB8x%)<$9!MbZc@5XtMF}SYRyx$q?^Ye9M zNY_+-gn@a>g-}tcpyHAgXHCX`e?XaNTcH&){#@C`)^%2w4YLI-%-hFJ3-%53A`o`B|`<6ExL9VDqC6??=k-)eCM zL5LBns9l?iecRfETO>Bs2$G1M*tB9?d+$-9v9&R4-(P-zLXywpllS|a*X#L=>2-Zr zU}zyU2f?=P`?WrDigui)gS1tTBcvT9%UJSUWUD|G54#*|j9Fq(j|0Q4aa?@-w$iK= z7yXfiE6-;9t|)h*Qin_70z?zA&(w1WZfclRM1(DK3AaqZsBiX;@J2r3m9~m+dl+>( ztd*~ixTT*SLLgU%eKpyjQ$z4`6rKI+&+Zke%{; zS?;t`T3X)kzpi0}K20{SF&K%rtkTRX_n6nM!}Z;sG@Zr&CHVu`SYM#|v;ScFqAOkJ z$-H$SrtvoQTY4(F*R0jvx71Z)sistvKBQPB8& zueF^Q3$2DbkS?7bc2U59T*gXs<9Q8Q@{TggeU~{`KmpyazGJ>MOjHKtmGMm01h1*7 zG*WgN4<_;g$~Ymc`Jq}IZPc=aAoZB$4&oG{BB*3W`mub|bfP|^o&GD+I~mWq3-*dr zhq#5c``w%d(@f)gT)Cr+61z5LBRHJZrZ&g^t%1s!lvJx!fO+D0S}+F8+>t)4U34{4 zTLgKr3`XyzfFZf6)x+&-R;QFYToq?R)jgNSu>8zwINSoA(CtLgE~%L4F&dhmnQMC9 z_r#8&m)sCmam_~@rw0mLlg>}PC2R^gum7E{puFk&lk>NqFKccGGSmsm>*No9x>d!f zScbro;Tq$mk@qbJ<+LDO7GyKLZi$PwkKDhSlb>^VwRIqfSo&O0wH!|eGb zOuY!wl%s`@xcTRNC_j(p^cS9lC!dFY&ncCA8a^|X8f+j&&=l_1B8tB2udQ&=c%~s* zLtbw*#Lr$q$4-L1`CfEE2n@*bA@f)_s9rk6G^KjTYwb{Fg~nxTSYwsXA&)eCz+)Y& zW6Z2$uss(iPG*ZTw3CKUL3{xD=4akYndfOYz1p9RA8S4IQnnWuJL2~>=9R2)%rJsW zJ2esONKF&0RLj)AoZeek5>6B|1{><+UdH=Xg)0vnrv0M!g(s z_xEF2V^*=zPVAIPs<1`(g{JQ>Pojrf0On5hcZvX`6akD7&2vIMsN_il0*<{RJ-Iyh z;VJ8}_g|!EZlqOxXvT}-su7m@jh&FJoe*-z`(^P{WNj}QHk?s9_uq|9rQP7@-4<^> z!)fpOst0qh?F@T-=;Jq)Z(cXp+-&;6xSM`s$g#Ga1=!`%6la9=m$FQ>N^uR^&p~mZ z^;?VIUF)-J-Z(Kp*@C!S|_@PX`t?C1Ml%t24-y8m@bKY#{h-$;RgrA0u4qR30>Q_W>oBR3P;CT*{~w2?HeRuG4O zWBeXp-*3QZei?=DEi0Y1p#w!G~_%=neE-Be-d+!uH+q9x2oImUMzEKEm;@Z#SS`))45qX11+jm+3St@0~c<;{XO7^6ad8W(CM*TE7kBtS7|G??3CZr zG~}``6~$N4vE9R&f3E4V0usf>AYG?bQRhE0R=1ATRgQLee>QB9`V>L)i!jBWb9y|| z#;==j%>QH&?XmxI-*#z17_;1+YR2y8N8)z$w`SH*y2;y}@zn&&w{Y8rj~29}$DTOg zcUWbr42&I+%Z_lH3dBNBj{T;@ByFg10)bg|@pOQ_#lP59z{D5F!`%qEW3N@DB$Ir_ zTL;|=xk)JFB#MV5AIs2)3y3G-B{fBF$NCUm6pq-g8H@wH>6!4a>Kz_710SvtZnP-< z*HS!MKh~PY`mQGP75IKmH7b9t*gl!{;sNqWm|V z-TbE8$xmau($T)1g`+0hdip(zBS;9wdGg2lMjWro7w0WK&bzxCSyyh{$Mf}DxPSsH z6_-=ElPGY{%hAh8)i!h+D1Jb^50*Q!@x2F^wx-TpFP^(%FkVWulECFfTZbLiEuLgM zx%$Q=mb$?#2M?lY>CcZPaSP^6Owuk7+8++cHG<9rZeA7f$9MH`r`mkLSa6WdzXD8q zU)5wship4okSSZ*nDE}62Wi!4?y-!M_GO*CS9J`h{i>BVcRv&-Sicoz&v+GCAoglM zip&y6cEW#~*U>QIIZbM<$%G2x&FW$%MZXJjDi%B@GHXF67Od;0j(B}F;q5(m@90o( zZ#KL_xBrv5&tEg{_>1&jc9F18`Qlb*3*xGkm1)}ky?L|nx^)C1~cn{nn*VPzDYJ*a4@PN zP70Bd&c~<@N<%v9);^i~`*U2#ysFDb&yV#6MX*`=tlVPSG7!Tz(ekk3~Q zwRLnp4gjQ)k@;x~!oIJ_EJaFQb*&4Iqq;QR)bToVnIRf*OU_kiYz?_*7ze_)n4H|- z2&E18rPjhl)6hvIH6mZpE&6U(7mx{+v`H1bnZB|)hG0^}9Mf;$63u`%AbqxB&y{$g zX};>BlJZPU(#Vih`uN5D)Z#?)Dt0=4Y9na~hwnE(v)vwRQxOMij6p>oWqxwESF<-# zil>Ad7`S^MvHY=Zj9-57_F!|xlSat*@-6SLF~V>;?AF?=ASypP=e~sWu?3lUs(6_9 zj#j1hLjU!8RmaE9q|3(6Gm1f8c(S{%BB{pzzd1yBXs6^N3^mmd((cCD-!bnHVT${6 zl`O39zL4B(>4_<4$8;4s1b=X@p`nSt7U>C zwHrQdq7&)&Ki7<1PEHtxu$1Q`zvXX}!=bvqm~NNgJ^ox;>9k4HF%6qYb^**9()JYrlz`o5 z0EP2w3D#UE@fWffivkUwhbVuT)qJBGTrGq=nfinfAq9Zr^m|Z(e_$uS7pRm&$Etwd z&k2unr38LV7}&`(GGZ|;54Yx_=aOOkSdUJYpj4V`y6c;Nh)9H^ji+KZUU|2g+v7`GVvZv?G$D$ zxgT`;InKtOTj?&h!Ea=h+=CBQ_H8n|yKjwSswCM}CJ=A>QzJDGQ^j zieAfogNN0sZR=M@+?t%`u)@R+@wx^)_92rF zY`avZ1)7}pip0}>R&H^ZJlDKamuAtFX98kGeVGU&U}?^0c$%F-0-q}BdXzl3AiPsA z&b){C9u-W=H3;Q06tUsc70pl?_CF5H&yyx^G_`5Gk!>_gGq{NYobli4r@O*XXkpcrG#%rvH;-zMS;_=b!b^HX=p~$fBpu5x} zS4Ka_{d^uRA0VZ;XA!XlizF7by6*jm{k*ts$;lZzE(MvsUs=88^o!p9cet6{cbFo3z$uDQ9Dh_Kbon7Yv=+B#I#j%71G)yrJwNW zz3X&5Sd?Ozt@x2ya|YFkLvxKtk)z!$dz(GwiZwLvLpon!-hY9VX}tJVBaJo-I8M9k zl^b06&fnYD&n>m_+-=V5mIJrYwO8aI#MA#_SfS=^_Ojpt&@+Dxyw=ysE&Hj zcSQ{e+pZ&bEjizJ>oM9e=g=oNedQ1<7lp@=!nDyb=0)hxa)h&CK6d55(p522R+b?TRp zs_I4B7sLaDs(H4~Fyu+jQ_;W1j`7J-&#O31bz6*??6(5v$U!-5He_c)uVTm#>JR&E zgU~0|e>xSeb(s&zFD5IJ*ZolsR3w=ha^7I42LKnKZ#&Fyr!6hOe&>}>fPRfhJQHXe z7I3}yh|$OzV5O#-@PgeQ{wAabpY14Tm8&QOj&Vsyy~`TY?YLu-k%B)M?Q-1ECaQrA zIFl=WY&njdNzr{T8rBQ;r_m?Ur1T%-)7y3-Yva$Q24^-cIL6!ABTLQLi%=O0x-SL% z8rvo=o0j|k`uQjM-#k-va{f}-Bdj@E@1ql76{DTXkoB{CRrY9S6+e|!X2zb-*%>Fu zwCUuC$fUbmxGyrd&#fY$Z$#MSbA2lLDKLCYuqXp`M>W8-;AOE`hYPq=Si9t`kQ-X~ z1Ob@x&_+0{KRtbaexd)qw3v0?4?=r0>Wb0;MH_k z>*XL69za67(xIvJZ}YDHvn z6-k?>V;Y?6)aY@?C>#}Fg`I>aL@e%SM%5)1Lr_9&Nmy+nK#|s{Kf;=TQf9O$bOxlc zypSOqu<<>Ckf*=Ui4d{`J`!CIU)lV~F=;!#(}>~3Tfu1m;gTn5!p?@cSDAk8ykkMy zdz850CE{g(Q0n?tiE(x*)qAR3V{N_tkp4x>kDNpcF*AVM)w#3W;Hpk#s<_5o!^iQR z6n}I47+H_)eF2PprB_X%M0e$J>C#2V7OOanOC`YY3-!c(U96tvpIl{H#2n(1#M_nP#zoMd|zmm_GM;3 zzI@#$ci7&+qEeleZ--6qwuPd9Xr$_Rs`lAEjHu-Ih>+tvtOEA z>~Z}#?qFG>$wZ5KsW}qzuaSN@mIWZH<6(^cZ?&yD?|V%VOs;|~?~0j(wQwUWIjjB(CEKf*jPXK;*g~F)>K%5} z)cO~)VD6QD<`m$Oum;q+Kd>rOD4tT$ncFq$SE$4`Ec=UW)@_R6liYILhr2tCcbS)I zD||8L)SDZ}r<93Wa`Jewyzj)d(~o8I>%kL2TWC`HfO%?f7jxM*tF_&W+er>z{kiCt zAP5{7X;0n#$-1ZcRgv`hdg}?B0SB!g>&z~`7RZq4IiT9*SUcYY!EoVDL0sEN6z^~L ztSGIUmdvr8xc_c66QHYd3b-l#Df1eEQV&R}%Pz%?HI)!IywyXu5Qg^Nf7eNcFZuu! z_v=s`F?iF;ag5k_4}{!|1A0z=LPp$nKUU*CCH&bqv93(|iP=$xG3EA)6TOLm@i}T=xMO(e=xGnZJa+hO3b0g7|4v|qwk&GguoV-ACRfy~1 zGSdOR>e;HQnX>l-+s@*zB0DtX;K86c{>iRDON9L!5e|JdD|QV#jVPNJKzy8aB#gdg z4cZRZ0Q26BkF~=6fsc>liLWoFPnPhhQXrB5ySQb~DDfH8N~))MMj2MH$YV-hkp6e$ zj~>XlDg8b*Bbt8yNg#fNNqF6QBlTXEBXZG>tI3}|ik%4(;IzaX zWg`)r)hZymZSvu(tGw@RJvwj~FjYiK<)M$maZZmVeeACa1%j%lRzBg4Z)aMdEg8Z2 zvPd^RMml(-$I)Mg&4R=LuaMFQapI6x{d&*YD+`=MFb<4&)AxPWyhd29w@sANN}orT zdp@+YIg_|apI9w#XJ|A`jQA_c5%YNo={MDC>09Efa5jrs>;NwVR|UVCbq@yyFqi76 zo66kW7~#Xo8dt21dH@xp)b3U>#)njCKqbKWOqd16ttz~67I zx2%_7WxcpW7Rd?ZwMlk=v-iVPO6uX)y+7w`k#{T?2!>hGsl04@5?_tkk+0-rdz^8d zv1*Nr!iK>x^9?>tPBs{PYqTIj!={SKuuOllN==@cf*syxwOVl8mm@n?&+gWiK8%$F z(?d;YUF#UM1Ah`m5<~zX{p&q?h_+w>LX95={Fx}=5tV-3t0|JpFK9h3@J)Ntx3Zn? zH9L8fB+)&!)_$=1aY@d@`_ZUS{mDNtSa);~yTEFHxO=7WzJmBz*F>t&%_OwLotjL# zp90=In`pom+ohW+H&x!##!yp1YfQ1lfuQ0hRoVo#{uEDB!T<|ypicQidCjDNm$oX{ zF7B(2)6*KWL9C>v60k-kJ~{PH3Y~FJ*@4jW^@^XjaLCF0&s$Mtr=lkcGr?`nkbQfi zQh~>60uf8hsaL>ybZylv!EEeoZ9Lvi2Q+WV+im@H=hvWIXs&Eo{qH|R)r;_nLYHk0Y&K`ok9<#E2AOXbH3_u!6^RRC@ zq2Z%gKp=rf&?r7d!LYqlLOxD`TaV>^7e!8Sd&OhbB`I&CTlf7y?Yv2l$18Ws6k9oS z8e1MRSnVX{@r%tX8Ok^v6+p@J@9WM;xn>@ucpJWv%husEz8e=*qt*Dul3q{Y>4WemwZ)JNl+=G@&_&gH!r&C!CU^$4xRYQ17dJMfWr)tD7=> zU|;R({`M_ZS-g7~!8gKfc0UC#;pDIA*BBxF1nPGXBW{jONaeh(ohr!rXxp5S+;#EM zYtGb+E=aGgM}sOE=SQn7m64?)dPzUSTelcndWzSKMcpzrzA&W~ z20Ad>JRTAHfVJ=^Q*#RLA54_#-N=`1jKO3<5CGpfkW#Scz&zmCQbSm*VPI`T9vZOt ziwzWH|FDu#79r+{Nr1zG%PBbWqfOkXX)@Lf70j+i^nK>WBkyyU#=08seyOl3{s+?i zNXl+3e%XRf8-uWDy#I|a__*r3Wc;;Wj?5LJ_UDx$dgm;1a38@Es>8I%NRj z5f&BgPb2(D)$npd7d_k}(X#t1U_-TO&n8!77HmAu^de{ZSd0>{ipA7-mnw*FFTSNlSUn1}uOWwJ-2A*_a9O&YL4NbQUwRM&@9Wk>cLq8#aV#`vy*5TJSdW+&U-|uzgK{f+j+YoT{%z=L%b+7#cMo3OE6(uY&zieG;0z6yGnRrgkJiJSDUek{8oDP>+RuG-nBpn z=>w!D{a2t>azgG8;eX{9(r^9^4s3kz_djxt|7iZ;n(c3}jHDi=3n3w0k4HJwv$QEnl%&iD)g zBYh{_xDNVy@&(#=GTNK%j_8J#$im7W`d-3p$9mw?X!L2V)SYMAA+*vCH$`Jf_fhoD z!nJPVS~AlUQJJRH8E%HI+@6?)%slUJFMlrB_mPe)>Is-Lh&I&=z5t$qwY`~6Hg68~ z{1K^4kzv$BZ>Q_Py@M9@1hPu4?wAT6#qcS04_oKx4yJA}$oIF$xP;s7j5R!(o_C)j zh8=q^AGF$12}(PW-d+oC;pZOVzQM0Y$lp$-x=dcIrTy*SgXiyrTlTUpX{X<{DhQ6e zRr&jhxJ$%}vpP8Nm(Bi9j^OU^1Z#RV=e*yZ{QWcDYxBpD(qvvmjraGw9 zyVFbOmz6}#_5W^s2#Wq*5H%@yqIRiFFO731No+;X!P@~N9lQU3qAIPqYaH|KN7Kwz z%&Y%y94!T&zo=SBo4Hwb_TPc`89Jz z)+ML;lNmeI0l(LNlqPMu)FXjVK)ZZZL-aM{&uY@m_Yc;b7GhRanTUIWSs;MWDH7^a zP$BDnV6^y}=1pw&G(PWjO=%6(SHu2xKmEmoUM2|yQp>>g1qFYBOk+I)jX*#bQ7t+y zfrTuSP{aVdC}NBN)0C4Vep{8$OINLT;5rRAr>%ebEW+TD^v#k;^jL8w7B`U&y*Ci! zRt0Mx`8$5=dF9{a?cun8YN-35_HB^AVwrZ-j}wFr=hGj#>A$>Pb0J`dWG5QDmEBU0 zJFY4Y&*^5&dLNQbecPNeX=6Fpn-gTTB&R8Osc?$eckWUue0b`(qQ!CfV*lCN6B~C; zM%sGSs-3-q97!^6K%dlFDE7QBJ(T@10$QkN4sq{%<)0JlPNAv1(Uop3%#@vUvq!gM z560Ki!808)QdtTfBCFMnh89Yn(I3bb-P67xcvv7_y~UTuKhMC(Mqj$2mU>;)v6AUP z(=qa;+)a*9zA%WI$&JcySEKEooPQ&;e2}x9_hN;=fW^O_7LeQDyUK4+gMLd?#Qv{| z_A_3w?`Or4I+Zvb%>4Wq?_R$o^sDkFZM@Vj0bSsKOS~1zfqNA|6`M>Iz)f@Io3Fvu zCg<1Dx(`Y`z*BC@7Jz&$x0U7J=rSDxrQtQfigC|Uwi^U3M_`55>g&9e?e2?7?1YaZ zbpT?9)Zuz@?)Bxeai=Kyz<+Co{lf8lsAJ&#y3P2%nd@t@-(*?NgwCRi2FHAN&S#~r zJUe7|e!4Il=#L-gS=3A`E-+j4%__`oTfF@>T`};>z-CEL@?~mQ8TVdMo?4~{G&vS# zzWwzl!#^pjSI$poD8H;W$xi!L06gmldVLPLMw=#EVzn!L$ARMg3YHCeJKo%vZ|NJ$ z>O&(XB7K_dYF&zg60e$pE$S{Gm%7_9Z6gTC^7M_a1i~ld^m{^#k3gUv9Lr$&Xfd4@ zFMt5BUc(eAAgv%F_J*VS^;TCc{%mt-&FP}OS_KqsMvnj|mS=31!2;7^()jgg3x^`Z z;5~Yp<5E5N%R<%h#8E@~S#X`3=%wtiwHKTB+RN6uzvwhPFNaEn=w6vUhkZEpfqP@2MK$=ZQ~VnP;vYby4Q&;bJIi zpxRfy^584-y{-b%yPWJ}8E9Eoyz4O@EUf7%m$JqT5bHNz8+wXtnn36-Mltwj*e>rp zVJ+RpNwaRGygs8`bpPnh5iapn?hD12lENAW%2rS7t5~maQZN3pGc!V|hlk%R{m4Fr z>~4K5^Y~EHn(0+nf2-doy!V&InvjzDsJ`y6SQYz$Z|^a|9II4rl>v*&;z8uusyNIP z>c+7X0GKGh+U!9-T21%Vz#dwg=|2lf_HK8Gz5a8vc2kYGgsH$sdWk1KKKRwSb;w_v zbwliyX!_hg52IY9Vm@bzhr_()dzVU&qpr>}Jp&F}6w%^dm6aB6Yh|$p%n-n5qvlk3 z?8wu#(20neGNbMx9bJ!Qab@m6*tEv7HILO=0w`HBW!#{iB$O_nzNn_)lEe1u@eQ&% z2e&t|UfgK9VymZQJU6Q&#ApKbF;>kaY6m=jX`1wF_w#4FEl8^<7f{dxlqnpl8X!VM z)tW7JUR?AmwYc~`5t~i;ei)yfAfV*CRPV7K`suf39XDTTtIV7CT zQIbhj0i*{I#QH93np;JU+Qa01^e;8$#WE~7;`j%0K>FD5{dzlnk=*cp@q;#{sGXUm z^jjV;hmgO|zSBxyHh&PcC2jMN|Dx}UMXylYEwl1Tv~FyfX@7nh`|erki~<#cR1W@k z4WHhcyRHudsrUQUmadt$l$WUxoCU*-m%V#T^?RcurKBfx9Lvb@3nG1ktFHQgy6ISK zp7iT;f8i~0uD@)Fa>6YR1B-`-Kwtns&V2p@en8p-9NyTyWT$&T+E(^|jIoY%Qm`L> zn3SBdnz_CJy1zML=afMzJRynxlQ0vJ(U)iUb;^WA4r79ARDa%I;}quO+bVn03oKv2 zGhA>FM?Av|`?z@8l$WcAlS0A=;D^@b-xocHp7$;$1wcJ@+C!xr+D=^2!H=%hl}E>E zHA?5x>0^yCBjpQNmbib!g5=Z_=2~l*Vq}rv`v+v7dF|8CeBnJux~g(AUOvdIj0*$< zOATL6V0m@>4YG2j_f+yACRh%2yL}qu( z$Hnwn%&j4R|3|M2#&JLXQJhVLJ?Q|HE_40SUN6U1Z2S$O-%pTnac_cU;P0E^#fQGR zgK#NT#9VMcWW5UB5gKlF2twyZ6!z(s)lrj(`L9-}z9Gxu&qAXLX|Yo&xgPua&FS+t zI}Xyp&F>z1{Bbromi5I+;N?7;fm78sYv2tY{2tka+52;ABIPx8k5gFepbz*olOOYp z6ZpB{tZk898GK(`HV^d#3a~rS(Ko|D`l^9!^8~^X-L33GeyeY(F$cEP0)=b%6?JQtJAX_om7Ecwvu7J;vbD#O`J3fj(=I z=(diRM;)v7t@7VL#6;IBumoQfo!SrOk zXGCEA{@pmB9c28LF7haxC9zN*b%wOdO#izF-1&5&#Y08HVOo=83a$6|DGWNL%;Id% z8Z17ED;7=dnKwbmgqrIE!7zOPNYL8#^D7yuSmfgf;{tKvggAfX0OQboa9)?RU>{Ot z($sj-qmML!m}wjE4L_5i#r~)e^1Ap}a`)JX*Eao#KwXn6Ge(pyw+1?U+7EBczxT+?6d#{^5|E!u z^f>eyJd3{9c?D{NuPazpXuK&uaA`Dr7U620Xl`4hGJCOS)``P54d-Qb|4R_754%&g zY87FObAaRRXhU7&`X#H>y^_=g{brBSRJU|5`LXBBJ-aV%IokbUDEdEZzG)dTY<#Dq zW7dXs^o;CONe$nu+60ziN&=KgZ*DO#Ta;Zi&*o+%1ydnOCF{jMMv~Zt6AML|vvrA{ z(YCP>?0iq1ZFYdg&nZ~*SW6&}33jj8jE^eySX>7vfs{dPtwYym#z?hgqnpua53&TpDko?|U8hXOq%cU{;s( z4=ce%gNj*Nf?C_Ly5OYT7${U#M^}!6=cbF_n4;W!r&>77rU|#+NQ7h zk+wh&4N%zwC{VZHnIjk+p`3UvusM%Rq3>P19=&D7e3LFVAIt5& z*=ci33}&%-+;d_0p&goSdqT&2dD}?h9c~xW536c^U&p)k*b~ZYlED)DP{8MzC0WW>yDe;lCAdUXrhWriP$jTM&Y?{BCzO9P}y zKejBk7|Z0|PbGS2%|}x>T#-Ti&#GLnCzF=lm!~2$g;PT&xI=WKMxK(^tqp2oH;5na z|Mf!V^OUWCnibY*QjV(v$Y-Ppn(!M`kPOzeedHD!P}+tJ169?Q7doozrcmF1@N>Iw_oa$I8sD1-5(FMvF_ap>i&0@XG*Gs189GFQzRO?=`#|+G+Vr-`h zqo-5`JPQ0*YFRzfz@*6tU@&JG4&)YXM#&KIeEr^2{gQQv*%h%hbj%rz-(}6g~A+7{(?HV#hO`b0DeCd8S_>=`s8u z;2K!PBkCl;$4Y+^^#nfKpJaCOwgvek(7|OXG&IDQPflNoN^Hm3t*5I?AQ;Ic60RAz z@E7XDvTpg?SB>$f>1wEY4=(YKMWX~uF+u_w5$8#LR~+|sEwY`Hg(tgtylb6(Bc71> zb&`s#o}^9Es)Hwyq6ztV0j0C$&2YocAb=^|2FLEMKYr>K+cm&(hEC`LC7n!^9b5Gi z6u+bUIKh~b^_0At@^*Xyn?7fA{Jf3n`|0K5p{#{Z7dMsDeN2qs=6)pV=l@Z4>%_(B z4!2-5DDLjf55236@tjP;lD$BJ9`mkW`@q9$l}#rX2X@4lzUH9M)tPP|%HmVLZ|nh# z`q?^UT9`Uj<4IkBDR)qX*ehXx`JZSo4z58kM?AvtiPm>Jv3pLLcSQ1#EU+)Lx_I_B zNn?av`dREnS4g4Ig*TOiVM2<&<&_qye}KhAlbl^dE4;11Rp zVb^lYTJeVi%%ZwS*9Ugi?K@42FJ`AP`VDGQW-&jtwdMidLt+LSJ5*y9x_8an0wG!W z2p2F}RChkb4JI-8cj1Uq_sqM>ficu?tnPuJOpG{i$kV*OkkOcVfK?x8}5oCj8b9^NDxy;Y$fO>k`2OjOsr}QB1E*p;` zZh)0xri#y-s~OHfxBx)u%Yo@yvMHp8beAo$_yyZ>hhtKlH0k$L2QVa`3Wl@lBsGlxAt$%W+*~P-7>@_%2^du;H&AORMLXbG3eeC9_D>I8f?LDxXD+no*MzbeEOxl73y+zU&>5N` zyoaQ?#0B6jIXz{GYT`u`GcmyQkJ~gD93>W^HogDtSz(@d^OO(F;A0uF3h8~1^uKxO zEWfOb9+NrXM5rmZ#TI@AYYETSa9he`*P7T^52Wx(#3&hp zPRp+`ExD@giF8#&-zvBhsZJ4O{U%+&`EgZ3hBc4(nUJZO9EsT2FfKd>EPl=IaQ~^C zj$873;X`iW3#G0C1^W}IMWMABC)gCLCozOu&t`FkBx9~Hh~gZVkJus54|v3ju64Pt zaqPVw_JB(%CY}4LfH8*9c$NY794ePa3*(Fbhr6fB7pg(|8Gry+E?7>f;}A<&009_} z-^DpBXcM`6ekkPZ+27uePly11vW358!~(&a`aXc6m#T&He1v zYWVGVc&wNVOW zdNj1dBfbOp@i=XF1Hag}n!I#d+S@m1NvQLdjlK21T(-UJR8OX#TA zC$o3?-1{aRrlQ8hC&d%wu~MTF(Fg5uJOpItwqBm*-?oBeR*!nq;r3&M5B>ns{I{>jJ=QU=42U@MN zou2u~mbw8dl}8g|F$SFUevya}d&F(A$;z{{sJa)d%G`}+-MuXFohzR*Bip4bDAFFf zA1{wLHJ?uG1{)rU>iyQ`BcYM9OIB0nt(^{D|EO?Rcw1%wk6?R;qQ5=%7T&ux8wUg8^e9QjW3=# zZYrWpr+f7EFVswOCQf^Hx)nTlqS|nv0zy8`cZvmNQg=T~MDjuViwU-j`H$E(aD97kP z9Z{NAcWCA<*?&*vB2osTGsJ#F}UZqBoeS&Pjuqm_PKyHe<~oUd0Fn}2=H(Kvm? zFJ#W)=D2KyAKZokpY~hd0WZ zL+LZdq7I*BTFAniUih`!#uLKZL2fY=~ikpwA@#s586 zd%3}u*GWf~h_Yns7DVVis1U42ONI|pwD&!au4@ufo@6ct&P&{xkqnwUW+X&bMHrXu zn6@fBh1q9C@*T`-XFL}fQ1?<1Ny*^@*eaUX+WeJrZSCvKYk47bQ;jP^iK9?PdZ3!i z&_ZptRo7Wk+9l=dnw-k~Arb|^FbxaLJSe;9PamwFKv1+lKTCOQ6pPJssqJ>+lOOSo zr9)>t!{6xg-hRQT_dBhTr>1lRLVAGY8HMs9d2liKgR(wxWs~dS$zz#^`Z$LQwvL26 zb7dvQo3Jeww=%2w9W{}>1IaAc)t=?yAH3GFZOtXhY?5hDTR73b*|29#R$ULER#6Yl z4*?Diolc@DJ=CVm!;~t?0Y@+bYndKhPuVn}$0Xt^ z@GD!;LKkq*K6@RHEs%6vm^UuQh^E4GP;ucwC+?+IzSx=nqaSVew!o!6OMWl#BHiH+$TU`MT}#LJS$ z$P?Y`EHY%;<+js4P)KxlYZArCL(7I`K9;moydt=NWAO;Lj&bpi{-_=>eDKZ!kMns z>eC8oKspAsB1^->6D5s6xS&Ap4fdy$6bRk(>oskPwYJD#JLkN(yQL}EzW<;@sOs5Qsw6e@$2K4(70zt_(I`g`Tbdsfu{zNpJ-YBW zA~!j^tSZ_u_f};UH&V`fIPY7s*{3={N*-c0#_3K`xks5#DS(fJ2lgI?KNvYJnX_DG zFX!8}BzxEDR2{e1=zPF6QJdR2tC6V=+5{uvH2i!2&)D%_{+=Ot@aI~{)xW3ymC_yI z#jw*gi!sU1MV%pGk>xf!ah$o{#H+5K2lx`pnO`4v@qW$ms8Joi-4$1p#cU?;H!Zi5 zd%i=xdO6>vY1%RAav&l!cfDfgAxcP^5&6J2kd7IVmF=mdOy41~$@O!yFImd4wD*Ko z!N5|ZjoD@CwohHTU2Jwk!WH|4-XB}Z5-;TFXVc5UrL6;7eZFFCp$Hcbmrw#jV}+&~ zlJ8K^zEDrHln&W3_xocYs?O$74OcAh1)woWfxz=IiCWB{=*+1!M{zxcg&M&loucO_ z{bu#DCSu%dwp9#ugc;05W4mW!#U`O{ah7;UiR<>{=VGoy+oLNj8{)pXAT4%Vz78I3 zIQgW0iXc+0$_1OR$t3Wp+Ut;>nvfkW_y4#+=Xxtz21NyD#mxUb4vI1vv@5EO#B*0^+ms3q8 z%p7~cb)gS}Cz&-Pz)>y(Mge+DgS1A#v7??$uSLRbEcg5 zbb;DGDNv72qYIqb$8)(0h0|nG_Tj44}P-0U>S@aN_?d4=JWsc+l#ohzZrS78OX;JGHrL(2!dbWV{}8s8?!Q6+4!> zZMzfA+pe(Skz1b|G!ylRNOMcn@UNVkgC{Nz#{WZBF=%^X*f>w;Hiw7sKJ`hnJx0F( z49XojXG3}%r`e?N22x~KIb*it6djE6Se!~}dh)LEYtuaEhE?7d;$);A?6*&d&)`|VQwN_nCA4DU=;JMk+_!X+AEl{myu-IsT zV_W>PjdJC5Xhtg$U^lV^Pe&*R4AF;pEfy^W8|mN35|z?f{QY0$?Q}#6TzreSMMR;0 zJ?TK?43V3a$5*^22M!mN-W*hr*)*!|9JG$e{7Z?CgX+l+$;Zc+>8d0h6o{L4ugM)_ zoyEUuc^m(pkz88LHrHb^pg^~OxV*TnCr|jhA2$Yf*F{7q)($@DcD4Fzv=V8ksVo@Z z1tsHtluSP!#e$SSp%rF=45SQnYEvCJ+zYuICW2V*!i^0Z$0MFq%zNoMOmJ*~CZzX# z2&46AQ+RQGp7j*k`{dW?{5_1kv1;-N+5gFi*BU@lSEMprV?fA6f%V@xC{p}wre2kWIFrjXRyBcpZ~|!d4{vS|Np<^bQrB_Yb&Q!MZ~5? zjZ=z>ii*UDRn$n--m6YqVr#1sgis?QiHNOst*BjzU85*!wMMB?&hPWRuK&&d?c_$1 zE7#{eUeD*_F{~UnU*GcCWi#++T*Q_7d0K4TuR8hCreIC>izhn8hhL`za zjqLTj^sfaLjbj=_K6KSePsz#iu?Rlr_kUm`fj4yjJ7qemsZwhC_vUYm7?YM?J6iSK zd!uSXIctLUpcW_J6|ROi{v=|wVR0h)* zQ?ZvHq1A%J-&vYWAAPOJlIA0955WNAI zuP)h~OKNu_IP62IFG#y_3%5z^+LJ`o|``8%n1s@r{`B{A1=-N+0O(=hQLhI7F{hfknhLa?a&!|=c zsh5aj+6)Q-9euNbfGls(l4Xt#fP6<@_bhNlKvd zkE~9|xmRs)qD3=L4^~jwEhYBHYUdDiq)q}>@@-nZ;<(2ebt28uw5GQExA~ zE8s)urOF}9iFEi*d?K{Ak?B@>(vxT!^XI!Kyj#uXpSmvjE?1xcB~FbF0jW`d!#2?V zgsP``IN3eBt8~@{R!C(MIG>{7G(aX9LNIf`sVprGvpAfeJ6FZseWSx$=&W)@lA37^HJRQXs_keh`?2x2Tq`W;gqrENXeMn& zl3dQDL2?@l9R4CoIzAamd;jgAhn6OT+WKujN2U|r>5?HelC=6{a~4VNjmGM@ z7~XK#2vIlcQ9db~Htfs)k@an0)1v0LwB!2~LG8jxXr8w=?FOzg^g6GgPMkU7u87EJ zX_j;E-7FAqy4m*98}$Qz#WNmnKY!ZB!?%EZGC=5DF+Q>s624v@Iv~oWsZ5=}nfAG; z3E%Dq)vPYfyNse_mumk^j&E}fDFL)Wu20IwH4V%&hTZ|y^6wD-?+rxuVZwJ~0TbQF zc@Qt(L}vCBk=JM*JEo~Ke~L?!o=r70LLn2!2K2O@wW%6bYK~hU64Fi@^fh*A5bbs63!1vGqMs}t zxg5!uQgqsG@G_>5wrluOf_QE8Pv>TW%3sxW*YsV;9Or$#FA<4_INUY6spj6^ERO3b ze_#Cytl@py^yC6??}cQmNBUs;S%R*bt%~q zJXG0zeZTcqtOG8U4yD{Z3!zK6`PI5`BRFsnw>nfo_wv1)^LHdaZ?q`xL2!mzAl?J?G6Fc!n(QVsh0 zCE_QCW*0{+Q6St_EaJ?9W<)p&50eErDnSWqJwHt!duogJU#q>cvbm80TnKZ$vTd()HY!2 z_PEc-y!mvuq;7(hnp*g<|0BcUouoC1R+sWtHy+;r7hF%$rVs5EJ&}xGtnypu6kdh5 z8jD8LW64terhM$XlJID!Ie~CS*1{z|Q=Hvg0d{6kAmq5e1S`%&0JDij{Ntw4jsmP}D+2qvR zN8!C!~4jE|29;+va6pX8aa8J9Y9=w2D}o zi`x6Lv~Mn-(!1Urx%V2hV;t&agZkHKBH!o?^+oFGznyu00ssP_9(SBZWV_!FY&>9l z)KveyG9QARD@jURpgptHcr{cRWO>*|#&jB=wLUUpb()a{ujNSyG^5SYX0K|}euY&P z&|dHKGH)|~(e(H<9^jte87@tn>L-7ETirS79a!!mZhD7t*8A#dK9w%^&_n$W4WoC@k1WP^rF`>`F5K;7KA3CrA%9%06Z;gW7&YP)0SpL> z9G|SS0IAeb8ikv_&#kh2(un;=b>^wQJKMRGuS6U96IQ$9*PZKYkAZ$X1MWpe9Cnb^ zdeWqgd3If!sP;Yn)lC!In=^`=zhC}PA*kxtS4|Y#Owaa`rrm=rxeAe;;)MQ=;M&)> zUz9#gH}=r;BoS6!-4(<5DdroQ0uYH*%$da z7tZHpI1&VR?Q}|5jUMpihX!ebc?7U$#5v(RTz45v|4zfx!urD6f-&kWI*j;CxqLjq zHkAq*UVP?ay-kJ%Xcg>*4K7gEOoaiE657soYO*~)q()lC=0VCNhlz+Cx@~FS0XW{- z#p~r4H*6kGqIvxc((iRVOXq&T7U|3XM}$kFpYqj*MXKE3dGFaeIi;P%e4w}At$O=d_ zy2U!T)~!(Sp@tc#PIp6{PGPIQi+UJx3%MNh4i3RC;TpS==x(q}BdbN}{`CP{QPu-$h$&X}^zkx|1 zrFu)<-ldP#(Ws63HyNoGrw+8C-C(kL6Q(K>vD3`*P)nnJKOrG5jB2od0O=Om55kFRqEu2r2*YA z5p?}$Ka$$+xEW%2{y^L`YhsmZat)2op1H-`P>zItF>v5U1&5{8ZufglI!|?s$(kFo zuJmeQ8_SU6_WF_6`-V)!e<_{avvPtA9$WSK^@+PL5Fs^oSr+Y2e5?tARnn%XU-|b| z&`X`SuEv0Vk%#xj**`?+t4Z~;>C)86PSa3WGW!*V)2eQ>zbO~^sbv3xuQHhd+>mW` zQuaTzNtkPYMta#6- zRSFvzjt!m#pg18X_Le^LP&sm9wsDBMg`5DS+G;pY z4?xUN#-F3etkl-T@QW2AXR%FvP$jG`_G_ z6|*;A z$28z&ScNp-3{J5=Neu{rlg^RUzTh*A;5QZEyv%nY-Vcp6>RPvvi^I>n4$ZgQw`1;U zK`)uMYpZ?uFudW!QZ_NP+GNDjOiE@Qz8HejMgA6qMLAi`^2I-Gs>FROu$y^j?`89E zs4ItB>v9jqB^fsNrx&wkx%bQ6X(2x64*%i!>JXWqMbtpJ#Z%7-n5Rh?%H>m^Y>o(r zu01Js887h^j?_3vIbSGpj{~f70qIYaz0;R-RLMt)_LB+E|Zx&3_s1j3pJ z)M<&f^C_*EN9L{%x|! zzWfiJ%HiZzvuKxvrQNcL=&f;p=!;kkt;*#bhHt4*fjoYga#@wMlY%k@w4LK9oO*>G zZBBOJv8dLFXEx61IJ3l=|DBrStIYm>b#=5^yt=WhvdpbEXTc&ti?73EZq0*K8z-Js z^p;ebUwiE@nu2D-;md})ROd+YJEEjDrzZ+sK9&|!r`OW3{ z$BbpGsavgZ7(P#r4ab5gRP_RtV2|a4B5z%ONG8VaMcXmV`!}N8s=j3+G{qmR&0WiR zi>~hI@fo`ahF+~FSsSEzd^k#9pDnSS4q2P)3uTGpBCpvS5sf6i+)2W_(q&5U5im_p z&rnZtOl8YU_d@HxgFOtc{F4=~5E7x-zooq5?DMOfU)TmcXksD(Lc`JnETn& z(0Lqnmw})|ebYRigi;KA=|@QlOq{g_U^j;hgO;saY`CNIAgOugDs8=7>*f5D;~_n1 z&9yHIk~*Jc1rV$wo$GGEYTkIwm}+`OKeBK?Rbp87$ECEO$-*&Q zeG%zKXQ66^-nqWoEq9!+o~L*CbG`AH1YhtV%KsVjfIpiA>U2%TT)4?_^x4n80bg@d z*|f@ZmN5IWX7wnls&{j!3kby6fm_&g5nKLAzE(XUNbF`=2ah3J3=u!SX4&zX$|?9U zT$8;6p7$?f@Z2kmg5x4G#S)bJk#Yn9Fl6LaBQUC$*C-I7UcZ_Pt7C47TYW3l@ zipa!$3;v&9PX-%Q`BWbtryLp7HJ0ZH$W@JZ?iN^!e=F+09lH_alhrK;3Cpw-4g|Z3 zp2ZD#tK{uwE?EbfZg8rw!IHKPfThv&QU((vBoNo;w7HKzD7+zHpaSYWi!{A}#M8U= zM>{B3CF?FO8v)7Tg3N{T9hx~;5*CsHHgJyrIQp0f(H@OVAh2?g7HCbiB{8JZkZN%w2V`W*nT|aURA{n*`rlQ0d6n0Pd&eObY2bI4$k3K-Uf?>#sBaaWJST!kdHe|yLKZb+VCbn<0OXq@QO_x@2x8h{Q<*n!5354&)+Q$ znMQ#;*@sD=C%Ou}n%n;AzmB_m7q|F9VHdsZePntT7yfKV?xXW}i%wX(MbGwnQE4z* zJx~yxthUHHEVYjA7!=B~=x7&>%Y$Npt3*=G+wc8|y_A%@jcW^Kzoh0R+qn_~*6ve) zL~9uTB&Ad%TdMbhZY?(?gi{$OG1I~P$V^6m82{6CzQkM8P{?+|&IYY5I!ueI`KhVz z%Tq)S*Q!atZJT%ojB144Cp{DqzgwFQ#^J^`ZES41BZGe0=KvCqE*I6dwwycJsD+k_ zGWk}g@?oFd=7yK;b9U?@RtAmedEn7taEFN8M|IuMj?m{}S0)!P+E;BiUUo_NI1ifJ z&X`xIa(>n84v{;Z4j)*=beQ)ZSMwp9Bpu7u!mu~W_%lZje@O5^)Z7i!BC@#d+|7y9 z?Xs-fl8ascS~;Q;E<|Rs?$=_UAvwbPk%!7HdfsTSTN9yweXf2t9Y2q6>t;RvrIduQ z1zN?usLug@K=ejMvG0K&k{?iuL_P`?FjN^gkRK6=8Ngn;79gc zBPNH!`_WLEVCLOR^J{ZE$X`x7Nm>rY0GmHAfo$EYc$g$^F2FuP2sMk|QrSxNCndhF zDG+eGlUHifO^qyF)e^NF-c<{{r^WtpA~M}BeWUg<+K)s1GL|&yKBnO?ZV79tsHya{ zmPtj?aMyDl*861Ifq6OD{%umu+`)9A(O(9Wp_VR+Z=gds*Yr)RDmnhvgVW?F+XP} zs~@X;urLd@^y|DZ>0(TE_jLSV9HkYGR9k)90sAz{aWrjSNJIX2%DiCT`N?R=cT2iC<)ew4Kw^^^sdy zW>xxIIjzq|AuHzw@T2u6OL^d${F!^=$Ngk;x!la*PB)&XCv_GAfzKMaF<1~>a$%+M zuEgrwUdn=k{bY1mW!F$gk5UXD=W`+8eobQ>-`M;cp$WA~XFKUgsJ1wl^-e>m#R`$1MomLFiQBhC&n46EFV%r;X2Dn{i~>= zjtOV>ENg^dIrSmR?#wP&av+kxsVZX&M?rD78bP0lYICc*dRNO70JU1Urf&cCEY*=G zqLMqab)H(HdXLc$?19j^V*bg72K@L8v@aG}4a15Z8f=Ot{PFe&)Y_-EVlatC9vXy^ zre1x&rxhbKm#PGJ_fk_a{e&KLBAkIo9lY;k=`MvDQX z?4^d$d9SdXPIE~wrsHvk{A7}NA?Grcx-YdKD1YjN8;NU@nu z2v%e#TuRgg5x^E#n}r0T?FZMC4qp*X1?=W2mU}#o0KbjPARy;X;oJbp@>vZ{kY|SD zxB{oRZ(1@S&zO_vN2?`ig)&oocQyH{_jc1ra?~y!hco3B@TFx4%}vy0(>z3X0SYwq zt8v)N#8Br;3$#5t8R`=JZZOV4DE`OImZq0dg3K|Gb5A=|8S@1e6HM^YZN#tnjy zSL3Af!Eje;oOe0+z(IUG*2Rv}h!99!j&%%K&_6ls7ZH-8^7tjf0i50VC-&~!)KVqZMtfO4iJn1wOF*fUI#{VZevLcaUB4n)Pi6HEfTrDpsE}D`K+n2Pz%>F zZmGw^hG2z)t?a}<1GaMk;~RgnvNC>X&x$v#bqiMcbX}b`^sHloH3-elo%7By9r|+= z2KE_v$|pluuMg0vjDTC~zJd@Ph`mr(2@ZkAM`%b5FA*s{i&n6m=4ZEWzn0LuStV`E zZG0)Z1N1gPBDTwXiG-Bq)0p~9jWTmqJacYxbJ>Z`J6$X4gK(YG2Q@o$bLo7R(AA0oXj$I8zDEPo$`9J^scS@c9E&J7p zVcq|OJ>*BpKdpBYFb@a!p8oF?8BU+wJ{o+bsWMOfv{4$NQ#56R4hnmDkp2d8eaeP$ z|C7;WNOFr@kL8UEoR^|JVKk27ZkeM9E!jW2&18>i`Z>9^?~JR7Xz3p5=k?Y$O?z3R zqn2-HSEwkjfGnCgjqX*FSFiL%v(;emUiXpaCkQ#Rgq?9ZIbnOEUtO(cqjoktz-~Bb zbaX@uK^&OJ;aHo0zJ$*Vj5ciq4L%r?l_~sO^(C~bNn?*W$yPA@E2BV9yd|f>8P84l zbX4(_`vd=}?5FtqHM5JyQFepz+A<+}CQRlf!}cwszc@F<8R>HUnnLvkcC{k@OE>_QZd`roOyQPZRIi{aZRH+~;Yf7$Weed;ODE%fi;?I>-fDgUJGue+V%(CL=V z+x6dRJFFio{SrODycDrD)nDv^ucM8(X9|~VRFu7uZ6k^MC;8`0sGUlR5y>l)9_)Ju z7lwJeGJjV$r+XYkjO0R5YWd`1hSBzi-BF}FtEK6B)xj^5qWQswoBm^$Mk{S~8!VnX)t2xi%7Opg9{s@B`hbyhA9+TUeE zYuKjR6^(2JyM;IWn5?~S+gBD)eORMtQ(D!J3O5^MA|5cqHSNi9P z^0C1^DRAJW+u%1duj;KwWt|@~j4lnVyJT!X{Og(>KgviazN_9l-T2FlSMP(;oElr2 zXOHGnr}uSE%`#P<5q3h;UyPA|Xt(!X4~twF6YAVXI?Nht5l^BK(ZAoM3e2;smZb1q zU~7*YnYwJ?Z=WWO3SxN#d^`F5+|%20=J$Se{L+V-=^rz%>24nMpx;3?d*6R-$hAl9 z%kbvclU_f+IK{a7&=eElN>;N=z9&n|kH2vO<6mBEKOJ-Wp)I$=+x-IB2&m~#endb1z)C_01H)HS-DV9RIk{aPLcGFmiHF=bxyr)1n6w4%HWqQ(7(o zT!zm1ghQZ=9yL|@^N1Zlx384kZ~6aV8_xX82681uuIZ-uu8qfWRqT zsWdf2Vx=$n;(!b-E9sp{DIUcfyA`l9{962>L17fG5I$yN>k=~it#Kyq1ehj0otA(w zqg+iVwv=f~rYy0#eeunl)j8!OX^-1EtKO&GSs*s(#2K>YDI!&(3o-aYHu0|LJvi>{O zok=>zww#Sx;fnXz8We8%7U!_1{xNE$(fXMF>->MG-fjPPYCU0I?pOya+O?e2%)OQ? z7@ZI7THUKz?%>_BbL+0RlRgeCpVaflOJg3!iW9eoFMDiropBcMZC`@w9_*|OC0vz! zkTLnZ_G@^usoqG*&w$<| zw>ud*B0lMIkmTX$X$|w@f|3GtDI+3(se9|N?P#*b+Z0f)2ASvH2<1D21zTJUehI5z zN{b4;a3}9hHlH%UMOXi|f;2HWD~rcx*1dImy@(lo%#_-Z>Heo=xsN;b;@i-_)Y$7_ zX^u#O;D}T`R^8TV7c)fa-Vh6^)9$FZO|XZEE0Q|b@xuEw-eEbMHZ;{@wy5b^1#V*wMh=jReg|hxx=)zSDf4n-(rH3?=X+ljag!w+e%gvsA)Dh8By zRm`;P(mG=B8HKCMduBd+jWZjTQ2esdq-}!cXz(b~ANiajUgQzVqu0-Qenw~ZRuVnC zd%_Y;7*NdXO>TIIIL*N$4pYUd^_z8=6!);zEZnWj3QDZP`=Z1HN_NZT@K@4)B3R}$ z0jQa0P2o3YB2-4^?}O~SwMw-O);E=uT{R&k@o%(^USgIxTR*0~F=%V$|9Z+)MT7}Q zKzNRmB{h2FjdMJ=sWo5c_622K0*P&;rPBYy_S`?;5;H%2BJ4U6GpgTRl8kchN{EPQ=9*?p?HEvfK8Mxq{8j()2bNwm-4 z)v26e92GbX<-b2&1m2g-2?$ki4te(eR0V#gTulXGnY6{lt0-4Kh*CtEn3HoV|y`{L#On=d0=6=N%wux>~hb2FlaLNp0AdDYj< z>vPPPcV03Qlxe~*F-XB;79{2=sb2%u$4t z7?3O3Dy_8lB-wE0B9tTp@iR*uRa)Nj?EGGZw*Sp)zAR|)mZZD6|Lw^Id9XEs&^`7{W)I>oiRa25wCHlU!@>Tt5eWeDWgBAa?Ut`OCu zOeWtmC#z3%+e09l0}$CEd@dNp;Nh8VagnC@XRoTOukaqcf1mgB9z$WtcJ#4MuFm9d zi%9>y*ZU-Dw`l6vA%mcv{7;8tqgDasJsb9jI&ksh+7MPJ?ax0ghYLCWD7g|?qx}|e zylO|4ri@lp22VTSmybq%!GjNVLR^_lYXfa`zlmh8R{v9)^o)`IWdAgBFx~ujZJYM> zSVq+5!`Cl0gg?2YxMG5$|9WHcE#m%GA{b`y->KW>l~+V0I7{lznM65+80xruj8L~5 zNmc_!ocNKn;cWC!igP?5Ai59n-Ak}oehK_aiblZ7mD2L4gi&L;u$(ZCS8;(H6j|$5 zhnOc@8pPO(^ju%{>zz(WoC)(okI;IeWOA$J*2CxJVrQgAH0|;xRy63Cf|2Iwk_n{D zlw}xu7khVe7j&Da)Keg%F+<|X%)ikbwZF211QErfheU~YE+LIIuZZ`@3Xp(Mqnrm_ z;u5x%UKu0ZHPIce56jkCA}J5I5c0BZB*VNR=1HR9H6&!qzxL>GU%vuwjlsZSL*C(2|1q2){rOf-usU$|JyH!@zRUJL3*{XtU zCq7(!9ii={3iktA*nOHkIUZ@18OVWy(YhwtOP4tC(O}KT9q$&R-PQKSKjlK+p!+K zb~d4H-Z3uWBMc|OgRw#nk+0{))1e`FWnY98<%=01Y=qh9xZ&sm1VHa5J!K zY!_TZknFA4uSJ>DO}Qitt`cEbwvi5r1cK2h1agIZvA+kcaBr5|e#*ml@jZetehUot3u&S^7n&43`>+$0_pRp5J*u;Oc|&8$ z2}4WAtg2#1gNNz=2N~5h09v+y-Zu0u$5M z#26ZkaGXdMMAOUDtH>L-sp0w>X}%TI^#$m)>2mfKjSyg-l*XrFz=_j+D3!HSVv>NnDnZ{>9T5K0-0?9aqCm>)@zlnrJ2ENP_@SMLLBiOfbo~>9A=L{)&REm z>mA|Ya9cPUzQC!utf>zPPI&AmyOQc)Kgfw!uBrD&n$8`xux=54B0Y>h&bsrlUF&v3 z->iSh2!~a?y_EcI%s0^`6}i#p{1UjCo1++%`o8QwX~3Cv=o)jRmsG?^7#|t(SrokN zH0H1%S`AZGb!Dp`X`<>g5*lNv_Awg!kHBK)=hqBRr%-j)Nidp5ML&hvWq2tm8VgF> zx{iV-`Ro>e-Ylot>4aTfqH=l$jZWI<2O59c_;a7`@MZ8)iFByPjiQ`$#FCexUq5)b za5#R!JUrf>ImUL0hfs&pxrZn;~`~tSr$2XetrcC zidltT=dpd@t7Ab=#&Wp~>S&bmi6)URBhx}+g;yYI-yIhdu$(UFT_7(5r^g-A1mVo* zGn72#ChRkpmF|9n7pV8Cvu$|S0!q6?0&k@2z!Dps_G4~DqOPIk2wE+(&iez8EyDWq zEG0W@e;2$6Tj;HLJ90z1$xx=l%_^zh>QMcTV9{kif-Rj-k2~E-@-uydWPlB;q{Yze zQ>0H@5Cp;yLnBXDdF^e~2JqXwg(C7Rht- zg;gkvtZ%Y#dj*jk27A}ec>ZEjsY7Gzg|>t-^`cBwT>tJssrM=T;f^6IL!~XP0e8V@ zK3Q)54%2K8{_ctru@^bUb;Tt^xR=e~8a1V}OSbnG(IEEdoF??fl1iRA7Y62=D=vkI zxoDXr<>XO{P64GUR1zoR`xgvyE-iQ%D|WO2GgN(4P!Q5 zayN_0se&9C15=^bbqeS)hbPrCDb@4h^|dHW=3hf!P_Md2Uad?%L&857Dz@z@eQ6Jm zRBF}gh?n`?(ERYv7}oAYRHb`!WK&otzVnHK@uhSiHA`6_L*W4Ke!iSv9o{y7+yp_8 z{|6Aym~-KGB*qpb88HCkpZV@hNU0RGzIA>xpn_ykweZ?1Nv0SwzKAiSNkMWX&T-!1 zxCY~oWiRU~3$ZqfCfQsw<@kLk_X4IgLi9b-qs9_1J-zS$uy)v+PD~lK`sr9xT{EoR z9g4cq-%xc(n#_CYLH_%7H=$rA{fVKiz`H(wZE<48;&@{NxNWHYD{9V1iE4bM99pU> z8sBzQ4XRJ=v>+h2OUSMG`97onp`{9??S1qFLG?dF&9qmGKhb`3% zlSuywMl!fk3XoNetU#k0iKb_Y5$V;$vtz%w_^d+wkKAom^*TrKcXE$oy`TTSHP(?n z`smQLAR-kthT>ETO||I{vR-_^Ql^G1i3E86m3kET{c+YOB|(0CsFz}q9foKu#UKx! z&T#S(c-1<$7(=+oK+__`ISm9;1Zf=eYx*oA(9Tn9f7xuUO9UW5R!D?T#^C`C+=G>* zFb|7Fc!(*TV+4nic`;0z-WvACBe^Pi0wvFY$K!F5^J;xmGD7Tg)%3Z7VHIhPOR!ms zgnKqkhR}qzkmtR@!Qy``qI+eUnwqHMm4-6)KX0ic1F~CFloBjl(k-az0Jp-u{apOV zUU_;fDZ})Vl%oP%UYQpJAwa5peaWCzt55SDzzlq9FA(Mb=f@c$q^?#RY!{}i-Mlr_ z?;A*9R|B=!(rw6ik&u}tE@ki$0ZoZp^=fB#ZSi($^zFPJ{W#j86d`p0F zr?!@8j|ns!pVNw#uXfkHk{8z|j`Sy~cMlWMZxa2McDLRTjZZbxU$rya#`-|UY%t?= zAt**LJGFi6Robd<$w>{>$=SNiFLv1NqV%xY{?Q5h>}I0z{^FKuYxCJ~-nx;(eOO;@ zS$Bnr(xc%Bqj~qAnjii7CU(`H$p-8!6{neiZ}r{F%;BQ6>RkhkjA#Z4#&8-4tyY)4 zYn|WvpM)+ocT_9}dr?EaG`)-toHfpFC3{kdoHFOp8V{t z+Y81R!x5#)qiJumUS2_tZnvOX7~e<)GIzt9t2A^-yg}89IZ@PGbWv;}y|q7lE;qUQ z{AiV$(@4Pa8EH|jRcZGJ79vs&8kodj*>}#~0-)c>XpOKgVtp4_?{R${@Ag^g&i0JO zgTftq(N>H8$|MWRSM-h086mm6WMcY)g1VOrvRO~9D$=o0m_Oc8{ki> z5*PS5#(}f!bXsdHknI&=C!(jS&@lSN#%3$q>m)q^@T0QSK9LJ+DcKb0M$rHrN9S=99QBOofE_Vha#A?LA6 zsd73lDTBQ#5FAlr4+%N;;w^Q~SddrVvTq~sFNXdAmQG%gk`-s^ugwkr_5ci(QY0jW zPv9jL=P2cTLmfeUNw8w30Z=O)6XqX1Ub4T7Cwy=^)InT z3vw8Px!?TlX&rE+1>Lw++0w#%-|&xqjra;Nj!~jX5Ko$0zY`Tp)e|*xcK)|(l$hx> z=Wwn=*=MJ8%bX@C5Fq~{Tl1!H;3KUl_XSHf&~|L>ebzvEhNd{=*JfZ@)s6;`O<7}9 zE0;ZI3B(dEe#U@e&QlmU8Uz(7$M0V~H8L{cFN^#&l5z0?<<=o7gJ#1{A2vG9$%gH2fq@xaV>=__B@Ss&7URs zRB`D;dX65XNkfvILwEifp77tP_*<36v9;waM^xd?6Y1c9TgE2rqfg}68B}ensqG?{ z1RN%e9DK7it?l!tTGv5Y~rmGa_lRc!-fW1XlM@R_~qJWY6!f*zR zm}o zc6TCNg;YXNkv8w62Mt^jC0+%YPm=brnmS<;#^or48=n4I2^O1(8 z^>yLV=YeZ&)n^fTHtPL8yWi&&4=8XSZ@vo_xXTy`CB`rih=B@aaTp8fadX~LEX+!B zXC<4u7eFDd<4IlI!nIrmr8?t}d$%VuOBEK@!Xe|0UVJy=Vuby>Ed6k*T(B4|o1PiBim;517u)JMXJfCuO{@;%V5VVC3x?M1Pg}bn7#!H{HQ%l~+TV z&lef0QCc<{oaJ@Hy7`rS_g3?ux^<8#|8geoOp`cn!B_2}Wx*?YG|54h9z)jHY?Ydm zT2TBnsZ!2EifLo#6zk&VEqUH<;w=aM^yN@`8cEGCdG)bFB<mo;J~5B1Dx@OMedj}=A;&tNbv+V z&|{K@8ToY%dy~|YHN#85TW~}Tbk+P|b(9mq;EVpq?y-o_y>Jc_dn-+&8zY@BO;vId z@08Obv+UnlvKDh-{my#_KmKSBO+{C|>@X7k5nsEw#h);C4t}Qs-GJ>riaY`N;o;Zs%+AG( zo)M`*OX} zt8I(w(H`|7AS}rA(o0IY-0FCQGP(z-RX?(OXxU#bk9~+h*jbIhBNx8=D6f32_#+bm z)sOBkPe_iSxvKpvfyT^bj)pEil6lBVpk-)2@a2!_V$&FLGv;E4CQ^U2MOlX2Gx$7a zZoEVPvhQRQKCK{LK74K<*Hb&EOvqH*NKDmr*&H)9b^l!B&dOlD!|dM}pl(hz;sP{#U#{q zTvJ;F(#>zgFh<)4-jNeJKF4T2DDJKwmL5p8eYd!G z)Nn+QfWKT-Yg}shP*+{MGc&-^gl;=BNm&|Q=V&T{Nf)0oQ0!O)XAQhLs4ES#b%`UV z%}3Qre#OZhzrLjUw$oJ&uyLq;8tL1?D}Kwq0a$eGLcT78Y*Wdgfa`x3_xOD6K@Tc* zI+p{IPT}($O39&)9gu>8x}Z zGId8I=Pcj9U9NSqH<+}Twh@xB3wxEg6QsQ$T2zOp{r@tqn&9`OHO%JqHsa)sg9??NmpzH+74|MQZV-<+Iz5oBa0Uy zZ@A%sV5`Jh{1FY9|IAR`H+?a@^OZ z($`dj4@XNT1Kt^jl21NC{7D5xfr>1O_t(&EV2%(FZ|>Q?Ukfy?;0s7>^XcYG-J>neR3Y{M0S#=UrVA3Yl{j1=F@U3jnsCif9||+ z?xhIxub%#04qRF7pC?WH_cm@uSQCqgzEQ?3V}rtAp2hP)jtq-dvo>aTj&)iwP>-O&axPqg zz-XE}vMwNm9~xS$dQP)sgIOir%9ie*=M`s>L?$#1xxa;EgPUR^T0}e57Nh$pOS_wu z1@WC@?aU6xVi-ZKmrr<*>os6=wQ31I(h<18?whL>*$>(%nHktb*OOu!?~%~88sK`D zrpB?Ym3Jl{F2vOnu!r%>Cm+Js)~p|nx?qQ#Fq7XOv_&aK`e(o6Ng|~$EJXKi1(t_E zLi-BK5oL%<&Kqu;*Zm;aMKxAIVt$>4qp(UaA5>Ni)x(c$Y*t=%lq{KV;#8r!*2RED z9NNnmJ+wz!w)r*O+e_DPS|G@C)Wy#v-B)cex<*KyWxK&vJ1_zpd-3aq)2OQb%@0G3 zW**_xOB$Y9xn{$ub0=fsCwU^Z98ph_V#U(8|=H@n>kqU_n zL|=L6|Iv0H?riS=|L-|H9ahz<&1uz&*js~7IjE$9AR<=LSg}bPt4?e0Q^X!eiHO*n z8YM!By?2G8R%_HQ=a=sv@%saEUstZ{zTfxze!rg2$0Oy0Blp|rU@2X3vswzP+(*nG z1t!RGif}8_yOS_-Im&gE0KlZtBoB}B@A#r<)G7}5Hv-kcIe9Owhf^1{iUMB~w=xPT|w3^CLoquR*O*c$or$k9)hcrWA>M3BmJe4yB7Ii-Jo&^(K~y3Im4Ns+8`s zf$h~dq_>n!9*`#EwlWd)*rzgw>{!HDlXCJNhvYCz{!8Jxg~te+#@L{rO@IGdT^w87 zCv%*J&;)Btw>q>!(u_QswrCr~wbOd+5Cm>38@R1fv2vMyz{!`8J+;vu=7`YU9XQfxCdUmWlZJBLO?ljTspiVok)Oc@xtRfx3Y6i?XO-(7 z;ds}LIt$^VQ-5v((S;G4(bHND;X`t9t-Y)J4ehC^6gAXQ6+Gz?r^@I3$=Y9-kWSgY zz9*jy*qEujv73oCoO^L6>_qy3CH?FX8-#IxIwU#S)AxnI#q<1g>zHTdFYc1r<;PMR z?kcMTzPG-zE$tvFUyWO2oG*bx-e_0DN!~e;I76749#zWV|EP66FOELHP!!PDf>Gtv zc7?QMdsZAGE9j|K9W-n7McXFc#>j1)6rL~NZT2rg94g&i-sSx+5BLL>+J&#p#h5q zmfVR$`)4+2GR36JBzJ#5O(9oW-JuTn*T3sPV0OU%(P_z~w`5>vWIbnR_S#==e>7&J zhARl)mL^rh`A2bggpHP)r*VeDWz9b4-ZEOx83X z}-? z{Ut&+qm|j%$0IJdPf73Y5n0@#GEZm~ zs-!+>3N2lp>lTp=Cg=u-y0g29+oRbaaSFg!VhEc8W&%XvlO-*p%(N(`P;FyUavkB} zk3&|P4snV^(9`+5lKL3AT4HQ!*Hm%HNigug8-np&6Fs9F1W*T_`5p&@0V}v(kx|&9 zFuE{4>bC(v>h&Ng-HFTa%C3=Hkz!f_=W_2>JT16k{j><{-Q5Z$R9f4+zqY)VH0E8N zzlvKuMQHd1#s`*Aq#&YgGYVhM{Dzl@zv@b__f)W?>4--ep82R<8h7J#MIjz9Xk`X zN6N2_o7_?O@S=o1_$qxE6QAyuM4N)=qca^26zKaJb$1eAwoE%&5Us}Z2})v zprX29=s#eiFuY__+0F}10yO@fCU@4xKX8BuQqE(L?0a(3Oq?jLPP@uiWJ@U0Pbiz{ zappz2!4lo`dqF>&-l(alOt=28dNjcGm?Y^z$)!E2Yt|C;1PcmmHI6UYR(#Jp$r(}^ z-z$FCdvYKvJm?CaUft>BCI=Sq&V2eh1#nU{M%yb4)m@C{i_nd{#C4zk{pQ?{!muP> zlSuKHD2MoN%lro>)E#sDy%35ni!3}TEN!h0Wb3M{gniy8O?lyysnH_D&27y8cdsdV zL%@*P&NCcQmWnrE3s2O*DD29p{~Ux*MS;frEy~fPJPpoE4v!#uZ6P`+*rr<>f82>X5uX0c4j+A8wkwt5=8e*?M zTc-@HbyiN2B1IB+?fCD2a6=Am7G-IL(Dpkq70i!m8r6lz)ZznW;*pVSi#NBdFkqy1 zP)Js>P!hs;e!v5i)wF=A#p-BHx8jw`Cc}_v=5i+y<`dre0)3lPO-ag}laAxwZJL-> zrcl+931`onP=D!$Vz{rBf#}|)XqsGi3Ipo`ClP{<6~o@pLZ4$jIz`g?wC8!Y&n<%H zoP~we$K$)#t{Sz4K_EG+P#!Z1IA5C;>W>~Nf>a{9EA%*=CtFD{($*{gj z$Q@=+!c-*Gqlt6&T|63G+2Y{Nv7Uw9VnFK*zL;ZVx;z{2__*XNP<}fUDq+GD3 zr4iaz|9jx>Por0ZPnAC+Yy#z|zJxCP&>ud1?mxVJLHV|I44FO4C#cALZ5D_i?^-pM z5etm+8T9c>mlcenitmNdp6~~OBavg3`08m&Cllb-U_1udJ!QtU_d=i?DiS^R4RXd@+Aglu%X6Boq+ zr21_+N;0g8^u^@xF=Q)fhX_aJgc<2Bfb*(+CAUR{_tO#fLtux0y51;B*^{h0Tk zFQSOI>8~Jv$BW(%3Cp^4`v4VqxR4`}zA=7ijZgeOv1iGEs${xJp9-nB9nRPGI7x1@ z_e_1*S4K|{t{HFJ&m%na7_3=hi;Q_8H?8?&h<54XccQxKs1#0Ow|rG!hJ)N#kNM!T zOg;VS9Vp?Kql{KWRhe;F-qBa{koKs`ujex0j_ro}<%Z&cN`fw6&O(joltr<^vTfGj zQoDKUt#mjy+!$09kP%dpL9|xB8VHR;v^D>{LQ)Oh&sk-ktWJ+hC|$lhe9W|vu|8{4 z#T8v>@Ef3|1f5g}&&DAfea`hf1daq$P?6Yj?#4tn6XG3x9N-{{dnXIWH{1Ye>D$^V zQxEY`E2}5=j^#Vpnwcf|3Zzn;;NtAt6jO6|M@6+6JW{4Y0L7~}Mug+;NUSW`EV-o* zrrU`&Hchx3F#8!6?!0~_ddxMwyV_nqKK}%(Llw#qZSP@WhXC{#b!6J2v&KLAwY8QF zX*Tk+f;>aK>=Oq5-F7H7|MXHBE`|?E!!g^*DA~y%__#`k%m{a3eXuf`sRM~tMopFZ z&|dE|duCCUK%sqD_KYsw9$|~5ipN=K*U8ORNH`wAFP6Ar+Ex`&xWa)i56ASlO6pwv zSBQC2R zfz~@pes6>jZN{u7-Q_?!xi7A3DhZwC=&b`cNvL?nlyjZ!QbSB8#$py%s>V^~!vf>F6tmrX(xo{RrnD7n6D zD3+x_7Vxn;3xGgzlD{>MFFq3;4{-badvo+Py&y7N%i_z31kFdlr}+nE(RQH> zFKUDC@g|AixoQ#!1=5k^fAy4&RBfy1SGlJO$@&K?}n*P6-x9gG9n3Bzs2hCe0qQ;cm_ArSCJ$zEw-fs&w_V#sF?hsU&HJNJ&k4s!Ga4P?D zcO92{sSS&o|KoSs6v+L&-v7BY=pJL9K+up6kA_vFaMWUTvtC4DEH?U90>ywSF5QXQ z=y^pOXi@Zd_l*mZpv?R@@Y;zRax0mTT=j0Sbh;}1f)4&v24E9D-o*8>MN;S+hXZg? z&qi~(7eKMARY_t*7>eh^kj4|#U1XQS-YrXwx0(9W5-qI{L_1HuoV<>1VEE87wd<** z&1Sp(yz%0Dk>HWNpcadccCEW5pEAC9Vm7iaeO%8lWo_Vm9{XHKG5Wxl#EjA6@B8mY z`J!fKuzTjND%U#O=Y2G9>S&x-M2+DjeL!gnPIH~kLt2Qy)WS&gYM0Awu9r9$gClVR zkz2^%!%k} zIW-Sdh#1%9tr!y=vyD9LWV*F!d?kvkkG4+q^JMBm3U(9*`Ui)V+bz#)MiEwxpcBw9 z(&Jl=WO7hq!(IA9|ur8Vd%rvN6YF| zs7g>&^t~+fhi#+`(cw4ikC)G63}#iny-x5HZAd~*pxR=FYT%o%c%JK{py?2uM%i1t zN6n7a+euH@?23KnrY)ESJ-j$%hUE9j!yT+FiIE|qT1bw-C`HzOaLGf^lZ=*x?iX7+ zTy9Qv%zwyR)bJoNH9T!9vMe!_7y14fBS3sX>4f<<9Xs0HVk9~AV*fZ#jR?||436F% zI1T#IH^Q{-9~#945$4{3pCAJq*LJ5LT-f1hXLhTHV%Ac6ouMYS#`yWFES8Zu&{U#` z0`-*Bee5Dqa;+%(da@!ZO6Y#?Btc-v{36mO)O~V_55g9g&d&gk63PpqbcGrV$E`Pt z=ST1lN}7E>YWsL68x-*12>_o=1hM0<$BvQgMHwSp@HF>TUp1}__}7zr^lF|{toZ>~ zAYm`i`wXZZ@$-l9FS-3YZ;w46gxz;rek7z>+dkn5^z@dEEdS>Wx(r#8uap*ZReqx1 zn*90jd;O1kUFkvAV15vPaP6}sK60cw)h0mM zaY4sL(Ov8G@tg?jyXdCE$b@`{*hDQl^x?`y*kJn*PqkCR@uej{40~X-9(bx?7+B_Z zKnX7X5S$pxJNe$}iLs8G^4AP{Y+wdho$~TE(Wxr_I?QucW|8 z(z|X)&GZLtI}oO%ZVj&zx+YG|o3!E!=&+A3E?x7VH?M*R_)Q;P%qG})>&{W-)kA1+ zi;_<=C0@A17g}>g7lr4!(Q0^_B&PAY{5iu(Y~w_|6&GkYWt>hUiRyE3&|58Q6^bUf z2N`X=UEO0c%`hMLT$|kc0g^&vd^x^(3ZaAS z8Nk!VRjdqXn%Ma>(5znm$B}^y|@|?s_Cng

i;Rb&w#Pm6KcfnH@?;}N#xRM+Uu%=6J7Amu=zJi%ey>a${N2tVY@UP%-@ z)kIg|LNkrEWavS0>&w@53(xt2Bf?A6p6gq@8`z(8F=jpj_VFk7Oob=?-XJ+j-Awwl z!Fhlvb&zP&1Tm9l=m>-S-ujxXNCszwp`{7gfZ83Zj};Y-@78FW-98}Y8M9m!dvr?xlD3E>zNL>S!2b~IKM)fdbR+&|W8{5Dn;PolWbzbZUA@W2eAg08CBZOBgoQ=D*s5Azj}R0aen|gQ}SMys^0~u7GoIM|o zt}d%-aBTzbH%HPTIz&4}i0q_Kbq|fSLPxCAT%7>xz7+|O?I}7K#)P~kbt$VYPl$=U zXHQ!7#T}$M3A}O(?<<>Cb7tjE#DO_|W^;NI!D*7yMRti+5T;lnwBDzl0Ip;YNIzMC zcHDRCoS#pQJ}#}_(Pm$wlsrY9NE?HLXSXAghveHHg{Hx$4IrLJC#)eNNbOw{%LZ{th$AeVFiReU`#lB}Y9NNK)n2u7o1m zG!5cEY(p4x)enx#P*`^!z4)j{6&{+mq6r#jyGBT}jM@sMRl05VG=`+pB+ck!k}DDH zt}L)p!?nJ|m>8iXEcE}Wg0sB-1N`e_zlC!G?y+n}EPj8io{HdQGRQs(L03=oFM?#T)X z2ee~oMnfKtTAO?Ks*_uA))h$WHcz%m&jv@Y10IfTd;X&K7Bk&AsK8STG1s_sTg!$z!b5HTe?SHoA$)!s>_vf9hcY;f;Dq$2) zYj6_(=S}!O)@~cZdrZ=xN3yr2q^Szubn=~mLzARL@>K7-TwzS2By9&AA$MF2P1xrF zX+4T$9!P(baG>Ve5HlpQYp2R3A<_GP^V)8^o0@ogmbk)%D#%U!HWv`9w8kj*8QcdS z*E0rY;^4I;jWCYqAu(k%Cu~Vb=IH#>pS^TC`$0 z4^PpY>cE$d5I^X01|=q+yee}4@dvBdslQPNYZw!<Fqp|Ct=<~0ULoE1hOL_QPTAg{(a>AFgz0%W-& zayPl46&}v4toICb0PTF7;t}*FIgyuEr;&tlgWB7@8CX{Kyt4*>A6yCvbU+1E+mN-Y zTrjkSuQii0UaDI}!BQiIc?LS`%AsB5^g)&PO`9*a)?^1xVUFCFJ|lAH_0_W>uY@|- zpi2MUsKbL$>Z=d`?xNMqCZK?JH+eI`hzwrKlhHhoVw9N0nhuL2QOJ(<(g4^Er{j~0 zlCd^S{phiPntFeYz);swQiQqWOgzzguJs5TqLUN#`lQVnwhI!eP&(&3kpvL}5L#YK}*R>4} zkT%#GVKpW!oec$C#$VbqZ=YKF-I@9+>0CSZKA=-f5=tuEo;I`3yJulsJ=c2+Dnxd+h>%UWrcFR#nOHydJm z$Cy>4u_z{5-zj6W1;zK%Z`&kd9~-0=GoqaSD2ncqi;di|=o&Y}g$R6e{FksxDjO?; z;zE=pgKKj`FLe(>?ASl5vMtVGKPZ+W5!O3CWWf#sN`S%dgnn9M^Y6sN{OKiUUCECb zmd;XIOC5Tzp&c%K2SwJ82Yt*X)vheLtZ!)?KTt>l5bAp@``7PUP{!ALVAQgi5Bu-Q zP@(b81|sj3<#^Y+dOkpH@UQ)2_mdx?m+cQB)EhUdLW{|{p%flP<<2)?QuyLD#sFT1w&&PoSia`N`z2H5Bc_LVf zckdBFwjg=hbyfUbx-Ll2BUH9xn(nSvTU(Fp>ISR1!!8mTkGdhtmV_(_J3*9hKNrOd zSqAarw^g)jUG`EjME8vOv{nL{HP-U2Y-PYsm#Z}`ET)O&w$)T0=u>V|zpx#)9gmq_9@6^89M=0FClajx^l$^Dz_00t#V zoDYjt>6ch%(TgnTd~UIxV7-Jy1UOCV#r80LTU|9|0l05B49i2N;y!#`&3!0L^U}O= zR{Pg}ZEMf6C~A~lpFhII%7JhPB~V+~y!gMJgdod9S=PQBtS3*c(F% z`U7oR{DG~uB1zql?>%N=h38)mbXUG4UjL5$?*?rDOYE*#bz9Q%U$xWHb}x&8?~0qx<9WlAhli2wnsI^Ygaol2gAi;VB-QZjJ;@W5JM%i+3GH zw4r=&V@4`1&{omDsdbRyx0*?(7z3_(qgu(Ro6nvtGH_^|R|bkMt|X*d@Gn?+hWvNK z{^Nx~ae)fSUYlO~dP`UgPRa_qO>!gH*s|8yBFKMm`&obfEmPlj<2jSc+2r4^-v6VZ zK0^JU-?Cb={>O>q7#Xp5n|o}IBc?WiF$?|;6X^=K2S^eg`ggt4-hJ0*KfeC>-woTQ zn=7GyV-GuA9dSI8+G@l1ra_y3tGfK@^6K{g)GKq4^Gb{LuXoUM_8AtKB4iUmx_zbV zkq*y;`8MXCOF#OZevaslsCA$8p}eRrVLSVskh#OAO<4#URgy8LebkY3A{0~B+-pqS z6n>gq1rjob>bgnVqyM`>{#A7TWNEKT;b^DfSLdz6rbVrmm$>ElH%px>H}2fnTeu4H zpGjWdz0pT4HV-s&3tfJ7-ErFd^XT}?%*e0PVD?(z`)alyqW4C%I}^hHR{zv>^QLCU zK1Tz#l)RnE5`zrKW~{F7IZu@ri`M_78jcvVNQhzI=AiIZhz{Uhg}RM0^U zqJTR4@qLhB`Q1OlSpQdaBdzM6!TpdjBWt4{XwCeK1%o9tDp37#zrQOq3PeMh;X}xjhV(?dC zUg%p_m^G?(0`b49*B&AU4hj#>YmNk?|EzKDa`f{ntmHy^wigtXO?fspjwx4Wf8O+k zUMy)%Tkc-(xX&N!&7uoaR=<$K+ zow_D8a&zm)Fa9EW`*G*wUpg>mhSqtV*=B0*zfyIX9{S%62ZZpIa*R~B_o>a!b+=sD zg;&ef!sN z>y9UHl7Ig8z5a&Do&U!EzmWrme(V;wHg$3mB0n7QU?Dass*a#$QNw`$ZpZ}c{w`<{ zV{$iaSwr5eUh0j@Pk*v5_v)iUby420foZmjxbvMCMO0q>=^U85HshGsM9ATF>s8T| zi@~>V1n!s3mys=}K1mQy5lxnFM&Dr6rMSH+n@q6|7ph1}vo&lb`{hLr)z z0ELp&gsb!B0Z%!mbnZMB9r2-X@-<40Q*4evnd& z$Xy-icR7L!k0Bs4Vx3o9I8Y~75bQ$`-^D?UmwZhx-7ym8?}*^CjewOF@4yMV9{g%u zMt|`|ONEym_Nww3H7dQXCn?IZr31ZQ$F7Nk1;SsF3;JP_7zv8fA?;`$=s%pW1WEHqgKh0?dC{6 zjHrgcPXTbF9Y^d{^qn8g%MO1Po*ZYMcjH`G z?r(JHMMb3lW)qbp`55szZDB}kPUsO^^;W|iID$Vbo~)x;Ss=D}dS5Q#Fz}&pM2eExeS#(=@mZTTjdVP`tip-!UE`-rkt}2Lm5eV6R6$4wJbeBrj@ z{Q(Zp@=grEZKiy_^y|{UtN1-B6HjH{h7lfReto;`c(`~vV#yJw*SPM&-lOtE-#+iJ z%1&%b@vjzr9swt&e$l;k>#WuGVoN0v)gQr+TXH{4C#s^tT(|`TUU^wRHIGklFql*K zANT+^v~)*;3zW*#4}Z8GQkJ)D`wgc@(u7?Qk7I`ITvw8L!l~7N zxRz9Qt*@YdPeJy()}=Z5a+J0GFZ65d;}mt?B1fdYh^Y0=yR}gvd&&!HbER;cShmf3 zcwC-UNlKczMG8iQ$B0A`<-WzMg&?Xzi}B#x&8NK+sqtXayEM(z3<`Rn-_NSQUysgi zyVAIdzm`g7F4wS}#~WI#88|#*cxsph;kNqC^IJ&0rRyh|IW@TX`R*DkcIw1!K++;R zxeh8Lqg1@42A20S2^j!OEls2&DUj#<;nS(~%SU*_1?nqQmHVN&6M4jWd4IQ~Uz*Oe zOF^2waQk(E>kgLYGWGU1t9d8J&qI>kk_%F-&EaJO9X8P$(g%u(sw!J}sM1y!1?h_i z9GJT2eo?|bqx2f}OA-B5Ulqs_xFj##>%z;3z2i7>Fd$9cag+0!zuPRN$ubnr>u<1w z4Y4iRQaSN;O`lP1rHt3tEG|I>dK@C-xnl9`?2y8{oZN|wS3ht40-VKa9J^Dq?@c=C z=kZ*oSZocX`sL}}oov@2;w6YWUM$KCcD9+y+#0nXh^vp&(i~(l<|io$v_EKKCEt!p z=l2FK{PjK`d&=Cc*nKghtjz|-$PEJbo?co#6PZ&gdw%yX$o=$Z@54QwQg41_nE>kg znR9?~bpDpwD69x@7Uvb2p<%k7;5hYHaf{1`+<;iWLQ!Kb{g2RwppGduvs|t6b-46I zTz>4pValmlf;(8%(#!sz&U)o>yAaod^?{e=*?Aw{QEM_O#cpHVQlD%GBO-+X`y`yy z$Mf)H0X(H;u=qnxg^r(Tu5-~)I9W?iBDhlC($sB9FL)RRTmSC{Rx6H_@$HIM3vm^IhK;8|($-_hzMt{?XlUK!e>YZe!oN#5+^rO?|4lT@lbzS=u5pZ(beCQ> z@BIhPy?Y-s)L}l|osGY4C#&Awzc3fEzh*mvZw(J<|3D03a=od+%>+rK;Ii+AkY7$0 z-oqab7J7bZ0%2XCu=`)JysIdQ-dxF<&wj79(L?Y!oVtYHWL&CWe7%!chU%w_Q?iQF zV-inSD6KRwFu6ZMx4B$!ss&TBGKLT^Cy=tue)0N!hhxzB--Em zv%q?Pahi_qJyB_W#_brUA&!+^V`H-Z-`|V6o<68|A_4=012bBFzY2I?Vi&cvlAOYm z_z-lsIS>U6@0myhAq&+l(}mI>RJc#k#|3EzN=`=L2$y~)oivH5i^cRvU`X{D5)s!N zN7SiDMUga`69^2v<;pe|Sck7Qn1`?m^l)1BkrBEdFdAO4_L%$nVba1-+eE;}^vSO+ zkkYlV20J9g36!p3`_nU!Wia0JW?)b-S$hHaRj=7eIF~}oVN3jEIVkd$>K8adC;N%8 z8nDJ)3_YW=Xeb}>l+uHv60L~XGMq0sQB5c0h@jChIl0(TmVYmg@#o>M0>OA}f+*Mm zr5`ei&zy!40M(?(9`kgmrJRJtDWpP#h(2K|tx#OndFsudXO$8mYNKx1B5sZFBE3US zNQwUG81gFGBy6U!p5E%KL?%zr1JzV={ za`N*aKn_P=?J?hUA_Kt@9Jy%N*W?y0S4fDM88y6|kQk+q&$XtAVy->J24%X}nY+OA zzzP(9b0QCf{i>FHWJc02sBc#{9#UpuSRn5OV4g{PdscZJ$JAe%ds@SqaqArnzQyj} zkkeA|&YMGNAXP=HAx^ekL))1a^CY)eGHoqmbVyF&dg$V-#jSUr9NIG`7wM1yAH{txLLx2V`Dp|%oZXt zZ-t+#_v7J{3JB9tkMK*VOp;~IYPAXx{X0plgt1s^s%uSR+ONVOb>6XT1puXwdA>}F z(hUN{$U^GvCHK@H6#DUhh_pM#w_g4}y=*(&;Qn({t!ve})G^nZAQV_ z8H1=?(vGeV^nKCtk~?2xOzj^=V(P%h++yRKyDEP3Zs{8;P02=(=06SpY%*MbH*SH> zl7(5g1uFa0U8%Kvg)XH9Wb!_0{yI0Vmo~YGwa0fG*9V3ydcBan;A9V6d!k zM4E$!zyRBUVu+Xpvll8l@MR5WKD~Sv<}%X*z#PBTB6w+ z{=OpQ_1mrq63)V>2cA6bFJSAgo+h8UWh@v;G-E)jS&iijl{~@;yXl0NZhWWDWM!Q< z16`(k*(onb+U0(9pLwa1phhO5f3(P$LqHGs{F?y>U#fX&sUzUa{L@PYco%JwD+FTe zcu=9V!&*HeF#o-%#L&&xQ(#?*#q9aGmsfQ6H)>6FuoeE>50WIG@i`vm8kf$?t0>5OJ}@!XLUz?XSx;mnWr@D^ZZlqM^A~s zA>V*jb?IF*>RNaaj&>BcPqhBcny!LjqtiHJ3&HImWoA*J5Fgf^oh(VK)}B+UL3lvL z0|%_YqYisp*|%&k{&>-j(wrJxdd|RMR4?cx&*Uy zWyS0H%{!bmL!ntc%qLwwJ}NbX7(O}Mng($CSJHT;pj zMMuSX;olGK)#^088ZGunI<*sIu1yyUOz>w|Z`O+(s@8@Fl&v21kN2#&PWEa{q9>{% zD@nAi@j(%LhP!4-_qe89Cv$TPS^dS6ggFuj5TUw3?Wt<>gXV0uZk;H03(=?~t4w<6 z%glUdwKne9Cv&kw-lwEJQ9uy zkLoPNx*u-O=+<~EKmt1kWPa3}a;*>CwFkcytA8N%YLA}41hD6B0)?bxJ|Bi?8I8nI zoF3X=szj-9Dtf%)%eB=oKTr!?MX$+S52vno!8eLv>Do8-*}oU&guUEQf1?$)_kK_@ zvu``oMo63qnskT5fW^?Xr@Lv|?aH4u78?{YPNsiQ;!VMAK7M$Ki#EH5*CV6#4W2

i&m(KJWSoJoOmgXB)!atM^-!~!Af;!ln^N*te1XN7xekmu zI4(-2SMYr4TE$fw<7|*gSFrk8XeA&LCfS%edMgjjw5>_lVJ5AP-sz43zw@fckFf+0&wCbV%Uylgzl zrNF^$MLco?%QqTn0G|ssx15nP@2Fn44Rw;QitBMKf>*pEjrk>4z5;^hu8G>BXc4CT;zovzOwD>htof&#{Y#_{oB^w6kFoN$?)j$>(&H?+pr;Dx63f* z?k1T>cEgRrEU*SX3*Vn>e4OrJb_=HnVlwfvm8<&rp@Cqu8`zvCVDK0KZRaWAEpYxn zfWl}&ZJ~amM&>W5Mx~UEM)7$y48aI$DAUhZyjND%oSjzfPXTglq{+>enf=P0esdpr zR=Z>2&1OIc0CAkb_@f(gEb89%o+1weQbmXIvwx`0z09$x`N*vrA6hD?!?58O|LUO9C9j89^qu=*j^LdF?&%T;Rr#jW&L(m5977_KRYDUiD@WQ-i_W8~35q=#U zV-*_`aWTRa-3wvgnxGPi-Dz8I*x!t6*S@LQSJ*LcYwT!m8B?ZSvfg)>+uFiZeKY=G z=RSjW5RU;`8#l8xyqha%eClldJo^dS`eTc8xN&nsmA2w1XVU?>EFmUQ5;7848_8!y z0V(ybqsR?wchP0hWr^!G#apx4mAf@1oAgZdt`+r1;zebQZ;iisXuJ~Y zwSB2GJ_E@gJ~8}Wi4hGqZ;9%oNE5BPSQ3ZUf88FRdA`5#PrhI>G{ulGj`>YF*aLuxAvj}89qpo}r|D^p{&v~P}p$su`T;ax&p(Qyby z0EOJ){5FNB)^C43&zDsu^k9+A-!{)R`Mgt72dXhUml_IGA!&(~wTLc#JPL_eyi-kG z5C2+p$1V{t=^{j2jrpaEA9`K3_?fgS2pxIu`GnjhmI2!zr_z?5YsVaO2=>IU@=Ngt z=P5jteur52oN?M{1eBj|yS}y$@7@0{D^E5}5(jjLnkiH;_i@9l62XXHUL0JITh@TW zUGvZ=Rc@%-puk$@D!?@V0m9=iH)xxaRyn8!3+#6+HEe?dqENVvv%yzFblOLc4xC_=Ro5&}qE#0WA{)S%OehgESk~Bk1A& zy9N2D^Lc$Is8SAuofRDe?JD$A0j=>*>TX7fyl2=()d)nMvf_vPo7VOK^>;VQf50Je za37Ifzw8iCG2Ss5RLsTL7^(kv1N~y(0?sXg=Tj4C;;e44sow9?PYxe-weGlZAVQk#UiRaA@M1U0w+N=Te%&Hnsa3 zb){QPNUivCI;p@Tb!q!S711pSN^~h4A{uJdas7g)AL^;J-!8gcpymdAuUG!yTTOZG zr8;4T=(w{|$TyewT$Y(uhg55IZ?wft56YeIJ-4%EhH@(vWv?nSch~P*h4|m4p%^FE zH7dbrqRJ5JKsvW*mt!aGCd+a8g8-r>whXaocP~n)QuzL6jJpCZ1THN6EzX$UnC_{0YdL2#v+XHyf*rl^uEnN# zwK_PlGan9(1syJnb}D=1C=Z~rR}^zCYoqvqy$26eMexkZ682n4RGi1lI`I7yWl8wR zxj6($h${lea77JWS|y6y+ljnL-Rh{QGW6}k9avLm>jW(kBjx&1 z(vveuX{xn4|KveEq~*J;ooj6RD{yXspg~+6$XP_ayf!;4lHPiR$#v z)MTZ0w<&Bn2SbFDrCI{k;= zd}T(dQDt9nlW7xV2iGz-zv`(!|An0XT4!8Z=KJsy>%YaDQT7IGZ@V@E-2D!alr_JQ zHx3EZ>U!czwe~!sO?9eT&4!uO1}t6kK>&C|@VOgmS&pPhiZSaklD<{V-Fm%$qRm86 z+a*LF*#L%od2QXBf4$tYmyLv2^sF3k*@8M`Igmy46`MknYrx-KK^t=cFc0qri+ww- z#SVWzGCM+ro1{O9H?l`eR;27HSwBhC-=Nb2+Lah)Ao@w;GX_WHDgEO|=JoHKFn=Z? z%k_;6M0$*+2JC)sr?3BeJE#_C@%yy{_17dAr`(qXyJ2&>hz94&BphE6V?K$}O=rUo zLH*7{xPs>F(23OQb5Ej^Rz=1OAB74a-BZjF(d$6JH{VhWQaNdHeN9?+ZZr75iEvh~ zV|Qgo%sgkh8Mbo5ep)8v3FdZ=r&FPw&9-ORoU5dOY4i9`TaerS91{JC6pRua{F5o5 zJ&7sx^>6nnT$3{t$7+lq<7^0=5s}LkV&@xSlWAi-?VH&KT-;Y1z{uAVS0CDELGd9L zNTJ@!n+#TC5Ppf1viDTE&i&}fLVLFGz84nsz(g_|u*Hm0Hdhg1K1zAomLKD$jqL8!<$x!g>!u#nH8r%V z&PS3o7u;1Z;vWk;r*BNFy-=yqxc1K)i9xT^SEGAQH7)su89J4!+<)U^Hp%$tKIeQg z?>mZyTIM8qw6`_$&2s_C%e!!#Mw;Ygcuq!P1S#Eum}&kAKKOuxD{F&?t`Bhn%1)J# zhCA4EeYJY?G`M_IDFise!%Ln>`!>}>^qcH~?AS-Ew!TD0{)qKV;2Swfj*$j`S#tMh zz^DPsSK1R?IsV7qE!n0+FQ!i@z2@e?PxMDdsr`yPf3BsFB!tuBJ0FH*k9S)PIHZQJa()~?Zti_w z=)S+iB8!+Xp8uKmmyKAlZ2eC1($2C$S|2!j+Zh5mbNQI!4M4(Y^3JzSY;j=DPB)xdeO7+! z?uNRM1CFkqcHG+FX|P}8Nk+Pop5l&Qn?YSK`MvOGL9m#gJh^5i> zGFPzUGP1mJ}|WxpJi>P=|Vhsut5 z!Qg{CpLY1$c{r=XdpaIY6eX6wtd=)&Qev~|S_do2W~kxb%vJzwJ&zv17b)$#$$~L` zFU)H=ODAxQ$NTkDxAP>&@TRR6B2>7$79EMZernFyBK;r*lZBtZ3j*HAoDGkFr;h0Y zN@9TZd5Fu}!jqhmsB7``ZfS_ofmoq(Ws@hdU@ym8+yV`eLVGG0hS^b22i>SPO$}Z> z-UA`oJ6W)y2Y1+Fhu*YjIEGDapTA+ROVYxjvPNX-M6Xa7PZ$Yx#sDvjqSKOldWF*t z?(rFOAqlJ_`GNUQWXRJ!8qFR9`Qp4lILDn`;gf*s{jTxuwQpnH#;kd!5$@1-Z0nSG z1Rh>Bpv|T2^52c$e+9@5tyJ-<eY8(VMne@vf1)K7lBgp!J$;`?1|wkGmS zwpwxPyTBR$wy|wCdnMDS=)+WMQOXN!Qu2fH=RW7oGFHQ~3f+^9jPzTRxKalclVwWG zXsC)N16e%gP;(&?PQ(#F!q%ExnnP5ftjps9HV|2AP%VyU+ka4z-=Pp_hte-`i2pP; z=p&adqtN5v`hxTlM>OC7Dv`kL$_b^_Q(EPvAcNJBL=f9rXXG2zsSf@SeY(o>`(B%o zf04Cj1!cH}Fcez2MWrP^=@Vm;`0=uK{P1G3+u^;?q*F%l*#tqY+ z(&BOR5E3>1V+Ttn zhdo+7g|ufqZsJQ!qI4|rA$2`n52Lcbzj_bMSnTt;Hch0J&uD%fmUPCrqFS` zc;@H2FP1=m5t0Xl9z-%XCIH~wj(%+_>=jZb6|v@zO7$_~)a2o6Ix|L!ML(ZI@zee~ zaeb;fKwgd%`)}Eb>uMP)m1Hdpi>H{8uP+d>=D260c$m%PqyuDlbF|H16`kk)#jrER zdaISJSNd31`A3hSy}lx()G+XccLV389`5tI?v2xs!>638+&gHD>syfmx~&O#PY<^u z38OQZtE{>0IU)x->x#nrx60>Xw5>i40r6V8=2Y3pVcX%`bOrBaV3S>*!x9fA`l88BA9VxZSx&vQc z)4fKoGQxNRtOTmF;f=u~w}~BQyYX3=ulW1$|B)b#4+fnSDd$L@fT+9T_MkosyC{B0 zymKnP0L%x`ozv8E%}q6U3Ut1wi=ESB12n7Er3xq6cC6O%Y1p+ak6@P|5w6qDRJw#s zytowI+bmUCP4+BeLVjSnmr0tyYcHoeL(hWQ{|^<#{sDpB6ZS3ARRmd8C#7cAT*Fv=Cs{M&2ZRos+Z6=iu z*rp!Bav{fR@wK?m!H@vNo=sq}kidc@f*un?vYh-GCZkv8t|G5!)7%yA3)^z0j6eF= z6yC{2%h}~LePGd1?>PLw=H!reDQ~%g-JE9A+w}&2^h;zikKijl-8vs`2x9JVh(Sd3 zlip$Q*%kyGf@u4m#^{xqKJBYEfycjSC z4=|Nx(=qnIf5w+LMl`Frsp3xNdi~XR1u05PjK|~5spSqkL(N~l zUJeG&$uI&(6#to2bD)SljT!VT(AG{spE7Nj<_zqhyyziY}7!^&6C-z z1~V~0clzvGU_WHmRlA!d#j7+McUESh+oJq7g&->V;dDTijq*?P zSz^C;m{jf6x87BuQTD#KHh)^~W+eIUq&9qQ7yX5s(h_>bX-(-g)KZ zU69rOYFtVVE)x+omOM10F&8-YgrLk^XGaSQcv(=5lsin!qLfRi=_xS2s zO>RpMZBABkHJ?&|D}?l(sa}iWJC&4r+YUD?RLK5<4aged6=tT$X@&^!=1=Z7jNTE* z3mzjSQyxyGV7Wg2cj3Y@-ns2K@+oov7jyr%y86>8p~waP3FuLkamkfgCt8^6 zI^CW4Y2p48pKohzjGU2pSuxwCg^{!pH^8Lvkcxq=ypyrUmt!o4}817b?jZ|<+XVJ6M3FyR+$UBY)9pyUEK>PDlvKgsyWUbxE2Gdf&7H)LxOP4Kk2YZphR>9gre95VL{iE@2QyuVv$GwsJ6 zM7iNQ+tXcAI!T}NMK+kuW4@K^;3m%h+Jd%x!(RUy3Ec?FbJ$;yLZnjNL$w`E{8VfsGPsZ|31kjYqp4nfmiStmAD$$%oSeR>mi`#! zy-(C%3tx95^rtiXu+H1^#^&vv`#(ZHHgR76>DajYDG}Q?H}c)G4fi!yaW(z?_duA- z_X`g~8gOHSfq6Rjajto3C|izCN&wUGgstj1zzWc&=?n*kI{0}D9kWq#CIfQ8HHb|n zAuc<@iR+S6ja1=xn`XA|`j_ZCwg596q*tvRru|i)HOB=6cAl=^oXM|@LrszpwaG*d zp#gU;Zhfw7nmGJ*XxKgpSVRxI+w3~lrgWIshSmuFQm!Dk8&?kynoGm4X1GJ--!1}E zs_|n*sT{+$&at^=IXZnU#=cF`p!>i#Qqw&b+}s7hvBYn=W$#xHux}qbb33!V7;0oY zcFzT1VAzcE-Mn-N#YEKW*uHZA-s_yUUVDvoTXuz7|+r4V-FHqiE&fGs1Z`3Ro+FX6=Z%22Uhi_Nk&9d)dsEUuE=PVm%bm=g&j$w3d+|CMNBvjHCOYhj zc$`)5qpk5FrEl?fQ?YgXwh_LttXms~4!NOge5LR*GzbU%;+}l{$`51v3Tb}%%1zUvoCq@Gbbp<~TK-op8 zm9;t6GTwO;WJf(P3DHyt97Akd!J zrIg_RF0cxjw5N3+VMj{NOTzriZRdo$g@kSLtq zHaCPM<~RLG8*{#tQ@-?(4Za_@)9;yEdYF!s{V#@7-A-&xI1$TAh?lA9W&bigvZv`& ztm)2Srb6)AuS)8hKm;nXoR{W&q^?Zr2CjJS4^EQy+bjsiJUFnLmkP~{?3~`WrqYiI z7Rqvu9om{ozm+CnmhGS>nHalkYS{y)RvYr;C|4%pBKj+{q$-w6Z9=QTcvv^9r+7l9 zv8aY#x+v-c4^?Wk&k2+sU3Y(37{H4+nfeWSv-%KP0n$*QTA5Ip`VENdLOtCd8yxkP zPut-)E|Ozj&93=Yv)z^Pp@szo=&Qj(iS)sM1K^|_8sQ3#*qwbgw0Dg<5-$}m&A;7Q zc2m*S&V`T5S)QPW^>(=<6dIS&gAV3+t4wnVzOpRqniUW=D*xW=K7|DyNCT-UTb4@t z+*{|+Jp)M8!;dB(G5jb36i%mp_b$^r<_!62)iW)`BQRa~FT0iXTF9na;!AD)(J5l&(? zVzqVsBjn9VtXH4*-QL!dUw2`(l%6#KBg5ibT-U!^kk~&f1=<2dkTlsfzOYT}-ck1C z*GCMDqvhK9BE%w96g(dp~!{ysY(Js zr>;$bUZL7P^?V?Vr#?5TT4v&lJEdf~JKUZxz5j!o4i!(d(ehK^63s_fSrhYJaN=A$ zzQ$3^*ctwi{FFLW0>a z+X$VDJn?;#1h$$~Nze?~$uXf8IS<2b_ID6rckp_)iP&@K-yhRom!a|sOc~#I)a-Y3 zjL^lWbBDht(XO={HqZX)>Hs2cUbK5}^uHKL;+>^%W6poq&L{M&+p5-23|IYMGd35} znE#H^3$jWV<`Wa{wLvHyJ4CVY7cB?Eu%JPNhgqD=2-$P2_g2H{kJa4uFfzv)#Vgk& z3X<-~;pWH&9EsDkkqvz#g`!}Q$Qt{U3`x}!*~*+aBqX@XxN2N&(P@H)IzL=Zi~G@D zlM&{RH3zAuvPHbH?idJDodQmK% zBAgn3@kZVF0NVSb^#R8$xEol1tM|EVc8Ez8-{mr_>RaC5z6$BOQ6!7Zit6^lqDqC< zH~hCd_so_>6{+1^l(Pqr;-pCb+6di9@4=S0H)jXCw~ng!7+8_cg(37k{?fD9ds zhhEBqO4%-jE$_`}XU2hVfB;GzQxPdOfM#Y+5>X*H9PRn7F7~VLnhPhyyS|`J)DU2* zbu%ZAmON!vK<5}+C_h|4^W4!Q8>u+%%yCRa?(N_TE-ij*YI&v`OD3xp$T`+;(m&JB zk_=y!8{Jl(U0O7#^41aAJ<9gJ*NeC5n&|sh|7B#qdMqMUr9=G6de{@!-jw0bH!|}dl7~E@2%4SED;uSWk7Vhaw6obp7H=c#|vb9Xq7X~`URpTVXSfx*h^?Q)% zKBt@09S-@@@!-SW3>1!CIHgUEC(IWuMetpYyu5~GTn~4I>H8lI8#32%-|Q5B-Q%pO z_{shUtK^SO7f(c~`6cN8VhM3X;Nr4@tX;KbL9fFebSPk6kRh7i{W&DHozz1;YzQ#; zz~@F2@yRK^2?D^uUm8;SQD-d?HyC7c6)*sRoiO=&O6#TRI0@kox%zyN8ErQfJ}?)< z(TlNxUS$#5wil2)@yGY@}`WnZMRsPo;y`s}t?D#jNm=d%{pp9@<jxq1ZLo#&%ZQ z)JFl4fzMjwQ$DViQV1ReJ!;%ovmKHkCKW4YTGCvb9QMY@sRSX4EZ|^DD!ghk&zDrO zrFRm~E>Cns@3(87fK3`9z$6HclClmAvX(Um1jHk9S9V|3>ONXj|H}M2j66mDW)m%y zB9}+VwTJx(5i(d$Q{?PwlPYh%E(i`0SZPbO!_O8Ojt8>Ms(mU5db9j^V%yL0o7nV^ zj;`yy4AOIALjP2iQyQ%66N^4)N;*52UXej+FGeXe$qFaUYR-uY&bn!n6GCc6!#7mE4QLFgUU6*J~YGzUdxg+tKsLQTg|w5^q7uvvreSo zo%e_Xx-2zacThCu=ndKC-OeMzez1~Rnj87_W&u60Ee(<#@Jlz}MP|I1pU+C6{|nduUc{E> z^)QtX(&ma)hxy9Ia@>hk3BCFbVp7_QMpP}IQsgEOhRH>R0=FWv!yp&0_Uzr6!k!f! zLe4lTtq8(Xd?Q{LSX;tvVdAzlCTN-Y>-X=e=!U1g&a)-Z1lv7w$F$RhV72a;UkGoH z{Iuzmof`aj+EVwjsG;az|6OqPwt+mDp7Q4VjgR&u>D4U^hjA`eI?Y8Kq2q=;+#h5V%r<M<~L^* zq6D-inhE%bx@%68Q@_OSWfK;Lm%mbsiyYD%j-wxTMRN||J>@D)k9MH2%ypwlH6!hN zycT^o$4Y$_pq=Bje&xUC^3=Q&Vjg&hmBcq+PebN>4qyZv`>gXkAKJ}Zay)-wex}P> zIQDOytrw65C8Qy;JjMygGXVIXEy5erP61->y(?AI-}}%+Bsc^ORVDsY2&9i}KLTlR z4$)An-Z21kV~aWlH(nBttExC)(W2wrBt844P0mdKe4@%_k1wkGd94-D;ITBvDTK%v zvnTG=9viBKpJ0XMc{tZzi*11HUM0ok+fHMQ2F=>9d3)DH%r2o z2}$u{h!fJG>28T?rN%7UV?OhnAzalq7a04KiS9WR_Z2NGAUifw%s-i z*L*`TTFXULpZ7Z0)uJUJ)RV%P8U2PLSpIf_G z|4P0e&YJAm{qfwPg(q=Y&0aLE*Uh#Cu9*rLJzTbifgDU7PrM@EKgqoSsII|UhqC>< z7TBQ}aw*_0cW8As3kwq>V147Z2H8^h6helz(~Tl+Cj~4a>EAlum25-YEdr=8MRh13 zmxBW|QDtgz1n)&xu7D;1z6n^q25U2MtEBJ9!c!d;n@^z>O(pn~y)3rwc#!~@%6SVi zpDF(X!*!JYItpCFY-SMh5yh;yb+fG9R*vp#6*lh!ujBk-%@=u6OQFIX?d4aCFS6@j zG-kI%pLDg@pTUbSHw$wo;`NFZlBs91V}$i-e8I{VxYP~1u^Li|Ax#dJ8gpB5Llv>S z(O9e5$rpXD6yP|XOyYpWIXu9`zMG_3mB#n?kJNI`c3!Vdc+`Zelovuqbh! z-@x4gq^=j^ZAb=U{D*$PWS?G1PS26EoM(Y+WedHESHQ8eBp1o*)d8Khjmty+Fc!fWa90EwIcA(~Gk8M!H>xuGR zG+CkIf5(=L$u#2om*v^6e7GDDh(ZP*Ls7IWx_g@dL(~aQPgSg9_gWp)!dxdwtFNf8 z43&ieu9PZs{v6li_f~it#BL3q2+G!JL5k-sZ-Q+kc&>~@XqAicdQPN6a6)Q(GbUmz z7on^$+YU+X$~V1}aU$4X(x8*F-|L+G9kEr{x3y@|RTVqu~K)*y1d>7AV?E&RR3YvA@B701wN`FvX z=#J^qb~L8$&7?H^eDbs>p5fYbk9=R*ldT*+F2}gOc<78X^1r@i{Bq+-Kx>X^ z;k<-)PKkf>40VbB#BL(}F1VLLFy;i*eah*=N=$%VBz_cqM0pr26Y12faWQw50l?59 zA*;ETWW6*==uG?4G*|4YK&u7yGXVI_L&WZ?0%7Cv(88abNx@_pjHosr$aZ#34Fggo zxrP3^;R?&BFa407wNT3DtRJe|2Y_%1=H;O_KOGvy1RX)1*iQ}4-a>w)+wl7VFHclD zCQNU=0+rp!v5+$e_}EBOHT7!8Y_5ljxQT=NmX&f-)i|USvg&hZSF`VEi^-|bCP+3- z-oRNU_nA^QDr8pkaK_-(9TPG}QW2mc{bdZHtY?w@RGXe)q zeb*g4i;NRuM3$`>nR9~#lC$@Cwq2*(Vh-S~#{O47RCwon9DI#({_nygCE_iBEBYKuD!X5%ma{s7Brvo?D&|@ zmMwDUMVzKF$0QrpT298$wCz-2VnOwFeHjkSaZSAX+` z#yr;eLo5IHooDF^7*oTg5d;TZMw?>eUp>&ib!(K-)rjN*6NMA0m_S>BN0rOW#GYkW zEyIwyT$Dh&^(xBCf9QgTZtu0k;gv7GP(KgqiJ**L_)yd) zkw(*8>(17+3l7x1YOpa}@_6$MbrLTca=39S-fwHTl1wx5tLH^+Rg(A{rhlFKjLs^i zb=POaM0;jj+KS@Z`_t3CS~E;rzE+=`|C#UE1&QW#6IRYQ?fufwC9zxYu0O2(;VzhU z|6spIqlP4}K#+{IxABL{Y27>NT#K514%BK>ie5+h9nM4BH=erU9i2OWy@_I!G}QKf zpE+Ch`F-&?2NSZpQ2qMr+z*R~V1=ET6Wk8pczg?ZPv8^%dgH~O3wzG&&MZ!9Zk?}< z^ZM11=EL@e1t_)f%^aloctC5unyeMYRtu(aJkedg)iP=-y--4S>O&gqtbag%*M<%cO zOitIX;FvxN@~bhYN`8__Emt1+m9}clo&8UMdH?6=NOo;|6cX9uRI~6_eF~_F{CnRnuD$DWleyJTYlY(6XYhgFu3nJv-0mE3tL0H6h}i}8b^W$6kF>Y%l&}0* zA{Vq;8JrnDZ~u1IzMMR3kNDV$I0Y8f55%u_$u-xzg6kG}{p2O!nOtM*{xgLA zMS6*nRm;J)tE{1~U6;GNJhlZJepjt?^3>~fPOYKm=|;#~a{Jj^ImdzUsxA6a_w!!} z=9V}oYO`f+?Wd(L$=_>#TL*nNs3-5f&FIhi7YCS|1=L=k+CFb{jQIJ~KOAa0e-gAv zdTO9S$Nub_Z!jL5cQ%&0yfGAT(pb=vbX2&yTl>b&v288<19%dp>y@{IBY=n(p9k_>I5 z-N_rD7Ycm&dmrAG8D#4!E&uFu)5M*-@E`t`+nM|a#rNKlaV_{G%>w7jU_xa#l+yk7 zOUC+lp`0@}{Wp!&6^irWX?#jMY%1#6?fjtgy#Fq|2#Nku6vYrfg8b6>@4^IsvfK~F zOVJCB-_O|I0j!7W`#L<)?d#4*+%JH4v7;MTyZv+>*e=LiJgEgfTob)|-AVet3k@f` z$p0>wK_)Lm8$~yK|5c!|z4hOP$8t>Z-~Wn<|I3B__m6*c{~Q1R28I~T*p?uOVpa-l zE599R^Dp0!h|@MD{Bs{u$1A@kp(#^S`d&Kj*TL71?#u9?7ZrHgNmmO}GnEN% zquUe|g_n`9OV;(glXT{;nb~eG}yeemY8+^qz z%;j32h-CTfg_jLOH&craaB;bE6=9YUV>EQ_4`;4e0-U!JX%$>hO%QaE7JHV>i{@v6 z!vJwR)wIpdw5s3CLie4Ai=-iptb@whFbi2MB3|iwK!QFrt-KaXkR=F*@64*Me->|s z{<{8?DZW$0ls!z7e$cpE(#I(_?%m1W_e9-eZl4h1UIgn zhp0P?iq@bqZw|wQfj@<7!69qM$POOssHNwSiA*iTxXU{3GXnCC1f|rk9c5LXy9Pz= zo53kMcAiFkWD+gkd&W@KN$hYgm1}wQDDFJB3-WuQOS@}Vysw+nX(N*`UY=dk!NaLx zP4SfW_9kCGkw{iEXtrHN``M3x&axZ6JG11XNlsPNT2};u1oM)YrK<5a#kyK8WuaLF zC{neaLH9T4;$vRcv`W7MBS!Mu*V&N9qhMI2d2!j7*T|GrWGvRAsV$>q-r{X5Yox~a z$Ir`ooQvN2y`poABnhch*EfsVX}Al*do-ODS&Vc%Dx3U~3w>tXMdwQfvWC~2911eP zVb|eLo&=j06u)`1s(E0f)vsjKA9SQ9^?7{tC~4d(4I18aPT(J!(-cMN-!;Egn=k2+ z_wa(@4IRuTsr#}X(e2@*p?ALjd(-5qXQt|amub%y5z*?bRb}{3In-rYXBx>gXA{2X zf5dAYz>flnHh$bkuL2R0l60(~yzGaa>XJLFUa+e?IkLfjT{j0P)~irnl?NAC4|Jyf z{HGzzt2(p(k;b)FSDzBOaax-huc%#{`iU1TFt!a>JZza=TAA{b1ha9deMOPh9O#r3 z=+jdJX@EW!6lRU5zWF!j?VpqXE}V?}p4_TbtE^PwZYp0=PlFpd3qN=3vH16{oWkMb z3k@qF4)H%EKskY{AuDFp%a!|7Rw~M1P_7u}_sudh-w3wX`AK0k|Jph}AxH6UHdHeh zrkra1xU(TBM=t-TO%A-hJ;;fwAOXPgEg+)J*&^!5g@4^y-vw! zU+|d*IaV47B~JeO)!(3Q8*lUFw%I#i;bO!&FhZ1sA+vr%!nsr)!cU0pD*nGoSDY0)IPAuzFg9Z z(%{M8jtk%BZ~5-W%DwzEu0gMvH^Jp}ngjt(yaN3okxj+95$%`j&TSP7BE*n|f6s?I zPwf6)E_}RPQ+R&TZ@ut3<1T8pO6CBj@zHQUE~_8~8vfbWYvmz>%-Q)NEt>KuOh}^W z=T&b*L@KmZU!=tb}YK z;+$Ot^)tEslr4ysBow`ZuE+{&qkUpwBWxJO>F{FmK!#@);v#)x2QQvfU2` z6Ppr(pAJc=U4kT+;X$Z_zNI~qSymBoglv^ZTg>t)dK2~hn5EyidXp1-lanvi;x?TB z@`L9`IF%3a_XXyKq1-+!uW`P8^J|?z89Ai0&|mB+T-mfmnnf|5+~z9h1cy0%d|`=d zg(9`6UIhWkSgo8k;rYchSb4?o#1ne3n}=h+^Sj;qaL&h)pSJ(I z;3+zE!#ljd4oDXnd&)C&27W6J9mSQms4P*pcwg#^RNZ;iuC)D+;!#V?wX9=}c!tb! zAm0t=v@8#%3jvbkCXgO#3R6iYK>V!N*4bXdkRj!h#NT%#Rb-gNA20T#YCt%#CZ$6C z%$1uQ4uwj9L+a+>O+B@u@h`#o$2-FNErOCV1AQTmY{IVL_HSR;eDKCb6StI_>KBK} z4%*Qk_rpbp)2hejKb0DSqo#hluuA3TfIm@;K{Pl4!T>Exv(+fS8y{HKA;tH!Sr=`f zff#DV@+Q-Ix-OeTmBdK){g@z^)twv|=I5VnJ#>INmRSvr7^y0+pS+2xzFpY^XiKmG z*v&Jw_nSuWwbM=n0rYHy1#iGC@O7rPEUYp=1{o;32!tKM}Oq6U3 z1v#QRJI5XM1GxWuX`IDr=Ok3qtQyB(r?;WA?-S)03;x;2un{wgH!a3<)qGC{EXfbmm*G63xs-V~f-hY*}rJAmqWy zniGPqw*bsfJgs}zqU88?6k&N@-g`M=J0^*FmSQV0)nT^_oM*zPT0*to`yGZyvuNAv zhD8`qDa9omN_K{im3!`V_K&b-)nzHqB)9&|nI3jc?4P7glAaH4S{FeypJn{-Fuwtx z5J0oE$k4e;hE3EalGutrDmeMS?ZNB{Bt6=@PEG(=-=3Hi! zhzEh#6>!MbL}-a;QXJ|fZH(4x$W5av!DCXT#huDrVVx0cnwLynJU-IQVvZOA;z)cd zKAsG{yno6anvdACE=A@kR*hgWTwd#=nq|}E()mSm*Q%O?azf|Mm;KE-lV@4{KCe30 z%9~3~%U(KfWd4=hckPyuTN1B)IL9dH6w5xh7STDD8m?C zQe6-=yiA*3ldN8`)U{N%b%{Ym%KY2AhU06~+WNjOncmG1!eLQoYJPmZIywACsYb%B z;uD*tN#FeNg2dX8qb?8s>Lu%&@WDU7kaM&!bs@Vax|Gs%>Y0~inlna|8E`0hUX=8O z7U|9hLCD^>>ODi%Sr*@#ESqGj&neAi1|=fs-moGO9kkw?Y<8PI293sTE)V<~Qw_F^ zIl+c#HfwYejhgC#mZh&`F_KTa$i5dHl70;PEsxL6t?M^sVt7ZZdS96N>Ra{A+4m_I zDL%kGAs^j63rFNHa$Nh@zm~3YsyXnytUfHL&w|QyV?rAHbzmcvor22&-K`|Ef+Emi zz1f{KFYQAwS+nc$yiD^;uh0cK3b$-i)wG)S*y2#>nYAgEnG*HpvgxJ*yz5iGqmobs$tM%Q7(!v6ogeurJ~Qb5vroH)-)3T_ z*DZ5OBkAYQ=^#32nvl(L#kcsdGB>b7)sAVxi}2GtYv_< zk&$)vqK=2MubQbI&7@!(=@eR@Ot-9WXWVLOWZZ5|#x~{uS(ecpri8Y67up~^JohQ(7dDb#h1(PUV>3ruG(xF zTDza+jm583U^(45VVm>^Z{wP{-Dn1_?Oo}{JEnNb#E)a37LyE(v{|A-RlrZDzv5mQ z>-;l>rA28^}@Q)2pc(Z4p)e6gaZ0Ssi}2UE`o->iR45=Di)uG ztP26|7lkaj2wVH{xonYs+#hiwe(IfUd2gzml53NXs(6qbs|Y4W$cRaz7G1GO6X-DD zaMg|ypJi_JBPIpTeo~!<=Z~$d$9xsl!ca7Wbn5T9K#qw%@}|w6rwtNUIc~QwN%9fp^Q3_!i?z{wXn?^sk*ahuq#r z^_6b$n0l89O1usG_UBJ0xz?g@<5sR}nUoGC{mb7abl(RYw^|PFwQAG3iuCVQS^dvc zUl{Hc@14+RO+{BOpO;W@x45Yv2XC6CP1)jZVa4vuw+<}ep~6lvMDSAKSIab3n_8r} zwwgc5HM4ik))w6;Sm_ln49IOYtqBOjVmZO&()3`0ESxs5^F3iYzow1D>2}*0yz%}y zsb+B35vm$Ar0_%jp6XlGMvp^zghI`>0(^0Z{Iqnbq5wn zIrk)O4B=S)M&p?8G$-j8V;NfQ1#d3_O8vo z)!w5xWHwYWP5VJ3o5RfUYSV%CWoIpTR;4D|gXv)ytBjCgZdhl-?4Af=y~9oJW=8|h z9qAYMFQ5AQ(ChJnfis}+7_J+p>oqR-8U;^2=aT2&{ zm#BY!zY~g2kM=4N_1N_+r&~53E0P!g{yf{^NhJ1iv3NG3-u*?JGZ3gBFJ*f<2aWPI zU3gh62!qXgztVl_HF2N=@{F8~fjH5$2bmep(&>l-755w|9tD%#nY#LMP;#^j& zERc}v2{pf$+CwzNxx2)T?{&^Lx9)ZhI&9t;_P|WUrv=w;jx8(@CdXIkQqGMk?_O4K zOLn%Yk7>1>LlauV!Na>iMI4x!S>bT{22`=isU1$8AR{@G2GC!Dh|yS|{+Sa1{waI_ zr;hjb7fM^b=1M$H9r1P9J@k0AIo-EP=gf##C_qG&8m*Af>o(@r*R;g9vl@ZADU-!nb>}W|!(OPbMWL`RR$9LX-Lai#CjI^4JP{XQD)yPk+S>Ar~ zTRG;7jGGi>Q)g#%19oHJ&PZL@H_x2qT`ra4TR4Rp*+&GNo}GxtpzT#31tGhl zFxMHOTDjU6u{+KjM16KtSiBfE0_8j}(BTklVkWJC&vE0y=V0#PZgoZg^*FE?Tii3P zD6wL}LFZYmG?@{?Gj1R!B+{aU7jXvPWc^tzd+fUVY57uf)n{G7<7cDJyNja<+K7Lh zzo$F$pJ8@zIPST2XH@^hd9x$bJiF$_Cw4rBY&JH`tAVs?xnY;>dhB7Y*^9*8k+b$( z27o2%z?1k1iyUD4BLVG!7H)ekwouZ?VHxxWql!(ly|tP{S#3qv71GqU8>$5#j7*o~ zP7h11=iO6Np1lmh$+250_AXbstQHJrKT}(QhjN%WH}+`DgXqfEo7B*eXT*cJGr#B_ zMeWF4{r;x_s6*%a2EP;J*giN?>TTsrIa#VUj9Ik^8@1lMKDPzoYk5UFPca@ZW4Ls5 zCfk3a&{Ut+8$Ei3pH9nl%X33yuknJId%55>&5~;PI?Y_N>K}U0%=kNNs@0H;+jaVs ztc!#}hXd1?3#NuYOjh#%-}CB@syk`Edn*l)tiQu-xhQcDRxQg!y0hm3<&{B!h$tR@ zRA6Cka#qD8)y=w&H#$0jXla9&(biovrO<7^KHXvNh?_$Sk4DRl-q=T$t96b2HR1f5 zC;VLHlT}NyqryGI{=ti7eMjEjj4?mIrKO_-hhlcm-xAy$%jr)=6fnhB>2?Jj=8QnC z2u$jbZnMgUE1dcWr=A8qEHt}}yVapIbE1t9blVv3W4aNnxUVK>Z!W7m)e~R?#f&P2 z4qXN{3%|ZxX_c;0V3nx_DAgNd7jaze|9*P7Xfd&SOiy9}ytA zg<{y8)oC&;6{0(s)uY8mC{65dnW@F;ksq0dP>(lCm4^KnkOZO0}d%VHt4J+s3 z@W#}6PMwFSD@5JFUAx{ zPaF;856kl9AqS?{jQ9uhwc_y7x{z|Zvj~is5QnOJQ!!y1VW2rhzE8!e?KV}K@zwpnh$wi+ zAUp@(#O?{q0si__9Z;dSODRYI(i*+}%T3;D06^SX*B-{N=miuuO3_;+g>dMnyB95e<5nN8->UAOnV=sXwc zrRIWg#o{N#yn#!3YsYh1=|ax4uX@Mhg)b%z@8w1>o`G5``W0CXq@B1#Hqki2{;bf} z4o*)Deq-+IKb_t2BX6`_pAttoAha@}#W!Ax-o9W@qN%?pX({iP=i<2iiF8{W&e$Eb zRa&Cx+S{R0iOj_78$lCIpZY*PAl9C3SB0BoRUhMl@zWO7xkl9WJH-yGD=DZXXB z5H77(bC)~UYM_I6qd)YSDj@$6OcSp_FYwgtX74gK+Q$dzoC2_xh9YepQ5q+ZO@SeR zbkl3Vsp~VRlU9~ug$ce~7>se0Vf_*A6ZT9_YJW~b>acD5kVt?kAJ zuW4wQ&srCJUa;*_Y3An!pup@~iNkdyyc7;oz zz%zu*_&SY|2E$5&MLi}$y!AltVNpi8=zWn+m%!X8RGXn34=kk?!i!I=O^a7=M#Hlq z|6M@!GQCFRF3P}oaY7;Ms03BUX}EvNr>o_=YlP~YBp@9|pyha>w zFIJY>BDdxwGP7x-r=#S()YHFvoZnu`T)9&$GZ>ibpn4|)FGJsaw3`(mh-K59%X@N* zP5HEjojciD`3?;cQskZ#r!_oDvLjy6f=J=Xa6 zS}pWyTx~pU`snv;e?YGl$?n{l>sxF4rdj#cVcLU=ZklJ#!PfVn#p&rxZ13hfQb_BRe>P|-Am3Os++^^ zkP<@{Q$GXw^@_luF3lfL%5hQV^|Y+QSy$yVs_d_kY)a&qimdjb2{yaUNzD1A%y7#p zrzQQ%xp5&ox0bp19RDwT;k#wbv(aAtGk+uxD*`~k?|VMO0o6vg;+6M5f;v`I-+ej$ zHL6apw{~)WPH)(DyTg^(!wlpZYWU^G119I~b~(edACAiRGxxtTZzfTxyvj2quz|=E zp*V;oVSS_q{Tg!zbiBQs#&#W_L%TJqqzTge)jhB6_D5KhG-qt7O|g0x2Ebshbk!%~ z+4w4_kFqwciXhfRB-iq%?Uvn)<(<`rtrmWvtE5Q0DHDiYWI*d%80k5+_8Uhzueb6u zBg-FRD?&ELXSDBlK6zs}?gMkY*E==+`lJq@xGZG1Ce{p%>2()Th6wmXX{e?7nE4l@ zfd}C8_oUDDmQ+OP^Io^ZC3S%zaM=2x9fHipdlPH`*a{r4{xuwU+|eDkH)G^(MYiI~ zD28Oi!lE>QV$DSF>M=)5F;=hWii=9Mx-ef-f4@0*LZ3~%+`M%N$*>3_KH@&0JDajR z`ffBir+c@loKd4KRo_z{D&AlBKhM(n&@e?O+42l?;~kA{C&_lk@cCyur?vksobi~r zz9MRHSmp4UD>4iD9IE6AA_rVn7xRH5*)xk`E-mUL&G_nOzg_XIV)ZoXm>#;^fKBBh z|6%n=cjJ)-VioxvhmL1PH1K*3Y*K9OfR2@ixki;!r}lU8^wSzC+vGM^+vVM?vI;17 zN>7gq9!7RhA;DpY!0UUu+zuW=q3*pCv}*P;^DC*e5n zDBp12zGb@ir>s!k8bhMhz9WpS{{AYQHa!yhI<7u%%GIox?@@)DAQ^SMUCW(BU7f{V zq4LVP)=@R#eIWmf@J=81yQvr(v+8=)sG86pRjYYXfvLspinV%LUHm|hUPyH{IsS$~ zwfmVN|Npcfl%^Fc7KbA2xdjZYS}1O+T$&b(e) z2f{wt5ONs3p96tDN>0=NqwT%l+1~#@{`T~AP@`%GbxN(+d!@XOwzRP-5-UbS(FC=L z*;6Anr%I?o~;D=)7Wwq>-eoN@N> zHj;i16dY7(>{Ur)`*8=SEJa(cICkGyR^HY(H;G#RHl~~yz%FFKnrPL-mm_EQZYh6U z@xTk3%u}k!mt%Q95bTH2Q%<)slrJ~yy`cWP0x$ZFXNFhbZ~_~0l`z)NY^IatxZRos z2zp5qck*is*CDzUWE|C)#2+xzUrUOqd36mN@cb1QMyrk@S5Po_Y_o~{?-KKd8h!zt zG_&eF`ckC1LG52d$-1#T>CY~IO?9MHQf$M5`3E>P(jhTQ$y(7+Y+^?cj*SXP{$hQi zlzLu$EQdz3l)>MxFKwbKc7diaEEi4B%31D)Ho{Q__-TPl)C({y1-#wx3Nw8d{$#>ok@e2OteKW&9}j4Gn7Xvj)1; z7j|D)t5u|Z||A3czX$`+@Hmo7Kpt8QPHWf+n z(Bc_Ai2d=s*<{DVnXE5{RsAS>DRL)T{;!CezinpR{M`Om50{f7nBTO#;vk^cD$4zu z2J307-Je=28KvT=c44osoByuMV1sld5{-wV`GK>Cp66%t4yQ>!;i`!yv14os; zC>wifQESc&*CfR^kcS#9S2n-aG1H2xLeA))3Ke<=c{s85ccp%w;0)Re8o9nhNg8yG z?Y8Wxu;xK!Soi_UJbUQIgH264L2=%jxFr@Ibh-sq9<%4?8Bf-d79P|q#30H6B>;9g zx)aueis{fxtI&)NWi{&2G^i>3oe(YWDR>_=WhCRxT@BrfcDI)rDOq2f1DhdiUG*FS zkJ&BvBoaKfQ4vRLM)iB*Zy3MXJF`gfe)Xg72eI?ojS$shR$f|tb+@-0Tfvd`=WX_X zN2cfP?~fWoJU>R1J$T)|jCKjC)55v&SyJLZS$z5FUeBHNytbIeo7_i=qMN4H8i}K$ zlchzj(S(;9KWrT!z>!1?k*Vj1>e4bvmbkqUcE{n} znl(`dgm*O%%2`zE`=vSH%?_avk)ogH)fEeJx^Hbb z(~P`+j@8tg%c{# zyg7~qInE2y|8_1ZYdrIs3Qm`j?q&BhIgV71)BzpWn>CLf^a}4d+}yHhJu@_PJL9jh z)3wW*?f5xI3zO|{28G-o|7o)z()CIxy0m+HQg0=1A%XRGQUcx^$(u1kNoZd?AVhR6 zFGol1*&40)Dt0^VztgJ|vD)tC6^qR7^_tto-?4HR<2B{9fZCUVlI3NVO$2)tjy0Ax zoEzM$d9zkD)>1A8NP1jAQLZ$=(|{?40z>S1UWqQqc5VQg?ONQ0d0+&J&-B#uxbkIF z`KJ`_S(S{~`n(%ASJA%rTc*$+fBBt3hVS}c-7Q}s@WeK|-C-L)D^=>~<-naD+=YP3 z^{g@{*P_Lss&}OZN+Qx2eAXt$8pV?JQexL7&*g79f*Jeg^p=|)Xh7HN4{o3nUvyy7 z`O4AS<~c1nvSGK;g@c{>+bt^Stggr}UZ<2^;@_@*FArEvmf?*_SI4rP)<+*!K%UNa zONP+v-Hvaema_h?4Ih>GUWAzGJnji4XYo zH35}Ccw;Q(#`qCjdWftXT304(GxREfunkwdv37qk6!VW`gxx7OP#Ln?_Ip8ZD`defwtg$KCX=^mO$o|6UEJ zkI9BYB6bO`jIG@J@2#jm9##eI2p}KDx_C7=8$^>4E+?*4fC0s*P5WY$pr3cUMbO{K zBiO6Uaout6c5z7)wg*e(XY69qf}HfI?hi{O;VBzdIiVJJpE*TP6F)6U4JEt9wXfDF zV4IGEk87Wp_@@KQTxSrB2%`pDB|d^i0`n zDDN7db6Lm(N+x*RYdBpO_m=WIKeL3JXvqPi(8kNPJg+k|-%6>Y1AU0BaLbUt_Eef) z#Cu2^XC19eHB5+(v{miYdll?QCd3c8vA$f|->~2)zCQyoy;sl45Dbu) z9@z6_k02OckHlYBDlnApaIuQd+<3-_p}D4Sprm0m00jeO^V`Gn4Haw`TL5BU{X`+H zTN&a0uMt&R;35zeP`nF^S@LI$hcEC(cRi)#44$bH!SE6ph&Oko-&cLIesnM!*qfl~ zZ8thh6V2nZ+iBF3_hltgCfu!>!()>3i$`x)Uz zi4R3k41;MExnlw%LS9~LMMo2p2+TDbL!Gep-mSw{^5J=agN1dvj6-D-pVM+=dq=Gl z1Ji7B2kyFKr>f;2I%+(Ac!PQ<%t2huY}J2LjKrMk5U&23UW$B#x6`oM$WTJRowHT# zCw`ApBZT;Qpr&7B{adenPCwlakY{}`Pao=2$UGm&vrFl9)`LriK*F8$)7FG3rF!k= zy%^ffq-2gSA=sx~m*OR_9WiJ+e1CnpWISlLh?WA{w*gbrJOqKOghTO}=`Pit^Tw`R~%^81Qec7|T;# zbjp4L>s~o|a9SrVO-vwVqKZ-L=BIS&Go8Zc%iyPk*v{e-xTKz-Sr70kdOkvbo@r!n zoja%ouwWQJF}qed^GQ#%@@+_wYn{VzDW?*K)KFnD*dJqpzYEP}(Gj9+=W?3vu`IYm zK5A>&yQkG2V`?~6SUq0wI#gSAg>)2=twE*A(BB9}HQCH!jz;Zl?F@qJDxaX^_kC6? zG;_61zPm+qproA-_6(J}G@UeDOu+->(LU)FK>Q=v(JHNsbJlAvv4odAQ`GqEBnbpI zDvsltY~X#04W%lZl8n3fm5cc@G>}jlXqDjH85iWamZaIkEe%T+5lm|-v|F~p1|Lv* zc4aX0g5xs&o-B{NS%0EO9;m%Tvw()tg=3-ji-bXQZV}&BwO_H$B99YHYvLzHI9=-B zb{##L%Cyto%bbktXeu(s_TK6*K&6HYb| zoU3ZC;~?P*SY#hB5w1SS^Cp>agHhG)SNRw|P5wcmzbTTy`xju0cpYr&@ijHDd&J`J zlyYk|!LkMvB|3%2f2o4urOtty?_kJi=*9G zmzKIwqV=I0GVtS1#@l{8E9krbTGvP)`kB)9FTl@i#AcYdwB4an)uZx4MomER(*pr~ zm_?lvw6q#@zzu;{SleqZxfzF9_{fJZPBoH$=^W`Iv7xT`L)zXrksti6{xjpDXPB#t~Ga=BGAnTISR(7j{!O zWsB|SY+wA!a>*^6u{I3Nut|e$;z7|x*-O$wx<++PZZ2cB+UQKCr!&V5&2p&3KA&c` z+oalL`QL%}M?LOiPz;-bx&LJx7*?f_;Zmy^HTHI<^i?xf>%>QItnofgDD$&&}0 zh=GD=nyWGmwZfg#d{stf0}!*D^Wz3f9@GUbS(IqhY-8>3e=wTla+ z%n7Evhxr|Yd~G5l$)Uzw#_VJT}Whez~E=HN|J0pJ^XAl-XK#zkE^7i#6M zug#I+bl0Ltqz(jJ3Zyx4#AqthfUp_MTUBZlHESh>9gpa==+yU5hd{j2m4h{AmnY1V zK21bD`dll%+mIUM;otk^;LJ+JSligc zet)26X!?b3HzeZ;ccGpG+osvH2(p=TQ=RA6NRJ&69oXkgo5l&;>mKQ^;OH{E0)qKf z9OAiM1Ef=|ovo*>5&}+{@vhkmz+>Qd=B`oT0I-JL*(hPL*D@8QUV(7cG6;Fe`&QRTc_cNaJd4H&P%O%z{yuYT!V3Kx zsA2#*L6a%kWC&S5S>rQ&KILi+Ppe2TFu$sY0Cqq7%{ofAlib;Em+^y-OLahg43m$m zolu0^Q(&Q3fNM9SEwv$Z-6?J-lZ?b&R)9pn3AF*7% zAd53t-eEAou)4N6u%hYA^qt#j_@hH>84vyuI>bNNZ++#k!k?SHq-3A`KmcM4RKdk{ ztX!ihU~k&9HN%-@=LiatQ(pt~v@=|>tHB!HxuOyCPvz5|Pp4Sb8S1yIB{;b6_B(r{~R@XeH4m~fzO6Gbu{k#l%Frm`$v?nfA zZe+Ohu&RA|+fQFq3a)iS6_*;~l=;)ld;hysv$?+tUopIlYu~$e8%VmvbxsT@nghYx zl&&EHG&)pOC-~SC9g|%ibH+EwYM6a9nqU%D)i)^Hp;wA|2KXR^qlh+|;wTH{(^gm0 z&GG*`HNv741@)*7ycQ}y1wAlr{V6*@dFjvMvcG{{Tx=YemLeLuZ&rUaLC*-q`ZnHN(`D+{BJ~}(0LD4Y1a;wSDqDb^P4A2#fiN z*n6J!{El$KgXR>IJ^eQ&HnYaA#N(`snYm`r|Ev!kjvwy4Jg^)sy=C`jU<+=1am+(5 z>+JJtuTRfZb3MCWvi{G<7VW>CF7pkvo$2V849ekog&giB+nKBM@Av(Z0ay;(&Kd~X zneE!lcu&RHUHhb0f&6h+b0#N5r-&Vs=_WQs*)XjgU73%Fjn-F zf)5p~Fvpq(ipjTgS;RthWX+&{Owfm>QVYbq5{~Y2Q|1Mg_blf?c;oU&e z^X{uS^yZVf1Fn_%$YID4on$jV(54#fn{*=tB5Si?1zCDrRxp|Y9alN|9$M`iNSayS zn=$rPKYFx7jeOul`aF>(_^*RC-*=q_70}y$*`z)E(#7fi(UQCzc6z1p0PkQbNzGbB zs3(vuaB{*{ovZM@%=mPL+Vv2YaCU)z(l$^V_EuJlq z-szQG7{)pk4-BEHl8I1yDH9-P723R=tlxlffz||;^<|>Cxt3?>`S>g?4*+H zx;br%n3hov>edmgI#*=JvL+e}4T~^p0Y7Ij7DtvqQJ$L6U4*Ha>X+HG#rRH@5y6js zlS1Q4Y{imtzzIwrH`@UP$Yju;$}F;i;&N1@a)G!$ZwrYwK@&dGsV*_ulpA&4ea2$1H6*1}VDiUJykmJWc~VgU?7_DM#eHwpKi=H!1(T=Dv)rq#bsVPB20271?zud{$VAaPS;FkgL|v&X1;^vLNgO>cfsYA zKoZaneDcV8xnzQD&Ivk{f>Wc-%FX*2hO#t9Wo9Us_aWI46;}>JlrYGpI<}-Zg5*HD zjfz6`r=?0&5@I3=Yfb>CO@MY2RW4VKl#A@UA3n_5f_cdFuK~ELsV{+!Yt~3ReeJE9 zvG2=c?<+a$WMto7W=Sj4{jZ`^yztCRb!Z~U10-z7v!C+|(h z8LM_rbZvW_`+szH=Z2kZBHZ~L~K59}S{%LNUS zY{lG-pSM-7Xz`s6@L_82idiI!N*9uF0Q(@iy_etQcFyv3$SimCr)MMpP<6)+q?xF+ z?mX1(m?zDvpKi+|j?Kz6(j(yLBft?upUW15BG?pG`b$kjM#}>gSC>J7E&E#&f7O7x zr{s8~B!;&k>g1Ul{`azwowpVi+I5d$XmuVh6)IqdR_7i4yLI77Q*?G~u&r6#t6gs(4@VmX+^N;E8l}RlzJ#DJ2@mTm_^2{!yVC3vN#Ju1FW@p!XQl?4F8Lk-#0e<#4|tOcPR!*GH;3cygn zxr0mmNlbnWw`X4bI9-9HuCQ=+CR~9<^X7Q(?zlGs30MV#o>F4S|Bx(7h^C5IG$O}s zoTP`%DyxpVpdb7GSsx6^$RhUH(BFAe|Mq-Eap-!lUp0qB7tWvq+oq-OcUl|;jC2W3 za(33MzZC0ydn2kge*)e7TtNlAG`GQ!UM^<5Fq|=EGT@FcsW?s)yXwFcb(Fa|6%53h z{wdup!3l6$o5WP51Rl*vF7CaF^{YBdHRzS2Nt+ zTw$dIrdDeyeI4TNLT5nMuTFAljgV5GH9FXH<}l>GxoM<{(dT?;zcK&(gR9Lo*ta{k z9&d<<+(Qy$-)Nm2R)?zi%;}h#bC@KtK)pJht55r(z-BVgl2gWn9Z2>UW{1wbrMdX6 z4^v=3rlu}ew2waVY4vt5A=gnsBT=6RFxg_TITPG#Nj()qX&a7rqdLdCo?Z+Cq-c~S zry(nn^G2JijcrbK#(aJ?>0HG4ObRH4|4*Rf!-&2E(>XK-*;*OVbJMLK#vV2Q7tG`0 z%PTVUX!l`YUhQM)KXYZ)#eDSYpipaW=@U8 zH}BI>3J1%*Xni015eH2=Howf-3Xn=nC8~g*H!Qfam{t&B3OJrZQNvBFyPPn)9#>G1 zC@gI&%vsFB*AnUgzy&%q&KKhUyTpR(J{^n=znPHCw6J8X>Yb=2Jd z`vqMXwVrpgyaF*^&3pZK>F^@sA}8**!?9%t`s(U_%#XJN#jBJFK0f3Mf;KXV3UU zxqerK^Eia69+xvD%ZV+uS*+@vZ}bz&U;KI*?XfaaR>xoP+$UAT;!&_7pJ8upGs zCafVEMZW@S7Ytmv1GXpPW-~$z(oR{*g;Zf+gmBaLpyW_hD~_oU+j zxO0!DjX9wu#9ZnFkMUX5ufJ#QTJ4e52RYZol|JCJU!{f%VyjGK)~>MONLe3 z7)Y}09`fD2N2yBRR3<9#{I4Osk>kq0v3egOaSV%Ap8;+`#F<-2P0cVScclLL*Oo0+ zSyGUx{&wE)AGNi}kO^aox@)gwb@Cq9o3E+M63o7v(6xU%SwF^V@CygBN9KM+BrZ|| zsg31FeqRp{T54=Of;_-5On*&Nfaj}#{U-+t;rJ%koE~^1AL?~IztI1_{JH#BBAb#| zkOna(8wNcKL?c^%5Swc@bH5M$PQc|IPRw{tezoy+8+XWX$(MVvVAD;fq zv8)#GQ9B%WpIDHtADIZ)EVFe!g2CQeOl&NS`Yp&K!sK0Dd(P#5MeFA-|99!N0WcNQ zA==pGWp;2T_|o-PL{C$pLAf6_*x3G38p>++7RSGr>179wMYBL56WSSfwGynlF7 z_4QJBD9iI}o9eD+>&sQ>trPjyuiXZ!nGgaPEWEkb04C&wWjUvfIrfA63+A7J7X^h^2l+f6&T71l1y z*LZle27mo%c-Vb}Judq1(v*!|$)Kny2q_TxQ9DN@#!BW2?2k2I(QKk_F2kN92~ydVZKO_9&UGy4VkxA2!$|MK-_sU6pkozcZrU!S~o? z#Ob7$&FjYO*nvRBwa1<*NsWVlK4)yb8>tFNu$ecW+1zqzbSjzo zl}ss$ZP=j962GNqf3&kJ|Bx`;BG#X(#wwW(&iwM)bo#fd7cx%%yF?%SH7`7}u-&kA2w*{` zUVVgL1pmNx|8l!v1rYwJ{%22LO>ONi{CCO7Ub1{Bl>5I+K7(!B(pUbwR8)D*{{K4~ z#pwTkGz!yg)n(zESkC2tCYzng(RT!aLMP}qc}(@=XZKR$vHcCYfTvc#BeX00Er(PP zKaZ)*A5@38$Cq=zO<%v$91xa?Qkwg-3ewFgW1`doxi9QyQN{)@*a6pa>tJ4b*JJ<+ zUILTond`={_8hzJyer)zi>;u61_}@nv}*_fRh1^l1C^k)C>qK)#WU6_R0eFKLWWW` z1}M<1TpPcyD;ji%I-9_q2f!6C)g+%^hrh70$t1#)8~v|wWL9!0x`)k}zNr+IvIiv%XKXNm z{l=O(_SDSGz0(|SteL|IFRk^Pb%>v7hyz*il%0nK~48Y(#w5iezZ=u-9; z-=5IbUaA63ZEDB`Q_Gp%xxz%NV5seJ*Y2GQ=`Cw|cA0wex%BV04-V=agGCr&H?vEL zO|9?`_u|qPlG67y=CyV&p7iAN?at*C$i1Mced=L{2BgST-cCEpxqm2SeKtp>Wp63y z8l(t2MR`#c|GN~Mwz4B3XYG|2up(JQFlDrdK88{D{o^tNvhXhj$J4GHMdj#)5Yj3>NOd-;x)9#14lJ z`H*#P_n#ns49ZzCNK)#7-}k?C=gx4Tea`L3q2kA{eYO4;rseZ#)c-LpkwL4E0~IHh z)EI2{WOKb~q5Bm4!^iBF&)?k)+THcTl0=SrZ1;WocgLmaCLRqY-V_+OV`>dzPVB?# zyxA`__VRKxpQQW^>;?S!=t`(`HXL(akp{D}(vaZm@Mxr;SEc8i5OlOHj_>Z7XiR&A z3uEgTSqkxg?asfql>FX&anp32&J#V;TaE938mYWY z*OsCK#qJJp>6+N~`+P8bF3nc(fN~JB*XqA4!O)F;`4nb90#SbV#Ao4a;$Ibqq9tyN zQ8_^`$6&uOy}PbUZFooGsYPcX(B?w>ki!)61juK)Mw9=JnwB1n^{01Mscq zk|KKtvH^9A9&gfbLQFb>NiFTeZ>s0~qq^1ArQchv&aN^Q^Ovw2*Lj*nmphkQ7Cbsm zW<%c$KkCtV0S(^zvEP#Qm2Oem${K2&EH1&AOnmx97+(;oUMy3P{fFMxkxy^8?%n@c zzL0t1Q5(B=B|?ax17?&A<}U>mag2J^RmHER;^HSLd&cPJBV6Zy?9G%q@iKU0F;CMr z`wel`CMFvlzJPI^cwm;68edh1mq=MG?^@h0UliuL@gc#FC5w%~N_%`=po2b?`^jUv zp>a`J^YYuP-RGQ=#isGc!32koFN3H|`ngiC2I~=ph1vBg!5-Voz5KqW>%W)N(t<+o z?TL-$ENwwaH(kD`BI$c@LDId+=5byB^`&x0=~s~pyevCcyJ;zWT+jMObz^Gf#Rl0y zk}pDsYi{5B$-$9bwt8=TFu7TmgdSaLjwe;yR+y@H3}7hnDe77j>EBfMWj=K`u^-&6 z$rsvVsouMU6x-)>K@uG&B`XdXvox z^5PIkVid449I7PgA+#!vimk|*h~OrIMK z)oM@=7p@`fVym8DnWUjrlHYAk;_G%(kyo*@zIT}S}Q_C_lgtNwW*Ax!z3 zY%e(T$a>ZyU-J~T$j)7sd$lXQ;|u9GQ8r=_QqKQB7w`k^XHwA*jo@pZKLkQ$Hq)0J zu^*%DtiE{PF*KvAO40p(vIwag7ehx8_lruJzZZRLneurgCE4m=k?~KSdPh#WDf9XN z(w|tQ`tvfoR2CO-e?Dd2SEDhi|wNlV! zp?Z626enNq6`+&KE;RnJ>z;C2MQyynlfQyQ{^f@mRcTZ1{H?)#K1kQd;%gP__vUkd zB!d9eqP6_jO=rw${iAlKnp0*PILm zGMskPE3BGjR`OQU$@Ds&8uU0}M+!l*$jUMITVpCp`ys!1UOL`zf9)`fio_A0RF z!i;tP4&(=OErZ{rJztTm+o=6feEziR-G%&b+>cG_1>TW-QttNZ6;NOyI?E8a#=w z=U}}bPSy04(D%zwJWqJQoASQWUs;9)u)%p?UB$Is+hh#_M9^%#XVsXcCBvGGx z3;yw5r?p-XzW~`>dK}_v?bgy^$`k?O#7XSaI$! zyFU9g_pwlZXQZ7`p&1}jC!Xw<<8qtKj$+opa1jvWKnP8hMH}$}&%>q&sMoBlADNN$ z)11_XmnYuuHuRa?(U2S~w?O+S6#5c2f~jt2tv2F4Gm+*Kje8caU;pmt;p(4J6}7M`CCc%1 znf>wu;e>vLbUS8^(5o6Nqdk)2ep2Q~Y0Ds`w7alYaculP=A&gWM<-heC2|f z71%R;*|ppuGG^O2j>U!4Kjm{BB=9@$UXPowswO|L@`rO?$zmv<4=UiU5kYO1QF{j{Ysb4Re|mE%ju4O>&>RN;y=>ap z+w>PQ5QU%Vo@n+;Vwct6c60kgx8qM}V*rY!RaIfXc+dZ24=dxM=H~=fm2BcF=+&x~ z8c!?f;dV0aCl~*B31EJMUbzUzFH}#aBF;4GOFEaaQX_jH{Y7n@TzNR#{9@YENSDF1*cI+NZl9M|}Kj}xy*mEj$YANBs$;!OZv?ZyfjG7}W zbratXNyhzhIT1j$D?o@L8uvdMBg1qhFmE?bkKP2jh2l?(GPu-94_hK`c-YL)XO5mH zuexOls09v9oBEXhSyg=xU%wTE5tWigMSj@TI33N!Oa=eohw{Z^XVP3PYDgKVJuX=! z6O3qU$9yPWn9F}=q-Gb3ZTx#F*NSnbU=;+d)lwy!`zxgHVWE8ar6XO>N+$d6f+*~` zsJ8`i6nlS#s$3am>KEY!x_5!3^1F&5)JL9)ta#(PrBgaucXVQ8#!9AWLMEBY_0&$< zfq(5^TT@qN;}8(XH)L`B{MVp>u#5($d&SGXAS-uh&gNnTx5&n@InA;QC1yVT+mX2% zuAmtp&xze>y;qEOfJA1Xh%x^F%oDrwX9bjmVw^^d(nJ`ML zY$V#&;x=_n68W(r)n6TES~NX7c+~sbdgt~J<81TMmo~E|(q2_F`8y&h_eSQBQ%Gc~ zl#JN-zLcY2UurDfjDQ2yJdGdwE*hUK-Nq@^q)BxPL0WTfAUelrt1oXd0b7>J)8@)s z-ehRe-I279%YxVJvf&gKF2&45&O(Nk%IyIr&Wp*U zpi!?h>3u!Jg=t0h+!#E?ZY`LOI=Mg={ zD??pv%iG(P>%2tc-AV)hqPK6Jr71V$j%S9GSHq+hAE0^A&$}u6HtDJf)-{$G)45dn zF0`eo(>x757A^dO*lu|CK){@pCE!$r zGrU!h*kzW)46cRBvl~)dYWD6Vl^XjBK$;%@cWK(f<7(o+_Y7#e3A2XTd%mI@yi62j z71{fru{=zF<;)p-csyTlRybL;PUs2pPTxXMD66SL9uGD2e(=Dr*hFzC_3=W&&&XyN9#3}O6>KdL@$287a@((`3TFC zXSYaqHh7y?x;s=-yu7)Xc7A?OIZ+41Cuji*^4H1)H-s8%jhZDpMFH2pe&_yJD=p?E zs9BWAhumOA8ZcXSBs1KW1X~w?y9ju>bH*L7h?&UHD!o1b!qSFVM=k?1DXj}3&bCy!^_Sx zlP8ya%?e{RcOO%$} zQ)~76s`CB9iAi-uB(kuso>y73{!NQLZ%0qA%~Y%z8Ap>5zs_osE5@`kj*(%z=8FfJ z=Xf{RG+;}xm}6UeVBu?{T3BE>ZHzdv?a(l4WGIy?<$x{PpLSa!&?RqkDkz&~D_z~} zf0KvET2rC+JT)l0i70QA+e!9L-v?(!&Y&qv`Y~*k&pc(^bwK^4gTXV%9*8blIBqrK z`_Td-SHQIHz-cc*RVoOgVAMVkUC_cwtuiT!;9<0?TanofT$2mgf^Zi4!P`w7tw3 zjnDwKGPc$$fZ@;{fX{EBHp3jt?k>VfGCFc;uIB8Z|1QbBIGxWZLeGP$cb%!@U&{*0 zW(}Pv^Yfy}tzY3_-5G~HjXL~|yB9-ytmo?QaPFN0D` zMu_Pyn#p&f<_cmzp%{tn!`(yWHvS6z&#H=_DXJoD{H05dF;-1}3fS`J703Tw!r{DO zc}_B(N3F_N;;Br|06tOST^Ppt&Q19~r*u?B4Y`L3)v(Egq;TWNV1(_9@jP^r*@w!f zor}9?tpekR9-^I3K5PV3ZCd;Yx<(XyyJ=&5{sowWvd^f_if3&u?3huD2=4Vo+IBi_ z?QZvm@A*u3v;OQ#R=*t8uVG&l2npxO=W-%Dy2AdiI$1}w(NNEL{<2mu&nFoiE!f5# z{RIeUT9E#!(_teJVa#udhm8vx-BYKCC+K&SMC4b+}5x zkZ1Zu5?eu06}uhZ#&aQoV!;g(x&;trU(zwYw@W>%ERxuojizjZ?&ROk0lrbc-dL}L zx{BVisN-Zcl90yI1;2420)z9$uKwJ3VsWn4MxTRvR}HX{nF-bXhnPTjQg+AmRHMJ0 z;5lcWV@qre^tgSE9%+q}a2;da&D8=(Zdep}vin)(@eO+N?dIKoVH-GU#fzREuam;H zD8?b)ho(YJpsl6|nY1Ef>D`=wQq2i7*`tUReqQ0z^~|F`iIRNU0_IN^-W)yW_}%p1 zrNxwsdwcS+p@w^dM`5EXNe^sNO>f#`6BtoXr_nz*@s-A&&Py7hLgcTH#PBh$C3AYJ zgL24s+q2M`+?{QYtez36W1`?4WMV;FuTG^!b5-J|roFO2G7YtXa(kfOVex6KuOh7_ z8rp~lsVZ$Mp0?Fkotxa1^j%8LIV;ElyMYTL2P~AOI=)pBKq{260%j$u`E`B19>2CQ z$V*VJtqvG3_wqxoaCuXjq7Qw%OZjB{qI2S0jI?zt)M(@-HPo~iZ8L~-UmdR@FwS=V zc(t9tBqv)Nb`xIb0sZkmcw_DGx5zVDBTF;8xs8mU8=&7&zZ|5pd!_IaSE71TBv|8kD2hHbY>N83^9LzL;|1iXlq%@q2{Kukq6bKXR>jgspOO$FzSrZ7rSWJcvw@G*-%60FgrnhRt+uQ*(N-5FwQw3l9K+j}{V9Fb%*+{IWABE_m` z8xAtr4Kj9II|Ey_YDQH_V=HX{y#77)*)J{A1f8KeONSRR9Y1T-{+-vc{Q53b{A`u&ue*EM##Mir!EkEdeDeAv%>hc|8`~1cE)N#;CCa4 ziASkP);~u&5#=EJFaR+WTh0QxAGJHO*0sEHF_Nbhc~k=)NDuY5(O`1%2eLZ#hk^*B z`%GZ-6`ZPGT4USQb)JlRvlljLr>oJf437s6d#rRaQT6LeZdb#|%jKl<{{07>$F633 zmxnA2W8a5NdDMUH=gyJKPz<~BYQ~I^zqqw>f*0jZ?Bx+XL(0;hTIJY3f@y{!B2w3U zfpXPaP7@YX>&?B1Djw|^AVM&acx=X_#qx+%I--+Nk!gf0pUhoi2W) zkUx-HoU?y5HHN6>S-T>oQ&eYGv1M|NRiVbV0i2pK%q!u&?Dm8{*ND?(W0?TnE73IA zTY`fwUdie+!<(W&lQ_iu%wy+H%7yaTq;nNSg<3w~{D-J-U8c<&ms4?4#8aqnC<<2H zbaXT8^HQWFAJsbHJ}~r>nTzC9EBS2rG@oK^DiApvel|Qs4#)<8+1E`w(vpvG&N`hR zxX)J@SQnr$=q*eAIa?!PJ@$R4W{Y1&<@Y47l1{fRg_~Va4dAjLu9a4CJZGmd^lEyT1WGLgK1m+9s`{n}cDA;gr@wcq zz}-$EMYG5DNc5qG<7{D#&BOZS>cJ2|@v}=Y4D@hCOUsB@q&F&9yU1z8IZBPSKYKxM zb#u5ZGtgWuDCe8Oz>Fsusi|R4o}pod6$ftgm&t$RG3P7OM$_Q=YJlFp*U5nO|DM2E z-UpWxF2*~YOY)pzX)CR>+{vUk>!mgU#Ys=5Z^kZ5uA=JBoDn!K5R)&DD38% z$%rps9`VOD?*_&{!yDE+Tx)mP%u1sEM5|SyC&C|2?thvAjH>AaM6`yusCS4D@8?gh zX}ija`{#K6wp%D~U&`A>pFRpZlIa~|g8^UxBpp{wuyM->TcKbDQbIdG5l9pC=7^Sj zaLaF1r6t)KGJ3Cld8?N_9nmRI?MSIh7SXV_z}^^1w>idd(Kgf9^;+DyZQzyM(nDnh zdTCof?U}|Q2EaZ7RF>{0ALnFfxZ`UyDq7u8dC@=dZIW94ONPfLN5^e_&Gbw*X{e27 zvX0j}1RwLutoJ~30-dpP064L$>UiZk8BVVU-Fnp$x0V#%C0|n!OCZR|-MlGggODEW z9Pi!Ju;G?mdNB##9hWjAtKYGDUX_Q;SZ&O8hg2ezSp;>feOXLv^Mp5R?TqBOf17Az zHL!GO#8=_PV^lUuRiP$?g25fJQ{UZ$E}veur29v?JnuZoU8>_>b1XTmX53~Fw4NFL zB+8clL>NY@lcy)gggZfhVs(3bG zwl3uw2~GXlUt+&8b9;KuNX6~9vvWvS20Uxhw8rpbLh*;Dcxf~$!Dqf(zH6xjrHGAt znj9u53u(dyzAk`;k4mN7T5hYw09_5s-u*8UCc21ni#j!;79VzzVbWrxGD+$q6X~evji;+O#ejmD7r=KvZJS(F{L#P(t(e*1!7RM|?~+0NzjOUJ>Tf@A z^AUVbS5UXA+p*#p;tW-Mn(KC^ zYT`HIP3Gk{I0gDG5!TjWDMv=bCR?c)d8&KK9};|p3d3Owb~6Ja|4e&Y%M!lU@wnCDFnErs__LUS=gIWgQ- zDe7(_8Jbe-hnCcfsin$1{HoFM<;=4GdXVoEdLl_*wqdk*sVua7j~%xAb*)P`UcK7( z-e%TXocm!?h{3r0t0BORC2Of4`S(z{*HNM*3@70RW{X+ zA-76;W%Jl2N$D0{47XvjAotbmj&z9SWMyU!z12IePqKg98poqEn=eKS)Ayt7eg~y% z`F1&pK_IV`E{2ytjV;00naVF-wLe)*EKQ|>_Ef08sK%!iprCSxiR5_Iyl`@J z+|_hP8*&SZ-$g*vZCRm+Al5&+J1*`awRKsKEzNdU-=gIbe09pbgLtFwX-&K?ys;BL z`3e}F48C$JHb#X|<}ltEbNfGA^Nz-56M9__y|H~uI0@k>(mQycPhwS>gh=lm7Lh5I z$`Ix6<;-^UIUT&7&;jp4eQ2vLM%gN)?bf2fz$!=-$shgAI$T@WLD-_qgEsfKp=5h6 z??1glR;WEcFV($c8=#r3Y|AFinbL8F1wakt7@~#7CKn+ZzUT4VK{n&n?hmu-0yb>d+OW zw^2kO^b(o~e^Ed{0|Y_|H6SH~Dxg8yj6&!z(mR6?LI@CAD3Ky0z|f`l5)hE4p&DtP zHT!zsz2CFXm-B@$T-VA|*Luo*|L%{Y|7^;@LLs(7Pq9|pU{5owLqcnVs6ki3b$W6a z8;2?VTh}n=#5duL`(8c~)%apdpeptTy&yLv4FB*JnL$5nTzoug;33xZp>6)1?Ytp( z=G^U;VC>$(SwU@ofL5I>pv78YBy&05?Krn$$+8$Ix9FuSBpg5l0T0Qvoxa32*dGv( zDx|GJ+e9ioTol=>E`O>tJ`8nW&v5^1Ez2uc0iQf1%u3|V_(U-;Z?E4Y*$eSFRZnj9N~M+6)rZ1970UZLX@Ar#6p9weB2g>gHG<87v9L>yRH{vrLT zW&tj^=xW>pRcST{lyN+N#odX+pO-+k&)f}2NfOy>`TTJ1kYvERsWHi%FFC%V<$J?@ zI{1-n=lYMv(a^*x~9md0FCm-0{{Ts(yTjbDeUkHSCX6wzYx( zmOk~SzD8OCNc5x8m~ZrZ!a6L6ltUrE7AHdl{3VUTTIzp@>pY2@*s zYmGTJtaU{p_zQx>KeRX4Y;~9F>Di%t4~o`+vX+cuHs-ow;DXkux+i-O;!mvcGT2;`>2o3I99vx znjtJC6)z!?L^Z>TLv?g8{ubr#e|0R=)wk4bXxq!_7JF$MR$RQg>Q|v3B5U|O%%e14 z3|P3r)6VlH&3ta==gRX@md`c6J^obnwdE1fUXk7tOJeiwQvNbJKNu!o7~)KJU8ro! zFQ1>){dQMZ%IB+)Vgu%Rebi)|)hP={mU~vX%0P9NOyT8hgWsAWE~oho3G$~Qij2P- zmAb~Fw~S?}rs>yhy3txb9CM3-2dK6+7a%mMem#$;mJ2>2MMQ4yT~4^}7C?Jl@ax@v4N-geFbl`}El zPETUIzg0ITKDsMEdAT@@%oN1t1)u9e`w*)>hiT3PiGgdf?5YAD8AFDGS!7vl>&agT+v1AQ$>%M zxbs#}Q`o3M9>MAHkB}Cma}Gs3nL3rEUGHfI+hYi+)qFI*Zplm3t)GwqtM8v^=M#o? zFmiXs>+PZUZNx(62ED5S4eJw?yBgirx1WyBu3GQOrB*`7=$s+LRM-7yr5&L8IR~cQ zDlB7%oeP9<%^a!}ddb3M??Rt`%Gue&Vjk-bAu*%l)a@P!3K|bS7?g_6zQs; zSazqlnV(%M^ajxJStR_r) zBvI%wLcr84B~T#Ko&L7_^<a5A%sP0)A(jEZq77}5wrm4RbsXGPf^ z7%3Y@V>^f5&wPA1XP-gPUV**!#*?k}M*-UW1L{5vhJW-bSf71R#Kus}`jxe%3QUaI z%(-IlyZiG5(S!_80sBlCtAhw%j=4Ejz^5WW3nIv?i?-9VAS5Q*Q53OoYgTVN5nId1 zaC~kzkpqT@tst}@T&lP?)bRmNr@T!By%|+!RU4wrZxW>K1-6Y(~luh)x(&xhkm$Gb~#Hp!4N6_Z-y zzZV7p@sG@rAc|n{$z?R~L!zJrtolRBhH2C@Vrt9)BSN9~MUD5^3U^B=ofcnVnJo@H7o+s?hoI4*x55`!pMeypT5_*Y9xmCNOL zw!&h>`*K(jbC%Kck!BijL!olsCXr*PX&7McY5oB^^(?sP{tM&&0sjayigQhBWgKqD zJdNPwcew4GzSg(E%#DO(YBlG4$M>2)8-_e-x=@>I_!EF&OcE*_wr2IQL_>c+Sx9_Y z1WG(9RY|s`*VhFZ>op=^=2jPD|M$z(@J*K#m2)}r0BZP(E@7Z4;#v{3fRir|A}T|O zp&|$mX?{U;bc}8lD9vS8Jen#Y5M*~t43b9DQLCZ{H+W+Jj9g!f-@);b(4Gl@-23fE zv(ET+fTsEnU?RFDrkPG>1VQtkXa*se%mcD#8T#F$qr536f*tNC;VK;M?uS>cDgS)v za({&k2)V0f)|ts0U}tCdFxcJwZgq#sl2eA{?{4MUX)pNQY%na`R)P-dp)>0YO}@h2 zr|d3&MhP@ksCvI!tCxnNjrP0CRmw-H@Syx4J>v{WnkvPzK!Pp0lZJwIOyF`yyC1rU zWsD6dvp#JjI;8dhX!CJtgbNV#3fs^}vExmygC<{OlD-p}8OfAMmI$120KsF*eERW; zNTH$ z@<3R_y@X8{v7|&kz0n>(2(dSvOfba@NjHh00%_Da-OmZnc7`k59ufTyi_B5rp6&(5bwr` zdcA+(Biy@Xbj#01FVtIOJSrHJ{-qCAE)FS>|JPFa`o>2@y37M+>(}PpPTNBnA|+Cv zatl>jL)%q)pha&79Kiqj2YY0QZ>^1>INd~}CQs6qvp?5H26Gi>B2vFfbUR(lC@@&; z^v9#zA4=!Nz`JNEMyIYY_UM6H_pF^}L$tqN#-xM9r%JhRTD*8Pa)kxI?RK(1Dd<6z z``kL#g&pA446H`~StTp)jQJ!!-{yvTgEbJ1p-v3cCGe=;>~X@cc&^koZJ-NxpM?W7 zr4AQdwpr&WK^OfR4KEJ@d`m6$YYu2v(FmD=+bPap{7M~#OeX6zZ?)ICCR8$$!W)Hh zXC{lH2ezOY{8})L742eXhUZo(bJZ`_(V9suuKSBc#mLMPx1v|xL>uvp+!fJ9mRFH+D_0vYt zEGK{Td>iIY6iBPdDtbV{V(-u&TpiJbi%pVeiVE7cqUs@vFnLJR!U75{eES+BlOvZ zN_m~#uRI2c1O79KQlmxDNw92Juz%kDXezWwV=^6H@5f;3j(VN-T0Pv3_te?H%Ph*1 zt5DlL%L%nyW1*0?)#aQQ;DssG%=d!a3FsOta%c&Q+n_oteoa)1d{bV7_ApJfHsJn^ z+*A(Fxp-IF;Yzz*YJvz^_k0~5nPWO3OFUxoA_*%ET@DK>o%!M4!Qw%FmQnQTWv1#$ zq`MjU`8W_~@rs{T#|-URuMc2le-%w|yi3{BM`$(5bs7l%IjFSNHX9{GxT$B=;Y{aN zY&r|{n*eF)sbMH1M)~~4+#sRa4EIFfat2Z3sodwlnIv|ptlV0rvr3dJma=Z4K&s)m zX}Hesqm-cN-(`+{bUCWnp_O@zI*Dh>o4`ed>ipJ1iZVG)Z;y#2=UsR%dcZBgs9m3n zIZDpoAI9(HT2EA{*%;iz@l3NtjVlbk{Y7WaEjv=NUTTlsAahxHdbHq*OkaRdzZ&7Z zCYHLQ^kWn&bCM_N8t88Y^B6;S0sRDF!iMyKAiCOd&>F0s&nCD@@+?AB+hP zt~?tVFhfrHcLg8YD|Z{?kg3S{;A1Aeo_HU*-O912W6OA<9!3A zeo50}N+8|3$z=}=a%-9&=8dGfc)BxW%1eXgcM{~T^Cl6Zdi}NfSx*(Ic+vrZ<#0W9yf%!91#sQ=d);O{g zI0*SP%LtOIyi?PZv1Ob~2s4uZ3kOgovi0oT?r;qp;9&v1Uph;X$$#(nPOS~lv%DH^ zwdUcS0CY~ce;hWkYR}s1<((Ia5=V}N{ONyIx19Yns*p16S7hXPMU##JFPi)mBC#?q z3N?z$a#jXV?M#*qW3#Xz@wdm;!TO1k_)$@nW7Puj#;KiexsVBxz59P!F|&P>e7iw{ z3-Zs}8%EjFkzvA=yT-(MWSeNl5E45s3%q$t4rGHQZzowl0C?r45jiv^nFsK9y|q>B z_(<$vSZ z^YhY*PYs??+fNzYs>FHhBWJZU7RAR{dP|XQvUTGsC~qr^@l?~X+XX|$>J{H)iY^A4 z$PG2A4^QuR+#FfpV(m-f%m7j=l*k(6`(E2zxt|$ujRL(t2i#)|?vx77f%d61`~=MZ zmY;f)3AbfrFu|BhNJN?~woU9~*QZ4O75wV$=rsb6i{Y20CD`Lkvyv-HUx(4h_nW&L zL^XI$Mjp&?9|rjPL1U2sF3fa+_u@FR#>Fx7c70 zp6K(pX>f7865CfxPOIiT&dz5JDAs~pE4aeuC~Bq~q^LwVia;0>Z}+Ua2=z<#Znek? z31k1Dn3ruMUXcAWq?vLMHR%q@>;=-7fgJe?JBj#{N>;fC6BxA{=aJh}CswrchWJVb z;SsqyMZ@J_Eu?Ta-X6Vu+@J_&B<>zYPkwGuZS%`meJT(tfN4JVR{A<@Hb!fAQ&m-S zAdUNR=^#PdB22XWL!k&80J~omX7W{dd-&rvY zYs{53JdLQap4U#tn+?1esFUf(#o)DO`EsTQwD9JAcm&N#o??DNF5b<5V$lu7$9J#L zo9y(gVgG_Y(3+4oamudzv@x9iEhfT;Bl>k%Lo(BN3pZ--7ZzE#uPV!QJz+Rn!FkzQP_dnZ^S&7Ui+9Jowy%dYayUXgxo-r1K2`+gn@acfre_y51x(EptzVB!$2`d&1Ic zMCY=mt^TgGtS@&i(z5NcD7O8s{#2#8wVdjVhh}aQcXNG9Anhy>Bw%GD3C@4HGRqa= z{wrIU&})eqhi#K)a!nzufs{UGnj(nWzEyY1x%4cs?eWX+jt!p+?XB%bt>H}-VC|>=H0xTf&Watm_>?44$$SXvpI)sVA?ne#VaKrQ!t^~=W&TH}(kupo ze|&VR$xal{TJdiVvI{e^C>u&ipvNVao8kE;D|bENmEsR4^1Z+w=Bd$Lql_1w-BXWi zC%t^XsdTpkc??0*fw}j7UW#3<-+kq#^1;@4P#H=_ejT`BB2qvOOR?>F`8|^$+iCJ$ z!z~C>D$gI^x4CxYA4CrX&~2jLasAaT_cLh-@pk|Ty(z(#VsvY3oDkbVt5L^28^dR> z)V8p(dU-l&%UKhvoDZ^{39FI_zw!Nf2QC(4d9+>ltE@gCQU&W!B^`rzB{2Pgiv&W1 zECY@w{1v;*^Q6iTB_7q$wF+l7d3u9HInHZ*{vNAucC8!TIa+F9xb>Jf>P@|mleW!8 zy_(t>lP7H+@;(wNymetRouKwQk@`q5bwz}WH`7Ux@9E>VnuH#wEsfRn>gLEb2Lcd) zBn2rD6^^B71#&afi2~fHkGHSK07p|)%SLmO#>=fZ!xOE&bEcHOgi^uRJG-u%iD zdB49FX_5b0-AI8lfsMmCpsSt^noPS?|G=O!osq`8Q9V{gZz^@lq0~nlM>Cdc!s-T0 zIi_9BF4AK__|1Tq|BoOoJ$EBtrB0JM3*1|3(^?brUq#H*3BW?-0SJwAoC_Gecpb5f z7o|UD1oa*{&R#jT9;;G8K07S9y_ekCdhh;&C&6`z+LNgI4ik+DGFPb6Chrew&jhljLkskCbVLiRy;#gYLcp$ zpW&^jG!QIbvtAk@*`4mV{yKsU&UpRxv{U4M!&D2$%4vG?)4j^0!`DfFiezPsEj-S- zdknvqiBblR7zwqLLxPxba3aLkHj}YYagvr%RhAtndbggg5rB5y z<9jj@q`+T}kE4tvv2cL^;g%Hz@3c3~RIZUqRpY>S!0@&TR3I16i(B2aIIj4Q_rUTZ zuzG^tkl~;Fkyf*Jd{oEhEImOT=|s?9bai4xqFA}%O$pEUZft-P{hbZ#KX_DCwn!uY z9u_Gs0gt@#mU01L&%Wj7nEPKwWJ0%9+QttVJ1X0i@=&B3x(aI2*qEK_+LSP*fRF8V zg5z`Df-Mw+q@8PLBdiEV3915I-S{=wrU6@YAnMacGHKI{3Y=6_?7@m2-F$pVXIQ%) z`c1DTQI_|t?aV7NUFy!DN1C{JKt|FoT@=#^?SK-rgcO7P`WiTHCU11D-)a@o|!{<^DF5-d2dSL;61q!+kL+x9)ny9ksuiQ~IuQ+J2#AHbG7Xkc{tE zeEmEB>+B+*HzKg9U~02^^Hj^hG0iQjZ>Tl6XFFY?&?dKI8Rzh}uRwT=vf^P%HQ|8X z!jFAC)w2Xkxol5vP;~7kP(z6zbSQzBIXDdb2Obju+sMSP)bu(dCx`qF6}EXT!O|Tr zp3W%KlPVspgpqlXxH0$JN?Xr&v-X}=gAw@0$NRQltd!btI1}Nz7PC!qVS%khV~U_} zwatI9ql;3heX4sPJMd?|$=;Hh-AM|Ko|VuHz@!J(vX}jiwqWn+B$Ne)M_L~LhB87t zFD+kjk%92=fk62YE|$N2Um>_`KKE6^nMeR1Hs?B4Jv(-OO}-rTz+F$5ur#rlZs+q1 zHEx*36h)V-YSR)ANw?_>lyu)5-Lg7Kj@F@x)gpa%H!g-W-7;}D9mh?}sQ3@4?OZkk z(+QbOTRj#m_9FNBuVao2ZW5cwJFOvJ?(J}NoPaqXOm$VSV82%?#u1yY+4MR%LyRpl5`d|gb~x{a z_6sH_csf@rRw#PP@o?fTL>G9V9^y|Gb&dK27BuD-7E~}3d*qC^#Q)|9JKt~JY3a_s9 zlCNg{0lTZMAO`0)U)x9EH@_?+%gjmCuaNA-2Ag%R+;+gY9FZrs!d`Lk8M9e&K+Osp z&xa(W@apHDVB|B4GF+B!tH@Isg(i5K3n<{*A%_41Gl~*6c+%4FOjX(zz0uY%&NI8b zXft^FVOzaQnpdwq@}medgVC#{z5e`tA~H-V674M5FF&;q$2rS?kK ztO_v$d%0~ z*(_h!jPOmF-M^0tVfm-3;;YE4F`MO-O?^Xs{hO5&5Bd5^{m$j{9I(PuLa?Kb6<5lN zhs%CNxc!lx{Zn$39Yl>S>J7%BT0IB63JFxq(wx!0UCuaBal()Hmm6^rm|%HM{%cwD z-(@HjmMmPUV;#=bY4f!gvR5n&Thwi|cZp z;tX4pEutxnJQsJ`9hvlijGj{NhPwLE)eyc{i>gFFGA94x9o})#gq0KZa%^7bn^+^M z(WBBV{H40kOD?q`rJeUd9xeB*()*SAi&)*RRk@mQ*>c4c$=oIMb6MuY(ME@aUf1aa zZO;1AHSsu8yv29FAJMhl%l?7>^duC(J;7-y29-CNc2U@(2~jw{HB*cjhnC1q18$8` zV1{!r3Gi*D<1|N4t~?$mdI#ov`g1RQ@SObq%8WQ$_03!5H2$~7n?VsTGskj6{+S*W zBEKwpp7H*kVSVp^?$x3J_0&6@F)u5RW}>Gjp?kIZ2JTI#CC)P4TC1(?s@oxcD(^Pm zRA*;Y=rGUU)f2FLTaOCaK-R3oH*-FxboQ>)C{j!Z@SiATb-R0a{DE+v&Cx(fn*Zy* zbUTrIN(8g;BaMYg9fO~j5b;u#z~7&j<{G|+$$fvCYD)K|+PrD2dB0888#g<a*>$o6>xptsGw0i_&pKYFWhd6cHe)6PLd_@XY zoIqU_*H_uHF*l_`m!Lcb6y217`o6v+6N?h9ip4@1Ke@|VKH7tD>P$~J93 zLcx2l-dviYMX-qG7G&?$id+#TvtO3}i!B04*_8T-GIUbUKeX(x{Vtz=kmyBTAcbrq zMePBB%T<)*RHLsu$0)&ehETb)P%-@UQ^ay@dmVdfHh3 z{EABS>5>|ssg<8C;V^BP`JKNtyTpX;h2BiqZfWDiBpH4$ortd7iGCDQo#uIJAn_fhdypDA%p!BMTQse+|?S&m4L_1}xP*+dy$Eta%1pSq*IME%#qG4x4m4u%`hcqb1RWu*k~x-IVGTm^bF?LsxY9!X}yuR zV*xsB%|$ATfxRWiy3jP z1#z2ljxYZ@PY9Q072VajdTn?>hZGe0e4{wR>HAkfq|h%#NxUP;iJ_9I@tqruA=t2l`oB7I|)x_|{ zHsK^8Ok+X5yMSvGGu(!@6Wuss5PK$P102uv*oA*y`a2W=Z!iJFpELuEiDx}Vh%56fYQ_kkpsR1d!Vs{<963re|lxus@At`?@ zEy&GSs(l`NDjaI9$4oAKW8oKYP9QvI4-x*A!+}FgxF#x=G0_Qi{Mx*6!Rgc-=2Iv9 zvLVsy=cV)m@Jc58eMgSmyY-GcX}m-GT^;t{t-d`kR7C2yEX9^b3q-$V$;?WQ|7i0M1~n4zxwX#jU6VUWB&O2D8eGzW4eJ-i=c!hPYWsiPE)`@O11?G$N={K>w#cqt>i0R(#6@Pg z`0`nF#>)KAXur_QNvQj2*@thd!;8Rzn2z)R2<|mc-sitJA=KL#_64!~ia@G?EZV+= zOsPi4pDD8d!SNeHjqosYrVx3x#EAO`j+w5F?yVmVu5oelC?cl47E(~l41!k2Mo@LS!aL$s-F)j_tH|5;wv2M^ z%DFx5?Tx;hO`#U{FC16odDil5V*5dBX?yjwH~+fcT%@3-^8}-`;@+JazW6Q>^h0WV zt?^==|3y+eU=#Ww;YhlEp41LFWe>Yn;?5mA9KXw)UUXLLoS<%m$ww}IZJs)hbOQdn z5ODH{IF~&2%OA{_E`Www-Y)#{I5YO=rJc5aAu?l0r2mMHI_`Yap%xszrtCYZdJ^c z>qq5BwKHZ#yL-x5li3N2a`i{KIYykGTQV2Ve_o;iWGXND6II{DLWZxF@y|U1$T9#HD7EToVYNOkGK+bzGMtnlG^JOUrrI}RvSdynd@gyCH`zbe2KokL2b5d z{}C|Pf8fu-_;-=Tagmt2>V6?O%z3kC%H+z~YQp-z&)_{9o%wzts2HL1BVg)i?z!lH zwaU!0@VB3r#8s_+UK&(A+kHRT0W`4ADFP@U#+5Nu2+-6D?(Y7)isWjzdQ9ie0$l%ttOp$a7Xx23Mjmv2*4)^XH{(H+kZD zXGBKM%!f9Yi+fxjmrm|$0g$Iyxqqu;a_|Efa~RR{>h>=)ZK@Hpmc8G9UYZArubtiX ze~Llm{c$Qf60vXazuWZZB~CBm{>enU=mXhr|D$J?&eYn(e_mRPaO~N#WtjX|&yXVq zh`eLIKY}WWYg-NfcT1>L0>geOD}uriKJ9quwIrxRUqq(@^JVGGWb4_#r2xvqR~1&e zM9+)|o^5h6W_$1dbk4s+w*A7>G53rLR7K>!sv=T&V4`I>cR`zfwJO2y6}AdsWlR|( za~FzUrzR)qD?cy&unH{bcWtfs|2`>m{{97D#4#}3irpB%6$s{liWB_-5&e98I{tsp zM9FjQWuP@9>8eZnFVWW)+9$mLY*$Vo>BGymku{)u|9iZ-g+);}1Us%LVm63((6D4luTj5M-p9hDaxZ&i*s`-Ks&&)bNU3*YAnqam$ZQ z(vHrFG_c0=JmEA%UBWfZBsqRdm*|tm`i$$`Z@VVDoW(Ij7$h|(@gB`;2ChU9u~jc^ z22MIfu@1=0y;n(g!3Ffvkhk4y(+Q`NJ!{QFwhrn$>>zc!WLd15Q6+Oh57$+Az7b4J z3RbdVgw^Qk(;7*UpH{Z7Z!9!vVB|U--?RPU)wV!u-XPbh^{)+*Qq7b2jl0&F?uEED zxrcSbKC+yYipJt4JFDccI#kJ7_#M{xVAQzulQgRYNV)zqe*j1mO~na^GH zg?i9cb(0^dO0>L}E}GmD*?<{CJ!Ud*8-azYXF+fzq6xP?H}X>zR{dhrvXu6l^o!oE zW{?Np&{?;*;1CpyX^-@Fii-OyHc6Sw(3tJ7g)BUVvwC`X+U_oe+ek(IyoKoPP#kN$R z`IrJNPw!PcS}ROOVyZ|0*rG{>`Lgw2XEG-|Vsm&wp($Ey2$~Zxky2xC9Xg{l@v!7# zWMS>Mm>rT}@7=xboWS^hdQ%~!5iobkeM+<5%Df$l*I27x@Bw)^n0umwWW9T~@Q&LS z*QNesnFbBEKyB2EX#oK!un`Q8`mezCK0c}_8ViM*nUb;aTViT(>(?soRs|yYGVg(M zmfxzAd0MQQhJ8~BFAyk|zHDTMm2m}ui=uIo<%}4OQKZyZP2Cr32y^S#&F_R8DLlb@tn?nW}JrPI21R`v>E-6-*n)d1!3@XLLvq$kj$lt&I%F8 zDs6VRjF`EYVlk5tc!5{9OjJLW79IKpfKyf!XpZDML<3)k2GK|$w#u43{+IPa=$*-L z?*a$mn~O(oh}9Vz%PW_9*qv$`$yFpEvJj-n2;~+;&};km7DRe~H> zq3N%09)mdx#J0Ii)A`KOkX_xGlf}E+pvDBTYq>u!U8@b%ue)RyK7GNK?r2&2A!kwa z?d+N5l2hC#ifo1W#qTB|+*BViRW8z4hmc42*U9x)!P|YfI4Vu#9{+2~a+y`4b!WbK zZ2M`K=Am%JaSY|=&VuBSKmI!ZvtE6L_r*rq8PePaTqYd+G#b2(zkGa8y+Zq1rHzY3 z-?k;5Z+Y{f-p~yoDyrB}UwabvpyKnE033HFFt<8riT);WUULQ(J}0G5q_>VcGLyPl zyusx75Q#UdJpmtQy-5ep%EZgdmF)gW)sqRJ2=&hWF;I>G7#x#kR0MKe#lNahTmW)w zvonyObwBF9S+`5sDXX?T=UAfAt=72GB6x-8-r7FKR_0ETZj_dm;$MVBoW4jOjDEPS z`IjjHFv8p_f>ub_-rW5%?*D$_x&TDEtdNc(c8xdG{;A{5ajEMw+(CByW&5v3bH>OZ zCYW|t*~g5f8?>BRkJ7qYGFfpr_Uqtb8A45xD-?owOO5dC4pf9m0Zai;1|VH9YVqhx zo^a7{W3Cc08vspG40zw98|yMW>v?J^kf4x*r`-)MiJ04fJ#UW)no!usYo<`)=|;E0 z>p-b#C=GLhB|5i@a?`_< zY54$z;)v-1?@0F*h;m2aqVY0!T_0_Yu7!76NRIB6>9-1n)+nCT7P0zV=fzM?r3Pp7 zjYx_kREtW@*aHCcuVD7R3|gcK4r@^aJiR3*z>Mywa?q$Ngn1hulj-(Hq@%U+>5l6i z`MSUD1jbZ++m)AHi@xA8lp!9;BII_*pyR&YUk%>5pxE+W{>_6ff@3&%0qbQapwhyE z+NR{!@m7}|((Swy)97E*;VA^8L=Lx2-CL-U4Xn1&Jl$ed6j~*}ZP%1w(uhwEtkGU1 zX)g9~Xj#gVNi_;Zx(b1#R0{yk_@JbEe{A~(@owJuza{*6>Biga_vf`|iY_uQzw`3w z_b*?(e`kXdbfc#Ect)<}`>0Equ-(GL z`m0}1#*3ng;ECcfILIv=hWJRm2vf9sfjxD2T1Ki7(5m(J!94ao7G17m80%GY7E9}j#~F7>5#9n5HOZF~s0dGI?k5@(NxZ@; zd)6M~nFK3E>Qq0-2{2;hBz9XkfRqS8JT?v#I0;fo!;ceVP8vj6uGPS5ZgG38fIv5K zu|x>55?M$$Xuk!A&mpIlgzLArr7<6p9jsf_R=hPgOdAcoT|S-VChBzi@qGEfq1R7(cz{9zz)!mR#AI=$5gUH1Dkx0!ywPq)B&w=t9sQBK9mw zx6Mt9AxQ$nl;22`xHR3}b8hdNyskUf9?; z_hFd1J-rIwwz%c};&?Jd5k*7)p6^~0viY^-RCmdMBmdWnuWaiU$bJ@hsa-W-Pr6wg z)$zg#Z}m$JB+--6cjV9gwcJf3Z9zus3u0UAu_tg{R{4lSUB&_I?9l;s0OMHi?)kuO zTV_ZIL()CbE$(1X^R5vX7iE-!@Nh1QEYi;_Hs^p7>ne@E_|9@1yG*o!(G=Z1?fg}| zmd3SwERqZvT<@#$&DqFz$W8A``0OS*ApWy5 z@g|UZ@Oa;II!AkA9SGnu9_aX-wZ-@36V+IPsNw8K0*&J`#*0o9z~YcJWRo+@Ag0(x z%T-A4b^6le50nLTEvL}i^_0)?@wZoH=((rlai2GHp1hN@Y+Y$}o90^vRDptb%%!EA zlbsumtrI?oq#Ky~EKP@}n2c*=UWY})uC#r4R=EXzdUK5{4Yj=A>jw55>u~Y=;d>m; z%USLm*7A8ANn4A-SwfSfw+>e=Ps9q1a`1UI_VI9%?*pP-9_LIgrvcO9V@m zAD!n?K4G&?xouf85%hX&G9bFnqzFUO5OLjMJ{&5v;8o8)b-V6Xp*treSJp=bVqCVO z{9&)S<9n>urhBM6;hhx&*K4>=O6aXxKQCP&g=9HbXZGaed^r%*0JEuH zRj3{Gnlf2O=A`+6QQo!lcQdY-wvV%C$|%|)Q{eL%@Af{f)|OlIA@sL0;3-GM1 zrg>q5HxD+Q6-SBbx|KnR9}xB^t40==Nn?T^lI#7j(9)31^{m-<10HM5&K+YX7otq@-BZ+_n{jyNX%UF+Xg6wQgCB=!J2Ca`QGZvz7J+}U)bdnHo` z?>~*-btG;4NeX*?w?V3GD}qVO{6SWR?M&5C2G8n>u0v;`sI8>}X9uUYHd! zy*X80Y`v6u!Irt#XFHF4*-o0mI6flRH;k5!5!*N&f17)16Syhomcpjo&BMd{y6Iw| z!B{Z&)cC`FSKVP3t=eIgR-z~bTs=xzu5R*rpfOn)hlPmDqRH`WNmvX;OJ8wC+G)RO zJj2$qluN#VbCGhZdctqXri9*t&Ke~eaDj|06sKE6tMe^rntWc5rFvLQc>lzyLrDDn zEW^9=+Y@Arm?@D+F$%V z!Z^7v9qYSZUl$xoxbOJxUc9(Opl>1JEk^qKZ!36O0Rm(_tDbY{p^lI?rBM_ z6xQS47D0=PHIJkzv)%D|;t+PuC7Fw%k9`etRgOk&4_tWeGie(I(wkoQj+vTcnf)rE zX%-r*dMjc~&MrnJX`AJTs8g$`h~*^{A;zm`leaF$F8DGnCplGRz3Hn|RWi6GHW;^% z_SV=$SP`@Md2Wg2OUi1{PG;42uWiASHXmf#%3f2m8O5zBL5HI!mBU1uV9W-Zu4v#3 zeav%RnQBTgjq)_U2~B)rz+u295V#7HhNWv(Z(yT4^xH%lZae$;vppP*qZ+d?*HxO& zlAAVH`~Z4o9GV0gwFWX;WZ{5_CFEOsPA3-(8R0sOjE@^*wWsF$@0y>rc=O{I;$~0 zwPK8k)lyoz*x;sa0~^ghUEV>x;z7-=EsKp~^*CP^NGty%w%<%X_3s6~n4NL2#mH4% zxe`yUfLO(JPg0%sZ0y6)=Qd*%8*`AsHbIk`X~89z!dbr|vW7`Ej<^}dvW%54CjlsQHH1>9}nex#aU=q!g?gZ@hAHd)gq4B#ajpy{~%1oO(+vf^FOrcRLJhUbCvjS#_T7^iCulOW>y?U zbq*(i3_XgO+lF#JuNjt!_hAQC`wH)B$wf>PyH1E*qC)6XD1(4Q=J>`3wW45-91NXK zvoB9a>Ot%PBW`-;&#@uV!gk0w$nv>R1xbfKmH_J43(yk1y7>`=&HSoVFL$t{^#YBm0H3` z=a$S1;qASUp(!7Oo+Va2iCB_s2yAjWnKqDuBqx4Ond_x7`KWxz4`1(ce3&#T=>2f@ z&Ao}gTgN}=x=swX4z`cO2KUeOe<|f`GuExIK2loCc(z*iWGI6d(C7fdLiD`7){6oE zTmIvyF!%510h!_~C>CB){%M^uJp0eq=s$btGkpPWj|zxm!pBd5-m5@ck@`poZ_H)I zdz8an!09VZhzg`1x??hasqmP<8gRoC!Z?i1--5SA*^Iq|_FU!9tW!2?H_3E*RiR7i z=ChKyN8X6Ln&PnyZ}!*kY9_YNfu-c-;KODq(*scTm-|k28i=}3Z}IWvSE3AtdBk8_S*IKdFcsJ{{N0 z{gthC>v>fhU&89As%T}VgiBD*XFa96a-aD$vt$P>6%~n*z zY(%7!ZAB>pN>N&@pdf?}f)Ig?2nYcMi4cg2^tM%s(jp?ggpSf8gt8R@si6oViFA-e z2)v|mmfv^I9p5?Qcg8*UjQfv;g!f%*t~uwLYp(e`GY1gX@&^JIsXRLqUTUBd;!=hg z>Hy~c6nnPwvt#N&jlMS^H*307SN{iU>f3?^Ci>mD_1&+ex1RU);_}8zD{Ef%fWeW5 zTP?pV%-Yaj(bWM%mB$l+j4=|Ad&@LWR`<qhRSGOVd|K&8#1%RI-cDq`;+ zQO>xhW!c36US`RDHO1$?ZV=>9a+ifKy*vK2Ao7bsLiXur^8*{}-iqQ!Bg>?#(0enA zdUAa@>WkI(MjoY5OPlRrK_mXEv|&o9i>DA?wnVOZ@>zOqPgAPbETy-)Ci3&Rd%e)- zwd|XyhFce7vV~=y5zGL>QR+HC^3W3WNK)Yh%RsMTLPQr}%KcinNK*{iGX#=HQJ_E9 zKt{aFrw)|T7l6!(#H{oIAQ+0oma={WiX)@FYG&s@ zn5TV*t!M*+XE9v7ynYq4o`i@u_#JXbKX`;L!sL>qqe%Kzj$a9ZBGL70cb|`9>aXIj zNgVh1qo&@jUiA3P;Om)Gt22 z_6D^a(4~!0QFGLAFXH<7;=jA+M*{Oq_9)*{0&U~kExTw8)=4ASv#je@CCJm5FD$rYWgm0kILTLazT&2LFuh8qv zYiTx#uNZTu;(g?apJm-9XNqU`>Y4qs1+bz99$*jZhQ)pHAH{#8xyN-Jj|6D0&+%2u zLRD>+Z6GW18`U;FXK#N2K+lHUZRk%iZh{uoJ7_k+f$D$98YibE-LH!t(DlGj+B4qwi{{5;foAHdAzhYV+;5?tz=D+z1sp-O{U(KkbimB zWpgLXag#?bL-?!Ax+L*|u{6U$(v`~AwWCLK61*j6woDyT)Q5j!_e-d?cV@#x_Z8cZ zKXST7gc$_uy}$KPNzNhF#qyLzJFU>|FjCZ5D@CT3 zmu6MOdtxl+7is5E>+4l#DnVF%&#T?u5aj1LWzY&7n!p^PWB z);SE<^0SIei}261ul||ct81M~xqc1nh}O?~ncUJ8xu@LMLEms~<*f12-Xp~rf?Fcs zptc2FW4X4fYV9^3r~O6qYzEtL)zl)~-Cpqrd#=0Jfii2PsCHaz5!z$#=zF^!x}pui zNHiuvk)@xgn5bxTx4*PRaj4{^jdh7-Nfah6I#Y3kV4HCB{^wd9#dx`MB>6tR$UA0p zOUZ-MZ+xl?73P^E2h zob+XKG=550ne^A_KINm2TL&X_l+>*&-=`Npc*j(dh>kyO+a#T9vY6gxf4-qOJ_YV! zoGL!MWYKMX+-gt4=cSp^V#zNu_MSXf-~seH?q5_4@Ecv$tK8$l=+8CQbT`hsYcrFc zhNP}S+DcsxLQ!u0G+qf8p~CCQe=T2DL?D@ZO}-maQ7uUQ`Lj(4C)3u?t2guZKCro3 zI9dAK{VlMoude)OKQsADzxcxDWQ5=M;-u}^}?o})@4LWkiASOo$8B<~G(C(hrygyOuAI5csAqoSFh zIA}bg5DK$o=9hVDN4tZ&?d%-)vZ~eUW}@N|tzEQ%rH-DTTX#kq#619`m^>;q^s-($Ftm#;GM+Irlv?FCW-R}V)7`SEq{{xp55dk_N6DL z<=;dWVa}2^b>98NgxEU9>6Y{tQ&8R#Kh|xn-ApT#F2=s)}q6EVTJ+JyJH*pM4)I?x%U? z^9Qq=mzCN`itW=C`0;akomsMG2AKu%omNFw`=``x${yKR5TddV9^t^e=rDk5n zi})h)GrD%qmvXF(1XqmS9w!?TrtFz&>DXE~(r3bWUOV7Z{@3NXz74^m8=D6Ah%NTM zv+3e5m5=V|rFbj%DcwFBL-)88aZ9LiH+5Kp`J!O=V7&OP8(RyVe&)X7Y7kbBdP?!R zXWIciJ-huDMNZwY_)ea4{*nA6WqS9hafMqsW}-Q!98KdaY5yqI#_P7}xF*7}?>!T^ z(aY_J9**P~ob=pm$doS6E$j|0!nis{|8Pm4k^%kUUv$b@${;Gn9Ay5H*L?hP)-m+e z#49I!d1~Ne{zRmYqhNGE@ufN$wU1U^zY6bfT`Ey5M~ku2lf)GnZ8j-hDaZHpMwoe- zn(a?+iZqWf4)8K(zniBPfs#VoT+2sJH>|xvZkV~*1{4qUoT3*fp7W$GPOm9zR~8u; zXDXQ0Fn+Qe5o3o2Oam|VK*aVZ-$90!k1Y}-NKgj zRq>(m^CL;M>TQhg^S3?HdNFVpThQ<&+3$~>*bT9qy=rFF$yvdxFXX4{w9dV^eRf#l zy0b6g=DV=I@y?XutA!V7KGH|!{;rVd$6zLx{Et155-%fYIyM`QOnE0;*EhXZ?tWzx z5mQMelfFE-;p>)W-8zza_$KX?>%49L(qM$Fsm|YJ=Rb=Qr0gObo+s7h#ij(Cdh3|w z#?LJ3Rh@nTnl=~Swow%KxV(2R0uw)QnpKG@Fn;HvXi;-&`tCr2Le$#=xF^C}`?Mep zzidNA#Dgko1~Q4xAV=%T6<$a; zsoDn|JBr5gcnqB$mSolU&>XER%J+XNg$tjAg!r_vu#x`6V5Qw!xOHS3pH52f0a%-KIL|Q$}-Te`x zpq*W+=BW~RzIveCqXkM*`QD9oDMXE5_un~O_9X$GYj(n}w%NO>sv|t-mCcv4!Qy9i zUSf=giUyL;u;I6IrSF&6HY*>O4q&R6M8`8viyzfmv@J6(U36J;J%v<0?GoMACngrCHlNkYT{YZJ<=XrX&&82*KQ;b z4&6iS&oEgrxiX{@FoAoPmTJ2I@H?$V3wD;Rw4wK=XV^cxuQbF`Oww-LbsKcnjqwem zJklH)-Qzxr)!LhVR*+RZ*h+5m2)Hvp^toDkpv^=u;>%t4R}GpB2sRHad5=RfKzdoxFO& zZj!iyai)@jgB2!FRgGC<3k0dVZ)W&k&4HO~@oi8k3dh`T6`;=TJv!6Bih1yLV+?FY_#a+jf#xJ&(eWCXirFzaC_#_>X9 z6MvAIoh#CtlIvK~y7R?F5xP>V@Zyo)f!=Z0lTNDot4wFOdO>u~zTh4u*UAU%#x{#o zVX-va9lF}6!+E!lRyO|Yat@e=SAFH?0e2R@lFVm|PHla7r}iPj(`}JjM1P=cU9j&# z&rw-Jk^c7cp?B;R52i}zA87uIYJ0#w#ymF;DQ5QU){BH+*ZXw{i6#ZwHNC4;P!IZ1 z`c8p+?)-?YLtcGrD4Jth>$uxJr1{~GQ!Rg*zKPpXB?Q7NKDmLOBY6=6ZJmy<1}LN)#6sF_Kw)hnW*HGW|C5_h@e=nx1F@XJga>RpfqpPrNr_< z-leQlmd~^_k{~TQ4H>Da;~b52_z%*EF-gW^0jan0Hdy9bGq{de=l&zmV8LtVOCPFUagg0GSp_1 zB&Mt-1WWd?=ya7;^J{ZIc>feom*5vgR#K_f-E^nYBZRBqYP8JZWyzk;na$rybUVyD zX%F_1U&3R*s3A{(IV2w`v(qsD(2I7PRy{;D>2ulMSGT-#984yVA`U4xIwPq)Ajn(O0DrwUzp;|TcWonJ1N`#e`6tgQZS zt}@Wxt@-8t#MVs;%zccjmaGmnO-V|clT2h%r~R$fB$W+Mzb!%P-LsNxn#+k3sb zcLFYyJTrRUiv3+36J2^^$uw5qP3J>_ljle;m(b&m z(;hJfTBPX-ePO4;0B?Qi&_K=F=AioKY_fgSjcdLdA>aE0^J`lw(vWMQ)z!ccZH{Kg z$HxuYwNYQx?e_+T<@M~lYMgxBL{!#UL6~I+^ER`Yt|->@rkxxloTq|<3YMm`TK18| zyXQOa?TohVA!NX$;H z%Pz%BywdyN(lF+gsa}`Z(*VDK7UNsTJ2cc@HJsBM++j5_K-k^ZT(M}QZka1R?B!bI zuDPT*kZ_}|v3P-8aH_!`<1$~|C;Ie*RcAbrKZd`}@{qFjCFcjFg8MBda>!zuS#F!9+3s}_g+ z-s=(em__WS`=9&#D&G1yVnx9U_N;90x!^d_hy-OPWy7pg56d7H6VYjfTF%iBz<@~s88BI=A~RK5HdOeWncYBEYxeZC z+d1{qunk!^^hQk0ic6k;bYTvZScxhodrdRCMeM{L$5;Mp(Qt4^k)^J*GrWDU=<=?j zp=a}5qH^&4bp2-qCTEL`B=k&L#6f_j>=*E%;uYF0KKWFyZ?ifDm992%2IJ#k z)JEVnWyHH4##(3p_=WU4gdB%O`77z@iDais4NkA>GAEo#UK*U}+L8&Al!~V#W8^FL z20i;LHaD%}612c=Ll>=Te6)DD;{DB$9LpwkwD4=I1f+K?o4>#OgkML0yW*&HEyKFf z9z#Fx55?|nQd_4SmvlYce_82EMMZ?px#FpQlyQucO{p6PG$_LKTj1FG;0w{ zjWB*mNbWDQ5{xOcZJM*`Ez^0A`;3^V=kH$42^*f0%xY37!0IxB+D+l4&AMzU<_#T6 zw4Tz5%2Jf6_wg^zXPf)Eax~$XfJbiLl?T&pUXzvG>mx%YJze^=smih6hYKF4j&hE{26Q)0K{Jb6P??fy(&Tn-e4 z2C?H1uJwXOkFAfR8Pvm3l54mXY?Gg&+K!CZVmowfcyo+Wt`>Z}_{jC^Wud5nVYi0H z#A~kaqs&dnwc65sU+lW)T??&04!2F8q^b|QqtrSqbEH3HW~#r6h3+X8eKHbBc#|7b zf)aITmNhtH|4Ij=y3Ex8r*lt0Hzj4G_q)30ha$J*=M3#{$es+fEORicSq#xUHS)z> z(zvAE_+U{(qQ*j7TwJ?kdJtDef`eHw*DCR5Mr}CYJA+;>nlCzh*%mk$rkz(in-P+0 zlz*}1oWah+FU>36McmGkW)~_y=C>_Ml{?$FBnieR=&eauiNf4TwQiOH73L=J=z@ff zS^su7=I2!HG+0Dn#r4j7xS-?y%9Nwa>YDQMz5x|qhLvv=4gq#au@YHb8+SXA$X3hQ z>?1ZMGo!&83NiNgc0M}UW0QN%EVO+ol$;1amMI32j@u@9xt;j@PXH#YdzJ<&Tg?Kh7o$o z3tzKg8l7$xK$y5v+H|pw`kR@!c3KH}X68*X?@}@~ilpihS>RkV-zO8D>3pK)M52-q z>qg5t1s$>0{vy`vHn?5;MJx8_TsslVcgLUP&znV!xEp)fc#dFV%p{AY0nB9AKm4hr zQy<<#1)Rf^!q@NR)QB=t^)uLy(ZTRCzIOwru321+vGf1ED!#T(I zUHOoAYJ7+|J%*d0t(t_B7+e(ZIoZr3)+EanEy+c_XNuGuP?nHr@OhSo5cG8e=*43d zgJ_S}xa#E<*XH`cw=Ew6>X%#R9%b!KQHNW7_S2k;-e9?<0`8xa^pnMwZF-Gj*Jl_7 zvZs#zYIzOA}_LwPwO8@XFxs*VWn;xkmmR~1Nybio`v^rht&!3i*PhaM#l{j!- zeJ1OE-AMcMjI5T7@T=}UN%onI`zoy&@1sFe%dvs>&t-bW=i;?a81&*t03&NbmBot) zy#U48A<)CkJl@ML=P~A%Nv9eWQHjjLoPG7Sb!J2@MQa;MIBff7?LbGtXNUvWwQO{uRNGqj-+CT zpO(D3eLSl7E_J~!&-rDm$&qpf4E8kVybZ~n=uj5kZUbmWZ*B`T6$8(x1`sr7vQC=q z*R0@w0%d>30SYKl6PZhOirHr{F`pZrdZnI)T}n_e4xpl5XdXR3Owcq*xs+M=D@4@| z>#xH2*Jv@LTD{*5(XZ7G!@4|y_^^Ij`k&R^R&SJ>#YPtSqc+IKxiEFHo zf81ei=u+Zn)7XvcXM`VZot%+M+b|1^>TvZ7RDYchmoUrH)7#4pcN@qXEAHRB~;b_WMk(tf3KbOQhcCU&Vyc3WUpjc?B{gV5ZIKNJD#Jre*D zh1KynYjRtFq7Lkg+PJ>boOTM}2O6WZSwG_* z(ZDzq`HjnPCJewDD?vB7HW!Yr2fvFT3+qBKO4yu@m65dnE|6021Yz~iAb`^h;!mtO z!uW@AqPVYyNHF_A;#M4cF+27!FlOAgfKT|gz*!&{JV(CCe_NopDg5b!%+Lq1IHu71 z68_WsD6Y~ku>kns1Jq$$yDCkUz5BE7wm|a;SO%o_ME^Zi?m5AYv2B4I(#AtDs--SC zcUgCnzLp0D9};P)0X?B!F~JfKd}< zLlN_7Y+SY}9E_mg-y`S@1{%=dgxw@NJwiee+^gFHh@VNRr+-OTbt&YB5MN|lfL8}Y zN$`6qkQ0W^#;R@$=(8=r5Q1WDM>A7`U74PIDS&hSiSEh4wX4wJ;MN>~L8&%qzWKjr zumWx_$A&`n0_px_{sON4UYMQ_0xXLyIOluFFpb^=?w}Bs~@raAA*g7jZG{8RtQSs9&TS7mv7HniTtJY zNZ#+?iI819SVr(VNp>>;CjVP+ld?~ja2e?Cdg`HnN#@^kde}$cDukWu)jwk(u?d7b z|F3ENKgwT#gG|XmgRAfVhmIf^Rlk;pu+;JqH~ko1_oj@iovzp7MIfK)*YAdI-#s*?`!3+7Nz*-XI133o zXL6RRXW(IUw&+=rvim(vV^A+wb}i3X-0irwZN#p3lh0V3Ug zHUCA6+re~@!nT2y);Si}k?AQ)#;hYRk~EhmYN=eLl5C0$0A0YaG+Uq@ByvuJ! zAPrg)SAkscmndH05^=yGS#WiNa#uN&b-oJ( z=9{0o4g)CgB(i`Yd9WU9!N#HRtimt^`7J7n@(|ufh7$@5==gj6yodD#eU4s)@-%E0 z3#{SrByaV7pd|nGwt!e4j+DP6mpif5Od;fs@O?3Qs z$!T~v(O0&L`*0Q4x3$2AeNG6eUm~!04+XkD0Dn2xg8SQw%^`|}s?Nb{LixU&EyR-f zuMfCuPZoZy6^Ta$Z@$m}8;AGR@&8EA^t(2feV0!JIC?}zU<5b^Zj@}VP=7>7c^It%dSVh z7{fNUfZL%*D|H;;G0nLMHXuo{>J6(2Gx@HfU}OVI8WQI_ z6o#L}r8GEnBbEN)6Z7gCiNq3#794Di%w>BV1cGL533a2ER{4!lz%&e!aj1fsEhVnH z08ht*!Q~-Hk}^mL*UfEl(up7vmilqm)CVV6Aar04(I5L8^#Izqw@s$9y!~;4$2pcM|MX1msVX(3+qs3Gg618GkD? zyFl@g(*&Et;gZlxe3^3MT!nnd^L4gceW5~jFlWYea{+wSaborBuZgbBhl6DUifIKb znMg2f45bDEt=<+W6HGEAT5;KP3(M-U+CTYaa}Yrva76e7a(SURfo*|vV0?5|kDLm6 ziA^*Ord)un4gFe#xv8Wj@{sOk2yuzc8ND5*`_96{!r zt9&3)a+w?&y;R5MPI6iAfdPTta0)(G03>)UaW;#>q7VrgL@EYPW^ED|ViLE`FD$Km zlMgTWdF~)le2%acrpsyp(VP&I)iSd3{YNs`&{<(lz!9K){jW}dDJ}Ky1b=W@OQC{; z6G>|e6ygK2#xDy+{`A*%tDoWH`rhR7cXC%kP=tlN<=XoO*FAl7RGm<^>s;l(!{9u0 z{)6?Ut$wx=HjTx*g&;r(l_o;|vO4el55N0oGqVx<0v9h^@DPYKP74F*IDCQl1+iaW zH|!=iI9}dR{g*+Y{tlB*4@2cs0C@!>s$i>Cl3uj$*C0ODFC69m(t(C;0p}r{9Z!?| zbL`Qn9bi;*5b&;B#HE?Q&GmutH91Z*KU6n#DoYSfaDLBiz-4aaa#z<_>#)=Ks7YR! zGNSAJ>MB{^zfTbHblCu1kV;|jRu=sJWp(8fkqG=2i_Hwrp38%iDJ|OqBXKpC!HdI} zLNAvi36NX;n+39*&@EtwNCNBoAwCh7`UH$(i*F5F)cnez>1s$6%NPHUGLl09;#KXI z?6TSxATI!cceDA;TEIE;iGT9LKAc~rOc;!=EOxDPc|kSTIDo&Lf*d?oRXH85)L#lYGz_kVI+yXwz{;&31{=0D0YpD@EF8gQa6)-5xK-> z)io~@s$fo7HXGXz%DX%SMvo^OY%Pq6Bg)CF)dJjC1c1phw6+BlDscF<1qk=cf#bSY zVSVU@b$%K6;T&Iqn=aT#V38ehq?HP{f_gb5G|dZnIPpUAm#+N02-b>$vxWElMBHHC z$1IEnzCla}FU*xJ)lF*HUIYR`B(1MpB@(g#>kQApyha3M zLwH8?m950kJ_qeB9O^Cq1z3lLiTW&-3m7XDz>SarzfDFDY4eHHRi49y(E2a)NBD33 z)z1sd&Uh3$0$U^Yu{r!pZbNfi&Q3Ni>Ua`_Ze&rMSfQiX)ldq~sS!u|p$bNU$kxT# zYLNSIP^fd3=Ah4IHgRFi!KeQAM|~oE5N;Oyfc>IiW)66HRF`u-Y>ANekb}bMYwUZt zj3_`7wl;tRsOPpYxQ#fw=BBAdb`98v2}=~hAOoI#lBdOQ045O%bnDe)w?yOzy`+L0 zp+<;XFM$OG!iaM`N7IxIhd@_4(3Zc|vx#rIb^x`YtZ_cVZqeC%=dl(3K^zH0%-TMV z!H&4Uajj%BU#6CK@9C2%C(6{poimd>>ILWjAOAVX1z`pQSi@PPZa$1goc6v`-m%F8 zX2Bwuzxlr=pc?rFMq+J5MFrb6nxo{Bf2>5oW!x_dcb$hjI8*au1P?) z!}s%*yyPW@TE@p8*H>3F(;~UTWsq^`t@5-`jd9uFL2s?PuW=bAyH#eN8VPL0@!?c( z;g`toldk7#8ATc<-{zPDw@-E8`tkd;8iV4Vhk%prN5@xtu~R|mM<;q`Ez$)z1sgWJ zO57d%L=d&NfQjC)g9vZAE>KV|hG@yyUqlNPHf0`4^YoyL9KHTEaMI**>O?zRE21zX z!wKF#F22?+moZ-Bko=oc)N_R^0&Hi%?De11J{y?jagFgKsThhv4J`-w2wxgR*JgR! z4VC9q4+fMSy-}OGX*t9a{xtSyO=V^EQ}2?JqO8M_yWgc6S{rKY*!sjd0j}a5ajvL| zxQ#fFPt^$f0{=r3R2ELDLAulV%&vH>jra8AgG*4bat`xE2Gy}y^$HnlvMZ@*DLpH@ zqi(*~BO0ClFf`&o&hFB@7 z3um?kJdlu58dr?4QNtvXRwHrM#1(BSEQToBasm-=M`{rmtVxoXpE_TK+yRBr+glXg zGjZX17Su_xcK)vF>OmEcLupg01M80Z4(w9_D@VLJqwgXF&Tk7O!WlRFpc7HcgG@0L zgk-L5WDSOiaW6AQa&Y;JEmF(^l4^p3DJ3JH@@=7BBG~B*UStAEUcc#ErXU>@9U#+e za&bguSXCp-nElzl++Of+Mm<*|oWDniE<9n1Fy=Lf?H)yjDEm!x)0PNgm|d;$Rj+J4 z1Ceq7QWWf-R~YF2Vq@`#(zQC>PiKx=eJyp)2Vo2 zt~ZV`K|`$A6hIQRU9ayeuX4p{ea`@-S_5{_@mqC`r_9~pw6^ZhD_cJjHarjPN}LgT zEvWaG?&AmJQCtZke-HefV@9*x#y^bS*IrUqD>_LeRN^69&Nr$=?+3{JV92X!#iw7c z3wUVkVB;A}G+20;GS`5i+JTG;Ua5~YfOBs!f+7w6#7MMnSWI4ar>P2Iy026+;gOmX z*U)7v1edxI4O8PT^ZMAIBjbzb%0+!|N1D&SkxTgBov8lHV;1a|Au;ZbYbV?bP;o?EEa`bW zhPwD>>A;x4BZ&?;bQ;DzFgTr*P)mrUNNfvutsJEmBw=+Q951h?BBZ&h5S6;(`-z@z zkL|1)3X^O-HuAFRjEw#zN^fP$GvPR;n3YMn$5PWo=roRd;A~ezR^sy<{uE_LscN8< zTjW=0@a8aIX6)<@?JI+e_&?TB!V9T?UsJQ3{rO{RGW_rXflu!R!3n~c=@D5Al4N5L znUww`jfUIf<)DKJzs{71_(1~=6-(!eHzl*U7G?^yB_&B~$7yih)3jmUq0~tu zs(U%X)9-JXKJ|U=^+SLDrTE98H~S_{_`(anib(ohOcLBSzA)-u{{G_8b*%yho$m8Y z_3+MTo+=d5NsD)irL6~3+bX35mIZh|Uu%1m+Q;P+Xr{Y1R7@^2_ooyrrEBF1Ja-`u z)H+@x)GUp@xJyrQZLG;YML+QF{!Xl(S8K`zO+fJYYg_)$-Q$1vKfx^m2#?EgGY6a% zKv%3ShTXP+na;2P?mDh&m7Afx402(ADN*74H}dc|ut4x!#5Vc=%g&8R)8`@j=o2|_ z1b-biy9N!Q&p-ZSXo8F9_}R_X3*?`zZv>Op2H$XTX>||M|Kl6~iZC#U>4g&SkR<3R zd}WU^qeHpQS)YghQ95F8e1`otF2DyzmDltutu5A`?vY|%nnUqgr(9`8fh47siw9#;F0)pe% z*}xr9$$>&h*{)7r>60CGnNOUZ{@KAwS{`ErZ8-8G!eC+jcv-AOp*>d?5@Ghy4mEQ8 zpfw~@lCc?y6=6hh?HD*}Y8oB6T&NL(Q4T=v??y9LuqfPZg`uO>)A2LtPS7Y`{ZEZ^ju3;QfD%Bu+^ z$YM%pK_79^>9Qb9CQ%Mx_XFm_)fjq*t?i)0*tZx$P1YGz5$J%4spSv3y?j(`_7R2% z=%Qwm(Z)`gAw-uI4E`awh6J_|{ubeqbZCiEjgDv%V|Z*-KoK7=764dnOB3+GZn7W8;}S_mV4GK z*whYuG-&0;A*O4Izah{`;{30CAs!wC2Jndk^bTURP~<8L9h(gYK(p0n{Jq2X^elGH zHs*W6g_V~BQ3r@YTrHzA^d+i9t!^i-H~v=*}_|8i9n2lHbSZYi%|$e%Y=iXaa>RBP46_qN837 zNzqN3g^(r5WB_}%bWzB82U?|cy*t#zszP9+FN(sjT#W?DbfOO&B#bLq#E34~n2;;XppK-yTw^j;Cht?R=Rzq|j@s!7Iv8w3teG@Ube$6-6JDq6tUW< zX2PH8?a7DYOc@eUf#{uBRVamC_TWaphH8}jd8T+;yn~8e2m2AZ>3lI}&=h)vrX!%s z0ezyL-o@9(8x|c5vv+KIbgDv%NhH`V{#SV|UW$PLSA++Y$cHcvqk2T$YqDU*wc@Hz zL`;jAT!7BH6#hdQ8%MRTMiUQ&9p;{Am_^X#oX2H~)=`3<4R!Uj$xGMd$7|0j$+c=5H%F8tSB%|Cx||sv<M@58baBo1Ng!%Evm&})~@){7z{|)vyGqf(}&8J7Xm~J~pZ>=0Tsw-OgM`G>+ zYO}*sw`Fs41*1I9Bkyt8pSadx9bY_R#T{&FTG=5=o_S5Yw+5#c>LcylUaq7EbB%dP zPWQ^gcS#)jhper8I9W$^yj(!A_a#P%^_)4e;m*V3JVERDt~NvxMTjfNbfk`a$orH# z33+$4$XB*J9qGOL+j$M$;cJ0N5ieWIW7;~l)zpa{Eu1tFsqyyoWOmWkQ)#n{wxaK}eooy=UOTooL6N$)!|l@I48M!&_!5; zfj$MJKtn`?A-ESHCyu5g_NWu8&0(sD3AforK=3caGNsH@*;uKGSmEevAZMQ%YFZfexR2_q`C+ zQ8DOMd&4K?=-a%PM6ZyOr}L**vz43-Iwikj8;+MMYHi&;DL9LUbRU>O%9I+TWf17@ zqoNCvpp(t3@tTM_g|^-OVX97dPpq}lr@!$};6!{z96PSl|E5#*>N^7aPA-vdJgkbP z+!os4dDGSybJHCKNntur(nUr!22RbYkL9aD)t1fGgIIOy7WO>#E(c1N*K#{whR=cOam164MfGAPPXx=VC#~fSeeCkM?!x@FK&h#0drd z!L&%_7E!N_hDmV$si#fPK)}GRD_R5gVOxp_7wNk{k4ik?O@Y;@TyC#J-)%YcRg;sk zbkakBMVzqX3qRqU3?t!S{C!w&CfIz5>5)d}F@`*edq5t;AM&84zV-|)Ta;HH3Gi$=O`3Lb z_n4j#qsJwvf(v6D?HGeMTw8Ltn-QU`|!dOoT&cM?| zI-j^RN?Iugv3qV4rNd5p8E8MiL^*zgxXv5hxM+Pa;+rxVujx3_0*LWj&&J) zD7?84CL6(u71&CIL8tK_aXa|~h`qQwN#pe!o;(n+xPZNri+x{H10AI&jeCQL=y44? z%0Rn`*foFn8(UyXFQg%al`Uc8v=kJDav!6T) zATli|M$dyr6vPNpH=dMv-EFuNwZER0L-TpK=;)t=L0g+-1Z4_F1NR$>Yjr@}K|v>z zqFYq3>QLxgt_`Hixyao$bUI*LARb@S9uVhOB9^wsbI*Px$670jO5Xi>=-p#APp>bov{Jowo zfeiFU1k?&BK9V{cHdn6G^`$qL(>LlLX+QU&CdD{#ivmmUI{!AD*N6sV+{g7e*UY$* z>a0&@C3raWuV<8LTQ>^uv#@d;LGI}Ru%Q&m!@yi#^ZSBPBuGzznXzFAeE>(bsA#TO z@j_A__7XF@mcA|U#6StU$~jZw4t~~wWDeXkzN;L9!n{Nh(W{nN;k8zI;YKlJa5ox1%ju2}$qrN}=ymH*gG0q-u zNpyc|bGNne{T42GeFx7vY>-k(S?=MuW6uDU4I9Ak;)*kotqxP!9e|$YUC6Z z2IiQxi3x=Z5w1y=&BGV;(>C6`yw;DHX2M3Jtedh)*X!Q%GBuUT%=kYr%4Jj2{619e zo!9#|?apfW$4JYB$ef(Id9cC+W6pT{81c4mf=nYX$AExJUXJ%NOwS9X;wGb3KGA(t zH>^P!`V$Qw$5ucmGc(+xFzPkZ4^5E_hgI{^$0^i-F}S#Dtcvmv-zM#{vAaRRVVY5c zmgcbc1~QlveN+O8umgL3kg!^7iU5w}DOY7WLk?;4bAJJ-*R#7^`LzsP3$N<%0c{@t ztT2hI_WAvf(6`t3sdY(;77BU(FT14BRv&r|;@fNd$K}6p(porquz*-0*Y{_|Z#Xuw zZ;MW}_@939|E5CW>wliI#b(H0y~;&5krQ3*AdUHvB9p{R-he0iy@3xm|3~Ibs2#zu zM2>@M4j00x-9{#_czGotZY78+L;{m$IOAzM{Md(bnPSdOl?)syRM#jbB( z;d7igB&OIp5UBCTMT53H^mMLHZWOfI851Qay5Bo@|B6IdRohI3 zXvml{?$Nw&^V#yLq>cfnC4>D#${KNvE5_b}C6N3oDY*7K-1~(%vAKbBgyi*g;^U6Z ztN&xf_u+pu1yTtSQ#+Vl?G$M*;XI5kmHbT4gibi*mAJ!6o8)`|G!o`LfMz?>4^iz6&-nW)i41=6*6g-DZvlm$q{kc}d}m{Js~@JLhyM8v3c7GMH|rYuTB zkARQ{mEP>F5VmAzdl#Nlr|R7Az2A86uRGp5zCTtC!M)d7d#$;i`OIg|$&@$UJn%{^ zo9c-CfjBh(Ke!s=AP?8O{+V!%jJJq{*lJ0!q8#fYYXI`(Gr^a@R(#>{b%fG?d?u9U zV~dE&(292IDP97_2vs3`0Qm!oda>xX?@KF*CP6}D%opbF5rBGXF;RC%?KX#e>}FL= zn?r|M!!A~Yl`ge6jTygNmR@y81H$z#K}o#%kTk`VCQ@jR*c${Nzz(QyQkGyxg>7|Z zk47x!G)FuO+?O`U-Td4TEJq!49!vYuqTRPIJ*rv%B#iYBO(jw4c>&jDLtxh&W}Bmt zx@F0QY;CkirNySg-rlsgeM2H}43lupVTUDU|EOD-6P$JE-B(q2Q$EzbZ~4t=Dr5AK zCW?c9ekjDxxq~Y0B%*7}Zph2pH?WOwu@VO+%SBf0cYkG#M?B{kfwJCJ+fLkeqa07& z7S~{(m0e)+MBT*7Jcu}!ZRmW{tTh4NHCN4YtL<^a^d(9n_@)s)B&zIvvAjF0cTaJ0 zF0!|HfN%QzKAQYyp&~Q{>+f6j^6t*6t0r&Cx181TCvdi7!3YyfR(e?ipMJq_giIKA zRHD#dfvzRjF!hCXkbcO4n7CSs0VJ^SBkpBy$2BA zTj)mI>8kd7n?k@nunvfn(P*h0GFf6X{H~R<3{~2f?;4v-t!yR^`{3HSCuB|ZSD8w% zTP`Hx9d`Odno6{bLgsW!mZaAyyNrKCU6cn>YdyWKYDgL*r(S-;%TO)EI&$KH>;=Tg#7Gi1)R zosZih(mV*xaZ=M%F1jVt*MKuY9=oC1^+=LfQ##{OmMqaaZQ<@}@dv^3)zfulu~aYc zCE_?so3Sn6_@7WGDV#P*`z%7Y6EAX>A@zB`1p5atRu>M09;~;pdnV|Zjqlqunl;`B zx*c>r7#!b_+1l{oXYCyXtO9_zZEPqXqX8y7jGIIucMc%N z*FZavbmalCvge?hNPG_ZZ~**fEvVMWkEbr-P&r~F(!z#onGrGkvWg)W1bSlBtT>8(LO1eUsf3Zgn)l1(7;xy0eq77kR2Gz8)@eU!p{k;UaDp@=|1-zjvDl;{W&V0z( zS54|>$|jb+!I$dY{CGM4vIhau+9B`7=L3gb>l6!Wkj$}!OxY&tWP|N=5_?FC$!k1u_rb+~X_HFXJ? z9Vi8}l3c4u;Vf##qF_a%#T-~GvFe0Wv8da%Ac$hwLgv`94;e@M6`dfze?JyB>%Mq) z+{u)U)fb|GhIFP=&jlUe>rkBb0u3k@prUeKlI95m>1m|70tz+@ZILRHvNd54{Z6bd zMGqrT4Gv`M38iUP+p9|2CVS~iSXMhhuxrfoaA}1H*{8iE=Jf8HUm3aWoXU z+|~fF*8;Ye|9}orgZ(W6)k21n;h!X_y7qEnEV*kJlAmzrS!Ho)S^ImoZQ(BwF-H`; zGE^RAo$Dvf*Yua=pNO~lCgef`iKZ#pZdE~;nm`M}5@`MRYIIZInz*WONxUB{`X zmpq`C*^lMGX3CtnYHx9^3TXZGO6W;P1e(a)+|UOh98yVVrb1&-kr;>CvnNZ+3DXz;y5O+iP_TA$Y+?Iq1-eE!76lHmtQ-xLLl*2k z>O%Iq0lK*#>xOG*Ns~EM78u9gl7n{bYb{kDbgd}OQq&!p?vRLtOI+AL(SszfvQDLj z7t~I7G`v_9`;8D?TRxtQFqF$-`&uZCr$mMUKKyPGxKtYWJzTlfWo(nmf0Vb73^DjUp03CYNJ`@@Ypc>#*|Xd{ zOJPZT!gZMcBE5#BKNC^X=B8G;=K?k;W_up}Y6n!)BYeWI;iWp9seHhuAo*kU1&wlRM-jyl85DVh4ckz=dzIOU-9Iw2 zZP5TZq=ojnxpqv1Qhe%K*e>}G3yzmNQ0|ccIh0-!_kkZ_f zUxOPXjblwJf5-AMkt&3}3x1#eknMtctj;O$9qwFr7I8URoVl<02CWiVgxR53sIBhC zW5MOwT4+AUhOcw%dEN+t^bA(oVjSGY9l)eP!SDhaZ(L%$-2*w=BKUORSe^|iE$_0$=z#vkF>sLYsbP*V1YK? z1t!1%U)kR+VWr_)uytr3qT}6qD!ncvdm+5~mvgckq)VoDu`aI*8@no)7s~7N0BgyyNDe{DmETxg2hofJ+qRRZ9H}*A}BNH1BQ5Tbel%>zxYsi!zr>LUI z)ZudD^BbxThUSe%FPSxS-AwqpC;{1c;T2T#17!)TSlOt~hXNF7T~t%HVO7V&f#bX~e@TZzsyqjjO=hH_3o_H9O9ZhfrQ zXn8deT{Sfpr2-<6-8Q_Q9|x7W>H@)6c(1U82ZRH5j9lylLKD#!dSPxb{h|#ou>!hW zk)xXu8w@nmzDsph~bJbdw5o6uNDbpn6-LJuNrWwoCo91`~?oWj7f70bvk6ITl?*1&cJcY>oH4P_o+{NUT`8=O_zf7ANiF9pFF{l0IG9F+9> z#&Qa<)xbLT4)8C?&{R0RK7;Z#Y}=K@X2{Nw7YA>YxZNG`ZWM`4fa^@G@~-fBF`0X- zqh#E%zTdbjqA)bd!`NX%Nd~>g+YryW`?`nzQe*hC_uh!mM|3@9+{#>u* zuL%V0Z=9XKxkVHKKZJ`d4j)rnjY-oNG zmZ@_D6sTrDSiJ&z$z{{$7${mP z%Sh@)rmSz;cL!+ngMazi8yZ-`RYcxLr&2Zeq%T(!A&MHzr zs)7$eZ}6v3zVPE(4fSfgNyHp$Q91JStA!WiJ^;krSPl}gH2Z*pg!sAT??jZ_6vYWF zg6L?rX`2%1vM1+_`^)#xU%t9bTry~~SVQg8{I?(yWC+3G^3Qi~fu>9Vm;>8*_>#ZwGfK8;tmNhL`F8}uM4k(T5X z$)ERt(%RD-GF_EX@$9MAM2E^4ubXZh3(tKa6RG?-?Yt7Vxb>L1j5Z5hS3|NWrC+q~ zUxG4kp_JE0gZHBwx@3*Dq(q0b2a@j7-NT!84<6_U1zFfdSJ$2Vh0YiyGP~(k zTkeVQHiznsd{9q(vfo-h)pFl=x5hgv{0f4Pk*8hUY8054eXRnIyheaTCxF%eK{%{S z(h?#kB|5@So%^&#yK0@!$?a1(OIXA@$XGxMmdvMEjdF}zBS{u)+g5f!C_?mr-BLCb z`DY%6`!X-DFS)7LRKGDeYJqa}K~J#Vk**u;-&SlgytXPtAD-6f`FtCASHsJ zZRM{i?*^1VBH787-j$7CwP7Ags$K|EX?a^^Q?a+`oS}Tt0fv3nSNg3xb`SvPirV$` zfNYKxnPXJLC+klO5|KM^FZ{4z3S1iv?oF9rzj?mukJjJbeEjvLw$^-&Px}YPxBD94 zL=srCeB%`0wEjL_lu-F5b6dD>InY~19ZVcQw`0|QYWzf~;7kW`&SO&5&Uymmf9-E% z>Kp=RD^zn7l4g-ih0=S}1viv2sY+2RxXil;5Bv%@l*)OU;GQW?uZc%_FioObzsTi+HZZuhIy1;pvKW6qsq=!Vme;gWae*Gt{W;(oA(!Fi~8gqw@ zYrs>ub^IQGaJQ5siWKn_Jy?96vM@xSJ&!A$x>U7E#?`Hl3}D=4-SB*b77i4V8qQ>7 zc`7N_?=%@FI@#ZU)jNFP`TddXSSe4t)-AFY{w(cD1JlXcs{;ry0obr0b4GB|l(Y9Z>C60M~}N-iB+)68mKy z?qK`Ny=?lvbC-;t9gol<>$=WK_lb>GV2eO<=Ta1e@@B*8o4_ME*FY+1;HliOE$G>> zPU<|X8`5jk`A%NaXXO1|n1|d0+SwI(gPJV(rWDD$X_v#V7Fc|=DO#iwDKifC&|->u zeZ5@o5>5-@!$NdbV67Nkn=cZ^;u`3chvo5FH9T%V5zVnH56pAM3m>u_XvRd)u9${m1M;_;m+>5r18BtcDz}#0@WG*#Wm5|Bz zLFq@IKCVi1N$H5Cd_dD-vP@V{isd+|vuxG+-*faa7t~eGJm1rp7-8gL{XNBkRany{ znDwmH#%*V=hfNPFY}&_p!%^9Z@4h=fkXBW6O#_o-nqUN>g5|*PFh=~9E=W0MxJ7vh zfc)SA1~o}n#_U#9XU}cr7z|g?lh^@yem=p|U6-pog9qq~NBg(H%Cth?dbtNvmX~aG zo~=6|)*mkG!mS?P*xOzjGheD%fih+&QuZ+vFl)2b2!G53kSJe~FHe$)m`C#@F;TD) zA*JA2yhSWe5lM^h`uv*X+Y9Pujc?J-(s53gI{${;WIHw~km_W+Jfwnyk z60E_D)Wwt)c$Wm;LqgZsr&5mx3+yE!#zJF?5%D~3fXbxW?jKnZIQ}b#G%?)>P<3u3A}^Y^HF&eEmUo1pH*Liq=_UiqkX0w$hCXOQ|eu&PvuhQmIOxtoXJQw8Yrp&kXh%5FJf#q{I6{$+9y%z=agn^{-U_qsmxH>o(ido`c40cqZrR zv96lC)MX7O3!Fz>8vEB?Vv(wqAQE}@Zcx8z$4R*LST}09y}X@S@~PVSpqz>s5b^nz z$j6#;o(_is_7#I;GeXs=a>*B@4aAV7)G;2cqYOv#QzICctksu*zR@;ZPFxr?davf4 zm!u{~6nJ;U$l&$S5O0t1yHg7{Y5{@oBO+$tsoV*M9fXkusK3gZP08G5vEu1tAu?4* zT1@9BQ>@s#J8XVCRo=$Og5~*T#Xd<9L+_b-=`ytet+{H|?HADfV?zRqw)c^tdl`?2 zzw>*9z$sVl<8(^O@@tvBqIw8E=uEAam{K(I6UGJFy{MLQeX}LZiv8Kt&#UHvYZ70Ex*UT6X$gDx zO0>Pv#J#_^@*~9ruqITF9#AZImStY~In3-^#3Qrbs?+J4drN-llz26VMT|4{UJAGb5f_?z; z$9k`)5KRCLoOF4ZcCnj%Y!-v+!gS_1x%iG?+Uy;(U47I}@1Fw(0Hw2Bj zK@5{R*w*RDpWiwl0D;J@)0>4Dx@Yw>KNp>=$;2*)RuD0KqZSB zFM{1=d5J*ZdplFPjYI^=AvS0LESARe#)Ns;Nzi{Pf<7yV1gAEU(%zx@1-?DImU?fv zE*qNo8KW}7JgVD!#_pbKS))0j7fW4E*#Ol92?MEdbOS5~&Z(mU@#gp>=!&F=c^08m z&(10Xl@WFlv5zbDb=xMqvA43_X`P%Ax_TXX5i5Em$Rdh%Q&OU1m#EVy<<9_ z{UNmg7d>%Yogp0Rfuwh-=mokd^vP$d7Dg>sdV_x1!C)Kz1PU)`v%&wp4JB}Dfx0s8 zF6M>K+H#AT?qQESy_p@3n5ZZ8(JWq4*mkPniEF1k+rqmBnJ z1-3&Ji#{*3DBr=jw`*r8MP}*Y^&o4)_UD^NHPOfFtKcfQkcD?cu&=P!UwIvl9~@g% z$c|9QVZ;-v^^6K$N{NE2P&o#9R$QM-s#@;M7co4@hpGCR_10%)P|D*Gu3UGowcWZj zTD^{L&fRH7ore0(Fi$%IT6z>CB8}s^utF+K6Hqa$mZC{_qG_<7PU7J=}D?)d( zNWQuNK6n@@F%@2_GRtAum!$;;JA@qRnS2))n%B$l-10&vo&a;Z3vq35z|53UC5Y*{CXezlk(+bRUfG z>>N?h5~e&drhByiI3Nx*x_!d>kDYMtc=1lFt;Bbuz`kx5_hdFo;Qhq;;Nt1()x8$9R&_m#&@@@5@F_eyFj^2g2ZOZtMc_zBo9xx2?+4|jT1 z=bIb8!pgGF(6A%F`|KmO03TotA2V=~4PuK2l}?Gu5cM6lOI|PL+B%Lo%gOUG7EC`6 zaCDdx5eeVbcBi<*DO5(*91*PReE6Vho&5OpLtY_9X|Fn0s9j}y9}3(hFNl0Wc1JvJ zX>svCAlO}aNk{}qb0&B_wTwJoKppQ>twMRy{v0^m9fbzOu^<*LN%Avnc^6|Rami>J zn0p;@toO!?K=^P&|9j$sMt-n2F9{InZn88Q&{w4~W$xx1hBQCWWuR%>Fp?uJ6UwOx zLTyO;NLUJq$glVf7Av22R{6k0*;`%`W(>L$1(j!Rs=3Ds--lQw;?`c6bLO!QnkCol*K@IX$7Z?j`$JLV7R!}fpo#iKvt>y z&U~E+Cp}K7Z7_a%J^P(fc_?w*AtV3n`l;!MIkug-_l_O&>!Uf{A^`=%6Ju-8{-b8X7Lp0ABS$8oD~a8ba5)jlGS8H3v>s2ou95io&Q%u+8W%GS(Qq9@4D} z56+hiclNxv=!rO&J-$QlroRsEUjvu+_I8g>pGkdUy&y~>N~C)87<^I7lD%Zc&4Cw2wKX_zH^;NwB~$nCt5Y)y(Y+?d26V<5|s zKA#0#h`ptiZMb=Gg?V2IAUC@MR+o8OP#6KMW;;+xre{62eE!S<2LfHb*izer(RGVp2I5iVmUb) z6$Yf|3|lPuu3(|oD{x@<6JJ@%%g4K6E9Dswz*Y3zA65QE2Rg8>F6$v!j1uKIeqv3lyux$g-_}jKpx-nYT)3)`kn6SLlhVjke8@qXjTOtX>g}^vwLp1`yB6T?w zY_6m1QD=Q71oO=CI%=u%`rM2xNu5w5XllABGnHTEcsET;gs)tLG8#xkwvSX|?iIAD z7yWUtewvibU(xR5eBwlYA9}_oX=S?=VR{PJo^j0hnM#YUsz`)Cz#Df%Amv*%A2>8; z#MJo2JTj z9;W@Zy0!%BF+etztA7@Puv*#Rm|@N+R|QtNW}kw+3S?sG)JKcCoV7q0(xGxd&&h$3 zDU{jZ-H?CJch>`!7R_P{+<1wzMEGjM`U$n4uffqOA+o=%$f}DO;NiHltgV{zNSz5u z)4^iIeI|VG4*0Xg@nsd>(7ZKs8BwlEpC@l4wzgYyhZlGYY)>hJZ6?Hk_qM z4fFJ5c$}+uIE@_1mv36t$4z0ohDYV>lI!|S9lNIamf!1x&kI$#z)&auI+84h7&%A74IyS_VSETUeeAnIK_78K1~DFBpv!^Us8fjXs$k9sY9x!T&U6P~>nkXBXq_Ef2=}$B(pz^2g|^ z+4u`8Oru|*ff(m56v}5iwQN|)JJRXoa^Fn2m{r^$*pSgR_FOJb@>}+6MQNwg!59nu z6OVjd_O#i&aHc-4vS-ND*2~Ju3D^&40oWQV)rEp}90|u53^BbQP@zTaRjNIxF|DM< zNhd}|dKFhIs-ft^Z_5*G74zI>FYIgm)}o)}_eym)d?tL0cqYq)kiOq&^tEC}SC{_C z!sq76PYBcW0T2i&#^>iCm9nm6podMwb$lP7J|fPh*7p&#g}#`L`T}mi(yEVga2-2k z)@x2}@HVawasnM*N^AFQp|hBWTPC+??wUnkzlCNN%gN_7NdTY%TOj~=l+w(xUa5I2 z>Lvw+C$-pit>ialmtT&0({+Z*vH}K^Ce2s@8DCE_4MH~gj!xHjt@>!|yZb%Ob}I7+ zy&H0Fg91Ef_A=O4(m+lYXraFTh(V)6l!!b#gyM_US?o6RdCnW7EnWvwkC_s@ z|00^7l(M8D^jFU4LgoYGLX7#}OJI$(Y$Bm{AKN zt|q^_p|nRksN>;4BpV`@+sCIX6A`zun!6#?d7;$6@iX*Pz(3`Kq@^;O8N5YJC@Sj@Xb0BQt0atz|+zcRa z5;?!o4TKD83THN=SE{1pO&nwOHFo3)c|n9&4<*+MElNmSrC>RHf7m;;on!SYVw_mD zPIk^(Pd4e3=Dyo>X)+Z4Hn{NKE~ia?+jI#r{#!|nWXu!@N1bj&Ed!J+&g(}1?1 zhVW;Pc)xhjTUGwCuMaI&rgyATooqEed&;Np2)@hWNYvTf>(5WE51K_s9UG>7HET$) z2i53k7}pz?jQbYRgFP2!_&g0LZ*^K%@UDNSkbNm^qS8czJNR+MMgAYDTS>2q{ssxP zKDq*N%y+vj!4cdua*qav&|@X7b9v20cjq_0)pnjf7qFF@N9(Sz)EXOy7tPvu0=0(A zR%mVYhwUz2%R$n9%}d6+);TAJo61JAfY>g+$-L<$Ti#lBm10c z>#+1R-g$XcJhgetr8QcUpx*>UWB6avf9> zUz(7gbfVMg!~+Sd-wfcXG|GzW>#L3euXX`{zS9LrGvt0N`AS8*=9H&$xB6iil>u}Z zZKnM5*jM@GAe}N@zBdz&lMXiYI{W$bLR`)!xGXb*Tb2U|0ZRYjFd~-#-*Q&+YwXE2ZZa@i!p4urQpNTR-~{($`f@xXLd#-LCFLKS6-lMNprUnzVeg^U@ zU;woiLoMOpp@15YWvTB|KULh)#1{(DuXFHJ9=6C0XnDHE_kSk5=pb;auodNK5d&_l z&XAbfk~J9AB~rK{-MFskpe!u&;Sf(xfgLY<3=-6QS@ydSyZi?XrNe^qb3GvVe4ygl zhsyyUQa^1ZuIA2qqni;L4sfe2OmjmwvLo}(Msdt5(5?rVa|^{hBzsQkzU1tFpT4!B zjDcg(m-g>&>!!25$$6TxMiJUwO)Z-K(-4A8F+L=f0tQ+!=B#pI0pggBss^Cs3Tiz+ zAyu{mIdW5`h__gcY~Y4D1xxvQ;8(V*R+r`%lsx-bWiKyUagMu^Tl~7oItN#3*=T&E zW3IqIo*n&}aOXM#WRMH!mxO2^frJ=JF#SWfMK=Lp ztsZRzdk83P>zXxyFYF6|i-m9~mmLTgN8^Fz=nt_PpFR^d0dw@OR_eyi&`hEY! z!$`P&7d8d9(h6Y8E;vIiyHPQyxkhfFV_QLCt*7-f@MhMfu}$iE zDIq%YlOFA@;?;jO7cy=+%{lbHtYs67>ks3OPmd6&@^wPgvP->~4?@!DcUZt@LcIU$CR@y2$DAerr?fqKS31luRiradr~Y^98O~ zbN%Gy9P@YaMJqE+Vm@%oRwi-r-u?t()=k_gNW~Imq1GRxdTw6`Urhba1Ro z6@qOnLF-i;uoG}%137WZepc=1A-Mic6NnTZRoU2cZ-Ejd(bqt11CC0%Q}SzBMdnsy zNBZ56;o$JlD5WJMeD+I?iI{)iR2tYVP7mCq`VI{D1qiP}-D3X`hzR63qzjZ40P6;7 z&*|EMye~X`kCpE7>rp-beW1Gvulohw{>SA!b#1}b9*wWHCeFfK<6WIgoQumsaNjTrdA2{#9P57zh@A`7D0(xU1tX17e<)FY9)Q+-_F zetyxb;LXo%r~5@GH73kwwA;tP>AHaTSrAa(z>Mv*!sm^u+%az$ig)rV8nQ4&Z{K47 zsJ>YeN|fs*=h596d1#|st1ZotQj`bi`_jwS2WgKwjdZ_jZI!QyWSCR;UzYz)AUXi} zpEaXL8=gxqW#TKX#@fIg;7TCDA8EiTQ7>zn0r+(n)mhM|d$)+MXbBcyAy$_uW~f1f z-)0ml!mN9K=aZ8V^T$0!rT%%5?pYz|Zgk**I+q-$`JQP4eR}PN*fL*&yoo}mC=mK)d+30iCcGf_h zL*!3YUD*CxsE?P$tY+*R*|-BEiR6R0rBF6QwRJ63mbuPvw7d}G)QE9wtAt(IGGNlJ zH4i%|i_kj{7T#V5fa z0lplLe0guW3tN?K1-IU(Tcz1dK2quQJ!bfbOV%&j{t~FFfr-n)YpD|qVW|+G#RmS= z;B8>QcQ91*J`-9V;+?=EX~W>c$c_hg$Amuy5Z8`hRbXADRy7JdddX*kQ=|yOB-h_{+~a3s;KAHNbu;ze}9Nr z?eJwRJe>5~-+ue=g9HXL?gey09~5B&@jzO_ zPeYKkP!Z8X;Qcv?N|g_=hWW0}s~WMxAUAna7Im-(6QJQ;}3r^qy?(XRU93 zy%HKR#6H%qiJU6j{6a~Z*Q8t0wOB)S@XwP>YRbpVL0?T#gYZe_SiEW_YlqiFqxz9B zjDC@%W6NLo+q~9L8}xWb@9x&guaZ;xzuHjce;@U!v#X7o--#Otk6+yJp;|*_c8Aka z;T8`um=^)b!R-dt!PGMabA)-)7;!2{I^i4mjFK%tbP=PrPFOqE@`}ah-=(y6%3D=( za=ovg$-@cpybX$P6r9=+ov_e z981i_d$VZgom`3I9l&kwE^MGKT8Zp=!a6dg^oKL+nA+&xu9`siwj=9&ImBd(WnGc$ z6#8kQk!LSW|M=>aTi){k{ax=lEh}PYoLArkVGBoVJyZrzjUU*8#q`Hob%A&dLaOI4 zMctH{=p1Ij^)UN9YcZbiFfct1vgVB?*7|jFj zTeYcDsaTsl4xscLU^6cOx1ZvqWm5s1Vg+Y2dSf8JA#L4`O}>7pmb5gXSUPV57Wlx` z?Dy}NLGw{h`LmZiGO zKL{t(YfWWQ=VSZYm6N2J{4G(cXLB`f5l3!F-)HxD*3#m$eA0^Yu&?1A*}w0YU&>2} zsQhu$%Z=Yz5^%ODVFHvY(EQx?Z_ihZE(b%uXpheq0+&u7vw3Ra{u+Pv6WZoh%Dj@k z>&8If_~9R)tXP`i*@k%n)!tJ5w^z=u0fIKKzYE&f43#^WJ>(Dd0CoZt_G%nAfY*tj zg=~iOg~35saDHG;2ir?VG<21j2fR%`44=xElV+ibA_rj-+mJKmSrjf+==*{6)+?pf zhsrYc7T#0e(i|brMlEY3y6ojLAs|4AY-`yJRxzuo*l<%O)<#`wD_k$f$;7%trXD3{ zqEB(}1oeDxr!)<_>Cafa&&S)_r*XmlJNMU~-)asJ$lx?YYxoj2or$3Gg>7Y<=MYG^ z@FNc0Byi4RfRVp&6bGK9F=ahVIFOeE4>kz(1Z4J(wz;W@eWS2=u#wB97w;`c+;{ap zaVIBB;9G)KY=Yq4EhQZ=ePYL7w z3{h8jaBo#bd&7CzjdK~92Rq5w;}|}g?%T0pMlMoZ7xi4X$}@WfLg5#VM*ZO9-TRte zWmksOX(%H8r3V8w3z1P=8#rdOU#stdRO|c!kUZXPDa!<7Po>zInxch`7R#B7()_(G zOyPG|WY+V5%N97=d4z{p!~Jo0gYEFcCD2gk!cRBeNGxN41fJ-qZm|%q>w-cZM9c=ceJ$ zjB@UK5AU)_&J8h+`|Sr}hY+=5Vy1?$r7TcMssm*Z=yfDCh-TJ1bI0O~6GiTQ;kCTk z6RD-$R^3j!fV^@@ts0hd?=v zg%}lPiinB*OG=IWEMQtJ+dc=S)%MsvdefL66m6b+`6lDtrp+%Ap9krGh@JlU=vYaJ z`b%1=^|pK*V4vAf0d>sn8RERA&l3g-FAJYUjT;wXhE?jD0!vntv|d;nbBdZo1u7{= zU9a_FB|!VCD_C)q1=aUNzPxhx;gtazQ4~<{$~9+r&hiY#yxd#FQYtV2A{hNctudK)9rN!lhDQ^NOnvP(JsOD>u>cd4jBlGy^2QDKSwxGo}5GSojig+9P`sQ&?-BBf-K=C{c_W2;WzXBC3* z>o0P#vAdL;ATU4@8=Rx6`>lYF`T%nPsk^@beciW!`VKeB$sKap-&T^^XQQd~!2lE$ z=1~&=gV#-G9|ZmedElD&dXgDM2T18f#Du%TOwl9kAQ~rU?ynn@;g8( zvDD+BR`+J88$3wAQYrzA*EL`x37neGgo%?NWKG2_qiTe>{~7@H6A0?K&xE1ppi&Nm z?NG!)Si=lvU!bAV0zN@H4)6$?CYcLb$Xo(g`u`02|I?Kw#ZuwZTx?N>1W2II!e%lt zW*||nKu=gTT1SDBud|~cfP;bS1C?%g0l3SFp3=r~Le>jFin5t`!JH*+plBLS)ZZoB zbf1pqAA1B3D#xA;f_p*5SR~@|ycG+OS6TkdFA>i1W*PPWKK)vKqdwcR?ags1sT-(z&r7tZflNY> zWIjHdy$Pn)k`ujW8MaoL!75QSJ$}OMte533#mOhFMdPg>4?X*E)z{rqpxRMT@H(ub zoxI_p@4H*XgMUIz;#_qObcz^D1?BOQDU0wH5Rk62NBpa;9}II=mbS3BXFfU>)W535 z??|hYhpgzFTUDErn~c6FxaoA{oIIiI8GUz$thh?>*j@Zs;@A6`o=9MtlY5lzv(l3OWr*Le z4?@NR8NmTc5re^8yww8Pss$KkC(_4u(;0$X^NR@?%-akqW@voS8n;)?#eWx;;*X_N zBX$IOyr;2_8lSnj58H&6O8F+}l+3t+o>;s`v9dr$OciQ7?U!CSHtJvL zYay5QGg6JO^u3-{4%k2q&hOMGfvHZBh?%rYpYV*$5Q^J^k>pW-jZ-VxZ=j) znT(cG%!G6H7?af+BYGCl3 z_}rqjCuh%eo@w^>X`o)vVPz~yFYik;j6O5I)#yu1tNq`|Uef(DVCQXtTh&PgQr3$- z`Ivi^v&sj5*<)M}X)x6-h*q-o1o5JuO?%doq{CN2-;W7w8$L9=d|Pt%Sgf~fpXT(F zKexz#w`}Tvr@$)c(ExfTeS)rlPx_^g%-jb<#e2-!JTZB*~O@;J1oOpWfF5Xm9@_BrwtGtc23D(2>B%AI9Jzy{G{Ezt0j16(7eV816L4d443^Wpu)wiLV8mJ6J7HMa@pg{4f zb+uN?AoY#X>{G3iB*T!5{*~}rMz+N>cJGKcCHHO<($<)}Z2#%JMub|EX^>eu}rcj0zAzB2-QuD?~&fyqIeto`;=+DYs>L9XVz0mE!qmipjDL%y=MX zL%)~hj;-6T7 z%6sZmTj9cC(!9$>Kgh|+!a3Gf4kf0{cqX%|Ao5ieDSyPM-wOU7NxI>MZjzH1_zq3~ zI4oGu`S2D2&xQPMIs=$gXd!64dh37Y$Nb-q8lnnex&mF(U#zm?ysQWuD^)oQa^&=0 zNZFl^8*0^%=c3>4iWwm5q30UxTUhRN^nBonQ?=8*o`TH%%-L+)tM+A;l}P8ktcL5# z-`FM(T?kskbWFbq*Y3Lm)ol7qIIg$|4rr{e!$)~QdpNceodN~zPX5H=4p1)@eZLZM z>weh0M$qbHXusPXT@(V$vnBqaTHCjW6M z-qnmz)lZ=l>HvHRRI`g3Kz{=KvjtV|IlkRPKVsj(lEe*xoz|SC42PS|9u8!K;qpZi zVQi#x1Ds1#u(NtqvXxPQ z-UPRGya{u`Do#TGzh@4Zq7sa6VSUhzUGxmFlF)=F0hr<%QwF_f{9&cJY^o z?$n%eTB-#82VdwCr}&fK{NI0;|2f9vmqsSkWs%cW7UOt+D=C8t9}=SL$TOWEXIG%E zR>_>@l3uhIAT_DkszuxHSiE{Z*#5#_Nic7cp?6ZXC%EkB{i-QFMI{M5rOOw ztwY6GV)yokPFv2cs(~|8gff%LP|X^Pd4UW?BFC_*orxW`ovITq4k?r!Cyw<0^EM-X z{v6NlU9kVcpq48dLQEj7d3wwXiW$OqPe__)CZ_)+! ziF>c>Qw!uzD^NPJz0D&&EK-t)FYi=Xj7T-7b=B9X(p=%A{PD`X?mi&sD`^ywlDzBN zzgnL?D~5sVGgBNmZ<{vcz@mD1h~ikb^R*K_6t9l4I|~vtqslkMUyY@_17@GPXJQbW zupw|r+)oNLW=q^w!jyV5ltCLF+mc1tA2+szOUKu>l~ZmVzfPb*AIC?#%K2rR{zq@? zc2ZcQaI)bX?09aY#wYw3$BNrVP0%HPPl&TQ&(N1agmE69Fa27#>os?;_NT4j;>rc7 z`rT$q$L3R@>XW_dTlPBi8;1F>6=iKsKJpv$Fs}#SF8s|?4e;nx*RoGCzO;EUX3bvqeB5h?a^q806XT|v0`k3Z>0E%ds*~c9AT(pE5 z27&DG`mdl+;6kr4`t_a<>n3}@{Kid}I;xI<$bj$1BtV+oAWx%nw4Sr7+3)~RGZlKb zl=vFglqo9$_#(+{)O&D8Y3KV`YHrA%;QZhD++V=i0_H+c!Kt6zJP9CF@%EOg{jz62 zz6^ErhNqHBD$N-#oi?iY?$amk4?A2lHZqOB_S=~kjI+%3i}-qJpfrPcoDPx)pMev$ zni{M=GF9(Dtfd=*3J`YBuD^c+Se5{VK`%?kmC^jpCyJKPgC`FV6HE_RZ7~-USI7*-pnn4q7Qg4%t(6L;7Qz#YiO1bB4Y&yc;z>T2H^%jKE<<>T#3&@VO zt&?Y~sH*)vLD4tWmzE!|Y%i+P&woXKl007G@zt)WCt>p1r zK^rF5On^hB7$=8H357D|MF~vj8Q`6C1E6r=YCtt-r~yoUPCHlyjztjFP+*CzYUh}s z7p#G*RTEhTHw8Pqo>u0oOhzdG7kh6W)zr4;i-M@A2&i-lLR3UhIvX0LN!+>-0U;{V zM#xq+LO_fPNQ97}NH4Gz0R<%@eH(;?&?fY#h)6G>goKSq6G#N&k~H4wu5r$(TUD>> z)*bKNamRS)KgI|Pl9e^*{J!7!Yql{kdw_bh+%Tw7x6M6`oIi#u_@#EBR6l#*`GW{} zE~uk!gFE@*4<49Ek@)71nMtS$gByKiKtP$`nH zceF>kX%$3D-5n!!&eh9MB#A60lY5IK(hB420ty@KIDlt10_;T{bfwam9};~ojLQt+ z?qzv#L~HvYL%{<#(Wb7TDHG4ans^FOT$egHJ_?=?h$aJL3bOyo9e z3;Bp!5kRxni~xN%2f1qdZQccfV6Ebh#Me}FggP?-@kS>-Z53YoV z9q%JffWEMTP*4szqc&I|U(ATrxrqy9tk+ckLxq^LbECn4jHdrN*(C2btCf49_mmgI zuC#m}>%ND5E~mld-vnAK_`1BSRlhRnSt&`rPzG_VrfhCBGJ z(1-E$+)7*#VT*7pq|YKLfy@m2dXzEAh8uEc1^XegwZMg^lt&#%|7NC`ky>7$)tJa> zOr?I#*QW@c%OWMkuVLI<-`WiC5R{=eB<@+#9gVF+cn@yZ87RS@Yu*8f)D7!cu={l; zIVHGjhFjc$Ev20KB{ee>sc3ACtA4G)WdJCI12`gy3g`#_bzQ%l6H;vGW>EP11tS&8?7zJZvGjrer~^fk>~cxPvV^t`ATpx!39;I6zBUKHm5Xi) zK=Xkh2OCQUA(QnT8P&D^y!2N0Pt^}@Xt#c#t9=;ttFF5`G+bBF|Kc${hHYGLV;pPj zW?{V9>`KvfiA7+>Er65+Frho3X2}TMtDxk-N!XbGq!d_LriOR%^5N{VO+6h4R@Z6} zla0gtW4*Za*lP{QoRj>)g!A>N+s68s;Icj z(Z9@fQ-p6K{`!G5eOwyM%@EVT5l`am8rTxFybNNGm!EG&Y=d%IJva9n3hgK5w|wzb zcHXF{ zxDVxVs)wT*%z5?^IFbltbZU{>F+*o6@XhDf5YBPWMDl5|K*dcnEg;GB(03 zaCYs)$_r?DEgrIss18X6!R|4(NVj?HrY0W6AK{%HytWXWa%mHXByhCrU7xqDyU-Us zS{Fe1_5hRygCr#ciy{5fYkG4euK)~1ggWxjMQ#4T*JPp2B4h`+3A@Fe;Fvu*{X@bF zFbIFf5b}{=L)8{Sn_!IggG3>xpJvb%P?6vW{v0wk zKyaGyK1FENE3^#ZYEjhH4H`7`@tU{hh~+@>$0X@}SN_Hvy@H&dL(kW8avL8>h^iWX z5#Ya=BC29VQ9^01W~cHfxpPr^hD7Pd2Mh(5?L*6odjg*jSq8%mQlgYnUp7|J-SFVs zIks-S8~l}CgF1U{7Wab$Mm$bX5Yg}eMTgQ`0pT5qjz@10%MtoR06!`6Gj})%Zt}%c zV>j10Jw_jY()-4w?tacLE+gr@Eb`p@Z41N5`Wh}VcK7DKF>B@Ykl+Betd7)sgfAk7 zxRanmc#Gaf-vQ*vgIKO9KY~YWRa=yWP?Kps&)*I5!y+bjTF>tn9E2Er za}Zc0!?`iXZ@`WLa}75fm!0Mpj$ zy8CAP9?0d9{Z&l(CO6uZK02QmYI!9^62<qJu! z@jieN!JF*rmT9NMQR@bl5gXoSz~hY;H@hdADbqY`f{ELhNIe>S7Y|N5Sp9I9Eb|Vt zA{n@A9uvQ3Qb0Hnm(*+)eTSFMZyFTtFB9J6ts73TK$f{efGE*CH2O%@ZpKWGTr}=0 zR!g#3NkpDyB%h*EQ6*!o-}HZ@P-zkiV7~Qx&q%9-DBn1FY)=^D>hzr@h;x9M0f%UFMx^%KH#!CflUyj-vB7M{E=H- z(<+BJ%a*4)^w0PHSxtA#e$X3X9&Yz*FE!5Sb#S=mnL+Q~U>)i+ReRf(zEyi|m%BSS z6N5pWweijs1KG5?+Pk`Qj!Fa9KlW_1-G)($F!}-rFJPSVbA|(I`v2gtfc>4({r3YN za83T=F-RuwylHgxOVaz=hx>kaKJ?1#;U3<@jn;?k_IeM?zWlWDz`TwWh;}gNZx&@T zuw)tG0d5FKmz5aOt}5S5PSn@}txSXkNVki3bMe)51lNgP;+@w;3}lUs?O0JiFo_(Z znyYc(Azdefr`yDlDvQDki3*nA<|me`;F-oO;yqY%>ZXpvLVZl>%&>;$`{hqQ z94Tw?70Ril4=j(VyN-Iu9$w&&s)d0;`Ni-w8+_cFi0h-toggO^(SemGyvrcB_r#cC zJA0HN^RrMCix_D-e&~GwVILIPH0tzeFe#he4QmcWYsVVPt{n~lcZ8M~L zOx-BahI9O=JkZWoBR~L{h0sNmC6)%&W-V(`Lg*|iZa7zpGn|l)q@p~ov4QF(j-u5I zd=)8OGG#|>8U03)JH@-+FAMz1+nByXW@%-mm^zcp;NaqM6v(q{7muN7w0Us!tzG46 zw-RHSl>B;jfK&_csUaM}9htDcS8icA@hPk$JrK79PN+d~s`^S&q<`QI?>y8@mc~%9 z+T65D%9~1o0SQw$8)D)f-n9N3haqssVfm_}#{_M{fTuo)zCg1--{H0}Tl<+nDN+!< zn-|h%|2rhM_O=LcmSH7WJY+JiJsCyY#-Nx zpfil{>4{rvq$R;M=5AVk#IUeiKYIAC>VKkwn#L!3c84)q&exsV7$qtiYB107iwnyg zjkrBLFUyPJ*FjSP_$ai<9}zvKFh(>d@mVIk@?_JN0L{)-WE<)nOI_31WPCes|Il(+ zW|yzlAm={UGRNcHwP6Q)!l$dtqHA5qN{KSTt~nCz-Anf3Xg+KV)l8IZ(3Rf*IIoLU==Q5az2&w(|72g>#oq9lJCvU9{^jO) zgkcMEJz?D4h4W0{fNP!9?m$Gsbwn{jI~F;{nOWJ{g4_f-%sD_*?zgs8LaLX1o8`$) z`ks{5w5{k7f7Q~^Tz;(BfLF}y49T}I7{SR|nteMxcw81Wp~A7cEeOY<_=)|%0r#2X z8PUU_eCRq7fxH=;^$d85aH$&$Hx4#gjmVuk8 z2}p9uL`INc_>F>JAqQ+E96(q1IT_`rBM+=LkGnovm~ULlU6Thhl5LpGDBMcLWV@x(kR1*bfG1RSi<=-8?jF1(pLE0c9T@QEz!Q(l4Nb2}BEQCw}W7;tF_% zA$cnvqDh2hF@*=h(X62wgB5*+a}eIhh&u}1T(B#761*cj**ad=mz=dcThXQH(u>v? z+5|g|H`X$;X1|@U%lf=@wzjUmw&q!r9$p`^<`ztZL)1Mqh>HTtVDh@1n(%De`q&07q?KZ;WqW~l*BxR z13TR(`@Juy(cI3gJm*HKUyQ@c>PoYuGMpx=@w{-%N@dJgEiZa&VAze%7vJrM|J zU7{Bp@bW;r)bsUU_UIoH=u7v1doRfm6N|(QfSG{iay3L)DABnrLdY+TVYMPQ6O+No zf_U@Sb*taS@&6TT5BB44gwlUkSp3UT1c)We&*cE#)rwt%_kwOu5&aE2 zn=8dyY+8&61?_;qY(^O&1@0wN%FlBnYZP=8t=E7Mk+zu zkh={U4RZF;N_H$zi^x|R>eJ538;YXf5_qiWF?bBu2zUH6Q$wnVM-WQ*BVp{4#IQ+b z60oS<0cfyg#yyIDqvMJBA2G>fs94y{Dmx$^K0&P;#M_rKKeqo~YM_6W(3y{!*p9Bi zb}~m3_;HZSBv}Ovyemx#1gemrm8ps+P9SCQ#|H7?xx$mAc9N{nT$D5pG#Sd|T-O;s zzrvs9vf2?_O}|jVWJHtNGMrk!go@K*CBGo5ra7sC!{R~DeGmskj(uZ~NAiHHQWc`D z3$!WBoknGyXY8kd$XV z57Ge*11a+X=iFr1f>YlrFX~rP9)W;bO{kSi zo?Hap2|^D@iznaAR1&M;-VMzzwPYc<(y>N8iV(6*nXj6-kX#5)FPl*@byl%2m|eY< zojbcFcbq^fc12@`AGF@~zp+W;HhR8D;4OYjs{VGz0?9MwJ3+P2g}-wFs;7xdXPL&~ ztylv2EtsJ?mp1tgV>2!p{5yN$d;5$~W6673FZNQ+^_|}hg)6xAQBkrkRs+GZW(zU} z5|bdbaE!^nB`Sj-77sBc>9TVg2L=ec3E*(u7DS3dtLp~?T7`d>T3@M!QzW@&UjuEx7{=iqDD8&Th4K z^g6K|&U$hma31sIZmAHFgs1|ja@T<=DKXK2rQS7Y%s+zNq7Mzb;v7?L%&H9{m}Oj)reLQ?(vct z1px4oz+a&yZYG=7-qj-`9wcpDLB@_+-(5ubBu5|G7s4i{?JWNw=&vcxv?;1Q)Gvw8dK)JN7cJ zaUW^y>Z5ekHfXWK0u0?4{lRvPQqI+tX&u*P1xzVn2+wf7EQCAe1Tpe(2!7@;!{>X$ z)*^fu*ZN-B0>yAM{?>q4-6ZNZFQf&&cIZlc-=s}%1JNSu@Oulb;*VCFt8ek^tmb<) zZNEsS2sH58&@eE;^M-7=nPBVsUI@rps(2Mv*E7RTlKKi#9)&}L_`w2r6~HZBQoe9K z{AAR8Gb|ULu?oqH2IW-!oBGQ7fvzEg#%jICHEs*m5MIIei+~;6EJ?ZnEjTX>6_u}e z*s(*B2)jFZ*8Di00+ilq7M^_H;A&nq*E?@H<O`TnfVbx8f!#R#4G4%67?tQF;?F^ zE?Lu$z>r5_%^KUFFrH&4mQ7Oh9GT17&h<`?UjDRasJ|sWgCbVxE#F(g^@-$AWx923 zDK!lmYA;itTr&v9tn8ATa}zxRbuMBHsJ6F?$W$^2+8bbCNRl|I^AKuc@%}gWKpP+j zgrr?+2Crd-#|p-u;O|vGv=2ikft-U}Miqs(p5f&avM!BQjPi&G88?7Vg3NH~cmTRj zc9LYo8o03z(#Bv9YY)f?EDjZ%ZYu%siCZnPu9WyzmmxT8ZuMQ}?GoIP3xj$A6O{wO z@^YVMhC`|=PGSS~URtT@Nc$IJ+&#(a4QADumx|gk;XXy9?S*b*O+_#s6Q2=M~5{l6xKhO{UYz@iZm*>DK^4G@y zVD*otpImx`nDH;QM9Ob)@I-^C6ia}O zdjd^j+~f^1!28bNrE@=FZk*)Sx4!83wCqbYuG8I>^?7pM46nTEU41EW>X8IDCZ325 zO9lbXJ@*fIJWx8z6(KsqLna@66T^_;d2ENnQanfw)!g>7 z-0_14X257r=Xt+ycd$3x-g(J+c=?&mn$B1vmOLV8h0#JHh!f9L%Q_Q>`H3J@!OjJU zPHOapO2r>>n<14`gT^8Qma)9*Zh=x-l~I<;aQ@v-WlW^g%lJ2o7pQ|P_AvVa33w;z ze194FYS3J!KsWrPql&ft%dFWAWMfG$)$Y)%0a;dAU)$Mc=qz){v0aVKjX^pZO^VSQh0h&SWXI+E|-BJ3W3E8+Eq8$4cM2o_M3 zH_P0b!Bg+Khd&f@Te+;PJ=e|Ja&YX!*qOB^w7y;5mG!<7M-4}h@ZX7mcs^h8=D za0Np3!ngY|DcE*d-HD#&1bvh}Z(pw17)mUAja4RPw`<2x0xqk|4RnWiuVcmv&#an8 zEsrcNL&27Q?@)6_Po*A<>WJ4!5x^db5n-0h*)On}h3oeJ%$_^IB}Mv>n&}Dy4c=vR z>ZJZ@Ox^kX)O^k%_g|gavtPe1utyc6N6N|)hf0F;XND)#J2}RJ)4s$i>-jF89Y3pq z3u`0AXTcyZu6UX)gHvFkqxTIHG@$}yyzcEwRqriK!wu4PYQB~~Tsj}{%X~*dUUQ+J z3h#w$j}nO03+63g<4Kj%_ZXPujo^XL#NL=B-8Bp8K+6ghdAA<;u#gFffu)eXg-0&l zbSNlnZpMhC(y0;%0ySoKkSg=Tmp{$(gZ zpe{VcD~A4<1K7}XJE~~WB4Fad3mn-UB)Ayl8GnnhP%pWyv8Ugt9=Ubqbtz=s>i*Dm z_K%H5L-$bQpCSO?pklb4Ic7L1A4xFqV^ovon^}t^{_UXR=1nfH7wQ9r1VIyn*gC;u zHYe@~$^lqNEG;zp!R>H4Qb_4V5S1F(YLvEZ)+RTfsvMQ$=BJ#tAVI21DiVZ`i+d5( z>LiX8a6k@4%y$)lDL#+TZpLU4o%F1Q63LK(2f__*SOZbl7ZF3e*XM06VUczR%m?`- zpwip;{Of*MF#Bz*5%O}t{d2KeM2GLjp8y^buzR7&LWTZwkW%&+m>gk^E6(s0)XoC_ zJqP_&^+u-?jmZEoZ86=P4qOBKp7YioI)x7?9O=?1$erOrYBr6%3wX!U2*b9;kvV=k zkI1PN93#BX+9V=_nlOe@g=_&G=n3v(`{Iadf77UE-g6nYQX3d_GccP|10db#!rtfb3IV6 zZ>*hA`)SC^jci6sG#nEc`Vyr3GA9h9=v!xqYm6AttNk9h(Ss^T zv=w;vYjN*yeBq~G=7Ij?msWOYpxhuo3$s&_DM^sTtBKNqWADicmw6F)sg<#buoc=g zc9z0TzGJaJK&w3AMQ6#JYD{b}X1Ci^ZCy?MVDKlDBQOP+8%xOibkdR0KyS$MkNfkM z#5g$B(pfIejcVt)(=D)Qz|~fQ!rXZKsFUhmzkvB^j~otmYOukBZPN!rCl3rz7@IM5 z9*N)LjOQLt)(la*3bh7}ZF;rnb#O&oj*+3$XV>+3o>Nw~EiC%suhq1>>uxBXj+G4gt1jrgmj4e2m48(cqzLc+92kqQ z{Dc-lK?MQuhyS-lgRsBr>;AJ!;jh>JYCgXr9{)=hy41ruuGF1ZRA)CCAm!P)w)*9# z$6luAMtk-;+FwmyXE8|2@W*MTZ4skhuXT9St*R&iO-`E5Zxxt>w3!mb75T9vY~=^+ zdPX9%a<7IN4YC9QHiw6niE=1wo|IjHt{cF}Vp^R8^O7h-+}B3cJ|^_Q?mzuuqoa6} zp|cX_M5Pux1h=6AHhMmxh|o#ePS}h;1i7)0i9;E~oK)6gyr*J4PbHSFEtEOcCmvxT zqD_a!)rV6~@htwZDsSHz4dzk()!D@C*^?l<#LOV?Ido5wc#S*;M}A0dLdXb1ROV*{ z#|eEtY;-450hC7t1 zC47JK#sPhPW9dxjMYUb{kIWNgFWs^t5T-CCGnVG61X(GS*VXLnDQNImzvK5iIazAwz5$RTdS=^VD2f_{TqJ(lnY2}uD4?=Gqm zD{0U3iC*N9lvWre6U?Z=GXf}oQxe|?unkLg-rSMNH!Tx`LSCq3E&s z;nDPHe( zg=t+Ht#JHe8GUWqkd3#OpJbdskbi||%pd(Uh~1|V9y z!cX*^v$w$gvXaKdyFUpqM^=T0>dP8O_m{F?3Vw@PSo>U^3AQY6#>gZa*|B(!Nl8zJ z%R{hsggSklE0l5uB!5}E_DlcP`R~I{gmBhFB1-#5;+3w%%bvv?T zNuK@WDQ;(iQG13{e}nZ4%cPgTR|1!jJ>z2$=H?uD>xJqteTR z*`Z>~%W`oB+fHZL`4{f4z4K-vnyr(6KQ}h{xbm03djB61!{5(Jf~M_<1bOLiV}~Up z01zw*SO3pC1rYz0TKd17if^e9KUo%?3grujk3C0_=T?cC@mT)RdE$vs0x9O$C)-ud zl9Bme@K)Wa=m8ym%qL9mHKWD_8JRt%E zZa(Jj=P8n_H$Yw83jUrR@rx_;39Q7J^M9pS!FZby!fl=6sN_T@gbOwlJOAW`|MOS> z@4N#9H24a)5hR6{qI96dOpaw#frc+L+p7tBHwaVOWY0WBgt8Wa7GP~}QYD@inV87$t zz@lS19o;lo{=|YD+X2qDsJaIsb;+62Pa27rB3sT;oE`?2#kM(<7Ak5i^tX3yO=x#X zH9H!*<(X}Yjh5k5B>x%MVm{-E(4Ep*ck6l9rAu7LrkD15s)WYEnNVO#t>v#=A1_n? zJs1~^lz~7GtZdaE^vq!Ohs2o&QybZ+p|4kvQ}lhj&e%gM#l5UIL0>Pfd6a|PdOlUp z+1uTeW^6O$R6$W3%q=>XWA=!QEkk~q`XS+t*Iku@f?FT!nV7bHJf)e0yL&zAi~~Bl zee!13_NGDFk?fdgxqNw(w~dd+6572ET{s98wjc9WRCub*^)3)9Ch%t~2Rh2+0nG5r zLK^a*RY>tDb0+W3r|4en{I#H4$xm0i z5aEh8o~5O0)ib?Tb!nXkLiDok}b zCwRZe`Prt5#3@zRxSA%hEid!Sx`&sqZ*N#^zJEl%B-E?3-cA+$RuZA$8}Zd(Uj2ZlAFAA z23px%T!XRAxwcC$6%XhPJ8F8kY#Qvd_Kot1XX*;1X)aB zG{;K_!L%~+24iXqqsm$oL$DyuilFr4u$txn1z12*7)xvhrP~x1J*q8kW@<229H3jk znOPhGR}s;EdYAz2G~>6$b)$1krC{?$uMWcQyHkMdTGhIKe7eI^FD!7%awh&ZoBAGa z?0-YhXx&yvc{$SNj0!jm9OSoR9ECIm-Yv(L8sEXrcTR_lFJ!4mp6F|1tM+Gf7xul# z%bgp*7r#50Xj^_Tz2}Csf_KBQ6UK)sQ*BoqSF7a`pM`e&PL-U?v$526&pC(QtoV6A zOIR!X4SeJnVt}FQ?6&}J0XV85k-B?Q_JPw_Y{dPQyDW;?mr~zQ=G@Qhx#{iFuw}{6*ltT4~c8U^?v+*;Yljw z!b|vNNkMSZVF(YCj|`5}Z{BCsMb)nYN-N+7Hyl)R zJrDgBsCsc+cz`t-UC5?gm}Pk!Z9$Em&v8b4>MimC429V1D~d1eq?2;#N8jD^y>J61 zFnfIa)S+9APm3;~KcPtdq1tQT#M!N1owd zZ z;*^J{t6Y;uHloN$6_I8T%peZXCc8!G^+}g8-|D;~~X*YJAY0 zOk)9rVFr|YfH;-g1{HwhCs_ed4ldDt+8NjZsKl7qcNy;p+<@1M>WSaS{?ZBNfoCFv zF>?sMA6PU;5wA&F-1$GQ9#b=EGB>Dft8;4mE1{p7Vggem!4RH@h*TNv<7+e>0 ze8%t{f}-zG=yWWFAw^)qs>=)5U0rsZK->3wlCAnz7B}I%Y-(#z-Jaua+rD}9Pb&Am zo6|k>p!ulu3V^lNcL*^cc;q;-SraZRJOeEPI;eFADR#7=Ejh_qm6S}^g_s~>l+g4{`M(xPCwWZV) z!A*kvo%(}3OpZyt&PRJd+2@Z3Z=6i{uGuNKuk0~z?a^C_&J{cM?ssU=)NQHuj>}Q4 zDl*3ymRu_C%dvNNNVH+6_7}2XeCsa?EN7W$p;;OGnyJjj8`3-3hk_1n&-lZ0Y+dUP z=fgNNoS%V9sv$?Oe`9>-<)`5v9W>I;e?(W@&x888ldPWmbOUG+)Y!7XlBBcE)0CH0 zB$vQy+=8BQcN+-aKV%(0Ca^})fnLk9YiFr9old2lEx^AzEenmK(kGALZ>i~beGz%7 z-!Cq_^ksiv9>=eq3d6YPnO*3waw$4z<$tU8_a07`Hv3|7D~HyrmbfUfvUsFJnmv3pZecg|1}0IA%Dyc#@}Br%!!SQN8AC zV9?xZS{N(%+K!3P5pl3{(9)~VNBzz=Uz+PJi_D26>-3#%JKCF0X%BO_y>zzCY-?nJ z%sc!n;&m2Gq{sC<0DZf|72K(KjCYafiC(gB!Y>_a@~XH!WNy~vSQ5`42{)@LzR^0h zDW)P@^{B9V`zV$E(&^13B^^87VzoIK==OglzXGlHq7OeAtIr_ohlbW-x{LtRKbvU$<{$vs>-}L)s1tfJiI9vhMU*@Iu zaN2{nmN9#G1ET;h%?@4p@_DCje9?gi&F95^UB||*WvK>VvQvw(A31QH>=_k$&HwZ@)eLn6%;*FM6bSDei6I#4Ni~?+wOZ&;BX{R63W7 z8Nq!`-Y@$CYJW&r8;g{QPp1Fl{{C_V;t*ouBli2RhV#8(w8>0{tulbmko1D(f27U$ zw}%UH&(Hk3@2FvZ9GGB+bdp7mboJ-*%WI%Ko?0tu16&mc_F>w61J$t>hOAJHjogWg z_PtA)Jk9NR5M0W%_E)RhNZv=I;I2-5EVF$3M@wyp$H$s^@0|?kgwD%q7Y^e5pyF=q z{1?Ym8=dk>KYgp<)Q6vTet7GoC#Rrrzx=x|OUJ3r$=^Bqlw59U-RnZS)8I%jq8r73 zDtaN_Egod30s2uF`&za>GZybtVt>OYzw~QQKIGC`y}*OQT2$B2m6=vt{?khpl(QvT z9~0mO_-n@Ig1Ir3k5i_G3?MrrehB0T3=zG1 z)CeB|)2@vK!yQu=Q9+?uBbp z4hPTOZ+t`5c1}I2jmUjf6Lz2|g?%(3_7E;(N3fptUTU!F>W6pM+ zX1Z-ks(TQtTOT{hjTmO&+0I9{9S@@~6>}%Hh_j+9bpMotLV1 z%DPx9-78V0{-qcWfG3!i2R3;EEmYTqxT3*K%{kZC?bwgb-yK~H`qKDpGZ8O zb%W|t!(C{^7Wt;1e?Fq$LDJo)loG-x*gffcS6Rw1dR~i}tQeU4ihj~pq~%9J_1g57 z?C49e?QW*}lLntSUqTvpRk$T;`CjHO&)xJ~*!Ga>9xxMP`y%xioOi2n*pxP$ANrTy zsU+9uXM*86MW7Z|o#hX~)GdzjNGEz%)G|@BYMo{-EgXLoh^(3oaYyrM{8Q=dIh*xQ zOvvksKYm}m(Dw^Lwe{RX-P-}B`B`*F%gN2;m;*XjD1oX*p9e6PS$9fYHah1Na4esh z@$e6eU*vToC%^3*@ZL^?J$rYQWbo>9&g1^hzJmRywzQp;KA*3eJ0(Xr?VKh7#yF?BEX;6PRVqs+Ec^L(nU<9*h71>3XFj#<^bJCfjVI02KN zaczd=w&{-&2PMoq4miu&X=KY+#{pZhDp-f7<-QQOL_zG?aZ4~%H z)|20Wq{UX;6Q{9#7;)vVUhpZe5XB+XL1ZRtl~kDXF?GW1&x z+-zr0Z&(_5q~z9L;1IQ4FvwH#QN3_^_{ir+n)+2|CgoE_?vIKF0c=CnvXi>g8g}gR zp(FQper6XtJOxFMQn!1fO~*5%!G%8`d{1E`A%mV~vZUX*CRZAq>kNJ}$j@8cfdAz^ zUV)8>tn$^+7!dw~Etu0kfQS#`I64gP>sztYbsIZfNvXO&*3H%>D?*;g&32`j(8P|S zOFX59^Ia9Gx|a?;F$s)*%Z2J({YHX{&Zc^AN^itD7(dnCPPf`lRY8rtPnC9lH0_-J zdXT3e8T0IniSB`J-z$nYE^t?_8>H@cI#(3T$uV|$c-FpUzo$V-8K6hpt7Qo?k{g|x zep5dg@#b7b>#oCxHYeUaTq^0Q&0kc{MS;$HQV5Z3Dz~d!KkF?T>)AEmJ9mi-`ZE_ zVGWCodb?&Eoz%%IN8jnWDTbxVAI>s_#TP_JVOV~bDsDKEG>aUnwH$GeJ8mVLs4Dr= zaK*DXrqa8-j#f!UzB}lq+3J-S*WnViVK7S-hc~)i@M?M!^}EKtt(oVhTU&xM>zo{I z4~x{uFX6fW05#>8n!uY#CB7MFR&|OZ=~Bem44%r*5yn~R73P1z-6Pl&n}d)-KP(^2 zLo0(>U~0d*AHMM?;j`+v#%s{DJSM(TBCH3?cWY@RHKRQ?AhCyIuf0(C{ZK#FzLB4hI08rc4lBz_AAkS& zjqr{YaUGPPS}~cV<8-^0L4CRH;+WtV)y$-E5$1IOUxw)lD1QL*QkkbhYuv{rAx8_C z?u#0Pex9i;oqBTgY^U~%i(P6Cby;L)T^MY~$hgPMw}ay!JT8uSq7Y94LNFH9!v{~p z=l|%Dvet8`HTT$l@U>uM58XuJ*|AeWQ#uX?yhnQ{b?7|5ZiJDTBR}SUE+;n6Yi&WI*+&~cx>r@xDy`>fQNiJ8u%qAIEA(p^q5{+YdgPd5jvwvoN0HT49qzdx!c_@Y_~0) zGRaxFn)kI}->6M>AN}dOp?XAIAYNHUa(QmT{pd~&m36kB8z=p2(-h>b788hGRW$yHUXB1SiUDs)&3)DdMl;SG+T)11#7$=_jZ@B=^yZuU z-a547<=0q7wPDa7rb0S4mGn4|&^&=ZV3%}BN4pET|E-T(`6JTc1eu;S8st*qOdUfc zz_SLgQySKmsV=~Ww{}<@vtHNDvpDa%`t|JG+lmV}lC24+-woftLcC%u`hyr}{eQ9$ zpLZ0?NZ%+PBQ}GO#@j|-It|zj(B+K{&)dOLxF*(w4i9^*HH4q*-8b;-$PbA$_!aj0 zX>K36b~ueLjKA)-q%iD}k0xV`TWUM27)P>g%(1WaoHh)6 zH@oKI;rtA_^ycSOk-$hZ58HZw_$zEh6x82OMv>ln2)_ZqrV)%3X$X77<(?5QeyOOo zL8VZ*w;!&9#v??@Vny6j2vn5P@#5W3JYPN%CP$sjXBzXX@_j>0t4D9;O&Yz&uApA) z>*x1hou6OKYvgHAv)yJNpf85gWPf-2rg*6!BH9e+px)%NI&Qf2K3Qj~#;hSFu*Bhh zZnlMO&ViI02?ZNYIXKOojj}o>y7o(okA+oC)~2Jimntok(538>%f;Ql9i$%9>OSiD zdFolPgJb%EKkr|tEgsC33c?$gM;;>N+xcNu^nR2ht$#YxJ$i_F#ttS61=?|i8SkE^tA1K6Yy1A$I`UN^ z7rWWkwNy#Zw*87*9*Ru9{2Tv8x}nj|$@Q~^Eg6ZbMqifl%u<%2grjc`)>>*PvA!b} z?iHZtj?TB_C#b|Gk`^eo=K}w{_Tt>#!~!%k~h2;l*u4pEx&y>)dR8Q|&8p zdmmo^9-YCZ0ibt4ud@J5qHSQAxZD)hM{_@Zcg5J;4~c^{QzBxMIT1Rb3?k?O^;{Le z>hUzdP4#kuP~0%Fl2ZQjt4wq~l%-uCiNlhqu$q8koOFhrfzL)I~UKYeGf~!~6WxDKldqZL`4W zr>RBm2c8umwD-Kb@zJ>Xe^B<`QB7{)y00#mA_zvM7m12W2PvUL)=~ip0up+Sh)5HV zCIKQ@DnCGm~O*3N3rJJrF8~t#(fb$3%b=QcqiUjj{zw}hS0CEJ_duL5CSdW zIb;?%Axk{H%ads)!;zw8#r=0|^`4%ub}d5`9a&Nhr) zHfrtRyTPg7m3+E$T&XUBTlyK@TSr`-dz}@LCJE21!NsII>T_M7U$lKQQp)L)j_}qW zD;A&_ziopb`b~AQxuid_rxwMa9)quELRtam@(sV~t$ha`Qwmw3^b?W7V`$$z(PWtK zHDg`5R3Pk@J%NyuxdxCk`m7>tgnpp45(c& z4lea>s2d^p-c|`4^yU~kX&ory59}Uv)h8#uURLwp(wp0rCPEZmIY_c8(u&;mj zemoYa8SwBcwQIQV);12Jp+VNomGMfhOur{Hpi;V-MuMBum4gfR#*qyzPVbhensgHj z8SFaO(uH#363T#NLyW`@6{=80~ywTpT8uuHbMLxM?QOc=PA}Ude^LMf_7oD4pZ$}9MXPbWxwp-6u&#sOw z7BPVkZjnP70Z+RW*x?{dFbz*f*E4u1$uWzURFB`0DrxNZG{aUlggO}CWJ8)5fdFHp zE;B$1gw3&AWQ0462K&f97x(35a#e@DivEEHJIT0?&6mbFcb5;ydKr(4YfA!CaaXeY%1Ut>+{~C1j z-=Vhub5`{~zWRS(EJ4ee>~qD(*Sxa~ldJFmNc6~Za)F=bi}}bfBNM0FMhG!Xn}S*W zLIC!dm6=f=V@wl|I+IIUtiE@;Is>0?J2N+b4s&7ci~8_0uo(OC`T9CH_3hTHbd$`J#ru<^ZL$Cd0bU*N&A4{40Jv^6ce2$@23p28wvgIw!! zojb!0gN|4+f~HwV%|4^d)XdoyF;;06k0AXt&?edpRgbKWZ89Y9Bt1t6l5?ky@oH31s8o3NufWCC?PLXwy(4bp9e5HM1N=Tn3JxI+qSU5iwT1+*>?nR zAXgFpf>)n@Hu#j}9JY1OJL@qmmMh&!!k9?AB<(dGVxB5dqxFtlH}VXDW1{=U?Zz(a z_VG^lckd|DWWK!150?A$1x@`E@BSQ^w1`Z8!?}4T{BZ4W-I$2waQ8Bl877xdIy)M& z7GZIS-T=C9uh@G>K-=Nf<%sWLi*0_(0!KpbO zqw4pM(hPMtDTyv}J6l)Nd@}D2sp{I#FYwr@{d2;WakWh&0Vm(#FW_Qe`Bk%DE9eW~ zs-Q^P?v(LN!-z?szH3R5<*ST+50?$YEC`vx)@A81-M;z9@Ga{JKcg!MHQ`^N;NW&=I46k{#T-aVrCh}Mk5;$f&``p^8c~T~0<1Y8Tx_rn z%FxVaKL|b!0Zi|WR2x7zg;?r15%CD!TDQ3S1~Fa0CKAM<2N6u;51_fQ|D4$>Z37Uo z4b8%u#>pUnJo)C*pL#fV?%~weHTMeB9~)eG#rNu&P4c@3XA-N&t2bo>Jp=th{I2u` z&fZULz0xh5WE*d=bRpEbEC0H3(eEs+qvPWPv5TD`iN%DW6X-$4^Zf&+!TBNXM0C3d zN94YfS$m80q-rt`GDN=;V?GhgLc=S8qzp;38mB|SnY_}XUOyKX_uo*XPEKZgN{amw zMVcQ#sth|I7vwj_@&|8VI4w`BC8>Adxf#yu;fj|SF(g8}87Fd9pL#G}VW#?JBP%od zz{y|~=I`eRnR(G*d$-0sd#ZM(qUW2?;(4eSW;&H}9!I_`NKywfqqWJtc#?1wAx@QW z0zl%a#~*+|y-k4Vf;ZgcloKJZmAlU;vR0`}aHb$*Oxv+T?%v7GiLmY1B4c_ukE?M@ zU8~=+BGw-(y?@UU?%%SDiDSL)pPY>0qxQEN1@nYQ< z_H0WE7c?3`>APjQCw5-tr2Tq^3Xctsv@d1Lvqy|(X6m6S-F4jk9NN!Iac>#rnMme)MO+6U$=vBe_l$xDM#wx~CC2z9s zIE+0le?pzej-b7lm-|?C+?Smg@D#*7LTc)b@mf*UZFV%33EIn;NN|C} za`;71l{p1rw=$aEF8?CX(^&=3htOE?IS2^IZNhxe)WULJwLl3@^DjT~70+V<`d9#gEJ?=N+{~KY{Jg&~i_r?Psx~| zSy>^GYpQDO6t=O^Gs13&^fnhIp-n4pae=hbNB$5OgG4EOSg?$7#ziNA+7;g(Sv%EK z_W_qLME=$j@P*WeN(#Gr6jcK`QmW7*X$@_(@w=E~u7AqDv$En^+ z;<-A4F{G|no2q55=G6wqPBtAO6=r3OUb`B@yD8c}?j2cqmBq7$Qp!Z0G4tz+Bi-;uWjBB4wo$X54HgKC6Lit0AjeHPb4H~({rfe z3;rp3q9~W^+*H$(x`wA(lnJQ}Ky^qFXbTBl;9X^RykjknY)1HzlbNY?=wnfrGQh`C zHxH@sGo0KWI#yY7XYyv!1yaAE&!R&8j}=ij#+b&E#Kn{AE629f^^FX7^XxxHA<}*Z z@uiN4pSL~nKf=3(gLW3?bW-%}a@0rMaxS;+oXdQ)V3;{T7{8UeQmk*446TUFY0fp& zvI%UASUIX5I}Bj+lNMcGwKri-X%Vc6W?4bag`v$k?){r3Fw5;9zv|O`=dyi14c-J^ zshf8x_2}PW2R^<2G!uG~fD^re}kar%9Ad9e9RudXf6|`kaDD z|K)|PeWQ($L%ruLT<&$Cp&6tj(qr`s#m!3VWNSQTV5ueQVw7~Bo~}H@r*XR~{U~uF z^eFwuWt;oYPkPRlXX&*B?Ct>vs7OOpm9b(s&>U}T0+)S0ZWatL_nTgvijxgTPxaF8 z#Z3sg{1wr+_}lfnFE44tyr(v{?SB9MHnDW&-j>7#J@*j5cP;BIiD*6>9_p@<6o7ef zGr3;%&k6qzvqlc(gjH`$=-&`lR7znLyQdf9783b!wtBvCEf{ayI=G8wb7t|Qmx>Tn z>mLu!L|pYq@Lyk0qK%3x4cJx8{~`H14>6?m8N5~u`O@#`9CqTcMUsEA`OwVjg;_ia z`b)NM((kb31$2#mW5WkwyyoM(`2$LkI1N0GXu{(qTXgp)M&cj3#^{F;BV~Uno8C^G zS~t`wi7rq^(`xI`y;tzqYC^@p{@zY$+}QSUDa1=&uf2+wl+UI_X_KP?F8U~cNMpi?veZiZ-U zqd^@D586K!MIo2D%Z&XzZ*J{I_d{zibG#!P%P%)XjRwHO$ z-BC#*>xXIhURlce6?I=qYZ{ zcYBj%M)Gs1xlf;NSo9VkghdWKtjlg&z9?vG!&US-lj?RbG=QCl(`Y~Be?|a z={E)Z!ANe@&=wUGx|z{WGb1g&-h4W&XJA1j*{Pu^ngKAC`j$3p8UeJ zm-BU6$5}vsHEwH$&@+7Gdcl#z4r^jV{kBhHu)EU@ zn2@6PJB_ijxYQ^unH;>eMRHSWfNsKMOx+_5Fn$Hz<$7!ETFDT-e!wk0Fx}Y-rg3k) z(+F06&GbUy2g<;VLaL(jTJLb2ifSmc&B0RV6x4Tqu ztDlIyorj;^J}&|p@+WPaHFgVjE!Dbyf?|-d+yfn4p2C8JRKk$c0RuHw+zQU0w($p! zwY);3e(x2$RKKdE=R8{1irdXpB0uz(5tm%~yHn53vbP}mTQST;?aLI`y6O%eUdEEf zn__KRSYp>ha}Nb{59+oBz!s4Q>_QUdT%8q0Gzq)f(C0;O$924yK-bh#ceFm&UixL8 zan(6gP0Ib*yrYj>CmY;&eL?M`&(FnU>x(zSy-P?aJHCEu6xPYdM}f&irkVKb**KO5OZJFOAXRO6=l}N=@c(m^$$tXv^uN)PbNrZO z3L3J_)sKPNZdwb_-mpJoejnnfK(~GZ??xeB66lsdQ%sR%&%XKrv}W+XgaAt`6g)iK zT{C|1B-qyHDk0lM@K!a`T9DV+@APJdw{%_7NO*kso2&JYFLXnih6^f**W~ty?}=GD z>oUITjy=i&FcaU8bB|NKCgWjSyo2JtrfvfT{k_3`ALrAu#*1pQOt!bvvpimz_}z;O zZ}hBoQWH(om0KRWl5#XH`8C;Gg-6f$d%{O!kDaWUC3_>S_RO1{?KcukFNVWHQUYK3 zn+G`3nk;95e8jL97#;OFxm`qT z`z`VFnsWEmSuy{0wE%7PheegXkIdZWbNsu1ODQ#}O24PQ<=MHj9KP6VGttur!>VnT z{8>Bt9^Um}{96Zm>k0~lI?&7K~VK}pr4&Y!XteQGz@*2lTom0?$b3Hrb4 z8N=&eiK4x-h31`!*HiATzwLa}nET_oo8?`{N+s>v2`L(L*%gh$_Q3Jr7xMAf;&vsk zmvqgDk=m^1^^C3BikjN$s)-51b4!W<*gZnV!Mm2g-Gp8meDhpSXmVRemMpsSJ0shG zrk@c{_Leo4J)S=WZyff+`)onNjdcw=y|V!j+#7*)UgfJkrM;0|OJ8ZFI_DL65~8?9 z@~x5f`x|Y!9-S)b(mgqa1#qRD8&c}QedQTAJyGGPPMMUpM;?z{4GIdZhDuF8drrh9 zU`+#Xnpllab6+icmhV{j`i9nh@C62rsCV&;NNv21em>F_=3VN|58%N{r#xzS!owxg zJ)bB-WV5|pLxL5z%gQn=RCiHtWtC1=l)cH1iK%M0#@@y#$LQMsjT86OHqaUI3^d;C zJbWSlBw>95dt2wAWVGPCn|N6DRa3E%=Lw;oD5Bjz)3+DmCJ*12BP)sGLQa}YW3oI4 zvA1-w73(Qq?ky6L((tJ`==rQ?Rv=>Twqo$P)Q;xd+U!83U#^juCM*2y7zw<6I@nWV z6u0Fr6b?&acoN^2d)8Jx%E6etE3w8JrcV@`#^t14S+|Vj`$Ug)%*9F$8*DB5zWsSp zFUM5}t=I*OBxkDG1pLO>JL@_udjpSznGD~59-infsW3g<{<9!;1&49 z5o*2}I#`Q60Bry-xvKmvt`qn7y6y)bG8vRv+D|EV&ElvNxOaq(!U0n&C%uqE>;L7I zEoZv9_cGHLSnALvSE{|Qw!Q(YA%?I#BgJt$lN zd=$P9F}cdN`9=4LTUnXuSqSg#ed8l9?~<{yzP@7lYGG#KcTdT@&_cH)DVIchBe%Ed z68dtRe3w29NU#NJ+jao$!%3j-AQBgu6(6|GE+M;?LK1>_T-z38Y3R0{i%7qAk>G{5 zz|-w5;?g9AB?YUuhnef_(M763a-{u0WihgVZpkW$5JcLK9NGEWkTQX? zSj4WsVD0nfW3?7>+Q55-ub<^pesif9t!D9>HzY)<>q)#7PCyJWO_m^9<0X&kY?N?O zkv~>h@82JLj^NOtU7$oPS9RK@5!H>M(i=gmv9P{>PQXwytb7PnLr%?#yvp;a(rfH0 zmswn$wUCsnzj<6m@%zUb4Gb~fa<&#Dhj2L(djsv7{;A&mUk}(NWBU90v5v?E6;}5C zF+#I4fuM< z(1y5X66f2SuSSlDKuBqv_@d2laCnFmq4-(MD`8)&H`sUnfN(4@_T$*vlGJFL@^{O) zhTwU#Mb|V3c!G=tamZ(PBHvp1LFTSa!lId;B!&BoN(@S=M@i>m8bul~Sk=V?voVJ_ znowA5XAo7Xtp_Rg%1XNDL9qkqP2blcRQ0XU=re_u*kff zBNNt}XiPvFPTDjeZB-KnPs>ijN^AGP{p^gI9nxn*d}?N)gI#RSdZ1Go$j`M-x%fYCA&yw(Q_XW9p*yJ-9>T zw2oO(@7Jm1c|1dIlF27Z*989mOLQwB?5z!HSDXfb&9C$nJTn&f7{bsuI?zwf-B{)y zREPP9k;T)I&s#JZA?3tRjL|j=)kacnw*9cr(_jhS{=x+>0jz@1DZpa&|0l!-0~iw~ zKZx$n5IuH6x1yjfi__sm#5oiX9}oqRWQ%fSeLl!NMYOkm8$#pI|1uUlD8Bd;%p0t$ zFf+5~(9*yNr*3!MsU5Ely*Z{wq;VLJ`uNp~B7MF=;ZSb^;~I3cGK3o6rKiP;*O4xX z=t5M3U+F-~ka&`MJ7yYS4(cg0o-62BeOOEN(n3TxnG|?r5j}03!L-Zcxh>h~aNOE6 z0E4XDg?4!%6-O~4ocIdRN+7^9dbfe7<=8YTMUK+n&=jI@0NNbGv?lNX*T5ZX42(MQ zmfWo7qi8mc5~Xoi229xBd|T{YW0R?+R?i1^tE!`cVh(srCkEPPtt&^DPS6LZDQzu$ zBj~4~SyB2#CGZJ3YlzDPcUDMS7&xZd@2{^YQ)*2u)tl}*7SxD1zpk>OH9){I4JULY zN#WT}+Qf#!h6jE;ND-21vH&uAqupX-G9jz~8^;O`z%xE2yab-8MKVLy<}ZSqM~ezm zYnpngBnU8laL&k8Vh!Ou0YKsi8a0o&QZdng&wD+XLYY%-h`BbFqX#VQyEXBa z)D?UYQoU0POI|;c?|dEf0jw4=vH)Slu+`A5@TMEbS0ehL0!@M+fsLoE31BV8L8)*; zyq*|isRE_NX#9w}LS3j>@AVhr!wdk^(^ z$AjXp@DLc9@pK2)Tebl65*6Ly$HBbv1u>IK$&A(DKpboe2gtq_D`+v%s|;^fe!ZXyR2O3(mQc& zntFT$zlZY~#w_(5-KL3V)wRV-;t50ywOliy^|qqVr;x$C4(s%W<>s0)fAZp+jJNiG zk{aJQz{a38nMR}X`)f}s>i#-4Ls*JI)S%;0Kr8w8&s6s=&}<-i`z>h;+S;N+TO@8t zQv5mxg+22`<2xcas2y9mH7`q%@tq6uEnli9AflH|fw$m}RSO{-J`Qesye_DIRI%u2 zdh$5RpR)7Y3{naOYoOsGw_3z%W6GG0Ezmlecrxf!c3bUp|8?t@o8mGl2dWaJja)5{ z>T@r=w*VT7ozdkn8%4h>VJCh-2+9API0-yumIN7Ko2a2AhES)-qK0FtATe*mB^}X1 z2Grq8LbCGlJsN~veI~ZpF8_*dfA0R5e2ph?VUJU4hxB)>oS?BsKCyn96m5+iR$Xs zB%c04t<~rQ9^?DojR-ZRU~hVIl|!a})^&xdlRy8nZS_5d$!o#3K45)BZ(gPWnjFiW z7>`pdP=zjtwTos2*`X1WB=$W}pC3aign4Oisdnoy-+n_RcMNkrLLKR6`T`0>NALTn z$*w&a9be7^^B@=XRqR20NFN3FJa75h43W;5K%G%f`#Af#^@itIni%5SFFyfzqEYwK zp4P2p;tJmq4(T<{ZKAeRI&4y}AJ~bNR$J?r9>_(!B}ZK7Wu#=~ERF|qDft&9L~7zM z+hgD0`oTW1t-9&XpdZWKs#uNQU&f49VA1^nY#h-j*$LmRAavwWNXOQ1(uKwdKBhd) zFXlkh_-Cu01qOtCbx3Scsd?8?y?lv*oV~kTkhD#*)Q$kXW4LxqaV4ozFZ6jzdQ5(s zERgEf#T!(uJ-W8@sVdZJv01T_v7k-dmTa|5!M#pW%X*&p^s<))+zA?NKH9F|xDoao z(Ko&Vp|l`1URPiMG|H6qM?S+gsNL8ngo}!0;m;ndX#F?cE%y0(#7}MDocD zS1i)OT*CJ({HOCRaS{Irt-?pUgT)rUBlx7U+mTlq8~k&h8Utt2t=(zoL&vYLm&Bzy z29z?Kzx?exP_A4pV!6~r5=r;&nLOrmUzsOkSw=vPHgNc)pwB{G_<^?KvE3Mjfj|Cp zT?ADlh`8Xpzxc(Yg{QJ5`3d$TQ)}2QW#xsYpF~K-Sd&?i+0Dk!cClqk$+t%icu{ttg7LzqU|pP(#!gcx*O4r1^~QTy_unid z0ge5iDnMJ#FlJ#(e&->J1E{I7N5)%d{Du#qbo&KBA^3d}XlA`eFXa%ZaH}EajU~U> z4XO=gyQqe~bF7C7!rZ5ZBpk?FKloaWA#MfZ%XLI)n(jHKGr`GGkj7*|-AJ(CgwEA` z*-(#@$FDJa2Y}X?GV*Wve`>FkJ_aniK%^mklRY@1cZ-Q)u&^lIVMr;I7a2|pd08HD z@n;KY7-i_0-}|Aa_HzFr5ctz6(#)jShJ7wsxK1;zJ)e8CvgFT?#7|Rm+4owYu^QSu z9Xe@yVv}mom(pz~urJ$s6|pf`d(~V;53F2E`OU%{H*@w;vp&e%+`>FE$94A?VCQ~7 zR=DR{Dc2+970hpMtE1g|J4&krQ%R5QJ*~Bu8jqoQTmA^XS-flDh#MtT4z_9o@&xe{ zqYK9$Uyf~`O#SJba9X`$~Gm#%i z{}}e`2|})xhg)&->$~-!0o3q7tdF6|5^^H=?loYDLz`n|L%Iom=iPDJW2z z@zpEr#plfDHZ>bJsv1`6oq4r-zlJ(%oku#lLEX*uXZ*d)i%qd=V=2W3pRZbHr@8TK z=yz*;itnpns(HU`UuJx-ccEFba`gq$(hG5>g`#j6R_1LY%m>G>fs^X@1os$28CMSh zQQie$$2{BQa(st90_F|U9|1(TdVJHUyR)n7X*)_R>zg4EF)<&{A;BhQ!b&mW9qF(GETREy(=TIaqI9|h4 zuR68DQcG`06%Cl?O2HhvI=hIQ=e~`7o9tJ4>ZGU7Ez&VTuTtJ$F1xQFIENJ(iGfJM z9eb2=ay6x<3e8KBOYF*HjWt9C7Pock*xF<9%m*JWzl+EqlpzqIDA-Z?Gc3LQ zD`_kj0G)y_%^{SFmGN-W{=7 zC@!O;bt3;@hQH;@nu+B{%*3-`N=%eY?11XCTWv#Wi@ILH?jnIPKF*xq#(MHouWxjg(IyXGFl`7rx2F53gNu7nLNEi_pM{)MsT%Kp~OW| zz#!Z8$57B|DuK9ofw2YPZ2?E9XTIG}%DrLLMeeyZFi(}dq*X1I{vEIC!3-{7G+#x^ z?@zNwKM(~{2!?5o2PJ!5GvIxDVkR<{&C!=?6xUVSAFdf>;b43>%ud5{DEc>Kj0Mej zy=DBe5?t>e2J{s#hoSxWmQLqE4QXDy?K zOeOmXm0e6;!!}GM5E&%K9(D$?3ZWi57myTkOKEs1%JC~Laj`YmkcheTi7>7ZTu+${ z0w975nf`^J!Vj%2jC#YcKJNu^dUVm0S;ON@FzJaRf~pGcgYIXF{iYn!$-<*Vimgn^*Rc7ll&8w@G(2``iJFH88kEIrAlI+A`2UoJhN)WDkFFuF!o4Q z#%A2eww~i9c`P9&$YT?tds7kQnI{&%q|A8iVF;TD_7?3|TQzKmu`)4(*G-(s4=+ME z&AA|6N|9AcP=8vyQ2|1F>}4~eZ>scsEE-)dHZjNPyE(U-|0soDiY%@+H}x$^!)f-4 z%w2}H_?T(uh2#JxT)1PEcgJ!u9M`Q8E(Ny>!*0&WSSA!mLG(g3i%sDS5!}dtUK<)VBR3GcfVw-8H@YukOh{KM|dgW}kP8>Y5BHN7{a zZHk5U+=TCdLb#H#t$`fJv&Vx zf?T&6>8izn#@Q2kkcf5+H_-Q=9_ghAvpzN%Q2@wu*3-oqEx!)vMPt%sL2_O;SvzEG z)R1NZsI)O>kq&LvN85>?yi$I?z1MR7_4r65l9C<`+1Rvx5=YL(l zU7d{pZZ_K+agHfX16z$Gze4erUtbG!C5xg#Yg)mD>PPH!)khSw`V3wPWVHztt?ICHOV+#*_ z-+tg8?Tt)s#ax1Hp}WvrdJvRe(!gRHMzBTD>x-wj)T>?-Ao3-FKDMohCtsd4qCOk*0=?2=Z$V((Bg0psnsqbIxEf|(N8RuXgH?j@7RvTT%?W}k*smtAt zts?jeHOT8A&aQ+%$dPdw*Xj{$9VPZCrwIt(Zp<~ZOb>x@8upcbL&}*-o=)g|GCd*7 z8`+e1tsHV3TGzvyFJxt$eU9r=0v7x*-)bNrtyHt9E~1SQ^2ZlyZOlHDdo92#Wi9XW zi0VAZEYo4)0CQ=tP+0;x+DOvF%!Yl8}WcAHg3pbl5f}71Aj33Biln>2Y8k@2_ z7x!VR`L`2g_~z!MMx&&(s=X$PD5f$>!Lru5uyOat^(9t0>!vnotJ0eHj^ivTuw1PN zf&SRDqw&RXtX*B3jPyX69SmzUBb$Xaf)&m$OKYkvSLTHUZLkAbdUZY9Lti8>R|2(= z8TE+#mmqW%v)6?-1$ZHtJvMS@>;VUD5EvW@0L9>Yy=&-JMd;FJi~zySEFS&4s$U|w zBJV9J`E}R|CVZ(BOC@yfoSZ{;k-B1nfoKya&ycY6Sq8Lg#(zvv0WZf?D(@hf+}RQ| z6JhL*w8@6^onXI)KK$ndLne6>aNwPmpcc_MHnFrxV#F=lY3wU6@tX|u@_H(!)9f_v zdn(YeHKtPRy+a$f0AP8%0raAdDp0)tWsk!!M)2PT{y9Md zrmY@|h$9*HRi;WZej^GHH!ACbevF-X90u+#I`MrUn)=}6+n?y0A5KXOu}%H}cN}i5 z0ev@Z<^!PUeS&UvCU_!%KAC!}t{?@mnY}cvch->+u+ysCL4qa%)Z0fi!Z&bKo(4^) zA$X-AVBr!Y9!Gf7WLV~<<}6O*ju03daiG^A#2wb2PuTm^aqPPtbD&$T&@N^SX>in} z6Dy6ajr8kaU#lJ+eLz!e^9jvvg9@XBFxTeLZTeJ-0}?`X@z!R&Z8FKfS-Z5+Sol^I ze{o$(XW|44&`klEfh?($NwyO2+A52BjIxbtplaP z27&H?F!N4P#02;p)BjkWF-SyL*Tm;D^%+q#Man-X61IJP3mETdCOQ@+e=hk&Ykdx@ zjR_j3<|UG{F9({8w1AN|_h~n4N$J#u*Lbg^;Fk2$6y2^LVw~A4!8pv4zn#FfmV8g!I(Tc{@Z8HH98A0|_v{$Xj3Wl;Tz2|)y8YjYHx$G7&Y$o5I_{RUL=)D# zmJ|#V`fMtzTqdblM$xUJ#IzZiroD*LQYsd5DeC<(x!>+%(7I3pfx;31gC`h1YY^xs0>6%1uNLe>L0C!9Wz^;8ZD_i$%dO zB>ke8X!4FYdqDh3wxiRzHn#MH0!m--9P8;Y2?~IPRk!{RVG!` zMo=!+*y}uhxe1Ek|J%PsB5LiCH#wlB99Mz0_r;InUmmf9|E%3My$GD%MdSjJILEzs z|JTVoW*vmtUb+s0pFGXvpdsjyj9?O2*iOD+y+ssbm2EK|^m_|3WteH=lRvW_LzMNW z$A@0?yP%f!Ni^O&v29^x!H{Khi(G!WhXy*A+)qWK?uR=5)T|#X#QGw9xL^ezaz~rp z&5R7}4a`?qVA1waaVI+xtv*i>q`nMe%8wCmgCn?pVfsG-BU-V-Ylan_wTjx0ae3`l~CAJ+t;XXmW z`c2&up>XnoDDJgg}zLr3nEmFY_oH8(6x>?2JK5B_PX?s#)vwH_udy{q#bTdQ6sl86nGn-eCY!kB%%* zk`6D~!KP^lWkJe?%>uI@V`TZws@yWavg;{=;oiOB@v?QCcAGms+wuw@qgOZ!5bm4_ zZ4~PM*LQOIV$K3hp~W`&fT+Gd5GG&TF+F4cETx(x)uTLaoH;>!^aUU&&@}AFfZ6K!@EEIupa@JOB<#PVnZ|F^uWL_%lSH0LcE( zQv;IA4!Zs1s!DP7)r3(wRIqj;#@K@Ltmn+&oP`)FTaiYfm|2>MPtt04gA&G zRFn825z*g!)uK-9w{aR96i^QCzZ9`P=&w`0_9=toWZCxUu=A0V_e57O(y6Dyu|pF1 zncSRrXv`T|xt^CX!Kxi%$!D{<%#S%7kX4ME=$X=`efybp-Zg{gG#xZGF%dRRP71$B zF$XiRVmzZ(B8|Xw_Q9Uu)d1rc1r$^MB#HGwz20=^kaG=d=Bx2l1qYezz8N3ca4T0DZo4bmhOmI>7lCGPFq6 zUF{SlTtphSYo!miBDk1*m8s4&P`h6o&<2P)@X*m+nhyG%IvEG(ydZx*JQNi9F){Pl zS$I@FSl4tFF}hzfeu>ge1q9pPn6ueT~Xx`zU=w?w=(ZZ+dvm z1JZ4T!p|B6>sDP^Szh%ow|d#H+=I49{<6xq4)|u?OJ29?aFx7`tH|FRm!YLSF1WeA zYdF;gxxQ|2-n|o1v$J{CjgmYiNQVM}E@3+qXad0-8VThxB%)sfF+}EC$P|zu%4U)& zN}5ts1xR%BNVL;Pna;T-2Lg{LuQyw_X&fc(>HhD5V5DxQ-0Li} zEc{#aFR9#!D9#wdNA-RYdTL^b;Eic@@t7=G?pvQIxSgw2t%;G%tSS~Z%d&5ruMSEc zex_PNqH1XIudGkzM-t&>@WWu4(Soy<*#Vxl(j7h9gAN``CruPvB6^wI2Zgb|=KAj6L$3 zgRT~}i-Z?5X1ylOBC6+R_42XK$lLvXdRONSKg~^>6yIix*Vg5k=!N%s<2#Y7?U_U! z7vg(enJ>0NrjWWMDo$NYP4k#rCv;g5o3#R0M$3SnL9cTsdSn+K4PuX_|ozv zIrRaFjDoTWOgX+P4Pc9!83q@O8c6GQLNk4}fg$0>spRHA0PP4+8~=#75;27k0hVMG zxOQ?gkV?~2@vH&vnQRrNBbDsH;BC#jP)l7N@lcCUqtauFf99#scn($?KO^%Gc(m=4 zx0I(AJhW5?zr^igh;9s>PeLfuGq5z-;XePrAH=A+L#(kX^y3hVDe;!Mz@!&QaBo?} zESjMO6pOp)>JVEIseC+#z)zoh??-F`i-6MbSM)!fd&E z9=jt)$-eb846z|*Grt5WK6sysX=Ri>5!p^B+wS*sacG8}6JyT#o70DA#dM?Aut?2+NVSIL&2y|KqKQg^U~U0%4f(RFSN8R9JaK z`#_*ox}bql;#$P~JDN=-f78Y944aeRekFlBm}=n&!E9RL`Y3y_)6I`Rxzsf6W+mrD zF4c-E#Glzz3c4M2|2i#R*t%*J*!`cl&(3nxZw(s2Irk(4{LDR#uwPGH(cH>{^a2N?n%p+s)?Z9 z_{N|VA-}Tu$k@R++gO*3v5m}RkLl1N!t0RDDvh_H;6ta+3dZ>cFn({Zh{S-MAO zIDtH)z1#2}(5s%b(ImPmz1P=yA`+U%tI#q0&6TEccH(u%P^+sqNooJqyOJtC(w&Po zr{Zx2g$0_V^$rbV+9aE^m)1r9n-K-XE6k#~_4H6SnPezadfvXPE$jMo5%Fvi`kcKH zkh9RyaJ?Zfid3e2CChefOZC_$L%X!h?7@sg(y{fJ`(Msb3R`S7$M7A^Pt@%_+iQ1E?u&V8DY5Rb zKDJz#jTk~#?sOsk%FOz~7OY|{QvJvwZK8Ny2iu#)fuvc#SZB@&rm$N5nfLPJ3HE6- z_w8rbFWMT1KgkSmC~KT|_#AD;`oI>4#vvFlM@b>9>lR&$j3jYDfxX%cFj)Usqc*Zr zq$xX0Ll6kPw*cT*uLLoG7tn~0Mu%?B>FEA*V(|45cyt+ffsPQLlm8XIsex&yaDb@n z9xj_TE6#(`6KR@F#^myuw9wC3j5SWE=1Roup2T~XgLPqyT=$bo%=++c4 zH%f(M#>+^7GNcemJJ+d)G1X=M@?d%pbzeH@$TT}JqGnKr>GV9-U5$M6ZwXbG+Q>(0 z4+HVMdnT$VkSauCv}p@Bqz6ihH}Ru`4b{=QQcK`H_iM|FW$qo_twfKv$w| z=5$li$HR8#8)HGaXIjyrFN$V6g^Nxd=`etn$(eR$AS(*J^bT6JxHWxj&-58-g3xS$ zso`rjm=KM2H;YV_d=vB&l*m?Os#C34_zp}gT&OD7WPeui;`}_Aivczp-?xKgUzUAf z26mox=*2mnK*dDCWbMs zgWh@oT9#m+&Bx5jvbkb`=FnZBdyF)n4wB!r8Qq?-b9@^~G_M}5!bbtS zn2s4)R4MRTMt>na``qY(FVX}#_W%X?<aXj7f4=B#=dO?vD|sA@H=sknT&EC_!U}mtT`E`J8sH zo*iT-;Q}MZgi39yk(GP<^Ju(~EZV3Yb%MnK{C2-Z478m6*E#!p>_`)W7V-y`)fs#I z$2`-Rl^-Fw#+Ds^3egon|JHzR)BRuw;I*PYPY5o6vq`Ie?c;e{UF4gx!frMO(Au0m z-~Xi-3jDbMQiba{MKP%H#U)>}}Z0y|aYd0)FN+2>9AX z5mRMUG%0ux@NS=FdJMOmi5L`l3G%wx1r zkXZ#}CZ&{6f)JTUiHOV~AR+-mqD*0?6ag8dB1Axl$|wW^grSs4W(5V3h{z;~NW4Ol z>SMir?{$COU;pYq;ulDAZ*tB)d#}CrS|Q%U_uczaE(D?IaJkju98wLC#L2jl z?9OPXh~EZlJn;(#1sbFNFi3S_9nf?47D2i-xrZ=e&;pHed*Qd69Re5gCmiuKIMtsy zno`%~*>Ah$j_3`Sg94~L*!aVCH^6=P&S2zcFY^XEQf?myuL*Eg3mSZ#1YRzOOQ86b zNq5bQv%-6Y2f;514FTQUV4Pr(@j$Mg8H~owNulS;Lip~sl)kc&S5@9n)iP}Xe^W;c z=lkJoe4Q86f8aXrZGitnnB@%ML?M2|D)0v32M}Q(Kc2;<>tZapsip$JRFZcHvZ0}* zJ>H`=Xv7}MZJv1QE)BK*_@=C0hwr)R%7WeVZ*{QhXzE2LqD;)@$F5CFOS7a&k@P}@F!iYabMH+83tN}?*t|2Tkd>Zu$>dn z^15;22%p?UoFs)7gU;(IF6_t6nlJ(~ux6Y;nIx)DWH^&V8>yzF!;Z8tV-hu&6310+ z4rrxMZVTIJc%HT`xC3zGz#wz^iS2~H__zP_)#K-|JC%8T2-$!6!oe3{Si*k6Ej9lQ z16F%#43t?1l?;?0e+d<_M#Be(!w1USmV4H|L^cRvH_^sp4jVFoO20aLpuWjax!jdY}XREWnav{ z!|VLPJqdyVlCoGs`CgdIX#+ASykNv=Fh9sWw^z7sJTz{xmB6$?&4L-7Z2IW?g|ojt z&kz_C91rx$d5TbGEo5cSn}AZPaXs=ui(H!?m$;6CP57!u)^or#9Hk2jzNpf(N3d^Q zPclpj6c`4P0EvQ>12_`WJR#3IcN^egCpqN-i+5UY`ZF%f!vv0(0`08u0;2(06ae=sZ;_R3P$Y%FX><5Ar zE_72Yt#N|bk{kMciiz*p4Y7%_1WP5`)xBl9Q!}{jn2qKcVbyFht~zkVuX2UhGcUwc zH?Q=&wP)up7>D@JH<|D`aL*}VqXca&7(V1TG&GCj!K;wi&MpP}UmyKv#eew*cV@nJ zeD5HrjLhNTS$%u_eqHa72Onn^ z?1h)S{smb?IO<&m2tEy{E>t#wIf^?>20qOAw&^?;Vxv=S0uVPe$;u27onDWo+*z`G zj30@}9wGQdR?%mp(|KdfOCG<`ZzJyILMh5Tp<(zA3DOvY|1jo_zsSY4*LNZ`6HXiO zsdCPNU9&GXmy6^`{!m(Af+Z334q7$;T+an>-qiJQA6R~_0J3>;_g}thaB*E%aPRH8 z)yg{wbL;`bZBCa5AMXNaOCesu2axXq*zch9T|?d&MIJ|cgw;S>Q7JHe+i-dzdo)Xb zbE5<DWzZ4*HI*wE0^rbUzn`BIouL@6u;hi`Joj3)F1E=Q0QqO7L#yHXZW0F zA9g=5TSxrCLaY}t7cNd}MuW70H}x-{n0~kf=0wPGm@qzarL21CXP<(0-gY)?30i!tAU-t%H6ok(&?U;f+UGh38N*4 zV?Y}fg!1}-2+#~Ns+tSdESN)_TYRVGZnz%e z(6MKUIL_LQc@=Z5@70d;e@cNytfO7DZ%0LXrzs&Vh97(S7y?^ z6OhGmJ=s4I8?rboe7^C_t&q%k!R^-^Tl(v|scS5qEK{56q9&s*^P~Z=_2HVv?-bvjb1>y#61bOkTz_(cNT|QvK1_%lq9QcSz2bj9-qzT?{m)~RjnV&qC zMk<&w)CK7yGn7Wt@ZEFSzoWyVM-M@vE7Dl_nYhe9-d?`!zAE4xJ*inGb*meN1Aay4&moN%)u+3xFa#2C=(%t%MaHk({iw62q$OzB)}9vjos zlGB1)$FE(s_-?1TSgLgX!PTuSOI@*&Wy8^+jYz1qN1=1pKH4lrCMw>@?u~9q>8qgG z{NvW8HRn*#cbVnlYW-JrJ)mcn0VP+#-n7OHBWKD41nc4#{$942Nd>;QK*IkJ){Hi)=h!gS5c=5jc zOq17aM~szV{-UJ2bM7Q7HhC%rC?Q9$8Ca*tZPy@zq-E@M14fqy1rz&N`%(Aa*7dr5 zph|mG`FXUcz_q*8%cl}t#dGe}tO3-}z0Ik5Iv+W2RZv=CpaVvv6Lrzz-3V#Q;{63B z%yAZ?$6OA&L;I-AfcK|=Pf+fcQvswJ5xE^$lJ}nW#>wxQmp!JxY3Vw@XrFGfDG{;j z4%>WIAO5wfsa(xJ7M?`KsK}pOG@XOxQs094ry_s5d{f&KE-6NuErKT|tE#H1M^4u| zT&mtD+xN!qOxUYPriwf)XK}qh^>m7+t-9NKe6mK5zOtPSKmJ~s{)r~pzNyj*2N7#+ z+X3e&N8W*;U1i<~ToR0SmxT=AB+bRpx^z?q*`7g3Gv7;aWU=$Y=o612>)AOwQyCEqk6kt z*f%ADcwZB%hn_|my>ZMxE;!-<%boun2<@JMVsUhHRKnRL0zo=#aMQM&Hq)`5Y?&VSoK^o%`qt&a#xCqyc)h zk0-g~eyx4ic=F>$?M4n*T?hTGP3ztKLfH!vx zo!CzRMDaVZIV^E`(z5<@j;I=0zch5P*!Aa zMa7(fi*=hKlX|a~3yZkIi!aq>E?+_i>kgj0x$1hOP}6}Z|Hihp|26U2XwjmnncN4p zUPF&}_>@PE@(+Ag>3La~g&ezlsz(~aTI>Jvw&T2b8GpH901;@0qqxz7~?R6D=RmX(nLO6Kaak?+bj2g znOZ^&oRRySd#0`q<^DP(df9*b=^%B;((|5Q6DwB9qdF>5%FMBAKeu2sw`HxWRwu<;&{htZuC@!jJ|izBae1Pc>_NRCkCUV4c14Q79+39tqNkxunOo% z)AxRN%P$=F`{P>CyM|Wn8$p2c#ua}Ilbss5g50B>U_U4wj&C1dGGdYGU12it~HR&ObQui-k{q(Dixp1BT zbfIJzvYdbUxTw*X?~mty*&6=b`3j$=%q-)^5v2sC^TNALI-o-`cEv#8E#mFN0OTkY z2b?x-qiEB_3XJ`(Yx+9n`3CtYV*v)$x;5=0lXWzsKk?p=H@cBWvQwFI*|qmHM-)P;bkwMpJ3351VM^oYoG8eq3ue=EgAB7C?&Dbh zUP9+R*TJ^}t#1YXb4llaz#?Yp!SM5kSjZfXYl2cCEq6aU#+~Jw7Al=nw?DKF`5oL3lg#ZKcIa7rzWu^2BR9~VI+5@3a%(ABersho z-fHrnZ=nNeThEC2Z&{`W_T~LUoAr3x61OdYdv2Dbx4b@nxf5eK`Q~16z7|YeiW4BHgXSm1=dABedFdGa%=Y8 zVRG|U7&oe?94Mi3P<_Gq;{`S*X z=x?ihU<VtY=fDhmQ?lJ0W-MA)SW(l$?#2@`~(zvG5@e}4#~x`)dyyMGPW zmSxVRHmu@2X~p^lx?*>F1B&KRa`%rva3Z3#M#>a`qeD_fp`+J}avudd;l<6_ibb6? z9*{)_bsM1=Ly*C0aGaR}>7D9m9VccOp&uq6j76~EiP0v=v~tNNmVX`*!n+sPS|$kF z|I3%YzcT3Hy7xS7^XO1Uc@#%S@|t03W-penY6~-Wrt4~ym!g+~ZdRBVR(YR;QL25i9)9 zbFx`MzyoWte#z8p)`QZPeFuE1Kg)!CHuPwC@`Pxu7aU*8!Pnrr|BTkjUU*5_ILp)- z(B)0Q8_n?R)hyz`+gZ+^r0JMkMQs(jI!3L`cQQ)IsX=gHRopENDQP3(aLT$smKMD0 zWo964SR+Z3JyCNVq5M6xhpC$BEy3cQMfNO+u*|h15HLHEi0>&cBYYk2g?)jiOMzqN zP@r?I(bWb+|5mG%Ay#C*v7~CwV6Ah7dVWYXw|h5|k^^E~F540kW1<++eel#yLvXm& z#e1`I>X=)7Gsa=5WlZ_*;!~5Dkou4_C!aM>gcMf-i24ZxckK*lF(%B_?RB*=WzEb* zQU`n+at{CV(u<)#82P?Hy#wPH+AgbpbLE<$y7`1`TAiIiR_%1Pu|$M(jX5%8<7m(p zvXF_}Q}K5M00YnibeKYft5Bq+1y$A(Rru+F`LWm4be0U^P!u_Q>ZRs>A#$1V+b*Az z-&xRy-F@fmtG7|L)1NEVZ!RIq0YEi-3ryv4>#lOMakKzXb-{RIm_yKI+C~&THw(KD zLiL*)L(44Xevk5eF#X7Xz5}>-lMU#(haluRTmD`T?*E5_y-Jid+H#}5>1wp7E9})O~b|Pnw6!h zC!#}kt#90mdcxSTN-dY9Juep>?FZ`2@+`OvYgzKMJ5J~tIidJd5sZ&HVwKYG?-X?~ zT7ifdzLC{pFm(KZ-#fDC<$R~UtJRB44Uu%BU1UXeB|;t?hw8k^aslp(ZDb<$Hx?1# z2v(rCQTaF|&NaDHl{bbH;vHX&1Dsj7%nkIe~eD?C6bk35lhLr$hp@~ruxb%7;jf~ zgr_|G{QTWhbqAtDor3xA*?+az+Nn`D$PP3e!L7}GCrhJyW#P#fRr;tPgDFE^PQmEW z=OufVKKR}rA9)UWQFVxT+OttO(D9y7d&asS=@jG}W!f$cT7xd=xIChc7KD0)ohLL( zZ{T-*utRK0^N(B%!gtX#?A(MWbU$oUlLUl9NXN{jCQQW_M-PT{!pBVanN#AQcJWS3 zkyU2H);;`7q5?!dz3}eH-YhJ*#27ik5Y?eQjqF6gkoar}2&E-*#Y;0=|VbF*-M zsM#5ICDcLW9BpT+W?{~=0vO9wk&s@jJPV&qc8#Z#r038mYTIb`#{LQhgNEC?vO-fd z@Mv#B%*NFfH1FiRB!)fN(Wxl^>`pq!fOJz@8#1DT-A$P?LzW=~zvve-Ufu?hrY_nt zUizV-lEA4hLXStZBR|@G)3~3r4H(kM#7Bxt^`gaMUqK(a-{c#(AB_#`h#+fvEwwUfsp^qr5 z>J^^ajL%e~k^ae=f}OZ8I|a2*^=zMduM$dp5iQR@=$8h3@as2P5M_DQ`i6WeGKU+u znVPQ9z6`8Rs(pIr?!<0nIWs&(SD()6aZ{}GkCk1R;XQnfpu<0xt3`z4%LUOIUF9lh zgpJ@`zYnqfukd@FN4AU&vj(N@{fi1zv$lfu%EiU=uc#&uP=#-;UNvtAGllo3l~Sd@ zl<6`GfkQK>u;7)vF=N#M6Tsy_iF0HZQR%b9Y}2!k(KdfjraF(h1HouSnx3!>u5t4Z z+=1Z2S@U$sX<|Kuoi_Q|l^+{HM&`D1f@op$^xOX3f4eI)3D`? z*VvJ9%;l4p=>IteP zNzC!l{VOi^y|Q@GE9C;he_!#<-}>Zk$1mckGvL(s>0PO|j#vpf+MQNw9nr5;v}*`0 zurtRIi}e(#&V3wr?n6!hE1rry1Zl+7tTeZr0S1fR8!8=@7%kTMMkdCHxjn%7ecE8w z0-d^fA<5yScW|N9+t?q*NrTbqu0-mCugVql`LMhGA1tzmnb5`J=%5~ZH&bzRhP$`6 zh~K+d&135JJH6GGB+WJJQ{)=&D62tq(Oq;<_Kti64i18W5q$sW*ck=;o~yME)uwC4 z$u~GCDL?(7NqXp;yx|uTr)sq-vZ|ApiOH2Nqy{4XQl+3Gu}_4b@gKz%H7o7Sea18A zT;k>d=f6#Sn{B~erlThm$;!2cbe}-&&Xf1X7N?eHLchYDSS~LlJL)T*+CB*`XvyB+ z5bIm%HpeX$eLy$IFi##OKj5Zxe32X=&o~{b zB01%J^5(al$!TfT?vXk#ZMkw?L6?l$JCD-)r>i$KG|vlwJ+FuW)n__I?&jz$s>>V! zmDOARnchFGcHVhNbplC(w4c|$fjeyKhDxK1YS$}8MIG5EpB^Mml4{B?v zg@+hg+o>N)PSE3=qIvJ{LtpMSHR*X^CpZvE68)^-nwNTGN+{MFRkC#HwT4rwyvT(? z7{1Ofb}CfqxQ{|azB$pd&M@BHr4|KB-oywP^lpYD3EVD@5AdFa%kB8qn<3O0%w?XP zLHYvwWFha_DSZ3);(z(>2kfW;oizjGzkKfG+?|!>c~m=U8C2{$pd-b7%iHt6gtRni8{xlaS|aq%WFIx*513= zugkqy^(phE6NNg0}+vE0wc0bS2TU+gfj=m0%gm4)^8$Xx@-hHcI* zAV)t7CWvtyS#URqP{*6`Af9$H@HXCk`GPc*XvQYcp!-iu*eA9J*) zw@v=2^-W;K(+9G`^Z;CX=2hbRs^HATKJt0xy&V%!drH zV<@Jb&LQ4w!i(?}jA9jPVGSjuXNcLOR9yk&`8fz7jvy&$wu`xdKi(>3ELtR582=D` z)h6MzO}6=nE!?i7DP?FlJmA(I*1|@f^g!-A6z@Or_5Q*w-a|3Z3zx{(W}2z?!y5|MiKNw*2I{d3L5K~0M!cDYb9|t7e#W3^ zHEW>1w#x0pQsq72On)bB2X#JxSS;pH8e;ko@A7zp7nm;xs086UP9$rKe)R(f!?L1w z#PnU_=o^5A-e>diXk!_|o25;x2pOeukw9(;v^_)WEMhCX=e0?Xy;lf+sR4g2^8F0w z2~O?8z+$vC--qk|3m1f%3t^W*M$CZT2Hq59R!*w69&N#>`M8SMZ>mv?9<-RDyu5i? zWw#rK$kMwkf0j9uLN*EtoY_&S&?2SkwS?exN7D9iL5t42^Itw-@q{qu;|PQ0)ynH5 zG`DPs@4Dc+O*+kagGyqM6-(Kgd!G{oaxxhdWC4C;)??IYX43sXW(V#xQAE&GRBDe~ zbX~kfV;cY<^$O-?LnwzlyuUD?N$H-gMjrbEu7RDzF)!fesC|Sc!n*yg1qKx1Jvtz4 zNSG=zVB#DM%oA*3jHY8%$2--qz&PtUh^BL- z!)RjPyzaDKEh-Q#nn_6@Ol>XT%#$AK>1@W1NGwu_|X&ST_)p|ieXO*5fdnvXKy z#QuS>rG$>Ye?w)z;ue^jVuuTNK9$R%vJj$8n+M#{*+)Vu-!`?UxvWuVhx;DfQ|$y= zX=}D;wk|!-iI3G;_i1g+p?_Su@Han8m%R^i2b*G)dmk$Z1+X<=K^D7;m(jYkC$sf; zm|N^}R!g5^y!*sWt@&?bE}6S$+!8bxcl_7TJ}0YOiK;_zvlv-QE!a#dA3C_Dxc z23)nQdYTOkbbM%t11t76VYE@$T+pm9D!ApOZS}|7aZ|qxiUqzM{S_Gg<;(BD1rl}z zFmXVn&xAG$8m|^R|I;`e5@-Kvp8I0^D9xMw;fW}DN-$tDhWBs8urXsC*Gh~&GdDY2 zo75@mX~R&oq0Sc6)j)+^Y0NJ?gEm*@R7yux3H|#tMpxmm7kO5skJi%G!naHKb4(8< z61Wq9CmTHpD&BwRvD@rQ+!_31H;)w$^Sf2<=L*;!w~DIV`u63gWS5FPk!mh@-WMJ& zbnH@pT20NKY96j|23-2o^#4!>+&k)xApBg(`MArn+Wy9?2doCrZ2$2AYF|{P!e%#n z5RGskMUKc`P$28Dgcngc(Q`JG+X$Fmw%SH?F5bg5rtn*)t%u87y$5y28peq)#;R<> zJbMS}8elR`?qeDi0p&!gDOw!0^uFr?+;>|WOX zQ!{waH5vPM)NlZaa-3KJ-kt%K!LI=-tzfFZB}r_bT`&bqBFNZvwE^my~*yUZoWII53q7E$<}`v_)Q zP+QwvU_o33n&3L#v>@rWrV>&n>^Zh^S@UoH?`eDw)o)82cBhPW^~SkZnXh`md!g# za!}r`1LvfIHiEHcW&y~dKA6ps+#?MW-A&DlE;TwZtyW!m{JB zYoI3R+=tNxvl0Ohc!C%tbmuAh54Lz-%lZ0v!kOuZoXPV48GKc)7LYqdS?0i<3Kk)a92r@;$~Ko^B9p)44$Q5^1thQEG$K3G&0IY@8>V%>+nAjh zLSodY7$0h^T}a^#zXuum8osKj)B&;Au99hem#8!sm1d3iPT2>wmC6;JQP^Kp zR3A5Tw6_9TXSW`2FLo9V4*m5$kgp_qYeLG*wSMm-<3I%$$offN8siywtjyxlHaVc> z7cUE>7zH_!G1`g6VI7^M`ZKS@CM()onli0(FD8Dy)>=5VNUlvc^i}Tldyv&2kX~ok z6zU@7v}M?%zwF_L-W5uxeO@_n+=bLko~+o1eBXb=(M(BVFzTz)8;zyy=Q1AKz8>|; zuoM15Vzug>{o469v`;HfPmB;7yWv2WKsd`_NngXwx?itcUM9q2b-P zfbmJ78M3ca6LE+m$Wl^_a(b)3Acl^jD!~)S5eEk!d6?z}Nq5Rm0LjSJ@LK(rInCkn zM?QK7<-A43X$R-_-3!1NmD8S&b^CAiy6$`ym#LYobZL^)b8;527HPZjNN933-sM%{ zv6VME9~rcI*`epJ>_YAa$Y6|n{G;knYi^;gjro9OWB=rFwXrqlUWHKO@@Po^c&4i^ z&X;rt&U8h*BmFT&@gp37!r3uU1=D-NYdQe(V^#F?bSFcfbt<{7&F1$lZ4Y${kAFSN zDrmU!BPK@anE658$ob~!uhAwZIGI7>yoH`S^Q$vmK*XW?uFsci(0a3eu&JnDdas>W zk7eVBWz|%oep9=5sm*nfe>8qQnAjG^QQl<2d zEvc#>!nu`t=2dTFk+&*}oj)9xwHcyZ+k{jQ8>2MBy9PFiTfkFUqwL4R0}=2l7A*a{ zOx~qwjs@cj_Q(OUzG$)juy0Rc6x!q*Q#DPzN6xSFg-9Zr;+c!=>~wya`bV<^>zb)} zp9DGt@z0B?8y^%kr>003qNeIH-I~^&%qp!#Xw^Q!&-5hEOQ+RT7{zCNRaLR=@v=Z3 z8M%?=cTrTXJYYk^v9ZRvSJU4B9WhUl2@7iYM)v!YRijO)0PC(-;sOtG-|#_Ow~`Ee<-a2fR8wo1yrWBQUgk=PDYBLhbs7CN&dwfgvB;8lwCaxoOsXE#h3dIg3CASF@4yZ$>Xx>s^ek@GJV1t|Qfbdy zG3KILR2ZIWpM4@e_*>Xa@6-jmXOAl^&t#qGt5h4@Xbli3UOfHmjI@5a{H)KHx74wU zl+4Hq3z)TD#fHX(`KGv1@|42wPkY|zZEjklZq7`?&;2LBxQ`Dff?{F>I3=U&(tu(| zUwmlnf&Bqt4B5@-M&^cf!S1V2lMCse)b!cpl&^6~mW z9sbtTzB=Fk=U=`A{NmUB zb@&RD2-WlyO2j4Gxbc+4w`a{A>XWMbjGe1zoQQJItL^MdL)3TQtFWgLfQexlsT?tt{o?B_EqAZe@{KdJ)SfcXW z6Gdsu!}w#k^38V(>=Nks?jays3SdFAadTzp#=m^*OHgG!YNgmU`=-_feZu}g=|k-h zp-V0!xHw==Yx5>aWS}ktC%V~Wb5yIS;Cpb3bO_Onyv^C|{$O)2!Ya+{Y@z*7#01T2 zoV+sL|MqF^73Q~0bZO_~x(jdg)qJMnekNGoUpnDUY%Z-hU=2FRR+vy`LkKto#Kz2_3SbJ^ANP#!y2v+8hr#Mb$iP^r^wx^3|E`j zjMmcdX4dC34E0)7%bE~-KhBxwsJ7*s=7yLK4Bp|`=gM4Fo9tzd9;Th>H%gVX?l7>B zOr(Nw@LKtaYL^^kK^u8F`@H;%2Oodwd!-6XSyWPd#8@6XO-wAhr2)%F6KU9}>{@fh z;mU&)aRuz(S~}h+=_$a=TE@TS!XU}5kM$& zCZOtl#BA_jS!H9DFvo!E%mPH{o5kHG`}z^*DIC@EeN)ldsy)-joteb7dDR&`5tTO@ z!>)GY--AkVA%W}y2k-fLy+b!x6!~jL1F{iPLHW~tzNgnKPNiG~&8UNZ#!=wyx}0lm z1nuf%=%@6*I1o299Ej&^<2_C$R~msyccyq3=}@aix6TuUP~>$1wbzDuS%v{(sc&9l zkcU3yv-A)QI9)*rCS7v%q}!0?<@_sA2mOC{ia?io8y6Q&oto0HOc6R&>&muae}R;V z*jdC2*Q}dJ*oxdMmf~`1sJS{uqhW@FsDa{pr^|KTYWhvzOwit>wr!WCHa!aF9i32_ zB*Wu%1h&It%dkOZza(tbqDH9 zmipVev`Y0>qlwxBc7$owVVT!%JXNM}4om3(dg&fxOW`_f_jFE38ckb^ROoMLI;c^X z=P#4C_@cGVsNiy1@0CbMvt1e~Sayk&-0SivJvLg^&M|o%a|dJ_H^$Wxip)`Eo zlv$Z2-Dw<^|H3xd^7IUub?*C`7yi_}cc<)g{ubFicL-y`QYXpS@Ow)C&DwuBRbE>C z6sGetT;yESf$3tl6RWZ2N+2U}qWXm9d0D$G)dRb6_bC^c@keNcCoN-9f{RV2TLO9L zB-(Uj?(oY%U%zMEX5V5EV^h4eWE1>5FJ$xtKxDjP+9T_xi~CRKEBIYBiyaWQkYIe+p;le5n=zdN_#>7Fd;0eL}i?e6?NZWacoLI z-#-aq^i8!ikE8rcQ>KBGM( zxj9;wi10MTmCaezMFPi6mpwX(qFbe08N=!Y=Y0XfsQPPl9#rAlDg;#1W(&>eqx0r}o6E6gIMy+DAU~>X$HnlyK1Z|ZL!CK?n=mo3 zMZdcYjhX(>53KFWLRI8-h_<*O=eh${+TfrFx#<*qBjM3*Fvp+!AR002OU1oZ-6(ko z!Fdv+x#kCgI?b4<9L~i;IostVbJY*fT)(+u+eb!8$eKG@(We@UIo~YRHslc0{2cHu z1L{y-K|7@UaJFesDYMU8g&I*P`?l*@3Hn%2o)x-6eJX}MFHp<)DTx?QOUxa%VONCSVuX))H$asqkxQsyYf_Le)S6+yPh$oZExZWwD?J&7UI`ds=nDNVA z+J`Uwmq_Qt@2{-vgMGolx4iOlF*jzk-iuX;r+q+tG7YfI}(W_S|jsL02Snd~rn+eCDd zNYP)7+^gd=Rxh6a{3=V=%<HS357(GFanO*DmKLwF6>?b}|>0 zM0IOTgFjcg_lr)hoxPNduw((;{?JkSXtH4z-k63J*)eANM|Q;)$n$gC3nMmR6GPv4 zN4pt*w`&U=tF1euN|$vj@fCL`%MQB0W?k*vN+p9Id^nE-3b(l6%@ku-&S7c#Xcza! zngc+>)AVxja2c}x{`Pv$xge}8OEuRtfld++E{8)2i*tjSO_QeX^v!j};E7(jkL8(F zA3e}9mgTdX?j4QNC+p%$P5NS;bq+Lm<&bM=EWMZO3=z30nvh$lorz**pEGp{GO~VL zoz+((>Eqpa^84z!6jfQ5YNfzGf5H!wkJ8rzCUlYwxAs^G7x}&GR9PgCRH1IyIZ6Wy z5(M?Vxoh$eI@6@Wu5jvQRuO~g{B3<-=q;6euR(dC`w>nd@oKF+003o79_6=bW4p>!tzz;#eW{z}ZR?}tqOOuTiN62`asqb@hA$16cZyxD1E~RZL(h{U_SQ z`xaj~sgL#2VtFrY)uYP{ESu!=pa2?fLy~!VjVBz#3LluJNScZuZj=3(;0O>%AxD%e zPvB^<8IBv6x^?t#v&^TX8nflTdS)Xnru0e#l{?Ptn-AeWhPyrF!L1Ve91MKRv#|R@0Dr8h|V+CgQ42@bLKFq zg#^@`ol8yEsFcQ-o?lkV-4`f9A7j|uF;h?as2EzjcV{#O)H$OE7SL9gS)bD%y3L|X zF10Y{K^N_}S+|dFov-MdB5>hg^TVvYvp1y-+EV5p)qR|Qzq*s%!STKYPy6=FAYB2O z#@I0=dn@nBs7s|`jxir(B^)#Z!N^L)M&Nexaog!WTDerc_~Dfv@oM7->CV}~&r7i- zrVPOl8u-GMP*pI z#3w4NO{Q(?3oVewlz8ggy}0T_oCG(ffeY;5??N>KQgb^AZ*b;kS2ha#7XpF9-fKFmaHB@`Q4+JCUrV4G-_=?q+m*-77U(|Gm`AH64h%{C7 zmWq^u@99&B#P=_Mk#M2H%RAbD8CE{vl_}>> z#%oQgu*|aIPOf_C+POnRPEiVuHiBxc{p3~4CxCHh`{v2wT$V?sDelP+K32X?1#;{g zEOjd`-%uGJ@s_^o6cPPGvNdv&My@|y9%-Ew;JC*M<|^Wmsw0+`b%GW`eLquXWG#dm ztHYg#fBySFRQdlbtg&L?cK#o&bfDNS&JzLFEBDXwhT&{Qi1jaD?GO58J}l!u09-qg zhwXf|{S{}-huq>N1pWtDPndBdbb;TK5lJqvn3zshq%Vkk!KzGRr0XC&)tH?Qq(-a~ z$Jbn$1=Text}aqaD&uuv8dko{=4^W_-swdm+bHaKTT_Nfa$r%xZG@KjZ@6v)p0?*I zrJ=uWHxfHlxX^r(d#~woc<%zg-r55Hs<*h!W_ocdsrF+KLcv@&MD9l}8CT1>02M8A zrCo5M7?V5NdO8QuFuRoN^a=7=x_@48&7L91geQn+QTxS$7DOpws5zTncoSuPgQk)*-K9M%8{ap13AsMqM?t^q6c5{heKla-VRC8D z3<)qv2w=KTfHJea2>v_p{NXP%V_h)b_tR|me|$@OIBB?Uy?^o(#o?|*d9{;%%n{NlYXah(+pL)viorY7ce2d-lEOq^<(=f&n}$FoykLqFr~rc12a z?+IUa)*Eb2+-_VeqPKJ&Dsit$Kd$}CCHum7t&qN1io0WJkjp1$v-}I^-d3+K1x|j- zbNCddcH>)%{D+Ze0qW5{*2EXJCu|)-`zzi!=S(&-K&3)oP+wJQ9B67ZV?n8Z2Kze? zSZi_{aEq0c16WP$81@WQR*lhU8wcDoq!>D9e9F{>HunH?fx$Jn$U2kDY`<7y$F$5w zGcBqv2hZNh^dnl-lo)PkUoYRA@h7Jt>C~%v)pWxdoq=VU(y)trAEow8*FRbhe53y& zg6LhopU}`Vali0b&AIzQ)!&}JZVG^pw7N=`xQ@0q?8_R~0GvmVYR5HQ?Z{W%h_olV z$hdv;S$XqDI|2wL4+f}8q&oNnfw@Iz_O<_s?VA_`G zak|1|%vo=}h?Ffyh^U4kJ#4cK)wz!B#uvflDO;o9}6fL$BeSzud!0j|Wx*LOi z3r6T|75Ui%EQ1VF4WP?$E0ZOSgnqK(#+T`;eI!0ejy~8^{FNwu8_}$zt@)W%|E$xz ziJA2c%J_W?0xA&K~M1 zjKy1?_OCEIb0WmE_5$^)N!e#!gX_7!Uc?DLq)OkjPMlY*$XmiRrNjWFYNXe5VOu8H zpI};Umgh14w7J%xL(ki+q=D!2uL9lI4FS!8rkgUIKq=@7Q)W~GVjhfAS48i+0m10^ zNV<><-LBnp7%J@0IY#I0N~}=nO+uSsz3SWN+OnLDjjU?KWo=qv1B|W zSB9kYIThRi%GGT{8%r>8Qs3*@T_@v>xCJx@X47xh#w1xc{+T#Y=jZR2C?>cdH!u8x zq}fLCd;Up!adKs(&Be>hvPBeM`EprS+Q9ayr*3xuYqxm#c4Fv0;{qMk4(u;@h_xvl z=(qxSxDNBeNRuR82k^3dTT`L|@X#U-JtvFc+VVtuZ#_2|VHy#pA=5Akv?x?*qbiFb zu%{quYqAt~@{m(I>2I?;NjJZcvnRi*2eS~uIrpXlm7vvy%b)mck}5Lw4;d;gM|t)< zeM!f}42WVYWYQKj101`rwed8(53f^9$PY;DSklPgQ1MGw!f;BU6Yvq%ntl~ZCvGu6iJSGTVlO_jXYI|t;K35?i-iWZ6PeO(X(mU@5>HKM}USY3_vU_Ddj+4^YJ zG=%$_RrV@c9)`^Znxc z1J-tFP1>floO-7gl(^JO%nEJC!as1_Zf{I0(hKky%_-e)39gm+q^_*oU*)Sx$X-^( zlivZm)QPqxiL-`HPKNbcjtWW^KURAZaXmOyM39EcfI67zvJ+U-*rR~3Mxwwr1py=G z5Tr~O?#eDm{2I=IQDfLaYWoJ*woJ(6C4{vf-$5Mqm>#bMuL4OZ40R`tx{ZvO(iwyx z%6@w0rau&dN+I#@-5Ro`ldB&$8D&iLT?+2vTYUe?o_@Jk=?9-fE&#t5q=xX88GO7l z3vYR)m;6gsODSt151Y4~j$RL(j#1_8DaQVRf8iY9DA7x|&a%RA2&`n{nc?_$Y&9n??(bkVJ=U^<7Yzp-7himjdhBm6w%MoA%|cyZC? zO(t~M$L#qhyVzLKGfkih*$H#}I$${zsIDsSVvvho0Tz_Fk4xW#!!B=|D&id-XB`ew zVt!NxXSwn^wF}&LJ@*iHX2S(7_!R%NG=bEU>xu*kq^B)pt{VofnMZt2bCRAb%w66+ z$NgdnVphHhXws2MRz6`jrB^3=%IuVu1^bcJQNLX2($Pqur|`2aY3rdt$r7b=$9 z9_f9*GiIUUvK?mQ&Zy#9J9)rdXa~$D+}ihy?-`GcXE(>vKc8m9AVE=k)MT8+=kCw^ z?cfa{juaGt5IeACI3Ew6FJ(H8X$jKiDG$N1PU|oA5|~IDu?-#nXH&q|RLIr}ol6dDCIPh^As&y-+fJf)-tS5qx{BE#C6jB(mqU*-Q zwD4ehyF_`L=*vmrvt_G~t^Nq*#kwpM(=Env6>~Yw+&9NI<$VIz^Bkqir4FxbL6Xax z!EXD(;eQcNU_JNYzu1Rfs)ou#AA2)lk0|O)yMWgn3n_6eDv*E06(Uy*d4+IyO#dmO z?v}?JJNXpGlaZ!g;=6?Xm#}yLNGbj{kc>F%8_pFf2vyMCkTgUbO9IVQfr6W-! zKVdns?nxmF%Sk$i*085HRcCTiqF6c}_vpu-s-VxVi;70C`g~Q%`(^$1uqwG8&9RvInw`v#5} zNs8oC9XOzvFiOjB;L&zW9op`AwHpO~nt2NkC4FTU(mL77V5Q!1}Il*8fYnh0IvPXS-mbh znnLBYWoEz|d+ToP^l~BnIR17U9~U{)dWD{0;_*@p^C!>RP6RxO@Fg}Ix-C#^gniteT9g`Mb0BGeFLtS zUje77nOITB&qke@0Ssu=k^l@G`Oh;f`11Lbk#Cfg^}U(Bt@p>Y4-hEQ`}N!czYg#a z-1>K~Pk@TWM9ez4glV`1{B`{J$5S`%IamnZSZ z*nR=oB+8j8rKV~5-_ikRyr*Xqzfw2R`}@JyGR$XhDVe~k7iH$ukn8yuYR*^AJWRZs z`oRa4E+6!0BImmL@Wq={i)8gNlQTRQE}U;GyYQr}jO~y)8@mA8A=@_~X*45F{BCB( zd{E7*SMG3Hk)*Vmv_XTRsdta5&t~1%nV(xYSS3@guzGuh9H%Z9N?CF2qMHHhR6@cqP5UedKkA&U3uS_~Ya( z6^}N3`KT|-(>LRf@jCKZoI4cZUJ*m0NCVvtkJpfgq+YGM`J3S>b)Zt>fG)^;bZFGM3&I zy;-@@q^(^XRWxJ#a%%pEGiyXQL)iSeQC-WK-xbeSDe3xONW4{1^{`#ZTGRiPl#|k6 zhLCc!(Ct@-mq~3n`mfhIWvBEW+S748MdJ*$io9j@c+8r`c4&XITz`eoRJ!IQ)50(~ z>OMkkY~AIRW~F*#jmF}JryP0=!zfk5D9u0* z-R{mjDZSha%aR(lXAEVtP1Eu+-aYr(%u{c=rwEVDR}_hFr}|l#^WH)#G~d#@@VW@e zQz|`PA#I*rWO%yB*btSPD|XbqQ_8{2V0ia~^vAkngZ@?=8C!X+L$=A5P2 z(fC3IPwQN9&ljP((%z4QN)36>Zx&H6ZWiaH*I>CYSW@HN$BHpK+VJZ`6swy%dBVo; zMpXV9|BX-A=%m#7+G`h{5bAh8AA?;p(?1nMGBsD)ks5qmV_q^6CF9|qefud-kS*eo z&$Rz~(x>Wkz5H_FE-zgCpjDN{#7>|eEjQ0atJqiZu340Qw)0lIGBW1VePOUh{i4CE zp_&rcxbd5d38)$av1eRg0)wJ#LKaXarRAgWAloljGOj|ZN8YAX&&<;RcP|@6oiBR3w6zG(IX-0rQf8pMpMpHKIxi?m z3^_XPb@NSz^=7f%y2sPHRk@Lye;Tx?rrJ1I*nF-TYa{z{7`6yS1xb|{&6wh>vQP9F zo?T8P@GMHao_+q@^LuFHoo)LOg$EhvtR;aHW~DNtb0-C3+Zuz41oVRLte7Vx8MNj8 zD&3WVREqGgap~2GBOkDnG($D@V^ka@NqfdE;R8i0*+Kc~xN9G_1n!qR0Rq({!Ea=H zYAzia4TnV+myk~m1^Xz zBXXrjRyJ7t*fa)dvfO{JcA}i;f;|xH5Cw zK=;awchSSIvtPMC1#r|ZCzPgij&_*ePP%oAZm}F&D&%?Tsi$Sytbvr?r9|@_lSJoC z`PX(eBZ2FO#jGc7Yy_{zohmBl>-;Ti65gGp7WH}Nk(+SxrR)+@9Fo<48W;9MOkh6D zA%l2zW*|UjG8ZY9IYW`1SR^Xe;Z1S!o8gYZh7<3a>)$nRejP)>R!sg%Elzs#rmFF; zREfNM@5JyvR#vBvSy?VxU(VhBGoV3E`^d<@EltLQMz69ETv*_GVP#vYc@&&>g-vAx91gak%GjrN`KEdbZzj?$osf zwLd?0WyEWw3w-P8;w-Zc)xztak>M$FJhK=TY!+D|@Rcf57hvLRNpP#2aEW$G!96X_ z9O-hAUXV4n@Ves^M>r?qS!!dBk51CP{$}`{S)Q7>mqdj>rY1?|#IA6ON}tZjJp0Zd zuh{z)g#~8rul9jJ^42rC%p~5oeDs{m%)5ts97=u}lQA!pd7h-{m+lo}Bc*FdkPCL% z6tc=I{95VbrLS8Y9ne7m{7BQ%`1bycQ%H49GlHo(tt^01ZSAh%Ke$vjYY-wX>QS#2 z?8SHE)k@v4zG})He4IPtblWo!=@ z(dTcreg1F`0Qwm*1zy5Fp&&J3mdVL|73}0AY8Q(z9~XFNKjmMK1@3)&*aEZP*tcIE z28BgI=})TfzkdDiXJ7*r6#QrMEb4zqo?ZD571BQ%24&SS7XunAz07Nxfy23Hi^ky` z*Y^6W@s2Ydjh4^etY&+Ruvq`H6g>{U7QQe?Vj zx)+kCWcX>Bd8w%hxU-N&gGWm>R0Xb|L7JxJnw#4_H2fAfibHajnm)iGbHz2&CB+4< zp9X1E8n#M_raq?6-x<{3&0>yVTa~dMuqRX&hYP3x6~+~G6hd`IcF^&2N|~0BN5xvc z>`-7If7fH*s3tq=$vo$+w(Q!24WaM`PFvSck4KGhpZk4wcna+5Y-)P1=Da}gE|f2W zuEpW~@S7^gFmRjmMrj1zv{~J(!|WCMj7;*=WvRB;w^Q*LgKg91n{yzS{RisAy$0XC ziH>wpU~z?+UMoHuP+`bJKV4{ddd)C#QP$k>vKf-gel)F2|8v4KMJ6|ukqB`EwaU?l z0Na1!34mNat-}W?^!Vjl!{I#Z${4(U-B9>N&qj3YPST~Ft;1^*{3er_eAb@7>rnZQ zUBc9EuWl+J8yT&u&zXn*n!6Z4XHSrk3+J9%x{N~|vY03?rOKF9APXe;{6lMt)E*g_ zJrBB*yIS_Ash_%=N^emo)5yf-!RHst92m{yW<}S8T$zy=2~nTW^hF5*lIL^Y&5%K) zjA=R|3IS#+8{1$Od~^dEq92>5>XU53;TYnAXcBF{ZB7R*u!5#VLNT4|FPZQe@~m*j z{C!dQsN(X6AywlmgSO~iUKZXn5HIcHJ9ibpWZRPAviC6WmoSo%?Tacj^Gja5Mr*ZI zjsxgaHJ5be3dR8OH{+;G z;QF?Ve@?o_NQzuhpZYi5hO4Kbk^Nh&frmsI8b0+mTh|EF74n5YX*xwybc8&pD3SVv z8eN)Olva>r3`?tRPI!W8?u&R^Gpjef-7ch%6`HB`S9UlaE1Fee;1wd$(WK{^=X$c^ zexbm&+}SoK|Hk)nma^+StcsWpO`GztsQdbwMJGzfi;#wBYHsT((22FwZh5 zj#rProxI;z4D|UkLku22g?!ijvh;@LJPkbypq0%n^h`;$Oue0Qij1AkAuC1$8&r60 zaUrW8VpM!)uh-Xzq4&R7r*X(GC@?C(%*ovm$Z9z8g4cY+n z{2q{ZnMovZIC}EicI@nR6u&C5`>ZI=`CYNFE0_s&=1Vk(N=R6T3z3XY#&!-D8Cc?l zOxo_OnwIj%bqrbCrpY#XW&4+Em_N;a7R5GcB`Ivim8Fa#84d@DDp;>;x`KYF=X>Wh25=F7$0|jGvbFarandc@(Af+<81wm zqP%94X5X)mc3nLW9a+!y?Zes;&jn zKbZ-8(U~9CK56^n*4;}s(H?S!g)&z%&Zc>~tXX7S2^}iZpK2H?@&S*qtr-(npELOZ z{1-Q$?OzQQIly7PQ+QGI=OCvmGKdgM6jYt(TtlA-7hqnbb*1c_B*Gwfl#^tVY5{}_ z9N_tkv7%%UDEI-MbyM4weE4w9JYX&xBMiNrJ9mdiKDPRaqB7lbjnVu1YGltBO+6KY z3raTLoDTekNfYCqVIIyRoMDE;?dEgdx}llI|sO~ejTL!pxaOATtu`Rc|Rsmmg5ObZ!(!I;zm)7{hO_BC+`H)fD#Sqsh_samJsxO;fW(`w|?I z&#=4a8*~030drk`%%unz0D^()me3nXP}baYL_{KWc78tH^p=^$jtvRiM2x zvwsJH<-sopO2N=CR#CNp8*{a@(SABPt8%pwst+6ifdY2D^GRgn6?@+6#FKO+O!#_m z(Bp4y7OxCd5sz%&l=VD+n#ZqcA!}H4UqK=l$MF{5GbVMNyP$`*%%}f!Wt{x=*EWiW z(P2wG$-D@us)#IKG#UAlR;n?au5VhwK?{hwXE5dc?Jje_W`tC_H!;(LVC@(u0p9MFIzI+yV{$qaazh z_E%K)gQ(-ffy?T>)2N-M1bAYfl(RAi^!UA&#D#aPPi+%Vo#L!-n#J#R1PM=L$|{R) znk}V9i5qtYm@a2d?(VoX{-=BYGI%*h!5uHXndp`RG=9f`5=oUJ!^Zlsav0XmIzPe` zClgOYc*}dnk|a&h3W|uK?o5Nq0bg5~-fr}g#a!L^@Y~PVmxZ(RjM=akur!}g+k#EP zzAbBRo@NG5_5`?jHI{;cLHy*6z2|kWTMi8~y+uEO0zxe&JMi@63?`)YvEmcvQSyg` zo0O(%T8(XI_FX$~+g*i^2*Uo1thQm#7IM^Ep0KmOZ?oaMp?D{Lt)J1e2I9enzm5l{ zp3L!jaTntjaTik@H>YvtS^OY7b-n{TCEGS%<;FY<$k~##8y~0Btcb9Y1q73an*w{X zgQ*$V_)7~$M#niGhl;34vLE@n8NIDx9t-2+u0tEDiaTx}-qqIyS2*W6EVBKmW}SfT z>q0Pw0l-+oS~yr>x8vrvENDd>XA19M!{BVH2EAQ?o23ARqLu}D(~7KQm8s@t{NZu zd+i9JJk*%#%Rle&c(g^BR+->h?g1+)%19{ps-KRoDE82N_+l%_FZj-(cBbONTjKp@ zWyUb%x(^Q@B~}9!@1bd?5oADDrU0G0I#U?xqYT8h9HswW!1Yy2+N%t6!*EE;0YH9B z#6lnq&+O0)%@<>hs{z$%*~)j#n;CN+;xD;ipwNwoVvQEmShdejKfitujkrgQMDXc| zu)4sd2KZj2j^?#-M7mSyzh^{Zq@iu?eH08p1Ch*1w1I(qQpg*F^CuZLnjyPCW0XpFBov z#O*%_eF!ehLhd{#FfS%XVXM0$we;y&io--=bS6#F1S0t@z)#AjJY}gtBy##_3f;(* zCK>M<5dsX8Y?wFO(8u0++GZR`z^e3B)Go1w3u0T@Ta;Ln69s~Zg;zrJfTwfM_fV)_ zEtIqGKf8{ofhE)qOkbaG)r@J&L)(LCtPgZKW#Hn`@ zEEORkdvNljD4bUF=rZL01qco8-i=iFFkix6Ab@BG%$gH)WJ7%p3W3G%^ht&ppv{6r z02dIm7Np31jpjn0NMg!T9j;OxlZt2D>vLL!fT{#k9W}zI>`X?q^j~3~-yCT|RoJaQ zj)|;QZ_?$DGq+vK;A4aHLI@VuiGyODOP=$!zE5<(4%m9R5v8f0 zP{}j~EKgE6e2i&CCd4&jn}fEC3L(qQjBH6y&hL2KH_Hy zjX6?L!@ish?rNDN{hLEU7Js~Uu+kk4Iulep{Unqfyo3L5!0!Jz`}rpV{*NCbq6v`B zVU{tK0nqYy1N6wh*=}P`-ezYw?5ktDn||IN-d&=706z`mdZL~G1o8I}z>)viC&FYQ zCpwV~?@Xi15jk{zg{->hn5%ZrN%@jkPS3i%?3Kn(o_&m~q?01AEt1W={opxXm|tH^ z56F(Sc-1^tk z{I9S2pI3w_1~!^3;vze`9(#~LJc`{dVsYMPUy@`B1M<04)Im04<0_pBV%@gd8`%!J z{xw1P=OO;vSzup)F)r?JHrdClAq0a9+WniY>=CKv5G!WqXZQWDZvW?Zr|w!EQQ|Bw zva$Z9yyAOW#PMHaj<`IV5O_VGoDT>*@3V=EzKYo)8w_TaiOQzV6_`j;wo<>Kypttc z;_2fl=TATIOWgkwpMUdjHaRPY%=v@Rs9s)%bBoaqpY~N$T>G;r+l%ot&xWUY0-Xl& zG7)bco?l)~H0kCg$eHb+Cw>Pvh(D!tJqv}m0#mUu-b8X|k}}egvyRXGU?|si_7FUxvEjiz$7I>wCLgH|LmDSnfPgwg$*)IBW*HojVzAK-$|XG zut@Eh+LiV4FcS3M+{#w0y>TS!MK{MSG4HK$9W5)G+g zrVm5xjN(QjvrDM_>Xp`gZ%Ayuyx9=^+v?vVN=zYZAEX;_0+ju5Hjs zw=Qs1jY+pCO#4;G4u|!#aWBW}%)cXa`c7Lh%pni2eJ$1ymS#vuCh{@8iZO*9jdRWP z81iyV4I!bffTzirdMd<}&Q%I@0s@%SW#m}kqw%jTGv2O2gg$DRi9&_E{I5!@Ms9qW z>|YwVT=MR!OSuYm{c$#+^sj_{Xil@l**WN-(R6kwaH`tcysi_K56wp=I z&rm|BbXWbTL_M`}^lF{TxY8suQEDa*_jt2vi)Q#nF!`#z8vD{a>nqnD&*7X`op6Y;yA76Nf_Y{XEk}bW@`}@2 z3)*|FQ)+tFOr!RGu436s8A3cOBT1Tp4N8;fxzVR(V|j*g-`e-I@Ctb>DzJt`(C>ch#u0Za>f(*ODe2AKoHm9=4T)M#bk)ONvDRQ|W=;QNaM%$j;k!F=}q;}?&4?OiRCWKtuWHOz4w zsgYrK76ttg>O{LK|AYH0LwKp4BAFoZQ%=%tm;J&hUvd(*(Mg-~8zK1(T|c@igXJTR zU5cNa01;mc^Rybv|HQHTzaPdQilh|4JmwT>1F=kTeAm*dj^to1mTT?V9k?2Dd}lxD z$}Zde(s}OynT5oF?L)aBVtoc^N|rHyu>kY1VDo2IQP;t%t^1)O^v75s_r`fr$*wdq z%Z1wK^3l($5fOWb_9;8z#z8Slp7yW^a0TI*3)8d4bG78FVJ@ag;_)Nje}hk1bo4bB zHGO{+aKp>Xn-g&Nn>GF!32t3sK{E$8f8OB_*^ zOsx-e4$r+~e^9)7y`@8S173RCR>pZ?$zIKe(c@1LGFWHWv>Ul=BL%$H9;O;JPe+lX z9p;`f%C5eNF6^+H zxvyd*^81W68ZBRxy8!0_Pt}-tnEsr?&OBq*T2R}yd1~KC*@20wKFABbM!U+m1;O~E zS!aQ*5r@`Ms>Y7I87chmuonC4)+mYx5+_Nl6RZ0dnfef+EL0YvQs$#UwuIuw4B&T-k893$MeB$&wGVQc zij;$pYjlx6M$7MI4_MPg8@wrskiN_4j)x z2}~ZB1vMsj4vRxNj7*qzYa{Y95tI+uDFWk9R}>HCJMb7}=-~XnYg(lcYI3kbp3}&x zfCUI-vvHGjv~Ex;gecxHM-(?2qi;OoGVw%7M+00N1lC<2D&7AL+j@(*5C^Xrh|`j% zdizpgop}iA_l>dglMb2_9Ri5h&;N z#mjcx9^z8NYldvEfKV$Ye;|EwU?5r8A0PtUF;RF3O0v6skU$;ym#%c0L zs0?hNkFMn--a=v&tRN-^2y%ww+26)=R!|dsx!13JoAp$_K}j-lG}zVFd+WZXT$w7&Z>T-eO@pF$h+z*4T6}rN*o=1Zdm&#~fg4fM`knHKr zOLc@k=`HFR*l5*H21HoAMG8MStjI`#G#}|6W-FM?cA!2n0z_STe9-dMxkXj>w&U5DU;~W+BCj3^00koUB^}`aOL)GJ&Bj1M zDkRozJWY+&Q?Pjy@FdXf|Iy~;zZOCNxg`3>cW{yw6MpD#HVOJZIKq@0)cQAD2_mZG z@V>%9E?_8-qI^d@rl(b{3Yc1TJMtkv>I{=`yTU?t_{ize=li_A4XVdYaH5m!~p<6T01iP9clzpNsUfQcSW9#J4VnY9NcR*yMSpl{A_4 zxoc6+Y?NvN2%KN^4X`C6I-?-HCSR%|WWtAdVc^2?KP^S_x~>yKY8umi2eG zcXh0B(+s4=-AIXaL!421`><9sr8KF8>vLDfb?v-=waS$*GWk` zISZ);B@6e#c1l3-fKrqK{Hd(-gPp>2j7kSEei|t{-d~<3Hn@VWAK3VVqWJVNu1otW zwLWr$oDqk&TM=q$D5y<8cv}9 zc9WADTn$(N(+lLN=Oo!EO^E)Y4)qOj`!4n;ZB2Y?FtkFU)uhEIAbGijNz50JQ7z(7 zrK<*T1eT2B^^!b>@s_#bGvNaTwJ{q9`(~@zOBFOYMJI>)0ei~c)(#UfuC0t7R1Fga z`%6>e%?h8hCuSG2xa(seLJU-#{VQ{qMS3+ZW~rXs4;C}!QlBrTrbJQHp6ZBUjN?DvVg5!=M8QV;JjU@E zYu`o1-+e{OR0ZZ#nH@bnO0_+=*F(70abwAkmDdFoCB)2 zp(&=YE>GHGa3n_qx@8u5o&#F%5^KBekvcCbOQa#9Lv@QW{+QxasjqUo3B6a>A7%V1 zUY2!REiW62Y!keqP{$6>HA|M|q*Mihamz!*+M`VQs(_DVKOWk!sfS^n=byPg1b$56 z>U;eaDiv|=3v>>!CNQ#R?4{t%xkauedLxy48GJh)jzv?vr^ty z?(3_JxvxFn=BB@mW2R++S%5d8uvgjsgGQ_AC;ujgb3PnIWnApbnWqgGsp>VGQvGKW zU#T1G`K8&W8i&kh`JqnGC66q>m=mUaDiHp2IV%LW+w=i$Y*t}xi4&^v>@?_4f6QBo z|gR!WmtbIeIHTr(*ZG)sL-6;~YfS1j~R($am>tISy+ zv3%SO<3aVmCF+$=8`sTsv(~)LsJ&!ksh_v3@z5{%l@NUM4F1MpDGSp3@j{umrN#r( zEkfbL*y`_{-j>vBkP#hEe$*cJc;u#c_|`R=ZxZt=<&@8WZt_xpzqjf4n zVfU2IFom)-Ew%Y|tHRsuZa(JOL3w@bH%>}#A8$JM zC{Bwz(-{}p;Z|c|YmqNnzCx~o%2j1n9fnF1+sIx{Vy0J-T<_9^QVV1ge_*eZ|7I&> zPi`_vH|h6JX6qa{5#OqRsdcF9UKSTBi>k!^Jn_G34+%K z^IT22(DyI_?JaP6bkrM6VO#bbP%obHV({%%#t>E>jZYV+;8*MY%E#-c9~QdGF)|-k zxAzPU93coteyjR5DlA!;JEqfVh4MCi)%n3>ydVC0GsmA5dKDV@&cL-1|EJ`OUyJxg zR>H-z7PFF#U$|V(oj;t=tE~0mjM<5lUOE_8+`0$j)kE^SJ3rVZBP)bzzT~={XuFIG zY#E>Rc@Xta3dBDl5_U42d9DwDFq#Jde%f&O2?2Gu?r`9@Zo>aN4Gh-mR z-~St8beKs)EEJ)?)z@#(|7N?h^<;jpxJman_(a&xP{{Ap_4yX}!`nE41uOet3NrOde9VTFAj1qd#HSR59bl$C)-HT{3lc7ra#Eh?p7@3=bpr6q^ zc%yUZGpkRij!2!4LL9F>B?0GHn-hVAD?AWf6XrCY$KuN|1>|;?Rm|>HFVrvgtB*{k zXWfN#i*tC!$FF3E7$0Q#Z1{ZCv4Olm^BM!}H_x$puxGK(Hnqeg^l1Q!qvQB~8EX*$ zV!Rk%!fO5zqNsRgXCWH$4t63R@SD<#Yqai-v*flfG=3QAC%W;y45W(pzft_C<2Hz0 zm<2hw4>M^l9rH(PTj^8^Z%nKlw=s>76n>s*S`TFKtW&n|v#WEmV8KPn|AKMs{pk2h z)7Y-O!tkj_W_2|AB^<$hGwikJ_sncZeA)EulMpTgqV{n&C9a-d&jotclHnCA|vfRm=VL$A>hDO)P1&{m^NlQ*ki$gmj`QwbQn z?>2Tsly!##wJ-NfkoJ)2MYe1q*wz9_qN^<>8V#=@Oh2cKpWxY8a|kd;6nROnmbBUBo!QAsoxvRI~dEaqDa>W11+h;%$%oESE=2N zvbEc@Y?#U{@azL1r-cEYP#?N}D{*?6vGLRP=#(HG)(Pe?I+rk5GO82x%PKG>N5pA` z5!SN5)(5!00Uj8VaqLlB7ld97?rdV)wpT@^V@M34u=J${tm@mwJ23Aiu&i8IeHp~6 zvCIu=+Sg@@Z!3BVvhy4V63rHFXe>~XC-nMAlYv*s4DyL*yEF|PamTJL>6NNy6+BWQOPsk3LX{zB9A z=cl$ALiElmYQfYp6}D+YZfLSA_t2bZhjXq0vd#|S4CX3DcRVRLCjtpg?d+9YWOn8I~xk9|ZbD1JR1zEg`GKmaCqklEby| zr0;xh^))>_-eA&0)x5|AnC|P|0KZ_|)Ji_=?MRME&}fjXh~78h;5%%~KuivYE+RI* z?+XHdd8;mT1h`rVPk|;^I=A`z@o*U%h(OuI#c8S0T}&F9##OI0K?!d@V+{G}r*>>x zn(>~D=|V@lwejibS7CB$-J-9srzY9girB)9v8{pFMQ&_e!NK#NQueiOnlW35BvZ%< z+z>2&W}CaB7~pKcL{o^3mFE7x+pYiW?_gv+3-$yUd|?j25jLuscm8G@g}03!I>-#~ zhkx^hA0lofhARC0;f{~c z&Oyd#+3kuAKWmQ>g3shJkS5oq4o_Q)Wk}w1t&jhG`mZGPQ%LqH$^0W7 z7^!fm(&lIWET)Z>wp9q4;e>LZ1+Gb(c`BTF=Qq@;(3>HHSm7VRsrNm|`W_KHck*)A zLV(*xRX>wYZ>`HFZw1OyWSp9tZ87Cqs}nfWvIYTo7qa&t9wMUA{w^`vcmq2pQ$Hq}7OZ8h?>n;tiuIG-Hnt7WP ziDIr9UqAOOG}%OZzBndU%PW(H{=>%6p?#_o{RaifY11EqI-CRqSUF27O6RmUWL@Yg z;zs;&iQoLoZmIin_+quqMVQth(v&>v z%=>TY_dlGpO*TuakgJE8rsfMDUw82;UUgc0d}5?HT~mJedEqH(e}_WfH&$`y0;2aW zhrusd>qz#|tmhQ|q6NOsRBEHF-Tt)w;*P&o%Nstm%Qz|On*JGw0~Zlq$1`2yCZ$Oh zxxWhRp*D)heJ4Rd$>f`0e4;&yRKY8rf-HUiSS<&&i2Hbz$Mo;E$u-34t~lSymm`}l z(Zhn`MRyxcIg=#0bD4qtU z5x0%U+O6`2F@B+^sf$F!sL#q#fT34QhhGShT>OEy5mYgT16LX z>3SH}-XtB(yi>A2oT>7lMk9|b>c%|PNFzk(h=)(Yj{~0@^e+_~p70nIsd`3P zZx0n0gpNR;+T5}Gt4JZ@j7K@j3&YVZkgOYgL-x|+-qv_blYUIDK}_ptU{#Rvt?3Mo zvWE=o>;?%tA>IpP4d${vmq#*&Ka2zig{k`q>NxDA(ny#4X+!N_AV=$|aqJDQPt@AhQ0CINtw~{O=Ef!s$6z}sA-WN#h3#m-<34td zdyJ**fjtv03@wF-@OL`Ozn@^L@;&qBOMm65D2k(ahhJTnq~%O`&}Ka!JFuSL^%1L$ z2-8`^Dn8ln7wy3uj)SnVc(VWJt`k<8MIfANwJlj$P)<+KBp$f@joq^R6$#^59a+L7 z14{#>O3iXx>Q_&FbQJf)4okLy=mWKnOHIZkjTY{ROZIB*KaOhYT@~*xT~Ib~@$3~$ zAzjDV6BN@qe-DU?ZSRlf=8x%g*3Mn)&ydK4P1${HQ9F16+J}M~{mu`BUuH0H%J&3d zh9HbuC=kF!s~m_?TyZ3XAp8)7LS--8c}X$#k7Z}qwp3G^g|2=`OO`bs4(b)CQz!_~ zKY7RR^CdF;jGO;Q($QRJa#F@g;a%InZK=f<10_zQ$Ghyz_dTJ|FuMB6$_hhhC@6C%*d7=zBVk;}9$^FuhUp?nxgxX9naO9q@UZ^qDBr zw$!AIy7=i`t)NLTmqd$1k|!a%*?=OJ(`cd0sdM>q!MKQkI;FHMze7q!zZH{5DPY53 zcb-#_@_iUYha5`u0gfM8q;)@3w^zx=Qu%0fqSzm8CcQE=i(3v{B7K())7-n{Swkhb zbmv+AIQ%AWaCl7kM@04J@hn z;vDHmvV#timWl!@jXktGa(m&ice2V&?inSd48A{kzO?Pf$!?i@I{`5fU6fS3o@k$w zc3F|Fwe(2Px@OR?n$IgKi^fH<2@Fr>H`ar_-!VxyI#N!%bk(RU3%8mK_;Z$_P9)=Z zv)tfj8M22_TCd_+1HFZDB&)*cq9-^YN}~DqdR}wBNYymg`An!oaQwHH4v1^Jh>#-g zBO!rUQ_nn$V6;KM(%>I8zjweAbgmBR@Yq2&KIRKV2q!&i=UyR-w(vrk773{6;7!WI zs=+{SGxLJb-UK_rNuN9T-{9?!HnPY>NK=?02c03qrUn+U8{>#C+%x~Gzx3PXD!dZ=5K!9=7SJAooKyh@ zz~rLY+px@u!9$?dKLIoczJId~rFhOmcS0rqX6pkD=>Px6{~x&;>_ymCPJ}ZIlIhO@ zP-_!*CX=yz@I3qiQ~DkK`yV=&QB(rlGhA@ENo@fNMO8w4GuMYUHp}k^g;4JX9eY<_ zU;hW6g~#_xehu+YurC+?I}-DM9M>FTVc;}V!VkL{1_oqrJo@N+VCHz?C2YOr-$vaB z+S)C-z)$}`|LVVwzG2(Ij%Hhh4O_51vf3Z^TMFdd|YnTh~B*qjR_eP$JXnAXidn}GBLFJzDd(E7VAY)eBpyA>{<%N7< ze$!kRe(6ektZ|vk8BKZpIJgt7?J9VW+)=Qq6 zBUuGCP<>DJ;xH|9A_iv01;ERQAh#z`@_i6Ld+2C?n*7~oR;K%?Oy3`phaS`m(Ew|eN~};4-Ij_;l<{%0I_|sRTu@hBwRr~SzG); zjAd%*ocY*wo^TFz?2FACKO0rs7gln{l3c32d0OFTRV1her9+(|7W`TlUN2jAZ3ynm zg->JOp%bv~B5oaX0tW?6UQYA@8zTM7@=d6g>V0ha20f#|jp|^fKm0m*d4W|WG9E<{ z!8(rAI2iu;62DD)Y=-h~>C+zXX(9xZY#+b+p1?^V0n`w=zee-R0FSLFe zS90icQZ4#oi(sTB@lG}mN7UkTW!so;&*=BU+69^vVdJmbgNn>}V_s!bUzr^#ip#@j zUd}KxaTZbU9!ZlF5*@2mRhN3tp3ou>33j!d#)OdjjkBSoKR#(Ge;gvY+C*P{>Mt~T zpFYy-z98Erf{YO`&38EW`^pFbS$o1o2hT5~5G~zpm54ZjbxoOZYeUd(BVyro0Kt~u z*8&WAro)h2(+Nt!kyQj=lb`nY=+F!DEcj}q*-%g%>r97eedX%Ie6|rnQbk{MifhH^ z-eBiycfZfNk32L`9P~Qwc22Ay9bj##*l2j6mWY?its zjmj`D)vGB|m((@N=kL^!hj?=jL@)uZoP;ZMvGpe56hgb8UU1^VMsyzMghmi1g@5AW)J zvo|%i$k3$2C`yM&6NEr!bN~e*(mN3l>Cz=gNJgbe z9g(64L_~~$fb=2|sZkJ+E=3?gM4Bd)7$Ax7ljzKxbG~!G@1Fa9zx$s*8?f1|z1G_M z+1s@W?qOr)>$+If{nH}eooC#ang|p%3JjfYMN$ZJW9{W}Uw8e0()FhBcV+Sr!R-mY zrE94PHL2WQ(?UZ{k>%hipFzfIY340&Vy|St0i@8cY5s@~wDj<$ieV3%M0h2BaTXjB zhVZQAFzu%!Gv~Jsi=K*AyWeJs%+3h14jg{==C$H*>1n|u2Yzb5kjcOM*T(v%21W;x z9dbP9!Aa2mSp3=P6Xfl<-N>kp93#>`569TG^S^~8Sp~nA5t3`Ye0ODxw|xsO#gSBQ zSmPJv*Dt{}1A8qH7;(iuCK(02R2W|#vjw4=u{_DW=ilfbq$zgc574!Cw0)UklqoRc zB-o_)1ZDdMC00Ve(DHRx^oO~f%MkwMyraV!aib~_l&SaeygFa~LXxwI)lJjpit6Wi z{VPQ{2UOO9OD^)RYkrctitXf8l)m0@Z{Vi7kFZWd4igXYsnDbd%I(5$2~T}=gSX9=PAU>lq!T}*d~^5tCD$0h}DBTXO=ONcvr;aB+)iHl!td3 zbr`{4cdJF*$6PP&~``t;tp*Cm{1crA}__m5Ui+!_Q{k#!#5+WYcb$x~>)w-cq)}G8ena1PUU0u9UTR;;5}K!243tTsW~}8^>M}<{8_6@K^w?IhMY{>_=`bN^L*Zv^H6s++HhnbjSkojn*Td`vI)H>=} zVtS5TTh8%Q8Ve92MiBZ-5y@8Atv)u-I)+Gpn8Lp&EwKO4tOHVClKAvK50|8Q`kQp` zL2C&vXjIwJ%0gq!iZF_x_duapAkO5Y@%Ene2mhwM1$LEy13!a*GOT|iP5ur2`B!iB z|Ld;+7RN)AxBcrXlGgvPSCRfJL$^F6WN!}tyLY|ZHHFn`PEPNfjQ?<)oP3e2Gz8a( zaZivdFa*!>JJEzbICajDH!;0XCf!}|X`#ICaY3=#$x7o-FB?ObY>Ld1 zMMFw$p3a$NC|t-e&QLIY(w3`jxR$;kQ?S1Nsp#@7!sNQUx0`(b{({(?#WCzCzg2_0Sx)-G>)8fJ%lY9iA!Y(3)E!-1yL}zc zf(VA!+K$Kbwp%dW6gq9udtyV?KI(W@B&>7?<;-QuIndsyKW+BNyWX(C{3KLr4t4-c zCyr*!LH5w%&QWZmH{Tv>96%Z5yR;X1ZI@Pu^E=e^VKF{yj_)S7sB2w!UVIjaQ5S2> z(5&SViFqA3Tya<2K*{EClhYHDoSCNANWz`O44vCo)KfJaJ|qTR9cb=@E+6Zqg=lnL zx<_?P>Q+a!JS<4*3E|Q^e^QIXekjJ;gg>^pz$O{tX~7p-EN7LfSt$HUn?Pt$K#yXp zV674+JNzU(0jSpfW6>tMv~W9$Sx$>|3de+dp8pRMj>&Gq$EKk7E?1si*h(_Hs$DLn zLFyBIrLe;_rrQ%}mly)o^K*tgmHWC&z1`6A>7B-^z#G@9r=RTT^O0|MO6s;TBBPN9 z6Vz9ldxz{(4$608E_Xk~YieKC%s1J4s;#&0r?Pp8Q(4V?buoB9p7D^bZFFuCIH0)D z*3a8oj7)8B;jOG2gd!ffETti{IvYE2adfSMo`+|Gw|fhxD@tY@ChQZR?>BFnId#uJ z?HnlwB1CREnX7Xb@E(PZt}t8(Zq*^tNA)3#fCpwMqinqoK9(| zyQ#1EUOUH3NC$Kd)Ee)euTtyt?H9Y_eu8E}Da>p3S*W6Q>58va zdW3|YPxpx|YswHcnx?m-iB#i>hl!zly=US3-}%<+i&l@QRIdiuM)rnV+@LP?n^q4s z={;U*EbLfw@Scd7yX%*y8>y>UQWBT2|I+PiRee9dq6O>~Z`bW=-yNNM4e4c_tF!5} zJd(6<-~#S+hC}6@m{YwIhm&08&lMhyfbIc%b&>gbR>Zy^UzT`o^(yU?)+miGy!B#s z&Ir;roNrvKP^+lg=^B_`)Kx3XZKyxkbljrmnw58vRnEmAtT4Uq40?4kiv7Q*sXXV&1b~*%=nDqkhjU?Z2w-A zHRYgcmj~*|i>+z@_@0W4HG22+0` z!DkV3wkz;jNtekzJ-2X22zOh4YE zT|dp27Fp)i;zi>i1Wfc(Lm1ggq(<61if>!XzJ`YDDt^_9_Y-p+JF}Cko_DBh%y4)e zp1>yrtaMaV!y|nko%0Y#to4mO%O@L0?zE!`1+|hFvpE=&Q9WFnesH~|{n#UxKUpeB9N}7bd z3Kljm%K3nV)(U5*WJ-{h+fr+DEJ7}P80pH+aW=;8)s$;Yfxg1Jw@FF`5u`?6%LUpV zSU|yT721u2?h<5QjCL~2VvNkq!{+zb8$LcV`1IMZ$}%Zew4!~mc(Fe-wIg5xHVbRh z#qJviJJ9N8d46<4{Tc?}CmY{ng7aP`3BR4Z9_f1Q&fQ64%W$tsU%qMwr+_fOG#BaD z@szt1NrQAa2Uq{e7Z*M58oxar-!X{W%)sGIyS*b7yX8l-lm+__4m&NHToEM?bx5if z=GqWlxJXLd*h2RKT`fHyOoC~q=?WYCfyG&>{VJvu5{F&H2OA1U>CHoOwntY|p|ahYC{)0B|4 zAJSl$y_}kOH-10y>|AqIQ;oMj_Eo={6VFfc+Ee#clh0kG49}U>Rbs13gv_2Q4wjf* zQ8O-7*jOBigUWJfAJ;ZMWS;ewh9TGkzck17Hif`t)jrs_#%1bc$n7o{<<8-touiC8 zq|Tj?FEW^WULUd-EU5P_wtiw`wQOwVYf&m1=DKxf7D1CST9qI_oZ#U^DFcOehwe+p zwmp|RIb%e2CR|?$+vz=ceyYU(@yG3!g1Ml_i>d@67)6%cchBd}r#uOLnY>@HcV|&* zBxqywI&4pyLo z;{;$<;0JWyRmr0b1DgRt;OZnK^@_&o8Iorw=w0fp_9uY1eqVQ)53WwknE5-}H0mmA zBp(%d3^pc7oD_>vH?F<o=fj+-weB@^x4F@;1Hg8&m$VU;A?s7Ci6^7$Y-(hT#~YJ1s;l_d6-m?=ax$ zY|3`tHFJ=PWXN`>ET-|xr{|w0whGsU^qzkKY?~3#qrtO{8G}Fn#D7)y=4a-fpkrTm zsWg567ai9W8DI;~Z=ag?_Fn`5x{AnGNWAyMj&=<}+=%~H_#mC7DTH)E+AV^N_u)h58`*af6SQvnf4CR_D z7yi7wvG_@qwm$efp3bvevaz`$vcR#0#+1QeKHonAe0h6y{qvRUIbm}W40Ntu7fkZn z1tBJw#cG`~*nZHbK9vH0wjCJ;Ws0K+n{~^WA-L`ijs-}6c+xkvnf05D;0GAQ!Zzn~ zk^YN^^k95JZ}X-?IRqNP&Fh72?*&X)_!_fjY<-?CCInl+jcpRjmowa%`2G$4tLk|# z#IK=`%~j~te>@}~#`?{nKIYQrd4_NKLJ#evO2pS)(lCbK+|b(3Rp6VIwfO*~(K_SD zcS#G+I3%&Rv{&F)boL}TW591}tm7M>Z($skx7L{4iFufptZ%&b20b3kc$F{DGrVBS z^sl?X_X|7?g=Nhxu6Y0X0m1m8Grs)ie%O0YFzuLg4gK3;%ow;|T+PG&7ya{-GxW%7 z=zAVxU}_P@4!}GsJ72)TXcX)^Jq`o6C2g7GpAnISJtT2Kco5wP)Rj zWTk!CNj!!AabaUS$fO+nTs_VU{{rs;Z`+8!=U}$++w}F6eR^uaC!cX`f-jQC1;7c4 z+6BlvY?A5Z_qR_0%Ki!QzBJ52h|}Z*4Ox9O%uWb>&-&{&l0q@U^*{ z%&3YKy)`)o6s*@=CcAU(q+Gjt>IJN4ZE^XpPuK>plC9~v(873ET9Z4;wH>|)B9yEB zIVS-GDFzcmKCDvI#Q0-A) zc>2w9L5#AT-`t}I4X+^y4;FJMuQnHcWc?&)F3@oN03^1q9n6Ws`~)lGm?NMDSl_jo zsP^?C9At|_UdAoyIJ2S-OSW=0?+?JaAT@NFvwpR*# zVc<`WF>%2T86g<>sXjZ*}EPsJ5Z@+QcM*ny-b&-~LbEZ%Vhh1c# zxpWZt4eSQP|H1u+O*)Ur;t&>ncR_p=L~QiyuA$M1pYi2Wte?L#>oZJA@D%YQwpy!0 zYP^Kxc}s?7K9{-&nZo_U5LmrAz6#w-x*7g>aU!Fs7Oj+UPH97aRF@+7T3^wWulG{2 z#gJul=A~O0P$}cH+6A=ZP7t5=2(0B?<=}gAx@+ssD|b<8$9--^fYDc!*LNG2z4Lr%|s@%4MZxydHH8wb_S}xEsiE z7x{2ytAK^7U;XcP3-Hd*LxMgUm?SA(_>~vn*l02_<^#CThGB2 zoS|~<&r29yY&zZq1rCYNnAQzB>RU$vG=ubisuF_Uo)PJ%0qWYhXL3(A1e8!FHq!YN zY-!s03#P!ihCdt;fWWx~%?vZ8Ve;rqQ1sv}_X8f+qKbF6FfIt}yUQvO(k<#(@*c3u zfuoi~0|6lQIzyk@7>pTddj9F_F2mtgz;n_W`mGPImGczO=i zU~%ww6bJpX-rFF3B#Z+7$@?x$D> ze{?_Wd~cw`y1nU;8}YRDg7KrG8BWAR6oR*3ZYO=jjwIUrv8xw5fIb>^m~K!0BG(qA zv1Z#bC7;yu?B1i0Pol|wQP4wTLb1366YU;GdI(p|n-~L8uvTTsBMAGPtE;35{^mr; zA1SukGMJDtxB zV4j2Ia!~6vQeC_CeR?rTwWc6;q1`-~`Znj7s+DJA```s1a2|;_EkjOIXM<5FEN}eC z74nhi;fJW!DfPLyy$jHg#CDHy8NOPNm8$c>al@5QNiEjN`FAdB7ma{~-tVe@AYIl( z&_O|IA-cp0k-Bd4(rl@Q7tvzjPF#ys@;qEnBcaE(IH&=Gq$ygUkMqoq7M}{qT z@@sI1Q!Up)&_l0$0>M16m$ER6qw_x}E+j!c$=yA(kX2Pm_KqVBL&WU2TMXa+5xs}} zDe?G*En0gBdb}K*3qoG?zs-mivA;|t8Ec`u|2#mpGN zdFq!JWjpT4oa@x2p9a?iPtYW#d#iE`6?yKO#H%ZXo>(vZgA{`LQO-3)0h!c?Tzb1g z;4~Bf8GbOE`71!vW$8+dtD{1Pe z#u(X@ucm_GJ}`Ep)!FMwjO$8`mfTM+k3s9vKZJ zPeT7&%NH&JH8jkQy9*88dE%YvV`R^7G{=xf)3owV+mH#CqT$?hOt(DU5_B0fJnkCU$T@f0b^e{#N98T)= z7@^Q=i`;#VD;+*s#sRL|CgyA1>}0s`S@{~xf=AvekQjXl7iQPYLH(mhOq;%V#mFTZ zjy!hmO_PB?k)hL$xY-&m#e3gQ@z~Kg_Naz@JFmDvCA}+@JUwDyWyKeimXGliIW}yS(f?8EflEL~ zHPoLpE%rJjr@Q44RJK$2b-OaSI}s!jb)K5VOYY?|^CGVolhXb5bQ(fq2)s=PKZJTPj* zHvy-5zcOhyI%^6ys#JAKTs=Kr`q*k4PfMV4U+-{TYuu^|^ByWV-EuTjjMsMW>EdK< zZL5wp?6C&N>f%8vSn_;a2fWMj*gClVGi?hyzl9Z=MQWbed#l5}itCVbQg86}(I>HVEMW)yjnAWRJdb7#_)N?ejec{{yU9kvx z^8&a`DW(S@?Yrk$=)H1O{E1#WC$i)hWY25axGOeu|mSJ2}= zTc0&9g(4aHCq;M@(1o z)Cz=d>fx&V2s}y3Nq;^Z8a=!bDJ}RCtoO^F@PI!7%&`2$TX91v#q#@FHn}<)V5Y>i zLNL%u;mOd=nDgi5*Gw{=8<#?S4WX5mC1&Tk5b5}bJgN7XhRC@0G#)8A!yDHfBph%1c**kIn|8NpA+dPNoB1)NqUqz?+$2Co@Q0v#$fm% zxRwpM=L@ZAOyz~grn;YtI?oy9LPPCabDlO3o)wupI19m}^Pf&!9)v+ooJ2_}3W zhg#b*9PSo__GV6hk_Mip09m;cRzfptM~pFlrb7o>el`_H@HB-})QLu^bRP1TE{f@~ zbB78Z(C|)g9t^=MrkotRx4Ry1U%BtiMd^tOyByncGAlv+xXxQ+WWrXgvyo~>B^~XV z;Z8nvRZ~l#_(GTMgCYe;w(@B4qGj}@+;hi<3wL569}DIL#U+E{dn!MPlbpg2wONu> zq=;8e5P?Lvr6%8M+RuIW(p#>m^R{EsE5%*fP=yYXuUXC_anU9_$#WT;SX^!0QAc-Y zW|~qGNoKi)zSmkZ4%I!NX&KZ#r^qISy_5Oid*9d8m~du*)R4)ou=b&Qdt%685=|;@FzBH5bJ6!xOgg*Y#-4T`ZZsl@J6H9 zFox$ZoJa;LStA}Mps8Wzr)8vDcArv*o$Aq5jXki?dsk#|;W znZjVv9T*&RUv!wN6MbEoYq1Wm7}!ANx{+a8x0>{Bkemt*6ahbYPOJ84tdZqzu=|_l z^LFAw3*|W2CiOiLE2M3wFmCR{mz^KW0Lw= zbDzh*P%qLn3s7nlaEEF_y%oa+l_n!v@q!wWI}9Nr{`v-H|67_Np>tY=hAVNNYRCQh zpmYDQCeMB^9)AqUA8fQK(G%@n)73LLO4c6weQ}N!8MEdfa#>xI1eLUneiax|Dl*(Y z|Mq~LF;d%&a<9<4Ph;-1yxC)(Lvv75pR^n~Lt{%OR;}Z=E!4Ln>I|67pOXQhDO~LWD=!=j{&g7CK7Aw>Q4E z@1bH^^MLIXeWsNuK*mnuM!?fi^?YRbj@ic(^~0Eo(C5xtt6vUW%7`9|om}O=l6hL< zt&m?FW<1aiQ#4Dy3-?yQ+q7S3-#G`lhI@t+z4E9gqtG(#)Al=jL|q6i4*D8j8}f8c zoB9)|dA@+Tcx*ac*?9JKmrJL0XXF9@)ADVpHB@s{#TU2Iy;oE68dH^+qWD=F&z4r| zTL`lU*2Tm4m97l-8ilVAS<6MpV$7F>w$F@TH*|JUukHFe`ghyopN1n$A7HQumwi!D zjX{4190Z=k7;gTH{XszSY=K0SdaUNfvT!j?|1d$Z4lsEete}>P!SdD2#BB#q`%^Un zb|HIg$cCv@tzk?J3Y@tOF>fM|-e+LBo|#5b8E#^V0Tl)s7EW6&r%m{Enj^MqoSeDJ z)ylJmsBgDVq1DRvrAimA28EJ0J!5ezbDl77hZCvCoEOm6zSuKu!sqXwAoU5q2s*5| zg$uQX3Y5`m;(6tjn6B1P9MpmL#5DjMNy3bd`<>#N}=B6 zS4`jEHqLCZ#U8Uz5GZe}%u}Mo@n(Beha3_O4HR7Gl28gmtoWHi+;0}ee-)P=m zwiMlQ3sF)Q?-$&>)fJe(i2{qYsYB6oCRr24YUW;aDH?po5ok~M&6xxQcPKnws!H99 zxn~rGnPn(;P2lPB7;r#z9L+lnHNZI_@0jnPrjKSSNYz%?R!nc9CxI6;p46fZt`dNZ6|crF1&xZpmMeJpiAHD|3{o# zo_7d;i!*mni{q{B>5$l-AkE6xkP%|0VHl(3q=0~Y z=FR@NMz2v+WC03B$t;L8y_2v*Q^?3T)pby`yG03*H7F+#2E&>jlRm+!e(Bp3W{1@i!k znEmpm07BH4C6GTSAe>2DLWdUYniBUipU>B0OBb~L>I5B?+88b(mt>tus&Dd5-nIpX zMKoupJC&h7qwGddhwkp2`rA%JAX($nU8f>E-%oDi85*-s=kbp2~xX$trNK;dCbt+OOmS zY7L+gFPHHGEutTRwS75ufX?w0i09S`L~;#=W~sx>)4=cd(Px9k6GjW-r(VI-w;J97 zSCZfV(VaPs$f3M^VvXVKM%HzS8~SFxd9CgJ=7kMmcG11K>5kyvsoe9^oM~G$PUZ5W z{GRX%=I<2D&6(3l_-Gnds=Y-%Dm?y#lWwltnv&4==S&j1E{9k-W$jmWa1-hAM{amL z;dBhdowIf11J%boxM2rRL0D7JapWqJO#}Ih8S^dW6Khp+mqYmtjnqp00!9gmq1)b= zF%w%ovqCFOG5K8Qdtux$Doy@j+H&vOVJlBA{PW8-L7{3*-7N_Cr2EHtT6euDGzC}F zIn+LqCyK2yQ$Y__yGk0!HB67$o(Ij3dLzy|m&NVdXorq=Fiheqnhes2>QkPzv0_X2 zPRgpa4fLwQ>~lOtrEFWxni2kT^@H!J$>$8Z5MZys0hlk0rj*$XHr>_UqHs{XbhLi2 zNtHtC8dGY^!5{m&41whVbm=F^MAI6IOd)j(WdOYja~*ix)TkAF=BUHgY0u=g|4VF! zrvhyL8#506jm-+*u=%Cg^A7j?(^(bKvrFrdnsNzzmNI?r%K3K#$0}afzCK}9QG>6b2rx4F9v@9t)r=}AKYqwqC3wN- zP0h+m{{}}QU2Ht_4Hak?VRb`Qw(GMCd3EKdcVJwb;kDCam5>l%%aZI%l6z`*`+nf9#{$}J)h2g|f ztsVVS?rA%#6T>HMW-g_8y>D2D#@rTZxBU-cdHOpnw*Xj%SrAuPu?Wt= zlazIaIvP_a=P3dM_F~GSzCGo&=YG89Kfg6-xO82N{1lf6bu0gd$yDtFTd@Z+Pu5ZO zk76s^tU4@WWy-6=-sitE=yO_iINY3jk9nO97pQM=kteSd@YBWmaNVv;cA8yVXxZh6 zJ~8D^n{G1RHpNk7ER4d2Wb?2HM)s42JE_3Y?~JnT+?HzVzvVE~zN)+9PMCm!XGkJG zE&B)cUvA$5h>b&rTRdm;IPr>CfMEClf>CLt5$v>;clu=#vE+->Xqif^?LFI`#T~yW zalDA_9;4gC)cQu`wW@YYs&{AqgiVt4%R(XDiKRvC!oq%{nqPaOHez>&9kwWtsuf@9 zq!O7#9cYiTl@t7M**DuQ2f~VXyic1KzUrGhmh%mi!Ta(XuY6|&&|+SA z0Lpg?kUVyP(%q~s7h9T}oo)bf$b)8dfpYl1H_6m!bsd@D^)xvpS$Va8;(g5EWY2n@ zmL0W@Xb(S(>_lkxcwH9PTwyUeK_&ly6_f$YBf2QQkjoU|wfyQ#T4GMaM746Ht~%of zU_x*(qqi`e6n)(|@TlSQPqW{`4BMQ9bT9%=wR_YTkGlvhQF`2!&XlLb9B}F4ODyVL z88L_?e2FBr0NmvvdUlis5I^NID&|(D07Xx#LHy_~bt&q%rIr&zO{drdgV~>A_a2nK zDp2~yrL#||p!$zoVwJxCjK+QWH>FQVuPgFz76(e-t+q#AQHZ@dBT?1)a)a*|g3`>? z=s(lUckDo!yHvwwaR@19uYUpUdzA5FU~35Z@n*B`4x~+s`FHK>5xiYFaJji*$LU$q z)oI(D#iN8+x}rR(U%2E$gTHutY;(#FwXQb`lS>(?@wk;|VX7MWw~AJeyBJIMB^ASS zyWZ4kHTxQ|1HE6L9cV+{IFz~F^pV!UPhp8KpJA43_xueR9&stooNjtxRuu$V?Pf{u zD-qnW`JGk@!iI7+hE@LR$UCOYaSAncmgieGzmj3AJ#L_w zd;?`a7AU7m(R58HwPpH;mPIjC1RIp8Eysq@?*NNS0W40bt`6p#CSOpyhFUy&+wD?$ zn_8YCC8dSUF#HEts2o}`g0CpCpxWuMXxwm^M1)+Vj!G~!IkH&G`z>J0_233={>eSj zv;v9tJUM_FAenVK-)n1jz2$Jh))rNfG`dUWx6u%XFa#tggg zu{8;+@Ns(*8vjBJG(jexQ8LF3V>676&(92w1D#=!U)%ltxS-EY-P#kc_+fpamnFnRdP!=?Qa3G#> zU(ASnxPncU0Vo5iZ04&IIM{RqunTxKMW%qd1qJK^;W|**(jXKdP%*jX64JF4qXS94QYO)JCP%0%0uW(BA1M5DydKC1w~SJ$w`l8VQ^yI^(xtg?=mQSd9urVpzu+J z<;O}^3ptCOnm+NF&%-#F0%(w|WP8(aaF5$rh{Uln#z>u2b|)|o4L13M5vI1>(Q4pp z;P)eFtVC8Rpe|4ZD&8hai26?6jyM*49G|fOHIrsbzW)>}w4eV&8p|@m;{(6R5z)Ex zho%4G7cFh4JWknCX&)~Xu1IS)<}iD$Qgw1LNPQ)rJjfg7VU)=zQxeP=P3r3pFr{cc z)?~vpr5QF&#(ty8K|^zCrywz(YPgf1Ri$`60u(Mf!{k%>cd+n8{1;%63-`7^4ZVd^ z9M_D*E_~g!-&M^Ib2zYtBcAdng*(3^vYN>fBho;Oyr#hH(iIHjo_!M|rWW%HfoZAo zG(8~s$^g6Q_QkLy-^@>#%QGvfyL}~L=twz);ckUV)#2kk zOr$CRPo6pm)(h3~iU4+T&+&hX7La_E?~p9>^iN2(Gw8Z|-e`0^N8kQdNd~c{T)dI5 zYnnoPGFfqqlgrF6ZazQ5=N{73Jjz2GPloL%gxIpBrtEKk$F3-jl(u4 z+j>2c%YMu=ZWPgCyKf%AN-q5uD>!3*9KsS(Xp#Hl#$9i_c~?Hnc&jys|?EctN@$Pc*p<~=~!)Y2O!zC;9kJ~oAU zBMBiVel+==s4qtdT)5RE)}gJ>Hj?=np>1yZb-AvUudV&cxi^vXZ!*FWVh04G5^|i) z&<5J;Ay_bHd{`4E^bv6oecTtp;|HsSVjcm5GX*!BEW6^54ucEZ0g=~8?!!_A(qx+f znXoxIbIG2!j3qvjUNvLFdVN@ABE#?BkqQ0ZhOm17$R(s>{)w>V06!>%Mc6RK@9T5E z6E^cd30oCTlO>|B&cpVjL7hX8?fnB-WloGFv_fRuo>fM$${anQ7?e5eupg`nC5<5| zpX~2wygn=isDwKei0I|pNQ#c*e)@+LgXB#7fo^axNoT9f(dYz`V6@xuMC%~In%PwX zAHTTd=6#0We3<%qe9b(4zVCC-75@l0pb||-xA`t=!xL1&cHV$7?KqD1@lnW;)-sJY zH#94_Q>IQ;+$)D2IYEtkd*RU&`5}M}r{-QiLVu=%U6%kGlxZ2ID7|OQF$(j}ERXOK zdjBB0Yiz-a5)&6!qgc)bir>X^M|@{$m(A@aqi%cLDuebPzjQ`sn=z(Y0%k=%SXXYN zC#8%aUDhuK-iPUxsez@rwat5=4WS-SY+4K)?a>p|hsnA7JuID=S{&XlE{SSDg9?!NLlhV%XApTmoq`T1F%VFPKtX47bE z=b!2tEmEYzUWWf$T`MyIw)}7i6h10``Puj2vg#T()2UR7E#|N^rItFDmP@7_qz1E) zA%Lyrx&T2tfH8l@eEp3DPl8niQWHER5sR1h9|xzW7^MYawQEfujCcVFJ_Q%}MuIw}gK?;=S`-Xz1jQewYVN2%_wpJKtb;h9BMV9TpC82R#z7&mMMK(-V z76n(DExSa4$`C8(_Wsa%Ear2|WT}CNpZ{U6i6BVYvDDrf1j{N;2Uc+{+bW(_Wr+-N zMwy!MwL9&W?@e{`1}mc@_!Be7Mx=o8;~MN24tgFeW@brT@%-t1Jy6ght1aaKczN%+ zdSAYqdSy=Y%-dN{m-3oGY~}nyP{vdAPbfJ?F@CmkVx|)k+o;t68GreaxqF0;nO#-y z+AgQdubRL?Y-898rEtQ1BFDKfjGSC~JDT zZk6Iv+l#T^%36JK!)39hW##CSNWW0fzB>>U7O^ETrUUyH-U0o?AiQYF#hD4F{vdSs zoU&!B=!I%6a7`ue#1LKg$vdR4+0FrzgD${|Na%h$p;S>rxc~l^yV{lVcOee{ppyfI z*+x8iOa#tjf%HM$!dXt(e77P1Cj+_bcV7bZ?Eoh;8fNA0DHS0Yo0FA&=VV58LD~5$ zf$E^66bv5^jx-W+Ak2ON0uIYO2q~po(7X$PNY0r&OFmTor$~mk?yRy=VOn~q6a`SB zVRO-BC+nmZi@nS z494>)5C^t8_NDEdWts1AR%m^}nI70TpQlM3$GCp!RylgI^o*xJ)gbd^J>S;R-`4j) zSjOW=k)4Em?d}I)RmN#hIm(} zEwksYR%1| zqkR~3kd9{I`<+j#XgN)dT7+ML{Sz=qS+RlP?!N(sJJ7IXx{7lp{8bUXEJVDF4uoL3DRvKS9PzZcVUxTBLTj&t! z{oO!L*nZ1h@5|!4f658#J0qZ;g|IC5E4aEW+2cZ|LUyKVo2#qwZ}e5j_dgo_$;Ety zzJad&KJK8uQrBl5fbP>DJsc<9-A|`IEEKZ6eV*j%i8Y?EFc_vT6teFWePoy@Nw`oGzW%l#Ru`Ed0Da zb|Eo&OiMF8cQSQrt4-MHFIX7SX2F6C3l;)O7`8GUz;&>HEInEO>H<|;1egvD9xDw3 zQ_g8w02aVCZ{|UDFvCdmWx+zO<2mx7Qp%pzMnsAxf@Y;{f=-lPkYH=KkoUgI>-a>AKLpt}q@2@l7rG9S|{Kic{-fx-P-F;kQj@7RvI4 z#LBMt%Inrit*=L)XgH}0WW?T%yQxKFAR~g$t3)MIXKc6GcspEm9^h?S{>lj!-fH)c zudUa&IGT_#MA)hc0EK&_OnLfAHYk)nLVn|6q5a}MaYVu1--l3AQ6y!3&?$TB-lfCx zA_2wy@X8~8n&mBkguUUF{odGhUHVV_c0^&w;pR{|&aQkG}KU(0;Kcz;73xi3Z&KOgF%>z(9!La?h`&v%n-Gi2C?e zXG^Q=a&ZmNN;a80fW6s z1O&l6nb^Sr7;gOWk3-- zJ{0J|nEXpP{E4y!J$=Pugu|h8 zG5r-jf7UQf@$WT^i#65Lr%pvReS%~T(vN_4kU3}vU9KqyLp{|2@rWus75;lz0O--5 zr?jxRZ5oNdk`2?K8^j_A^|TwVm;E;E%den^U4sJVBRZXAM(MH&q*M_FP{NejlGsfmOYHkvCjDsCtJZC+}Q!3$0sg zT20~iM+;^IX(iQEov%%CZD;oEw)`e`UuD2NZ{{7%QPn)fcs~FB!GcOaMAuZWuB;Tx zH<#c3X;vG4i!ybJWW*M`4bzH0w_(ZzmKna>9k zM)q336npC7n`AJVnEUumGDM90bM;E_&8B_`Z^HC{;%R&T_LCA3#lz>OU)27#@5rkY z4OGZv6k=(d?dJ9dNxtiHX=h7@+Muke`Gt8@Z5FHbgPn+D9@P9+zUZeJxv{rrC2R@P zhrp`~mX%PD_YX;np^lEd-{GwSQzZ>M_9@mkyVnzHU)vHz;QX{6w$BKKE?!jl0Myt7 zew;t9vURv)Fjl6ZWEJ${e;vlE+a@nHK;frg22xu_*n@R-)Wb)2AX_2q9Tzn@S1|LfRn(Es<$%$hgkM_jKu`&;>3np;?MXWtnV= zO*&t)xRTt34ma)08qup%`>V1led6-(2HJl=PW2n($!}oYk`vFW2mRdy2F;)+u?pnwX)MKUk5#yVJ9~c zePaDWx*LOec_Ph%N!Zp!hHvHz+0kLHN`hNE>MHxm_+IwKWKJqC zCwEqlC^@OHv*TFZx)}A3QeJWQ;YT&6&9WxuKvD=(pxwfNjP}BPoq4I21<}R4jOg|o z&MvWSC;T&wwVb4Xe$0z{5FYE5k@ntxd}W$sgcpGmo;WnGRyj|g{M!tkz7+|vX8xA+YKkM|sSZMQEr--Fy*hO2DzI5%@hFU@=>X9Guhd1F?L-K5eW z!JU=m6_k@rGGvL#5knQxwhO%7(eIlZzTS7n6X5dk6!9cN;#ZfJh z3(uJ&t9gA&5yagL#Y688gJ8BMiRZ>>FcNkuO-lqEBIJ{Gp`Srn-iD20v%1#|WW`qx ziXUEUY`O4FcOCEkb?`#=VjkF>*z552U94;-EusQFA_l5FRmoA+G?9ugIL9Fh!`{o_ z;JQ-$BpV%DSX=?@UdN`NUVZR;ir(hoPgyd1ljcKxALXO?!U1*b~-_+Vqu*u zm6#G6boE`cCZ?NZ1}gf)exB3Cc$Yc-^zdYr&hL~@{LHBNi)=dvIu`Im zM;90j2+tPjV5(qt)BQcyVtp zB^PDptSKTsK*iec4_!)B?*z@b{kFPl?Pq+ybv_qK7LZq$yq-Td)BPf+%Q1&g7c=tm zMvjzZPnW@cj0!_)D?8C571C-Y&0>X_x?aNZAAD(J(!{AxZVx{!dTO!AHdH6p$Gms9 zpQR3RcIF-E7z;7l_bLa)=x0u$Bw(eiC|FV{;TXcLI3_?N$wwnTer?BbE$-=zYF{V`cx6UaTSRVDrp*o`XHKerru;b8Q}29> zvFRSDfBH0ir8n}(O{M6XVXaQ?A!dVvUQN8>(MXTJ6t7GsNsuO8XP(ZS^G+MxN-3H)F3h(K$ZyGXJ10`47ocG4KLgsfpD52eGjR9n zXJ?DP+{sj(^6(q+q;{_T!2$NA$CnF+TImeOii3}z7%EC*4EG>qDuE>IUd*|}(w>zE zes$*h4vdRWBbsWjIZbb`vmA6Ei9F?QVPdDzQ^zN&_I?1O8?YU4D z=^^mQg+L$Qm##&cN_ru(<;_`2l!mn74Jw^&6De75(Xh)BWwuRE1n<(dtXz7|%9>bx zaM@0Hm+@V=5<8@X+gA*sB!oCylWDjyaRGRL~qn%{*dU(zmSvowkBM&b7uY0JH3xNv9DO4YL2Y;KTB+> z)BT|3aFM7LeDV2b*E9&gN1GqBj&jwZwsp-}nh@8IeX?nojB2OJ z0&`}`!p;?g{$0CgTcz}T!hOFHIxoc9IY^FDjkgIWrRHT*_jE#1@t;t04HJ>2GCn#Q z&1Tp(XU609M7P8XuZ$Cjr6-E?4!0U7Z?ls*uVxW{V6QaRwbrEzj^=G${MPnFhMDNl zb_BWIZ2*ILPY4mEY8`4gK<$w_k%->hCRTK}ZQ|v(fl`|Y9n8aRx}+N(Fr`@%S;l( zdBS@ri$5w&R+Gjm&$NaH#qKCk^*z2o=t-uRjq^1zu2;OsXJ{14?>|>*`>F6m{P)Sj z4^ouG^ghLmUj&j`K^Mm|l5K9B;;w(!Z?l;ayS1yF+ppc$pRz}nPW)M=mna|*{{F`F zKz1S{Rx`)s!26O&S$5>rb9*`t)vPRtS(;qu?8zveH{L7NSVmhT`A@|%XV**QKU^}REH5&z(ADK3u!wr+g^Q7-;$B*SqIEmiSa4mdskJy z@GDv;Iwq^zLCMi8e=611)Rt+t@&IZJrkrdi9-uC=7Es1nHeoF!m#cjr4obM2=bd|v z61z)PhUYJe1gcuzeaV#ncEFlb=I4`bnKU^r0M#?qP%kLRE2Z)lS+28jx|5irt1Zm62EtibVpKbjZ|Gnp@-2_~~)OUurUR+nQ zC#0LC{qSx)BCK+@rXlN$&mXMGgqOryecU5*L3#e#Lwfp|S!uaV+Y&T8kBV*GQMNbK zlswov#L|dRioNk@A}d7s#*-%?#pUU?RMI&fg1!wsw5mzreQiACSUihyYk7jjim;dRzdcq};#irgQu(YRw)@X8*t%yA7ylSE zpSsbeYn-^N`+PFVOG$f1OZOK-5%jcKh^`2Iz}1g!^)(F2c&$3|n6!9OxFv#l3`^$Sh-86mAE) z_!;EJq(zg(e_)*T=RYTiWHU%nI0>+dga`)XyqtTg!J$zgrWEtK?!ietWvfm0$h9A1 zs2#87TIzoAO(qDoe4rf6*Zo%WxkEGS@Wp-e)`F?7B`x#`i_R|`|AUXyXP)3x#dn?a zG?)t_)j=9jhwagQsA+s_!;vUzPwZhI8HS#X>i+X#S#p|8N6}W-+Ch80+$T9P9aA<| zTXJ_-O3jCs+DRDa=~Q}>KBBl1C6V?ZIA_@069$>#fjT-FfHQ3|fDBZi< zWhgy4@Rdco+u+PLX;GAkmCLuBKV&-%%T-66s@`O1qc)#zpIqZjOK?jraBdK0%sFbS z=k88)F%dL;a|%qX)1kE2Qrok&YX>|S&tJBkUhj>7`@g}T=|Ymos77+=A1+4}a0MD(LF{cY8Cxy1M@HV{Z(7l4439F(&S6DSPO1p79}}R^L9O^I%bZ{g0K!`C4wl zgtx8*JEQIWg{S%bIm|$mW!}~T!yQo)uBCS`Tzp`0=8p%x>Zu0zfr<->NBRKY3BAYd z04iyDtNR}VMl{^8yga+q?at@^-|av${4WYrksZiScvx^ROOC_fHDG-fK7}_WkM083^jw4eHx$U^V96MlHDb7XcPM$Ph9~e6)5{~-ksMYeQkQw5 z*ss!4`f%Q=|5Fl>4-36^P>+W-n;NcJ=`qc@R|u5B!0Y(;rdb%RnXJ^^E|u7^ZfirrWUbN z6e#fT-#Ms3{uxS{TK)T-Aey>^xIL>2u)=rbEEsrg^y(Tfl#J_+`&~@&7hVMN-&yhSPy@H*ZK`wPT1C>XT9nedx7E_$!PK>Rs=wH`PIVLUB zQ)NJ&n(k=axGqfjy`vV`!qo8WlkKXM99{sp=Ub&q;Lth!#be-F%d1=TdnQ9jGs z-2eHM9TNV#KxGIDF2G6}DI zKBxzSF2(ESK#dJN$f(ABI2cGLd=GipwQ)mrv7Ke>Z%AFdg_@d;N8~1cG36KIFJ6Vo zQ(1rh?JH5st80OvJ^SZ_*gVoAtWcMZIH1q)(y)_SDC z(gIAPR$Ct1a`YD>3&?WeI*R{r{p+qyu5o$bAoYhds-FUGU*wA^0t^=^A6z=h?5)Md zv%S3ZA1WiD0F2m?o}b+B|Nd|xYqs?uSP zP?;#h^bum(9=7JUZ`HVV-$vxO5t_tg!%4EUvUSUZuX)i)mF8OW^LO{3&$;HRR_yJu zt`n?_chX&dt(z*zB>7w=n;Pt+?SrMCK3x2H z_L<*hhO&z2Z>2#m*d+z(gih5YRb^BGSvXXjs|_7tc%gses<4bA8~7P^e2+EF1gEX) zE@pR?o;MkzddqgboU!JUc)hHD!mH@S&*M`L_MIvk)iWcmmMK?1UAkOWC?dxfkyq%> z@GyL2U*vYACPz8hrD0}ZGG8a~i1rxvJ|R1Xn!)Zpzz~}Vr2x@zZZ2YZJ&1d4zNubNx`7A7b0XIT}n`wNMWm7`jG`I0_@yRu~ z5;yEEAL0rEZH&bugQlbc~|uVxdAl4HH#)rM=rK!@vr%x{V9>!*}ukx*S82vC)p!^ zlGdhfKb@m6mW7blf}Od*em1NRrtGpIzQGpvER#`!PwNW)| zm#X^g6v5B<=HZd?Y1zuEy?APw*>7dRx^sput%Nk!!GbHL(vMxBK#T#-^g_XbcCFkT zAuF{uW3{oFii`#&!$OCi1;?XnfxfvKzjx|dQdO(u6~daXu7+AiGcm!>91l2nJ_9i7 z$chXFvD5wD%{>pDb3KMQoSUT&Ob$~w`P_87RxedNdcEeXx&YE_TNu^6#mT+nK?+LP zSbTqf?DX~v6I)LQt2w?gV|=FRc9jDK`jZ)#|v7 zos!8T7kZQ(r7Az3jQ!DJUQ!KWcU-y=Ap{>4xrr^G&Y(zJ4Na@7!*_3cw( zfyUEPT~!yXn{9><`pkj;{A~rg7jw=Z$~S(2(^Qh!>ur`t?>@vtA)$-|OjzQBQi@xx zy3(vP=7O{AJx~9slcJHW7B4d~hGH_2K!_%edf{9qQQx-WTW8mYP&=XoFP`Ls{`BCM zTMMadsvRHx3n68&*;6)ivM86U!F$eNCq-2z3EDeWryXETMPmeVX3YgV^WQ$a;4As? zsi(&3+HKaCl$;>_wou#ymYdx5vjt8BXTA3t*J5+dT+B;hi~Bwf{$z8eo@Xa^CxVdw zuFH4Yf}Vu@{ZqV zb4|nVxKg5}AbZfh=FhsvpF4yFgfQjy=VT-FEb`eIoE^MEiZ?cfvK8aJZb>`|Az5S1 zpr!m#9=-+iH5bbzOth_yKl3Z3L08tTtA+sfsnEvAxRhH@+CFVzbj!mjz}rduypiNX zKeg7>geN*yY(RZiSC~RI=~S5B)gfxb}q8}@=o>T=!?4e&HT-7q9zo4 zYp7UHO%H$M`x|qP7sHz@i%n!~bJ4R&QXqTH^e}v)pP>B63NF5Tkr>rb%h zlhX2vZehid#by$Bo<$dh7hx1-U&}ryIM0!}CExuww`lJA#L|Z(BdcRp}$Sp+?cnmAMrLHhiqYRHp;hfRu8e@kM4wYq1a^ zXx^uA=}ZyE^o4t)2&-h!t+ZV43!Lid9CZ2T@So&Ay}sBBvep@~4F)&~uG z&O;il#EJO%#MbLS&U9RAh>hBMz0o7>M3FM|eegZNL<2Ka_ku|6&a=3p9_b5{gip>X zD4Dw}$kBDqW>)n)a(zF+8mJrvy|yLp=>?sw8l{IC5WUmFh0_NqcPoSgPn7g&J>LAS zXmNDLYHfa?F0ovpYbb}84WI+Vs<YTgG#Y0}hrX=v6deTS;X!uDBTI z4rKiT?#5Q&+7?C@T1W!b?&t{cnDg#Bi!Eh)xPnzcCk#pe4%TSCU4y+j3u)2kk5 z*MNGS`at{7=5Md>8{8YNGb~_UA=tGF0S(<8>XXwMELdv)xd=?C&L266S@<-k67GWt z0r`u1(in|G#%4$VY!741tA{x~hLrJdS*kpF?h)o^Tuhb>%Po4fLuO1Nn(_HzVrh_s z$PNav|8RuuMRspNGP7K0K^tg2#m@4dl(Ne@nE!!Y(xGagv26jcz|mZ>DS*(-i>+%w z&YXZgC$lJRvf%tR9G&wf$EG8gh(X`INt_`$sklh>oU{6W8eS;T{VZ|m zfXl@_CvxQXs$bhl<((_Cy|GHRf22uB@mH}^?JLP{znUh1I>E5D6f|@qL)TKd9Km2Ql)NkzT}J3>MJG-HIczWh4-b7ZH^qKNhY@6mn(SV6G5t zf|%=Zw5_8v!J(;Mcxrm{876ci{A-Iv`xOQ+msh0PNU(j3 za}qEkfpeVz9WgiYQ*0mDf$MSB~^)yS{pB5 zbyBkwSW=P8Nm1FY2b}W>M_WQseM@R06E<;bQvp!8xb!tYyv1qS{F!p+j%RzLD~@>HP%{15Zrpu7 z9xKX@iXj}0uUU`QrG#H^FuK#?d(JJ*SHvTXiJcq931+$-NkOBMa_(f=oqwT}8glkT z7HW)AXn7-3Iq`)@OCg+GoP#|Gdgky$8$Le$b&(}qYEJOViq&+8FFSm~^vj!!F4-?; zUM_UXmXkq#!i{J9#zsv^&JrJb+k2b$&ObMPJA5z-0e`@{rqSzoPeKt6wp|ikl|9Ya z2+Oh0$9J3l#xkXwZuv7e(tRX5<$$vb;cG&gg7o1-=LHcVE(p@EkN*Tg@w0KT;4Db8 z$j8CkzykYi3MytFrOJK?#&?inOW(0hasp!yBx|YQqQ|xS@qG*Jocm#YyNQQcnN^gD z$39;p9rU>;UqFGU8V~U5eO~jy=Si${xUs+vGRurK=1jMq523H(msOI0++)~mhu&{G zr(M_!RQ!&@I;B>cfc-m6*tkj3PJ+?-!TF`JdbVaTE}B#p@GYiTvqk}d9dly@wo-m0 zx&bU68AlNgSjS2bG0-zQO_%^0WsL9b|5TY$&%jE#bAmZ{UXA%s3j;?Tc$FQgy9-OD z4xNor*4r--_z!%Qe@SBb-*ONpb^DQ9LpS{WaRALUiT^M9E&q$=fPW7gx#<9F{{9Q` z9wex|vFl2Xs9%V|hxBv=#|+Y>!sZ1m9r*pf#fqAIy!{{l{y>{9UnMU>p_q@G{{4va z?6B^4Y;Mr9+I*rrKn|v1V`lYK47lUKeEi}-yVEN71wL>(@ z*VlN0u8nmJLg?`J6vUeHZS1e!e_m#*y+r&P0WgkOo4K z%6S$o%wXqt%5R0lfLvQBskN?Tfaoz%@FsYLnHMoWVawKkO=dVqn)vq?%@=AGZ=1f~ z($}Lu-}X^}l>yf67jS-gD3HSe|EGnHVOeHHmYk%aMww}HnGqL_D9Ebo-lEu8U(}~USrMp?u_^BEv39nt+MF?PV2+@w|sCKie-ZOWYR`r znF4Yk2>!I+te>2rRisA23WTWE6_g0Z?lrU>h437gW|_sHA3B)vb-4+|V_dbo)TCOg z8}|%o-ZC~>H!Sa~%)lX!J4-~yT>ZhfcIf}5MF}oT$`as;7r<5=UKVyvfhG3~abY<6 zCI8yO|9k=dwGOfSDD*n)<*>8T@WI3V?%Gp?$aYAHu>1e<2knTf5C>U%d^K&O(?Ehbq7~I6KwXGI5Wrx z+s|2oZXR_W?x%$xL(%^4^pF4VJm5b*?mzw|u=*S z(a!8{)+R`TsfINy@5P*}6Npx4K;9wQJ$ao>1-Vm$ZKZc-RDV`BNbNNGIq!ZUUN}3F7$@1Fa4GW^0>u_vnSTgMRN5QB zqKIMwj9qUHfn_Q!j48qQ6M_I^4%vo<1C|h^Rx?_a8E=p5BFMR;VoBWD?_g}B$&_p4 zHAAf_SR5<<3$Z%+a}Vx_3UCiq z;@(Q}MmzMQ{SyqOe;6Eq!Y=)h(qSGpKB<|$&t~_{7^_p4-zES4QDDjMzqPlJkRVMF zGGN0?#X7w!g^MSqTHVV*3aC-h)&PszvjmnNl5-v`y;Q90$RhbDU8;G6v@k{O5osjJ zuaT(*h>&^UT=oC+>U)Z$BVl3M1T10&w&fl)k8A`VT_+NC6~`ONsm2KS7vi6A;s2mR z`@j1$BuF#8g`NJFornLPdno;HjjA}pT!6g?>}mC<$s=+c7l)Ydmhc}wlY~BRf z>%X~$Re$tb0%*J3MIr16Bnd_*~ zuANiEA0RY6Z)JI7DCcAmzy2jJVq@Q21VedqVS zLIVyZKL&r4ocDe%3cq{}gNtF%)5T&4OgV$YrN%_I^I*L~Zd?n)BB9_M zeQ4ebxeXJ!OWglom&R|Blb!R8grW6!?7B?$|HyF$9Y*V0@Ww`-le0umBNfS2{7^pCu93AqVKuf-(CvEZ^-&56x33~3HDoUttbws?0Gf7voJRNHy ztOt)WZ@x)k?1{T9a0FB~jC)p90pI6T(x=0>tj||R+7)jlULqYeZ-_mjz86&?)t0Ri zqwZpr_LK4AvOTw{s*iS1;0H!8CDRwL_U#St3FqEwR=|Lcxd|Tm=-IbL*E6=d+=|N! zZ&I)9=&BH{;q%rK6h7`yh`zRP%H>q#(4^eGh{y{^BF~(Vluu~AdgJgGcmCvXrZu&I zEM>-mX&vL+YuMi^_DxPTA0*_RNNpS9G&^*)!g7hL%a1P$$``sk=(61Uwd9jKKfYCQ zA8YFF61#wq*D9+NS&<#+oR?tMDq9qpke9(bH>09(xYf~9M{;O#!Te2@+)+6vbY@_H zsugQb=k7g-letiROI>&QYsk-tjgDHz?|>XlbQ?^cd8BufNrli&(-UI8m(zcwdHJbv z?yXeOd)!l5b{UWFJW!Z^f7{QBCT*~DoaQC#KyE`tSqJAuRSGI7;rhKByczimOZt|U z14WwN8m2?4%z@FVvjbY7hY{7dwCqi+Tt=5Mr>|vPr>-{g$T2%VG+9EJI%p@VG)3BV4x{Epe zi~wvjOh%IzNDZ!xtj)$5iU^L(1UqyMCin3-6O??(=N|D{TCgc$O9>|Cy_KLPFwSIf zsaWJQfqJ2@QkZ01K2Sm1I?}}n=@Fli)X};A#Rj@DG;z>=HdVAO_qfiFZ*?Nu_X|u( z0a_+!7X)yp%@|%%#R3o{5hZybC5fVtX%6uO3)>FChlon->PXEu%0I_itk$|R3uW8i z6jah8D$TZz+d+w-QM*@KTTxW3KWM`7V4GX&sl+}y|5Dtsl78X=hML&fB#a{JE#z6_8ViNT7% zyIwzs`Pfro-0SK3@5%Hz#76-6Ur}2D*9=ZzTXTu^aCorOSK!QEV?lrU}}AFKr6@B4+Q#%!KIZHH*5 z7Qa^Nb=<`ObT!pj%3OP-C^0+R(Q$Me^IGA(v{TVkul+}!B0rF$QLKyTyQ4;2i9K|% zt0^_fQo^|o6Eq1f7J9=*aUurVU-VI$$B^3yx?W@v%)Vjm>UX)+3A~JB2PuDMZC|cZ zm;6&yzRnsP zku$9$3+EM1>)j0Z;CFBU3wo#1)=wHXG*&D!FP|z68o%lm$-n!y zR=}IUQ>^afpx1%filf1KyfN$}N0U)1a5QF1&~L4y81uv>k4nBX2yF z7kPt>Xv7fJ*pm0@w3xLVa#REUxu@RV;?|z9EX{szfOD&THXQf1Y!21zqg1JBe!21X zkalopnZ1d#!N`?OE{4aDUuR+A(7xq`?eGZLSaCi4gojM2R&=ZmPKe}1jskMA4MA+@ zcG>Dg_;)D$G~^A`lp0vBaW4twZKLyT?b$_MJE!#&vT?Z2e>VCv&q(e!f3;tLBZx2h zzVdMIo7{rjFJ}AZ@7d98yELwypRd}VW*VAXR}c#%sE+eu>!Ok@l1CVo3%ffEkZPK4w?V-?S3FvyDTKTk7p z2(Ct1*~f+}WSNGO3PX z)+=eujdMMTncDisj-e9=%McIpN+|A`f((hO@TY{MMm4N@0*cYXJ(WR4iHMyl>)+eI zs~02a_7rj`a!ow`G_Li*bQ9L2QH#_p9jcN?74|V3v4pn+2YjIUf@?-&j(O||A;?y$x|?Q_5eu1y+jb) zxN`d7OxGZgPu;8!P&6Ha8|OLPJ{)Qg+Nr3)B1Le|ur;Wo=N>-&L_EvNYgIVfnra|E zRO!8kT51Q`j$ln#`>(O^3Y7k$m`qK=ja_=bI60C;CF`A z5ex5v;$UnWeTyIWN%R(}1YY?mP|+vxli$s1pKIY=j=I1ue`4 z+rQbJ@x!d17*&IPGq$?^aovdIxi&Bb?3NhA-KDWV2TCk3zWRJ~{n+5Ne=J*Yc_Bjqr5(tEsiW&k+3VY4H0%rME%Hsgml1)*EIaufEuybn+6qaX7nEzh(EK?U%%= zZYz&NW6gE=7|r4>GX`p`wy3z}&NB;3xb5S!YZvokv_b^ke*VDwzYz&}2`GPk<7fXE z)=uf8ie)Cg?-1f6;n*VK3{yD^HY!%@%^qr~V()y`qSbJ~ym60F?^3<)+eP(d1vB&X z@%QgXF$s&Gd&Eud*S5QFN-mD)?jkV-leS$V6i@>jRVw<5v}TKiM!nJ<{2 zzTe)-g;(}I=CAFkUR4N|Ur%~F|Gi0GKd%+!i>qO^8rJ5dRxJNG^rQD`NbzP{LizC; zws+ZyvW6aC##=n?QpD~{t{$=`T9;bSr~GcXe(Y#`((G(UG2V>T?R!jKC(>X)SCieC z^XmJ!AQVH#NzKZN3KmTpNU?qHFojJFU4P#{c+Efa#LVouz0nBA(_7AT+^XPPrGP~Z zV(qXTqB{6DXbkR#e|u=bDhBi7jvI~Q+=kGAAw_DLx8gYa0To?ReCPp!H5DahpyV}F z7x3-%vs{96GrV)4(!WpZ%-7gq3-(|~l>hD26gOM#V~QX^*(}Dp->67xJ_d@mknsRv zNit9;lryAm!@H+P_qNxwk21#VbEZd=qUO0`%uK2Fu}Z;&KRch}AfHJ*(#VBbq+&JV z5%jDlnC#jAV`$jC60wprlFcATz=EOOLTk?!;vpcOG126>6N+Jyc8o&h ztp-O~!x5N0FWl3W;wqEGY_=}(KseTF>z!FuWRREp!q%n#%WB;vqi2r1LZQoK5 z`f|7rIz8~@j{NRWb!Ld?c1mnz>Gu1 z6ECg@lA1RygDU3dxHu3?xdCT!Er}}@b%9ropCh@N#f;LZ8CL8S?%^Lf>?>FV6uH*T zTyL{Yr3$bGt1@2_JQwV%YX>zyNzyDE>&DbsLMTX^)L|gQD(3EpLpsW(Rx z^ViSV04;MuJ+6O=fL_kD%4^7e6ImgJ)V znmklZH4yCG+-gN0Q&bzSponGvPt!^-A!07Jenib@{)dA3 zj+~L*$&dF7a{M9V^spjaYA zO~;6B0+sN8(IS5`<7D%~DD-?R%On}Xuj4ng*kwp`GFBWu0$OWV6|s~6i;lv?#tc)0 z8V`Sh-;ycd)^J^(Ee$VCbmQEa2^g?d4u5W$pcn0*E+Q z(hlCfOh?B_$`ThCBq^=~uTVYIfUtYfF+M0oM^PUNVWI`U_s-gyr|mpifE4!15=)@F zE$*D%Cxzhhz{$=5B+8lOjpPUapKJ&Ld3BIS46A*|Ad80fj*8?Id60gixKo6`>jg%r z87O_8))VeY@K4Za)lRocWspQXM}dN8l&?|@ED2H1v5F%CGDdzk+fJYu4PcxKUsNGb z%A{t$3UmUg95k$b2yX+98lcFufq52$Y**R$bptHD*2|OQRjxx*DxkU+Ho&!MrmjGKTofe zjjD0&igq`arC+U$=C^LbmE_Iqvo+vt)b&GzJrhzLs2Gq2rOJHz;GiCuw3<~|zV0a68LQTwQ zpyDphOVxj#;bG!-NP*uq59OSo-3+=>-5l^lk3H^i>^q;uTs5K34dz_v9ufXfK(AO96_`7Uby$T}&s z69#t|Hc#-~@N2}lC!;{bzq6d-NXdgFhnr9ctUD@k%_t7*gHO^smy)GEP-zIsu&7Lf zjH~1=1|kmAqxw%2Rb_qho)J$C;9vW1JNwbIWq|*u5xlK<-Ht27i^S3=7UHw`AhBYo zjK%@a8unxsJ2Ea}CdX9*-Ou%qNTM}6^YgeCOClmK%-|qF3B12!Oev9}hh`de0kXe3 zw-lEtN<7L|I``mcRZV40SQG!+X%Ln?#L}N(cT(t?fJuTBhi2(1mDq?zEiN8PV30

!TBu9>`ueUobR&nu3whWJ7I>lA9tkAs6u0T%lM?q6W@(~YRoT)TA{ z3fK~&uoaYM1v>^D4z}dYY^8Qf1uT8Jx^-de7mxFlxaH#bhqGBoXj_O*+|z;LN>jV$ zy2OOtCtrA2$p*aq4OiJg%?yFJN`Qgk1ME3803`nGH4ukKQB~+xTo||{j3K(R{_JZ& zO{|k*$x@)chxjLShZi?tvcG89B#KcS<&TpF(|++)MOB^KZOx2cX2MR|x#8T}`Z@$1 z>qCR~AUn(wQ0251;8Vk`IF=Db7;Yn1N;R8F6HMArAhGU+6xwK-`&&OVD|Zd^^Bq%e zA!b~YHRcX$fu^-zZUkB4s@S=d*FDUHJ#E@I>mt(%MlQYKq=oV^Xe?i|xe<0G7Kla} zk`qvh80!hVKcr$OAI1VO7zYcIq9}h7{4k1TT@KzOi&!>kRFJS1Aa4&^rik5%} z)~e^J>}n2{jcx&s_T6yiWWhw2TSuT?b!>yo1TNlD{UeEK={=EPGC^s3gKe?xwDCkU z>&HycQeM}Hf?!1;9USdm97836cEP|?FNSsxbH!B{l({482i<9#4aC77q6>DAmz1)o z4p2Ja&|3^x=`&+Z{X}neN3&Us!L}NxmJvdZOW&8O2x@#=QIeY8QmyY^Kzk-GeoIQ4 z1M1ensdu|;yA6!0$9Hl`jq`7sLHVQhRG?%;%wxedS>f9;eva~rqRyo5g8Y8tq z^V$wYJ%u`$Q3(bb@Ic*H_+a0)09+Kvaz;gQHJBOL_!XUd5Vd(H&OQNsX~2IS)D{!` zP7Y`y=e%AFK1Xmrfsr~qqbS27bLGK%WwRWQY`{;Hff(zuq3>~0AUw*z$E488k`k8+ zdcqZdX9dPcqDC?`dlc*lg49r@f!79dp4Hg^71Jj*ncI2Vn#FKI!{q3b#t%(cxzAkd z6yy08$xTRTuTB#QOpwS%ME5eZ)!-1jr-OiXp$QSUeB`=KU^gqZlcUoY5<=BZ16>M^ z4_iBiL5jvnW9*pN9b8kkQWQ~zE!9y%JX29U+;F7ZSDwcn~;dmhP%lUSv34H;^&7_F~nnnCZefY}tdR_d^IsO%((dV?TMu_6%^1`vM zMS>2z*9Ov|?$(<6rP146!2()5Hbed5tTQg`kx&sC6lbY*ci*ZhY zLbCD+!%UW&Bb1rV6|4svmq_Rk>3>l6=5bA3UB7q`5fw2i0s=x*if9p26+{tov{rGB zRt1GZv}zF$Q>#dnkb@$GLCjNak^R*>565ThNW!tFwrDldcDA&J%PWn1wbV& zGL7$pwPiy$I=xk-W8e+Vy|;7YSFfX)V5cVDki4rvtF2JoY)6E;#W6oInTV4L zfGH>Qo_l@eFWc3okO0&y(rzGZ7cXubZfi)o$xHH%j@q<`4tX1~^^6HsGhsV7DIaAE z`?ni?_@O4DB%IwLGi)Y=sFs`9wTNH?9@q^B@2ue@Ln`k87fL`K!0HG|9IcmF>G{iTWoP(o9NE#t`nu0ibj~|t@%l-zIkPKT59wl@vc6dPmHo?2 zs{i%q%1N+sAHul(B|ox9FO)|ms&vGH?`B-gpNkFGpcxH!KXU9U%x>`xJE4=vm9HwC zkL2<~YC6JGkEuSaF#20bFCP|Pk9e?XM``mRUH+8udovE255Ax#s*Pq;L(Uj3;lA)5 zzC;__-))4z;Og0ueMm~xLOi@)-fmORz|Mc9rV+0+n>PlR;)=uyZxx!%n%-2hi?ui^ zIH!`U*TTa8vNI+_FBzldc}td1{;)8euXuu9{y47W#?%ymU45%tF#L zTEm@4*o1PY@PfkHu3^d9c~N#F7mLkCtT7g6ER1^(NW#ZTY-^zz)pmJH1|DaCS5EJZ zpykb0GSaCg7n}21DJXi5 z&~N$O9!GjY)jVaC%hXnQlD6 zOxaN+?OICY;`(i+k6I42_%YQUh)cxDR4laQOn2?^sZsX9H`~hXGVZv&wlwU6y$PG~ zw3|Q*wdZ}lm9m*GGO%@mGjrbhD})O1^3&B*+p9$|UOL-J`| zt0rE&92IJ{vAlKRoRoRL960Y0xb9hy+aG4Tel0ftVhJ+AixG@>_y1}qcpclV!JoU8lGIlt0Tt#^~@y( z=Cv?2#IV)cn_~8!@67|^3Iu~b25vEMy)VR1{c25p<%|s@~STByKuys$#KP*eD zIC_r|)^_yL`0@9sKaq!`XPkC9H8IHOFX+6O;{t05;xw4`HAGU|*GX*2&8B}t_T~j` zSslGyRHMWSw2z1bg>WBh(7fPGB90m&*kgEk>stA-8gz0f(JU?d`Bq7^Du0Ev%D>4g z)UJ&*Z%1I85c8QbZhHV_&B!ujz9RSC?o&FERwuOVcBM+3#@}{yX~}I~Ffx^lLzBCv zNXni_j6oev5J3>r5U>qfnteOJ>-R%BlQF&UR*CP-3Hz@yepwG!#V^#KkcTECr+KK$ z&J2byEPIq?^m;UjGafk@0=>>-WDG8+W|6VDrL54tg9ys%GT;Rqmvut2szc6c^Tv(ob zCh^p`jJHIF*cYg(Ab}*f9`2${<0y^7}ab-Mfe+q~273}qbAh3sxki}X=^ zebp8TPnWbysmW2qm#e%0&5$_h7`@$znhCcifcfrqBO zlbX5@~k!v(e3xT|pa>CuEjB^5}A|{H{KD@G}pEdb4 z?8+b<(ypxDhHFAaiL>wzPbQ05p@28B8K<|9PIwt<*SrqTlL27GDb0JPd@Yp;7T^n?;O3e`9hp+)ImF2? z9+Ml*paQeR^7*Z*dwCI=!Bpkm>j$aHSai|Z1yH68dM+b3N{R8wO z6qkh8>CaOBSWv%1KL6Wd!U4ChLG4*{$p!dO;b}h$4Lt>!blA_$J)Li689#L+Q#%Znui=5Jz{uieXO-=_#Lk(QH6OI)RcM8)UkIsBSaB2ARTB80v@& zyt!Ur+ej@ZIaq8pH%TxBACjNq)3NZ{Ab~UHEl(GC_FO)k#XZW^($ieNu8=hE74O9J zOCMhE_?YAP>ey~CkG>t5KU=my3A&dzjJwJCxX&m^HojQwRJaGH_dgHEeKwgcQXY}N zMwXw;!Y;^8Cg*AklWx>sw#|K0_I;1Qx~1d`%b6e8TwxzEeQ8_pZG6j(=tCo-6z|kL z8sTFAq5?#fqqKmzIR_Wg{%)?y-=3NX_Z^Ex#3Cex0>W6>W?Mz=T(vkw;6@-SSzYKx zEkb_PC{E*)3Nt(_=Fc37$vbtkjEK3-v)Zg6H)=L>c9piqWPuIr7*=>B{%$Z$05&{Y zQm8wkRuW!{YEH34%5WzB9DwkKziInL36AVEiW$;7T*jC>2uaqWdddn&Pv|m3hhATD zsp1E|?TOpza{D#0^c1h%h5CvZmpkL~Z+iA7@Fy5~l#KBp`4Wh^GLmL0peFK`s3oT; ze@HZ2VRQu)6xBJY`ZhDZBbqg0Q5XvsN((2FM;`zmlepkgd9|xA zGeWJO&O2VOnQ`b4X&-HS)w1IeTJ6i42WQv%F9KDeXT-(1-TnJ;Cqo9Y*XT>VVwC9X z*d19~dEJY`i9SN6fWbT7r>V~@fHUVSOZP_4T((T>*EYqNf@*x%REgAIa!(ID>li8( z=k}ev(UBlnj8?Px9HRw)KF%bk3ngVw>-*+zn&~T0 z_&3o5h3#Df2EbZRuP4`)6RT9IWUO&5)ghQhMB$3M?|U|M$m*E1k0WK(9IGC|G(6_{ zq26FOq3{#XVTP=I{cG?KThfz%Z-2%D2Y%we5I}<-ai2+uIb2z2tcod(Q=S?Lf5x0f zGI7o+%9)&p%S9E|*y;E1oZ#5&uu}zHYRb1gaJg-)q>}w~e%8mv^qOHf$F5_Jc64AS|TT>@5js;_0P=7o%``;!*w*<1hRj zt<(arvI@xgAeQ=(@jhp+^QEbj~CYKXM zxSkpxQ3xQBL)9!IkYp+iff_Bz{jwOrr+g> zEHD0v%j2u2lL!WKobcK91jG!(`VF}XuP?;uYw>e;G)@hBE0()8lqD5syKX9@8IaeB z-(?wI!*pz5&HsTPgNy4n@7rn0WSLW)v5ZME^hxAya3tEyBCJ)Sl(5;v#%sI}&DAV7 zj1uEZs#)|h$H2tBDo)DMDmN_Cz)HXQZO6LDP5le=S1w11*+JwKv0;bl38K1;K5*B? z8`tmyOxH`$G?qDW0e7uuSYE?8wI9H4pk@%RYN0LwUzE?9`mw{hUR2P7@xp7x(~23k z{O!1V%HXn!75F$U2X7dHgNI1f2+BK>qIhev9uv*qlZiSJ^m6rBl&_REB=@6YG1d8 z$ClU8YC1KA|IH}&VKD+*yc;srIV!lj1D&N1Jg%>KsCroF6=%(??wI`ReWFSlSkdUk zncNXlof{!=Ij0S*5V9NZ=g(>?HZ5=7TvU?w=Zw88$0MpN$yk96C1+r8aLDOKbr3lI zgp>^tgvr;LP8UaWS7DZ?ygZlGbWO%|iVQ@p%vplZWHGQ0=@AERek_j%fPP399_V;D zJHq1k;^EJ-sOjIF$)Nc%+a2i>1)XsFrbBfGbsjn0zJ@i8klq!%L?(My_!yn}bmG;` zgVYK@yTyq`eS&G}A$aB~z;8HuuQ=Y$=*Bu&I73J z&7Dl7uiA`;HVs;~>I;s&T{PI)NRNgUT+3&Glix;3P2K|kU4Y%fLc$$N^j3oB!Lt5) zDt(5peNA>it*o3J#PjoGVO!HJX`#N!jEW}Q$Et1g`^9p@vp#p^cK$N zDviYST`~8X{x!A3%v3PSIVK+HX-Ys6n1pBc*^|Sh^8t9itY*r-RO#H#c>T+OY;oOy z)Fy&ag4D{VL?#>Nr96&JS4USY?p<_g3j2olm2D?>pAVu9BgFE~P54C^t3?DX#l(X^ z6^o<>PW`2lo^|DxVic*=%;Iaamkt$`zOe6Z`6X%Mv9e#dKoBpq$?K%j;eR zP-dl;ufp7ri;5EK=&c2$FwJa5@3G#wOej-9m}EbkgQDzx$;L9(VtQqpvR^;SwSD z*P*w)@eiNxp;yi`|34)f|C5g~-r_TK1YVTj1A`!=QXwf1+X^=t*FGhA(A-G=|E|{m zO6+27G?hpWa#JKl0nZRy@;hR+(U<>&={EIsW$Cr+-g?)ag5W3*Xv!tnr-nrp!N)F-rjPkg1ry^WYh#( zch+CD_uXOVxGA>un}(CQ35Yk?I^Yv!Y9+eRtCXynl1YjfI$J!%aF?Ltj@`1$?sd#F z)Ht6oIvgj?)b?KPy$Jg*-_3zd`*A}SZV%|P6a|O@LV7Yn$@x?6ut-$5Ic zcghS$On0D%3MCe>p9s}T+AnC7{dbJV`4hm>l&4?Ju^_tDCi=4~OF$2^YN*M0P!d1< z7JnJOKe+8qWY>87)+s2cSekgWfGG@-R?RENlEs>mqNX{I74yvBhbTMmK~ya+rzW@> zR|={bwi4Ajv@}VnW8W0~0b%z73*J-h!fWdF6-%(V`W%}FMEGssL(|v`4;K!$DX7_e zPHV*qySEH=P|ap1*;L-JW>Vvtn^C^wGVf+>o?$-pg0g-NCesn@C^aD$V;hc}?jZ-* zwp2rhs5-;7)-G&XYelq{KB)_0qXWfS4qV=*R-7CzlURG@iEEWsO6keil;Thq?IygX z?Xn^7c6@1%S3K*_c`hH#KO4HK@lWsz0kFcUxNutVPI3FghKs-z)I`eu) z*3@z)R)iW?0rs%8Fh&JiFlTOS@LwN?yXKdgu2-ybm#tur-_&P2oWNgGP=7J@VT8TS zYnnigR>z{MtS$i4PhW?f?9Y!e`jfsbgAGhA;|#f1jbiakD;xU6-V*WU0Y#aw8jg|Z)>ZI3-C!(r1!K=w*p zzzz`OQHE1lHL<~^r|{L^W8yRXMNx6L84gilUp;M!5zXK=hYEMKmZXml3|&$4Y0Cwd zYmYqQcnJvlH;v25Kug@uBC3CLY^r>yI>~s-j|eebKd)5FQ>tuXihWLfI>yL2(g)Rb zhgIp2OA}I?GvQ%X>!d(mMbe;rNUm zb{&)VYY$*_YQlPBm;f#b*!OYzG?y`A4bXbPfi;U^o<=4KY{?bHP2TB66;g0t^Uds~D^^7B3nR7_&@H=&sJikq>lVZ~FHv`=+tew1<>%~! z6kczgYJ3f;xK&Wopx&mvw=t4_E#YTmf}a_*oQBcKnHC@hFfhVxj$185A`9CSr6~Q+ z2#GDD7PUme0lPMdRjm~l$c;qFO(Noc#Swgab+Bc1s-jjriE@efpsiyqXuCfsw}`y( z@xrQtWtO>A-4Uvl8V?&j1#(}|&KrPLvkN=fHOeAO-6^0y5?fSE)o$jfZHrG9CVA&i zqqi$oH<2OQx6|l08(B%J>;TG^oqD*C8?D^Y>J=9q@ZA$h^Q1n9qtCylmSs?5MAG& zkDu?9DT~GZK3e^_H?R5M;(<@pA6a&ABm3HKJ=VPCiQ;etN4??zCa#r?3G2;qD8=1s zgPFC-tqYFzWxEXTcv4KmB*gq*U=>4urGl=YOP|t6@~%RtqM2|W3P&9ln-KM%v8oyWWVIBz`=9_jYwr#5WjHkNk)^m z$BV)6KYvO`5bFqBsh1;&*?auFtSe2@|xZGv= z)Ys-;zJ=l8np$Z>}gnV|P#e)~>Vm`%a!c`w^C#U7w3j?%e&bm^Kn*7$%r-gvOb&C8{dMBN;h8 zOC|4LuSGkNXO4OO=f&pazH9vHIBAqQciAe>m+L_P(?z z+?K{;leQbx64Ev#$W)H1E+E);WD51n5nSjD6?%$dwCMpJvmsqtZxVOl)XF;awd|R_ z<=+!&-J2h^=}MR>7r}20DRMr50my-qe^{*()fJwJ-J0JZPF7(JRDs!_qySTrb{-mg z(%#7cn8#^xj~LtN|BGV7s8!5$;LjvbERCIBexR3U8K5|ZbS$a4%qlYOA_JSftn`+A zH-)B+<%iZt+x(VaU!_^@Sz!s68;=P?%#;UFO9NF9v~h^ho=#01U04{<=`#LG_?bu5 zKv+oNQ)47)Ys#-+Ml*DaFemlS!c@Oi_d&@g?R79ycb`${cQ~Z#^Ui;GEH{H^zMMcfj*9R|q7l>?YM*_}8Gs*3kacf(C z^ib#V78=Zdi} zg>#yU#pe9I=lgbuet6}@wRrYwy&7@I3SH~O7$$n%J;6yxy)} z-?Aqp8`<&jX)`xpykg;k!mH;yddJm|-@WH|?V*|Kr+cA(rf){MJg`KhCC1MZ#-kxKMwPPeap zCuHMXq2sYr`s+z6{p8f-Y+|=DM9}5S?N?)#hOH)0Jdxt`#pGxS7`Y2!)GW=y8tzv) zcez25M5X7?P+5`Fp{UK73L&G11s#Hk#P3&mA|3)^8qNfV@Sql=&&!8YxOjyDs3a?eQ|_@Vgqz8$6q)B@sz94=|kp1xqF zbeRdOeRE2*Tt>E2t)sBc2(=m-_QuDml8EpEo`{+zC)P*nKJCGZ1A`SQLqF43LxXS= zs`f^?%#K)U`~l;4X!X}n;gH^bdf2f3)!@g97!CUjYRmejFVi>noL{VQWdNQo70+PJ z>uPKTZgvN!9R9d2Q+l0LFtI(9Z)~;oiFBzqPx)}HHXPB-__7)Nz;N<|Y(sY~eZVV(uE7`Qs zq{||^C)oLcRj>HrT$OwRF-KNgo>`mk`(kIjuLn1E(HrE<(7k-$-p>sCKGw{ps`qhId09BrCL9tybC` zEblSpNDjum-Qej$)f38-GHp zS0Q^uc2tehd=%I#<-kLBXbqXz#YBv)`A~@WslCBEENo9#9Twep_GO&yTEgvE+P5|H znPeJ&&arg39k48(5NJ$6Ux%sm+P?d5c#&4>2zBUw^LJdrv#_6zX8}Hl1#sG3sR^@< z4uS@8aky@YMt-I|uZC_P#hAvo#73MXLh*j=Ru=9{ckYFv(jD35uff^G@>k^H7MY2M z`nh8EEAQ8bnK52FN~19P$BmmkAO_fertF=}I2)!ie-DV;~k|w1-)k zOvIn6@n5YTI+uZJoNcyH&8=R#C^n`~S$JVPR$pX0*dZu9a^uHcjh?mh%!n1BaDD~v zHV<+>S=NM>n()d9N30r=9Fla{)QBfgvv|!Rri)d6fc1^%q6ZntVN0>hj2I`meQ(wD zmJ%x`(^S&TqWi43b5I?N(dxI~D{noyx8PvT!UtHcB02iKg2t+V#RM3l8Yp`O@)6*E z>o!oP0=`=wf0^kvs=8j~LEOMu-KvIjW&1R#f-&UW^Be|ISW{)z=C|sm{Ag|$QA!Qh zHLuq!^Xh!N;pK~sm_AY0^~pNIyJ6`c=1}R;`mjmD4>c}=PF7SzW8HO(hxWRMa5qw* zj4D^6OdVbaQJ$(TMYyu2Ykr%a@2QG|gwe(LDy&j3#*}rJx8&Vy@7fjR;vLGUF2DG@ zX5QSVieoWN?;lHOMyX*hJi%`2O_1afowUm`+`@BG#N!avRaof2XojXfA97V1B*6>m;+d@ZeZP|47}%o?i#anR5t~$E zuWAC{ms&*RX=k-w(lo@O_qJ7ig=GqduG0Txw<~Hhl|@1+^E7KJt|uL% z!S%`JoGA^n!5zfAA)aIpe-FVfAU8C7ZH$W!(b`ZAln3FV(Vq^cL(oc$+lP`nN!VYH zdIq|l?^kT(hEJPi`B6{W$~B65Ho+8{Z<$hMiKrjddRkFa zC1(we5{P^1^C%=-25K%k{`)ar3#`TNq6$mRF2Ch@zLCMdt@B>)<;kpfnfSPI@Buw% z)D->(tqy|UHbG5L9bSr!`&ck=qEMmyGkZL_j#t_%wLN*sq0pG5U+vY72TNVga_S_f%fuL4 zlHus1vor=1l4oV8b(JOQRa`{exXZVPq?bG`r&^M7B$Rs9<=5=Jf;%ySGsTa?g{p_W zBjG~Q-9ob~f|?DxF1hf>=qRaRK}(}~nhCZ(fIfDJ>K+5*D*9!{xzDkCK*Xywh6?Jz z`U{VCukM;+x=Q+kZEsPQ3ZX<}2m{5D3bnbYq{Be>wq z8N;5s=GN*PQQJBbj=8|K`1EPCdaYmIKish+C_(zDn_)$$@ zp(gtz)%RWITC6JbYJ`W1o?J%13BUkRrL5_Q8Tur=b)n!*gvv#xeH(5_R-mdkmF@zX#^TAT_|a;q z^tdlMEbzpWp%s^Lt@~P-`DDP&=Qn{S;l>=(xxV!k73brE&qUibbvI5^DkV zT8V8Cb=pI-4p&9C{9U;G6zP74$E;BvDtho3UwQ)@)`(8A=Cai~R`=GNjymu7sLfc6 z;nIyYCt@PFNA890?%a6v@cBzE=D194S;ryf6#$Sr)*FYTac4Ap=>l$4Q#Y=n)qdWL z*H&sy(y>Yw(}4^p%J9q`gaarr-`HBy>Sy@dgPvHX3Q0cZ>AF^e&n?oT}g=HS!(KnI5 zx{c*et|W9?r9~KICW>m!*_msauj0wsxgeO^++Io4j#cxTs*gs;-IAX)`|M8I7kgaMy5&b@Y^I zofmj@c;SH+kA?N;!xs1^XV0|T47lk1j{LLJ5(Fh^b*W>JjC&fvHUl;a(XWL%hVdJI zoGFKzN4*^8*g6huBW|dEd*$b#&2Z8L)Jqs7yNT)NteF=RGStHDp9SnjVGnadJ9^44 z{?b!;bmsQwmq9ETWMI3vBBdEMoBB&^j{c-P^$nk9$^Z}gk>>m45?rYn zcPExE(%|&E!W8gp#`s5aguxc4z^lKsQ(DEqy$mkyRaslHf(IQ3#D>kCFU|0P6rfo; z3G4bbs(LCZRp_>Z{Glf3aiig#=?Y+?h2w~Wyr581cE4N8LOw(DG>Sbj(vzzV-P+@r zBUGCKXN$DT~PH;KmT#RUzJ8oTFF>Sz2(?Q4$_^`>Ig}+C?#hh$Q(951b$v7 zIEI6-1k=c|@OAcUg|@Jsb6POlbY(C^Y5kVa2Z?GC8}ujoq&~qixIZ9H&o%k$D|V_8 z+uriSW!S*xi`>Z_optK$lP$doj2jYc6P@s|d?s!m(DggM* zT&kL4vLS%Bd9)f~j2f}(J?>)LT9TE$(|-Gf?@El{wB~#I{NVKSIO^pHs#~=W zpxOCUqqxjaVzi(-TxOasq6g^-IS!^Q(p}pSr@|gqyz+j*0XWgumuRkMF&qakCnu^> zV+xZl_kZ8Jpez^;b68J#)ty_r>SM+qq9G6O(tr&;oY|2{O#hZBdMxB;uAotFv~5 zo?fhTsh{4`8QS89xM$q=9^5?E{5cw>JcZ1Zs4667-K5Pxor{wx6|z*@-3?nzDP(Lc z9-xuyY>i>0SC)!hM^6hZ7pD4IYHqV^_#VW8`;iEi6V?;kOfKK(gxW+-aXXh9uZiBs zc~abDv#B|{;I266!KT2AK1Ynkzf}2U9-T^i6Inb?=sph83-8w@8!xgP|LsjXL;=DvOnvS!jsGH*Ttw+ z^dwaExXa!IiaSD2d<|~WD6PI<2Py_P6$$3@0l+*RPyT=@&Q;Cgr6Ea%^0ADm3;mcl zkU99b9xF_axF1#exwrKENAcw25ho4zFS9P)dDC}1*532Y3 zPfbYHy7t_}buA8ocC=wV;pQ#Y9l1ySbuzDB+S8rZBBCBRtRYCCMrWWSHy_n&YTArLU4l6CYy=%8LeC{|WAW$teC z_IN;-vWeO98r^C`0*n>LQhi9Gy5-1!5s%$M(p?sT47TT8_%kBkFY3fqNGaKQikMT<+1Xbb7_Lp zTP^=b{@(F)8R-l<-Xf1j_HFaJ$S`A->2_b(PS_=A)%Y7!>Jj((IJ9-R+p<%<@oC;ro}iT^ik z)>R7{lm`S4JFD{GKW*MNv7THtCr9Hg$Ryf~k)a0QiQG5(|L3^D>HpOR^%JB*BXZ*8 zF_S+q&Mf+y)~lmXMgi}?zd8D)e?z~`J;2gW8!b-u*=TrZN{Ep=2wsWlp!M|ajCvOr zV!81Me*q@Q#XgJ-)Gf8oWLP2*`ozl_wT?;3XUdMbGAT}q-kqv_$*}=o#y(;uJeXaafakx0&w>$V%v^QIqwV4t0xHv6z z&+6c1J_90v^k|&DvN-3J>lsdu;G0rxI4SA<#hZO@b(Qx! zJS*S+wr19o#TyFx&2-DInmfn;O_P^#KOen3x))$E{!CyUHr>}(Ee|0rahQZcZnRWv}%5AQPaYk#V3mI`Mc>$W_&oP z>n?pgFwaucO*-8(PKA2`wi#`ITE}_B&;mVE+YCiNPyWGJVsy=0$C{z%z3u5a{nx*pQw%Mez0sF~vq#uY0k5kSYW@Z!Q4r$4wc0G>Vi z&r<%ebn3 zQ78vn{2$r)&z2T{IQSnr+y8Fa^0TWEff)d6S0#aP{_Cr~}LJJZyl~V+!me@Fx$CX`F zj`L!sLy%%Hc3gz#Y4U10=|Qn97Oofh%~u!N@$P{eIH~xar+u}+p~ZW7#cJ!eve?C| zBF&5e|L}~%2_A_hZ;w9aq<>DcFUZVzmiXO&1mJWtJX3c^1&^bpClrel(MO6}i6vGdcep$OwHJXXo5qdahz3)e{R;*v_- z%Qq->XyAGTPCLnfCs@F@H$gg5xIS4@ggm2Ltx+S%46DHz#qo}!t z$IJVE-5#ifSrKyoO;{i0)|Q**(-ISBymQ_u3Z2_QqhJ5$0sil3tj)j7fIG*l9|r(E zSB~c}dXdB8Gfk!?Sb*VIA@aqEA$ok3{+3C6^;K0YIW3Et@Q4yWDC@sxZz2d+)$RC^ z6Fjixe={5LSjqSwS<}ZmfHs2*s70O}C3wm*@*P{%KCBz0fZ2iq;@)v5Mz>=h#rfd~ zEW`UiaYDvGRwcXjHuw({5@( zfR6|T-Jh?TBU%bIaee@@<||MH25tV5@yu$pAM!II|9;6R=kw7{k_sO=83V&~g#tM+ zWT1bh5A?uDdY8SSU6M6_i9Z>4h1v}xIYJ?@mDsm_KAzx7bN|9p=J=zg6LmnbJU3oq z3cHaLckKC)`DGd?Z|L=RcvbX;L^HP-Pku9|Tf)gh)Fkz|4qmQ2O2n`Go91_A%)|r- z18_xKelZ?BwQ~GA`KFNplaE_rQIJpwb;_YPgsc({5Z?FQrBj|n!eqpH70Uk_iuN^!`bFFmq`Vj#l)(gSaN4V?^p ziJ7^tS;W6gqc?-d$omBxpB6L+@{7qo9$65-c-}wL27{eW6FxDma?th3KExflOj`!) zh`$qvUnSU$iX~LulrZUUn&`_rH0S0||GW~W{4eV2f37RjmtYo} z{?mP1f{m!BPoaRi%tY)}^HU=RGHxII^Jy(SIvbS&CHUd0OFi)Y|7{GWNZLHJ2?p4S zpr<-T6KPLit4X>$M;gcMA3?>R;}OKN^kzi^OxGJ?yTe>tAOgeH)D zn!^YcFxr6N`ae&?`Ml;ohfVzcAL(~Vn>WCaGqgj0rqPz@OlT${;6a-Pgpv$&vf!kR zibTP0|M^u6zY0Gy3g0)-<{o)X(Zuh?R9RUtZLvT7T?=jhNyhWrv_A%s3tP>8{fN$m zv(ZRxUO6rR=4qB7e%_cRejdZQ8G`$k1Fp!a8Tu>yXH!asF2@`10Y-R|C!+u#`h$wA z+B!Zfu&G%exzws(@iX0Y*T1M*#{Ve+IWHmnYK)t!;C{W0zx-SW_2-9!NHq6MkjoDH zt(#}DiJc6_EaoF0&*Bp*yN^B#SN`E;W`t|b*q<|B!gscS*76ZIgPO{k0~9)p2_%y) zVKW(O2pnDyh|XC-yW|14KU~|eiR2L`;}0LhobZB5 z6>7W_DUzc{|)R+W&%E_Ffe}_IbE*$$et=!G% zSJ?f5Cl<*VB8vnY%CVE8ufOn#`l~t~)%-;@Yy=x8+HW1YjhM-QW=VPnkuD%4VhvoY zP6}jBf2l;M_gi~1rl&sc#{@bN$sqg#SAVADW^~hePWy6nkejju1PsUjwi&97KcTM1?N0-K zzZkUo6L(lJ4ffF!8^gF6BVR5*lx^uA0PzGV@_;{ERv_#oHC+NcWMV6rt(a9xlTrp3 zA0k+S#SNI0LNnykR#@a?(CderZ=bx2`)t-h6Jw7gDq=lLpYUxsmCGgOzOL3$rKC2` z!LpQAqoZ*~Ng-53nX$?WTKxr}kwqs4P496zgDrK~V@}y{2-df&KNFi~LsEi0IqeHN z82y^!8-E@h*O@$uei41DZn%lIfFm^wCVJs||K%fwKO4MuMCug3&YH7$L83FDP>>xM!qSarufGwAEUOQx|c(}(LB^iN#(-vo>ovZO89gXptf$`sE$5cKUY>}vbgHy7m z7ReiU1Cy49R)21a*G~g4++*;d*P(+upSULKhCaZ2e=AXav0TQr>-R_BfnFH527-$%V{~0TjYL) z05|X;-Q9otrhP5gxTR;!KC9-90sq%;@R>I^>-Fhb-yD^R&^<~0L1K>$v(BB|mzZ2V zdov7RULoOM%C5vOgmb^lLmz;7@ap6$MjpsTCb?vobomR$u01R_-a#IMtofMFFn9hU zyVbuH4)vrSSkng*Yh3vg+M7q!ZvVYPZW9^-3FRMl(hCM=OniXXIQW3>{++>r8|ud^{@ae%WXNXL=sYS%dPT zDZdnbdxBWF3>kV+b7@3n{*i6Al1}W^6Ml6gl)|_kp5DO>`z@R?B(GVG%;l zsy^RY9AbFht_QJajWwblC6?F{-8rr63J_&8Tq(L6^d51jM`1XNK~&GjLd%>0mu#M& z285Y2XgW*L^I=JJCA8G~oVNx=JgU#GI9Yb}pX-Rai-Yn0y5ggIUL+x}$b>D!ddBHf zI@7ZHUK*Q-4Io|I+`CLqk9Ui|EZ2P#+h>%FJ@QBI)o%ZDv9O*iVkx>cbRO6LH|^=o z??_TI=E~5p{1CpN8ae;oP(8AES8qD0`XN3LK{bhCf)fpH{T zJbc{u513NH7+GKc(LeUUoC(9wYNbd)O>`^DV|OTPL4IGaFr$|Bvp2w6wINvS{eR2J z=|{s&Z-+C4Wn>Y-Lw+6kxI2u{Hmvk}*t)Dsqxw+<@h5jpkhmISS z*zo}qq*75Ym7h;4XO1p4-|KIhhW#F}0<|2)j#pd(Jk|YhJQ6Jzy$~6Pus??T68zEE zS4W>}863b4_OL{C7fv979;}0>Mkh&Xjg$D#VE>O|jqT@uR$@CVuY{W$KALW|{7rku zOnO3Q^}OCX29;(as{V*YPa$;xHX^9+63`(ZB}ozmKC=-{rxfb^_I`J& z?*l(u1^C%!VrlbxgKhtSaeSq=u4hQr+Yp)082jU|9U=Z0T?v2Z7dOU>{>C1DmdbMu zPVb?ySI`SyN{{wRmY4b`jLYB4^r}BiH@qPJyu<;ht(2CP81Tvnku=HnCo=yqhp@pp zn3Jk$r8rxFQk>b2^qn=Y;JQU+sSOC4aM77gL=qVy{B!S{Bgtx|fQ) z2TU<-2axovd=<*^tW#}$r<-RSI}AUp8OAyupVW9c?mzr?Tz6$LZGE>Kd+p)E{a)&) z5>E~7+_o?$n^s9kC`RNoHYi9vHdIv^?Az%&ti!L(9o6+^ig5A@4~G5dyZi#ZI z^&BsC^Mq12ESId$hIXBdq}|KxU|pUbSU9ouA)$w40KimEh@5B(6Q>4vsU?1vO`sY~ z@vMsd5ow^!A77NM1~~BWHs`$OrCRQIPOHmybe43eE@XDa6jE?{^LLDOW8a1_;y+=~ zaFy;^YKbj$g+^~A`j=dv-#B)%H!#c`s->P~ZL%^k_|Ev1nt29ehO3c1yuDF}zMhOZCL z*&-ojvPKM^YwN>R@1E0n{Loj}2foy#a9U&9zXgFNBm!=z%C$nv z$EFT@b2r!#=dji{JA3f2k_V&Btn@70J)(P}2o0 z9Z9b#Z|5aSVI*VP(8O z_3oX*L16CKXP5;Aqa%(iOoE8N13%O97IUP~7OUuYu~Q^)%u?4w`7@AljwiiLiG8Pe zv@u-c8rI&R)HXk*rCJ-vHYc)nt#DSFeJw43mvg&Rtq0Td)*>IYYf{VHVO)>_Ll;)F znjH-;s8x_Ya$dqs!i3yRYg^CON}Iv70-sJ?Nj=eT{}*lhQ;{XXg=)@sceRXtH3{YD z1fg5acRVYlGgstZs@CkKzK3GfJmZYdn|)n9W;UHnEoD8+Z%PkMNp201b3|6xNxms7 zHB=>EFkQ2lh15*oa(1ofxYCm$1}7WHD(1k~gssI*RhOk@Nye2*XqUm}3Rlml80|T+ zH?y=dR<{Yx$}ce?)JRfK^QTzT%!_ZL;ykiH>HZS;dsBg=J=OLhPXtcpe>HgfWhVDy zgY|0QuOFU2!dEtSGL|hFuj*6YXVNPEobu(+#Z^DmAdT2lLe7>z7N$mTI%d>z#FoUr zVIqbBYju*c|A54kUaIdfNHRD1Y+J4$wd0fHMfr7*kTkDLVHCgAOmi}IS?mIxuzapkSX9v_aK@_oH^|UH ziVQ2qy-IB!V!#<{EoV)RD~}r$gZeypqbuE3zJg6i9PW4Txt?Ek>Zk z5qtFbM4DGSTB9c^$7ksZpL8@tfKC_K)THJVF7#EEcvr>a`XLMp$6*uAyYpy%9>y#p5bjBnw2Ofh zGjs@|HnWFFuAj?yho^L9<4Q{EO6T_wwyMhIe8qRTTQY6j{@=Sra-%~kNl%=JLxsZe TTiVkqyi} 0: + defended = self.eot_defense_verification(X_adv, y, correct, defended) + else: + defended *= correct + return defended, attack_grad + + def attack_batch(self, X, y): + # get baseline accuracy for natural images + defended = self.eval_and_bpda_eot_grad(X, y, torch.ones_like(y).bool(), False)[0] + print('Baseline: {} of {}'.format(defended.sum(), len(defended))) + + class_batch = torch.zeros([self.config['adv_steps'] + 2, X.shape[0]]).bool() + class_batch[0] = defended.cpu() + ims_adv_batch = torch.zeros(X.shape) + for ind in range(defended.nelement()): + if defended[ind] == 0: + ims_adv_batch[ind] = X[ind].cpu() + + X_adv = X.clone() + + # adversarial attacks on a single batch of images + for step in range(self.config['adv_steps'] + 1): + defended, attack_grad = self.eval_and_bpda_eot_grad(X_adv, y, defended) + + class_batch[step+1] = defended.cpu() + for ind in range(defended.nelement()): + if class_batch[step, ind] == 1 and defended[ind] == 0: + ims_adv_batch[ind] = X_adv[ind].cpu() + + # update adversarial images (except on final iteration so final adv images match final eval) + if step < self.config['adv_steps']: + X_adv = self.pgd_update(X_adv, attack_grad, X, self.config['adv_norm'], self.config['adv_eps'], self.config['adv_eta']) + X_adv = X_adv.detach().clone() + + if step == 1 or step % self.config['log_freq'] == 0 or step == self.config['adv_steps']: + print('Attack {} of {} Batch defended: {} of {}'. + format(step, self.config['adv_steps'], int(torch.sum(defended).cpu().numpy()), X_adv.shape[0])) + + if int(torch.sum(defended).cpu().numpy()) == 0: + print('Attack successfully to the batch!') + break + + for ind in range(defended.nelement()): + if defended[ind] == 1: + ims_adv_batch[ind] = X_adv[ind].cpu() + + return class_batch, ims_adv_batch + + def attack_all(self, X, y, batch_size): + class_path = torch.zeros([self.config['adv_steps'] + 2, 0]).bool() + ims_adv = torch.zeros(0) + + n_batches = X.shape[0] // batch_size + if n_batches == 0 and X.shape[0] > 0: + n_batches = 1 + for counter in range(n_batches): + X_batch = X[counter * batch_size:min((counter + 1) * batch_size, X.shape[0])].clone().to(X.device) + y_batch = y[counter * batch_size:min((counter + 1) * batch_size, X.shape[0])].clone().to(X.device) + + class_batch, ims_adv_batch = self.attack_batch(X_batch.contiguous(), y_batch.contiguous()) + class_path = torch.cat((class_path, class_batch), dim=1) + ims_adv = torch.cat((ims_adv, ims_adv_batch), dim=0) + print(f'finished {counter}-th batch in attack_all') + + return class_path, ims_adv diff --git a/case_studies/diffpure/classifiers/attribute_classifier.py b/case_studies/diffpure/classifiers/attribute_classifier.py new file mode 100644 index 0000000..9ff9634 --- /dev/null +++ b/case_studies/diffpure/classifiers/attribute_classifier.py @@ -0,0 +1,65 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import torch +import os +from . import attribute_net + +softmax = torch.nn.Softmax(dim=1) + + +def downsample(images, size=256): + # Downsample to 256x256. The attribute classifiers were built for 256x256. + # follows https://github.com/NVlabs/stylegan/blob/master/metrics/linear_separability.py#L127 + if images.shape[2] > size: + factor = images.shape[2] // size + assert (factor * size == images.shape[2]) + images = images.view( + [-1, images.shape[1], images.shape[2] // factor, factor, images.shape[3] // factor, factor]) + images = images.mean(dim=[3, 5]) + return images + else: + assert (images.shape[-1] == 256) + return images + + +def get_logit(net, im): + im_256 = downsample(im) + logit = net(im_256) + return logit + + +def get_softmaxed(net, im): + logit = get_logit(net, im) + logits = torch.cat([logit, -logit], dim=1) + softmaxed = softmax(torch.cat([logit, -logit], dim=1))[:, 1] + return logits, softmaxed + + +def load_attribute_classifier(attribute, ckpt_path=None): + if ckpt_path is None: + base_path = 'checkpoints/diffpure/celebahq' + attribute_pkl = os.path.join(base_path, attribute, 'net_best.pth') + ckpt = torch.load(attribute_pkl) + else: + ckpt = torch.load(ckpt_path) + print("Using classifier at epoch: %d" % ckpt['epoch']) + if 'valacc' in ckpt.keys(): + print("Validation acc on raw images: %0.5f" % ckpt['valacc']) + detector = attribute_net.from_state_dict( + ckpt['state_dict'], fixed_size=True, use_mbstd=False).cuda().eval() + return detector + + +class ClassifierWrapper(torch.nn.Module): + def __init__(self, classifier_name, ckpt_path=None, device='cuda'): + super(ClassifierWrapper, self).__init__() + self.net = load_attribute_classifier(classifier_name, ckpt_path).eval().to(device) + + def forward(self, ims): + out = (ims - 0.5) / 0.5 + return get_softmaxed(self.net, out)[0] diff --git a/case_studies/diffpure/classifiers/attribute_net.py b/case_studies/diffpure/classifiers/attribute_net.py new file mode 100644 index 0000000..c162be5 --- /dev/null +++ b/case_studies/diffpure/classifiers/attribute_net.py @@ -0,0 +1,227 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import torch +import torch.nn as nn +import numpy as np + + +def lerp_clip(a, b, t): + return a + (b - a) * torch.clamp(t, 0.0, 1.0) + + +class WScaleLayer(nn.Module): + def __init__(self, size, fan_in, gain=np.sqrt(2), bias=True): + super(WScaleLayer, self).__init__() + self.scale = gain / np.sqrt(fan_in) # No longer a parameter + if bias: + self.b = nn.Parameter(torch.randn(size)) + else: + self.b = 0 + self.size = size + + def forward(self, x): + x_size = x.size() + x = x * self.scale + # modified to remove warning + if type(self.b) == nn.Parameter and len(x_size) == 4: + x = x + self.b.view(1, -1, 1, 1).expand( + x_size[0], self.size, x_size[2], x_size[3]) + if type(self.b) == nn.Parameter and len(x_size) == 2: + x = x + self.b.view(1, -1).expand( + x_size[0], self.size) + return x + + +class WScaleConv2d(nn.Module): + def __init__(self, in_channels, out_channels, kernel_size, padding=0, + bias=True, gain=np.sqrt(2)): + super().__init__() + self.conv = nn.Conv2d(in_channels, out_channels, + kernel_size=kernel_size, + padding=padding, + bias=False) + fan_in = in_channels * kernel_size * kernel_size + self.wscale = WScaleLayer(out_channels, fan_in, gain=gain, bias=bias) + + def forward(self, x): + return self.wscale(self.conv(x)) + + +class WScaleLinear(nn.Module): + def __init__(self, in_channels, out_channels, bias=True, gain=np.sqrt(2)): + super().__init__() + self.linear = nn.Linear(in_channels, out_channels, bias=False) + self.wscale = WScaleLayer(out_channels, in_channels, gain=gain, + bias=bias) + + def forward(self, x): + return self.wscale(self.linear(x)) + + +class FromRGB(nn.Module): + def __init__(self, in_channels, out_channels, kernel_size, + act=nn.LeakyReLU(0.2), bias=True): + super().__init__() + self.conv = WScaleConv2d(in_channels, out_channels, kernel_size, + padding=0, bias=bias) + self.act = act + + def forward(self, x): + return self.act(self.conv(x)) + + +class Downscale2d(nn.Module): + def __init__(self, factor=2): + super().__init__() + self.downsample = nn.AvgPool2d(kernel_size=factor, stride=factor) + + def forward(self, x): + return self.downsample(x) + + +class DownscaleConvBlock(nn.Module): + def __init__(self, in_channels, conv0_channels, conv1_channels, + kernel_size, padding, bias=True, act=nn.LeakyReLU(0.2)): + super().__init__() + self.downscale = Downscale2d() + self.conv0 = WScaleConv2d(in_channels, conv0_channels, + kernel_size=kernel_size, + padding=padding, + bias=bias) + self.conv1 = WScaleConv2d(conv0_channels, conv1_channels, + kernel_size=kernel_size, + padding=padding, + bias=bias) + self.act = act + + def forward(self, x): + x = self.act(self.conv0(x)) + # conv2d_downscale2d applies downscaling before activation + # the order matters here! has to be conv -> bias -> downscale -> act + x = self.conv1(x) + x = self.downscale(x) + x = self.act(x) + return x + + +class MinibatchStdLayer(nn.Module): + def __init__(self, group_size=4): + super().__init__() + self.group_size = group_size + + def forward(self, x): + group_size = min(self.group_size, x.shape[0]) + s = x.shape + y = x.view([group_size, -1, s[1], s[2], s[3]]) + y = y.float() + y = y - torch.mean(y, dim=0, keepdim=True) + y = torch.mean(y * y, dim=0) + y = torch.sqrt(y + 1e-8) + y = torch.mean(torch.mean(torch.mean(y, dim=3, keepdim=True), + dim=2, keepdim=True), dim=1, keepdim=True) + y = y.type(x.type()) + y = y.repeat(group_size, 1, s[2], s[3]) + return torch.cat([x, y], dim=1) + + +class PredictionBlock(nn.Module): + def __init__(self, in_channels, dense0_feat, dense1_feat, out_feat, + pool_size=2, act=nn.LeakyReLU(0.2), use_mbstd=True): + super().__init__() + self.use_mbstd = use_mbstd # attribute classifiers don't have this + if self.use_mbstd: + self.mbstd_layer = MinibatchStdLayer() + # MinibatchStdLayer adds an additional feature dimension + self.conv = WScaleConv2d(in_channels + int(self.use_mbstd), + dense0_feat, kernel_size=3, padding=1) + self.dense0 = WScaleLinear(dense0_feat * pool_size * pool_size, dense1_feat) + self.dense1 = WScaleLinear(dense1_feat, out_feat, gain=1) + self.act = act + + def forward(self, x): + if self.use_mbstd: + x = self.mbstd_layer(x) + x = self.act(self.conv(x)) + x = x.view([x.shape[0], -1]) + x = self.act(self.dense0(x)) + x = self.dense1(x) + return x + + +class D(nn.Module): + + def __init__( + self, + num_channels=3, # Number of input color channels. Overridden based on dataset. + resolution=128, # Input resolution. Overridden based on dataset. + fmap_base=8192, # Overall multiplier for the number of feature maps. + fmap_decay=1.0, # log2 feature map reduction when doubling the resolution. + fmap_max=512, # Maximum number of feature maps in any layer. + fixed_size=False, # True = load fromrgb_lod0 weights only + use_mbstd=True, # False = no mbstd layer in PredictionBlock + **kwargs): # Ignore unrecognized keyword args. + super().__init__() + + self.resolution_log2 = resolution_log2 = int(np.log2(resolution)) + assert resolution == 2 ** resolution_log2 and resolution >= 4 + + def nf(stage): + return min(int(fmap_base / (2.0 ** (stage * fmap_decay))), fmap_max) + + self.register_buffer('lod_in', torch.from_numpy(np.array(0.0))) + + res = resolution_log2 + + setattr(self, 'fromrgb_lod0', FromRGB(num_channels, nf(res - 1), 1)) + + for i, res in enumerate(range(resolution_log2, 2, -1), 1): + lod = resolution_log2 - res + block = DownscaleConvBlock(nf(res - 1), nf(res - 1), nf(res - 2), + kernel_size=3, padding=1) + setattr(self, '%dx%d' % (2 ** res, 2 ** res), block) + fromrgb = FromRGB(3, nf(res - 2), 1) + if not fixed_size: + setattr(self, 'fromrgb_lod%d' % i, fromrgb) + + res = 2 + pool_size = 2 ** res + block = PredictionBlock(nf(res + 1 - 2), nf(res - 1), nf(res - 2), 1, + pool_size, use_mbstd=use_mbstd) + setattr(self, '%dx%d' % (pool_size, pool_size), block) + self.downscale = Downscale2d() + self.fixed_size = fixed_size + + def forward(self, img): + x = self.fromrgb_lod0(img) + for i, res in enumerate(range(self.resolution_log2, 2, -1), 1): + lod = self.resolution_log2 - res + x = getattr(self, '%dx%d' % (2 ** res, 2 ** res))(x) + if not self.fixed_size: + img = self.downscale(img) + y = getattr(self, 'fromrgb_lod%d' % i)(img) + x = lerp_clip(x, y, self.lod_in - lod) + res = 2 + pool_size = 2 ** res + out = getattr(self, '%dx%d' % (pool_size, pool_size))(x) + return out + + +def max_res_from_state_dict(state_dict): + for i in range(3, 12): + if '%dx%d.conv0.conv.weight' % (2 ** i, 2 ** i) not in state_dict: + break + return 2 ** (i - 1) + + +def from_state_dict(state_dict, fixed_size=False, use_mbstd=True): + res = max_res_from_state_dict(state_dict) + print(f'res: {res}') + d = D(num_channels=3, resolution=res, fixed_size=fixed_size, + use_mbstd=use_mbstd) + d.load_state_dict(state_dict) + return d diff --git a/case_studies/diffpure/classifiers/cifar10_resnet.py b/case_studies/diffpure/classifiers/cifar10_resnet.py new file mode 100644 index 0000000..a409b6a --- /dev/null +++ b/case_studies/diffpure/classifiers/cifar10_resnet.py @@ -0,0 +1,199 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import math + +import torch +import torch.nn.functional as F +import torch.nn as nn + + +# ---------------------------- ResNet ---------------------------- + +class Bottleneck(nn.Module): + expansion = 4 + + def __init__(self, in_planes, planes, stride=1): + super(Bottleneck, self).__init__() + self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False) + self.bn1 = nn.BatchNorm2d(planes) + self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) + self.bn2 = nn.BatchNorm2d(planes) + self.conv3 = nn.Conv2d(planes, self.expansion * planes, kernel_size=1, bias=False) + self.bn3 = nn.BatchNorm2d(self.expansion * planes) + + self.shortcut = nn.Sequential() + if stride != 1 or in_planes != self.expansion * planes: + self.shortcut = nn.Sequential( + nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, stride=stride, bias=False), + nn.BatchNorm2d(self.expansion * planes) + ) + + def forward(self, x): + out = F.relu(self.bn1(self.conv1(x))) + out = F.relu(self.bn2(self.conv2(out))) + out = self.bn3(self.conv3(out)) + out += self.shortcut(x) + out = F.relu(out) + return out + + +class ResNet(nn.Module): + def __init__(self, block, num_blocks, num_classes=10): + super(ResNet, self).__init__() + self.in_planes = 64 + + num_input_channels = 3 + mean = (0.4914, 0.4822, 0.4465) + std = (0.2471, 0.2435, 0.2616) + self.mean = torch.tensor(mean).view(num_input_channels, 1, 1) + self.std = torch.tensor(std).view(num_input_channels, 1, 1) + + self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False) + self.bn1 = nn.BatchNorm2d(64) + self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1) + self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2) + self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2) + self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2) + self.linear = nn.Linear(512 * block.expansion, num_classes) + + def _make_layer(self, block, planes, num_blocks, stride): + strides = [stride] + [1] * (num_blocks - 1) + layers = [] + for stride in strides: + layers.append(block(self.in_planes, planes, stride)) + self.in_planes = planes * block.expansion + return nn.Sequential(*layers) + + def forward(self, x): + out = (x - self.mean.to(x.device)) / self.std.to(x.device) + out = F.relu(self.bn1(self.conv1(out))) + out = self.layer1(out) + out = self.layer2(out) + out = self.layer3(out) + out = self.layer4(out) + out = F.avg_pool2d(out, 4) + out = out.view(out.size(0), -1) + out = self.linear(out) + return out + + +def ResNet50(): + return ResNet(Bottleneck, [3, 4, 6, 3]) + + +# ---------------------------- ResNet ---------------------------- + + +# ---------------------------- WideResNet ---------------------------- + +class BasicBlock(nn.Module): + def __init__(self, in_planes, out_planes, stride, dropRate=0.0): + super(BasicBlock, self).__init__() + self.bn1 = nn.BatchNorm2d(in_planes) + self.relu1 = nn.ReLU(inplace=True) + self.conv1 = nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, + padding=1, bias=False) + self.bn2 = nn.BatchNorm2d(out_planes) + self.relu2 = nn.ReLU(inplace=True) + self.conv2 = nn.Conv2d(out_planes, out_planes, kernel_size=3, stride=1, + padding=1, bias=False) + self.droprate = dropRate + self.equalInOut = (in_planes == out_planes) + self.convShortcut = (not self.equalInOut) and nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, + padding=0, bias=False) or None + + def forward(self, x): + if not self.equalInOut: + x = self.relu1(self.bn1(x)) + else: + out = self.relu1(self.bn1(x)) + out = self.relu2(self.bn2(self.conv1(out if self.equalInOut else x))) + if self.droprate > 0: + out = F.dropout(out, p=self.droprate, training=self.training) + out = self.conv2(out) + return torch.add(x if self.equalInOut else self.convShortcut(x), out) + + +class NetworkBlock(nn.Module): + def __init__(self, nb_layers, in_planes, out_planes, block, stride, dropRate=0.0): + super(NetworkBlock, self).__init__() + self.layer = self._make_layer(block, in_planes, out_planes, nb_layers, stride, dropRate) + + def _make_layer(self, block, in_planes, out_planes, nb_layers, stride, dropRate): + layers = [] + for i in range(int(nb_layers)): + layers.append(block(i == 0 and in_planes or out_planes, out_planes, i == 0 and stride or 1, dropRate)) + return nn.Sequential(*layers) + + def forward(self, x): + return self.layer(x) + + +class WideResNet(nn.Module): + """ Based on code from https://github.com/yaodongyu/TRADES """ + + def __init__(self, depth=28, num_classes=10, widen_factor=10, sub_block1=False, dropRate=0.0, bias_last=True): + super(WideResNet, self).__init__() + + num_input_channels = 3 + mean = (0.4914, 0.4822, 0.4465) + std = (0.2471, 0.2435, 0.2616) + self.mean = torch.tensor(mean).view(num_input_channels, 1, 1) + self.std = torch.tensor(std).view(num_input_channels, 1, 1) + + nChannels = [16, 16 * widen_factor, 32 * widen_factor, 64 * widen_factor] + assert ((depth - 4) % 6 == 0) + n = (depth - 4) / 6 + block = BasicBlock + # 1st conv before any network block + self.conv1 = nn.Conv2d(3, nChannels[0], kernel_size=3, stride=1, + padding=1, bias=False) + # 1st block + self.block1 = NetworkBlock(n, nChannels[0], nChannels[1], block, 1, dropRate) + if sub_block1: + # 1st sub-block + self.sub_block1 = NetworkBlock(n, nChannels[0], nChannels[1], block, 1, dropRate) + # 2nd block + self.block2 = NetworkBlock(n, nChannels[1], nChannels[2], block, 2, dropRate) + # 3rd block + self.block3 = NetworkBlock(n, nChannels[2], nChannels[3], block, 2, dropRate) + # global average pooling and classifier + self.bn1 = nn.BatchNorm2d(nChannels[3]) + self.relu = nn.ReLU(inplace=True) + self.fc = nn.Linear(nChannels[3], num_classes, bias=bias_last) + self.nChannels = nChannels[3] + + 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_() + elif isinstance(m, nn.Linear) and not m.bias is None: + m.bias.data.zero_() + + def forward(self, x): + out = (x - self.mean.to(x.device)) / self.std.to(x.device) + out = self.conv1(out) + out = self.block1(out) + out = self.block2(out) + out = self.block3(out) + out = self.relu(self.bn1(out)) + out = F.avg_pool2d(out, 8) + out = out.view(-1, self.nChannels) + return self.fc(out) + + +def WideResNet_70_16(): + return WideResNet(depth=70, widen_factor=16, dropRate=0.0) + + +def WideResNet_70_16_dropout(): + return WideResNet(depth=70, widen_factor=16, dropRate=0.3) +# ---------------------------- WideResNet ---------------------------- diff --git a/case_studies/diffpure/configs/celeba.yml b/case_studies/diffpure/configs/celeba.yml new file mode 100644 index 0000000..4d0c4d0 --- /dev/null +++ b/case_studies/diffpure/configs/celeba.yml @@ -0,0 +1,35 @@ +data: + dataset: "CelebA_HQ" + category: "celeba" + image_size: 256 + channels: 3 + logit_transform: false + uniform_dequantization: false + gaussian_dequantization: false + random_flip: true + rescaled: true + num_workers: 32 + +model: + type: "simple" + in_channels: 3 + out_ch: 3 + ch: 128 + ch_mult: [1, 1, 2, 2, 4, 4] + num_res_blocks: 2 + attn_resolutions: [16, ] + dropout: 0.0 + var_type: fixedsmall + ema_rate: 0.999 + ema: True + resamp_with_conv: True + +diffusion: + beta_schedule: linear + beta_start: 0.0001 + beta_end: 0.02 + num_diffusion_timesteps: 1000 + +sampling: + batch_size: 8 + last_only: True \ No newline at end of file diff --git a/case_studies/diffpure/configs/cifar10.yml b/case_studies/diffpure/configs/cifar10.yml new file mode 100644 index 0000000..9c9e108 --- /dev/null +++ b/case_studies/diffpure/configs/cifar10.yml @@ -0,0 +1,65 @@ +data: + dataset: "CIFAR10" + category: "cifar10" + image_size: 32 + num_channels: 3 + random_flip: True + centered: True + uniform_dequantization: False + +model: + sigma_min: 0.01 + sigma_max: 50 + num_scales: 1000 + beta_min: 0.1 + beta_max: 20. + dropout: 0.1 + + name: 'ncsnpp' + scale_by_sigma: False + ema_rate: 0.9999 + normalization: 'GroupNorm' + nonlinearity: 'swish' + nf: 128 + ch_mult: [1, 2, 2, 2] # (1, 2, 2, 2) + num_res_blocks: 8 + attn_resolutions: [16] # (16,) + resamp_with_conv: True + conditional: True + fir: False + fir_kernel: [1, 3, 3, 1] + skip_rescale: True + resblock_type: 'biggan' + progressive: 'none' + progressive_input: 'none' + progressive_combine: 'sum' + attention_type: 'ddpm' + init_scale: 0. + embedding_type: 'positional' + fourier_scale: 16 + conv_size: 3 + +training: + sde: 'vpsde' + continuous: True + reduce_mean: True + n_iters: 950001 + +optim: + weight_decay: 0 + optimizer: 'Adam' + lr: 0.0002 # 2e-4 + beta1: 0.9 + eps: 0.00000001 # 1e-8 + warmup: 5000 + grad_clip: 1. + +sampling: + n_steps_each: 1 + noise_removal: True + probability_flow: False + snr: 0.16 + + method: 'pc' + predictor: 'euler_maruyama' + corrector: 'none' \ No newline at end of file diff --git a/case_studies/diffpure/configs/imagenet.yml b/case_studies/diffpure/configs/imagenet.yml new file mode 100644 index 0000000..022579e --- /dev/null +++ b/case_studies/diffpure/configs/imagenet.yml @@ -0,0 +1,23 @@ +data: + dataset: "ImageNet" + category: "imagenet" + +model: + attention_resolutions: '32,16,8' + class_cond: False + diffusion_steps: 1000 + rescale_timesteps: True + timestep_respacing: '1000' # Modify this value to decrease the number of timesteps. + image_size: 256 + learn_sigma: True + noise_schedule: 'linear' + num_channels: 256 + num_head_channels: 64 + num_res_blocks: 2 + resblock_updown: True + use_fp16: True + use_scale_shift_norm: True + +sampling: + batch_size: 8 + last_only: True \ No newline at end of file diff --git a/case_studies/diffpure/data/__init__.py b/case_studies/diffpure/data/__init__.py new file mode 100644 index 0000000..0fd671b --- /dev/null +++ b/case_studies/diffpure/data/__init__.py @@ -0,0 +1,25 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +from .datasets import imagenet_lmdb_dataset, imagenet_lmdb_dataset_sub, cifar10_dataset_sub + +def get_transform(dataset_name, transform_type, base_size=256): + from . import datasets + if dataset_name == 'celebahq': + return datasets.get_transform(dataset_name, transform_type, base_size) + elif 'imagenet' in dataset_name: + return datasets.get_transform(dataset_name, transform_type, base_size) + else: + raise NotImplementedError + + +def get_dataset(dataset_name, partition, *args, **kwargs): + from . import datasets + if dataset_name == 'celebahq': + return datasets.CelebAHQDataset(partition, *args, **kwargs) + else: + raise NotImplementedError \ No newline at end of file diff --git a/case_studies/diffpure/data/datasets.py b/case_studies/diffpure/data/datasets.py new file mode 100644 index 0000000..93cfa91 --- /dev/null +++ b/case_studies/diffpure/data/datasets.py @@ -0,0 +1,335 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import os, sys + +import io +import lmdb + +import pandas as pd +import numpy as np +from PIL import Image + +import torch +import torchvision +from torch.utils.data import Dataset, Subset + +import torchvision.transforms as transforms +from torchvision.datasets.vision import VisionDataset +from torchvision.datasets import folder, ImageFolder + + +# --------------------------------------------------------------------------------------------------- + +def remove_prefix(s, prefix): + if s.startswith(prefix): + s = s[len(prefix):] + return s + + +class ImageDataset(VisionDataset): + """ + modified from: https://pytorch.org/docs/stable/_modules/torchvision/datasets/folder.html#ImageFolder + uses cached directory listing if available rather than walking directory + Attributes: + classes (list): List of the class names. + class_to_idx (dict): Dict with items (class_name, class_index). + samples (list): List of (sample path, class_index) tuples + targets (list): The class_index value for each image in the dataset + """ + + def __init__(self, root, loader=folder.default_loader, + extensions=folder.IMG_EXTENSIONS, transform=None, + target_transform=None, is_valid_file=None, return_path=False): + super(ImageDataset, self).__init__(root, transform=transform, + target_transform=target_transform) + classes, class_to_idx = self._find_classes(self.root) + cache = self.root.rstrip('/') + '.txt' + if os.path.isfile(cache): + print("Using directory list at: %s" % cache) + with open(cache) as f: + samples = [] + for line in f: + (path, idx) = line.strip().split(';') + samples.append((os.path.join(self.root, path), int(idx))) + else: + print("Walking directory: %s" % self.root) + samples = folder.make_dataset(self.root, class_to_idx, extensions, is_valid_file) + with open(cache, 'w') as f: + for line in samples: + path, label = line + f.write('%s;%d\n' % (remove_prefix(path, self.root).lstrip('/'), label)) + + if len(samples) == 0: + raise (RuntimeError( + "Found 0 files in subfolders of: " + self.root + "\nSupported extensions are: " + ",".join(extensions))) + + self.loader = loader + self.classes = classes + self.class_to_idx = class_to_idx + self.samples = samples + self.return_path = return_path + + def _find_classes(self, dir): + """ + Finds the class folders in a dataset. + Ensures: + No class is a subdirectory of another. + """ + if sys.version_info >= (3, 5): + # Faster and available in Python 3.5 and above + classes = [d.name for d in os.scandir(dir) if d.is_dir()] + else: + classes = [d for d in os.listdir(dir) if os.path.isdir(os.path.join(dir, d))] + classes.sort() + class_to_idx = {classes[i]: i for i in range(len(classes))} + return classes, class_to_idx + + def __getitem__(self, index): + path, target = self.samples[index] + sample = self.loader(path) + if self.transform is not None: + sample = self.transform(sample) + if self.target_transform is not None: + target = self.target_transform(target) + if self.return_path: + return sample, target, path + return sample, target + + def __len__(self): + return len(self.samples) + + +# --------------------------------------------------------------------------------------------------- + +# get the attributes from celebahq subset +def make_table(root): + filenames = sorted(os.listdir(f'{root}/images')) + # filter out non-png files, rename it to jpg to match entries in list_attr_celeba.txt + celebahq = [os.path.basename(f).replace('png', 'jpg') + if f.endswith('png') else os.path.basename(f) for f in filenames] + attr_gt = pd.read_csv(f'{root}/list_attr_celeba.txt', + skiprows=1, delim_whitespace=True, index_col=0) + attr_celebahq = attr_gt.reindex(index=celebahq).replace(-1, 0) + + # get the train/test/val partitions + partitions = {} + with open(f'{root}/list_eval_partition.txt') as f: + for line in f: + filename, part = line.strip().split(' ') + partitions[filename] = int(part) + partitions_list = [partitions[fname] for fname in attr_celebahq.index] + + attr_celebahq['partition'] = partitions_list + return attr_celebahq + + +###### dataset functions ###### + +class CelebAHQDataset(Dataset): + def __init__(self, partition, attribute, root=None, fraction=None, data_seed=1, + chunk_length=None, chunk_idx=-1, **kwargs): + if root is None: + root = './dataset/celebahq' + self.fraction = fraction + self.dset = ImageDataset(root, **kwargs) + + # make table + attr_celebahq = make_table(root) + + # convert from train/val/test to partition numbers + part_to_int = dict(train=0, val=1, test=2) + + def get_partition_indices(part): + return np.where(attr_celebahq['partition'] == part_to_int[part])[0] + + partition_idx = get_partition_indices(partition) + + # if we want to further subsample the dataset, just subsample + # partition_idx and Subset() once + if fraction is not None: + print("Using a fraction of the original dataset") + print("The original dataset has length %d" % len(partition_idx)) + new_length = int(fraction / 100 * len(partition_idx)) + rng = np.random.RandomState(data_seed) + new_indices = rng.choice(partition_idx, new_length, replace=False) + partition_idx = new_indices + print("The subsetted dataset has length %d" % len(partition_idx)) + + elif chunk_length is not None and chunk_idx > 0: + print(f"Using a fraction of the original dataset with chunk_length: {chunk_length}, chunk_idx: {chunk_idx}") + print("The original dataset has length %d" % len(partition_idx)) + new_indices = partition_idx[chunk_length * chunk_idx: chunk_length * (chunk_idx + 1)] + partition_idx = new_indices + print("The subsetted dataset has length %d" % len(partition_idx)) + + self.dset = Subset(self.dset, partition_idx) + attr_subset = attr_celebahq.iloc[partition_idx] + self.attr_subset = attr_subset[attribute] + print('attribute freq: %0.4f (%d / %d)' % (self.attr_subset.mean(), + self.attr_subset.sum(), + len(self.attr_subset))) + + def __len__(self): + return len(self.dset) + + def __getitem__(self, idx): + data = self.dset[idx] + # first element is the class, replace it + label = self.attr_subset[idx] + return (data[0], label, *data[2:]) + + +###### transformation functions ###### + +def get_transform(dataset, transform_type, base_size=256): + if dataset.lower() == "celebahq": + assert base_size == 256, base_size + + if transform_type == 'imtrain': + return transforms.Compose([ + transforms.Resize(base_size), + transforms.RandomHorizontalFlip(p=0.5), + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) + ]) + elif transform_type == 'imval': + return transforms.Compose([ + transforms.Resize(base_size), + # no horizontal flip for standard validation + transforms.ToTensor(), + # transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) + ]) + elif transform_type == 'imcolor': + return transforms.Compose([ + transforms.Resize(base_size), + transforms.RandomHorizontalFlip(p=0.5), + transforms.ColorJitter(brightness=.05, contrast=.05, + saturation=.05, hue=.05), + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), + ]) + elif transform_type == 'imcrop': + return transforms.Compose([ + # 1024 + 32, or 256 + 8 + transforms.Resize(int(1.03125 * base_size)), + transforms.RandomCrop(base_size), + transforms.RandomHorizontalFlip(p=0.5), + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), + ]) + elif transform_type == 'tensorbase': + # dummy transform for compatibility with other datasets + return transforms.Lambda(lambda x: x) + else: + raise NotImplementedError + + elif "imagenet" in dataset.lower(): + assert base_size == 224, base_size + + if transform_type == 'imtrain': + return transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(base_size), + transforms.RandomHorizontalFlip(p=0.5), + transforms.ToTensor(), + # transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)) + ]) + elif transform_type == 'imval': + return transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(base_size), + # no horizontal flip for standard validation + transforms.ToTensor(), + # transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)) + ]) + else: + raise NotImplementedError + + else: + raise NotImplementedError + + +################################################################################ +# ImageNet - LMDB +############################################################################### + +def lmdb_loader(path, lmdb_data): + # In-memory binary streams + with lmdb_data.begin(write=False, buffers=True) as txn: + bytedata = txn.get(path.encode('ascii')) + img = Image.open(io.BytesIO(bytedata)) + return img.convert('RGB') + + +def imagenet_lmdb_dataset( + root, transform=None, target_transform=None, + loader=lmdb_loader): + """ + You can create this dataloader using: + train_data = imagenet_lmdb_dataset(traindir, transform=train_transform) + valid_data = imagenet_lmdb_dataset(validdir, transform=val_transform) + """ + + if root.endswith('/'): + root = root[:-1] + pt_path = os.path.join( + root + '_faster_imagefolder.lmdb.pt') + lmdb_path = os.path.join( + root + '_faster_imagefolder.lmdb') + if os.path.isfile(pt_path) and os.path.isdir(lmdb_path): + print('Loading pt {} and lmdb {}'.format(pt_path, lmdb_path)) + data_set = torch.load(pt_path) + else: + data_set = ImageFolder( + root, None, None, None) + torch.save(data_set, pt_path, pickle_protocol=4) + print('Saving pt to {}'.format(pt_path)) + print('Building lmdb to {}'.format(lmdb_path)) + env = lmdb.open(lmdb_path, map_size=1e12) + with env.begin(write=True) as txn: + for path, class_index in data_set.imgs: + with open(path, 'rb') as f: + data = f.read() + txn.put(path.encode('ascii'), data) + data_set.lmdb_data = lmdb.open( + lmdb_path, readonly=True, max_readers=1, lock=False, readahead=False, + meminit=False) + # reset transform and target_transform + data_set.samples = data_set.imgs + data_set.transform = transform + data_set.target_transform = target_transform + data_set.loader = lambda path: loader(path, data_set.lmdb_data) + + return data_set + + +def imagenet_lmdb_dataset_sub( + root, transform=None, target_transform=None, + loader=lmdb_loader, num_sub=-1, data_seed=0): + data_set = imagenet_lmdb_dataset( + root, transform=transform, target_transform=target_transform, + loader=loader) + + if num_sub > 0: + partition_idx = np.random.RandomState(data_seed).choice(len(data_set), num_sub, replace=False) + data_set = Subset(data_set, partition_idx) + + return data_set + + +################################################################################ +# CIFAR-10 +############################################################################### + +def cifar10_dataset_sub(root, transform=None, num_sub=-1, data_seed=0): + val_data = torchvision.datasets.CIFAR10(root=root, transform=transform, download=True, train=False) + if num_sub > 0: + partition_idx = np.random.RandomState(data_seed).choice(len(val_data), min(len(val_data), num_sub), + replace=False) + val_data = Subset(val_data, partition_idx) + return val_data diff --git a/case_studies/diffpure/ddpm/LICENSE_UNET_DDPM b/case_studies/diffpure/ddpm/LICENSE_UNET_DDPM new file mode 100644 index 0000000..87e6566 --- /dev/null +++ b/case_studies/diffpure/ddpm/LICENSE_UNET_DDPM @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Ermon Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/case_studies/diffpure/ddpm/unet_ddpm.py b/case_studies/diffpure/ddpm/unet_ddpm.py new file mode 100644 index 0000000..5c18b2c --- /dev/null +++ b/case_studies/diffpure/ddpm/unet_ddpm.py @@ -0,0 +1,345 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/ermongroup/SDEdit/blob/main/models/diffusion.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_UNET_DDPM). +# --------------------------------------------------------------- + +import math +import torch +import torch.nn as nn + + +def get_timestep_embedding(timesteps, embedding_dim): + """ + This matches the implementation in Denoising Diffusion Probabilistic Models: + From Fairseq. + Build sinusoidal embeddings. + This matches the implementation in tensor2tensor, but differs slightly + from the description in Section 3.5 of "Attention Is All You Need". + """ + assert len(timesteps.shape) == 1 + + half_dim = embedding_dim // 2 + emb = math.log(10000) / (half_dim - 1) + emb = torch.exp(torch.arange(half_dim, dtype=torch.float32) * -emb) + emb = emb.to(device=timesteps.device) + emb = timesteps.float()[:, None] * emb[None, :] + emb = torch.cat([torch.sin(emb), torch.cos(emb)], dim=1) + if embedding_dim % 2 == 1: # zero pad + emb = torch.nn.functional.pad(emb, (0, 1, 0, 0)) + return emb + + +def nonlinearity(x): + # swish + return x * torch.sigmoid(x) + + +def Normalize(in_channels): + return torch.nn.GroupNorm(num_groups=32, num_channels=in_channels, eps=1e-6, affine=True) + + +class Upsample(nn.Module): + def __init__(self, in_channels, with_conv): + super().__init__() + self.with_conv = with_conv + if self.with_conv: + self.conv = torch.nn.Conv2d(in_channels, + in_channels, + kernel_size=3, + stride=1, + padding=1) + + def forward(self, x): + x = torch.nn.functional.interpolate( + x, scale_factor=2.0, mode="nearest") + if self.with_conv: + x = self.conv(x) + return x + + +class Downsample(nn.Module): + def __init__(self, in_channels, with_conv): + super().__init__() + self.with_conv = with_conv + if self.with_conv: + # no asymmetric padding in torch conv, must do it ourselves + self.conv = torch.nn.Conv2d(in_channels, + in_channels, + kernel_size=3, + stride=2, + padding=0) + + def forward(self, x): + if self.with_conv: + pad = (0, 1, 0, 1) + x = torch.nn.functional.pad(x, pad, mode="constant", value=0) + x = self.conv(x) + else: + x = torch.nn.functional.avg_pool2d(x, kernel_size=2, stride=2) + return x + + +class ResnetBlock(nn.Module): + def __init__(self, *, in_channels, out_channels=None, conv_shortcut=False, + dropout, temb_channels=512): + super().__init__() + self.in_channels = in_channels + out_channels = in_channels if out_channels is None else out_channels + self.out_channels = out_channels + self.use_conv_shortcut = conv_shortcut + + self.norm1 = Normalize(in_channels) + self.conv1 = torch.nn.Conv2d(in_channels, + out_channels, + kernel_size=3, + stride=1, + padding=1) + self.temb_proj = torch.nn.Linear(temb_channels, + out_channels) + self.norm2 = Normalize(out_channels) + self.dropout = torch.nn.Dropout(dropout) + self.conv2 = torch.nn.Conv2d(out_channels, + out_channels, + kernel_size=3, + stride=1, + padding=1) + if self.in_channels != self.out_channels: + if self.use_conv_shortcut: + self.conv_shortcut = torch.nn.Conv2d(in_channels, + out_channels, + kernel_size=3, + stride=1, + padding=1) + else: + self.nin_shortcut = torch.nn.Conv2d(in_channels, + out_channels, + kernel_size=1, + stride=1, + padding=0) + + def forward(self, x, temb): + h = x + h = self.norm1(h) + h = nonlinearity(h) + h = self.conv1(h) + + h = h + self.temb_proj(nonlinearity(temb))[:, :, None, None] + + h = self.norm2(h) + h = nonlinearity(h) + h = self.dropout(h) + h = self.conv2(h) + + if self.in_channels != self.out_channels: + if self.use_conv_shortcut: + x = self.conv_shortcut(x) + else: + x = self.nin_shortcut(x) + + return x + h + + +class AttnBlock(nn.Module): + def __init__(self, in_channels): + super().__init__() + self.in_channels = in_channels + + self.norm = Normalize(in_channels) + self.q = torch.nn.Conv2d(in_channels, + in_channels, + kernel_size=1, + stride=1, + padding=0) + self.k = torch.nn.Conv2d(in_channels, + in_channels, + kernel_size=1, + stride=1, + padding=0) + self.v = torch.nn.Conv2d(in_channels, + in_channels, + kernel_size=1, + stride=1, + padding=0) + self.proj_out = torch.nn.Conv2d(in_channels, + in_channels, + kernel_size=1, + stride=1, + padding=0) + + def forward(self, x): + h_ = x + h_ = self.norm(h_) + q = self.q(h_) + k = self.k(h_) + v = self.v(h_) + + # compute attention + b, c, h, w = q.shape + q = q.reshape(b, c, h * w) + q = q.permute(0, 2, 1) # b,hw,c + k = k.reshape(b, c, h * w) # b,c,hw + w_ = torch.bmm(q, k) # b,hw,hw w[b,i,j]=sum_c q[b,i,c]k[b,c,j] + w_ = w_ * (int(c) ** (-0.5)) + w_ = torch.nn.functional.softmax(w_, dim=2) + + # attend to values + v = v.reshape(b, c, h * w) + w_ = w_.permute(0, 2, 1) # b,hw,hw (first hw of k, second of q) + # b, c,hw (hw of q) h_[b,c,j] = sum_i v[b,c,i] w_[b,i,j] + h_ = torch.bmm(v, w_) + h_ = h_.reshape(b, c, h, w) + + h_ = self.proj_out(h_) + + return x + h_ + + +class Model(nn.Module): + def __init__(self, config): + super().__init__() + self.config = config + ch, out_ch, ch_mult = config.model.ch, config.model.out_ch, tuple(config.model.ch_mult) + num_res_blocks = config.model.num_res_blocks + attn_resolutions = config.model.attn_resolutions + dropout = config.model.dropout + in_channels = config.model.in_channels + resolution = config.data.image_size + resamp_with_conv = config.model.resamp_with_conv + + self.ch = ch + self.temb_ch = self.ch * 4 + self.num_resolutions = len(ch_mult) + self.num_res_blocks = num_res_blocks + self.resolution = resolution + self.in_channels = in_channels + + # timestep embedding + self.temb = nn.Module() + self.temb.dense = nn.ModuleList([ + torch.nn.Linear(self.ch, + self.temb_ch), + torch.nn.Linear(self.temb_ch, + self.temb_ch), + ]) + + # downsampling + self.conv_in = torch.nn.Conv2d(in_channels, + self.ch, + kernel_size=3, + stride=1, + padding=1) + + curr_res = resolution + in_ch_mult = (1,) + ch_mult + self.down = nn.ModuleList() + block_in = None + for i_level in range(self.num_resolutions): + block = nn.ModuleList() + attn = nn.ModuleList() + block_in = ch * in_ch_mult[i_level] + block_out = ch * ch_mult[i_level] + for i_block in range(self.num_res_blocks): + block.append(ResnetBlock(in_channels=block_in, + out_channels=block_out, + temb_channels=self.temb_ch, + dropout=dropout)) + block_in = block_out + if curr_res in attn_resolutions: + attn.append(AttnBlock(block_in)) + down = nn.Module() + down.block = block + down.attn = attn + if i_level != self.num_resolutions - 1: + down.downsample = Downsample(block_in, resamp_with_conv) + curr_res = curr_res // 2 + self.down.append(down) + + # middle + self.mid = nn.Module() + self.mid.block_1 = ResnetBlock(in_channels=block_in, + out_channels=block_in, + temb_channels=self.temb_ch, + dropout=dropout) + self.mid.attn_1 = AttnBlock(block_in) + self.mid.block_2 = ResnetBlock(in_channels=block_in, + out_channels=block_in, + temb_channels=self.temb_ch, + dropout=dropout) + + # upsampling + self.up = nn.ModuleList() + for i_level in reversed(range(self.num_resolutions)): + block = nn.ModuleList() + attn = nn.ModuleList() + block_out = ch * ch_mult[i_level] + skip_in = ch * ch_mult[i_level] + for i_block in range(self.num_res_blocks + 1): + if i_block == self.num_res_blocks: + skip_in = ch * in_ch_mult[i_level] + block.append(ResnetBlock(in_channels=block_in + skip_in, + out_channels=block_out, + temb_channels=self.temb_ch, + dropout=dropout)) + block_in = block_out + if curr_res in attn_resolutions: + attn.append(AttnBlock(block_in)) + up = nn.Module() + up.block = block + up.attn = attn + if i_level != 0: + up.upsample = Upsample(block_in, resamp_with_conv) + curr_res = curr_res * 2 + self.up.insert(0, up) # prepend to get consistent order + + # end + self.norm_out = Normalize(block_in) + self.conv_out = torch.nn.Conv2d(block_in, + out_ch, + kernel_size=3, + stride=1, + padding=1) + + def forward(self, x, t): + assert x.shape[2] == x.shape[3] == self.resolution + + # timestep embedding + temb = get_timestep_embedding(t, self.ch) + temb = self.temb.dense[0](temb) + temb = nonlinearity(temb) + temb = self.temb.dense[1](temb) + + # downsampling + hs = [self.conv_in(x)] + for i_level in range(self.num_resolutions): + for i_block in range(self.num_res_blocks): + h = self.down[i_level].block[i_block](hs[-1], temb) + if len(self.down[i_level].attn) > 0: + h = self.down[i_level].attn[i_block](h) + hs.append(h) + if i_level != self.num_resolutions - 1: + hs.append(self.down[i_level].downsample(hs[-1])) + + # middle + h = hs[-1] + h = self.mid.block_1(h, temb) + h = self.mid.attn_1(h) + h = self.mid.block_2(h, temb) + + # upsampling + for i_level in reversed(range(self.num_resolutions)): + for i_block in range(self.num_res_blocks + 1): + h = self.up[i_level].block[i_block]( + torch.cat([h, hs.pop()], dim=1), temb) + if len(self.up[i_level].attn) > 0: + h = self.up[i_level].attn[i_block](h) + if i_level != 0: + h = self.up[i_level].upsample(h) + + # end + h = self.norm_out(h) + h = nonlinearity(h) + h = self.conv_out(h) + return h diff --git a/case_studies/diffpure/diffpure.Dockerfile b/case_studies/diffpure/diffpure.Dockerfile new file mode 100644 index 0000000..6c3aa50 --- /dev/null +++ b/case_studies/diffpure/diffpure.Dockerfile @@ -0,0 +1,97 @@ +FROM nvidia/cuda:11.0.3-devel-ubuntu20.04 + +ENV DEBIAN_FRONTEND=noninteractive + +# Set the time zone correctly +ENV TZ=Europe/Berlin +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +ENV SHELL /bin/bash + +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + cmake \ + git \ + curl \ + vim \ + ca-certificates \ + libjpeg-dev \ + tmux \ + nano \ + xterm \ + rsync \ + zip \ + zsh \ + htop \ + screen \ + zlib1g-dev \ + libcurl3-dev \ + libfreetype6-dev \ + libpng12-dev \ + libzmq3-dev \ + libpng-dev \ + libglib2.0-0 \ + openssh-server \ + sudo \ + build-essential \ + autoconf \ + automake \ + libtool \ + pkg-config \ + ca-certificates \ + wget \ + git \ + curl \ + ca-certificates \ + libjpeg-dev \ + libpng-dev \ + python \ + python3-dev \ + python3-pip \ + python3-setuptools \ + zlib1g-dev \ + swig \ + cmake \ + vim \ + locales \ + locales-all \ + screen \ + zip \ + unzip +RUN apt-get clean +RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +ENV LC_ALL en_US.UTF-8 +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US.UTF-8 + +RUN cd /usr/local/bin && \ + ln -s /usr/bin/python3 python && \ + ln -s /usr/bin/pip3 pip && \ + pip install --upgrade pip setuptools + +RUN pip install numpy==1.19.4 \ + pyyaml==5.3.1 \ + wheel==0.34.2 \ + scipy==1.5.2 \ + torch==1.7.1 \ + torchvision==0.8.2 \ + pillow==7.2.0 \ + matplotlib==3.3.0 \ + tqdm==4.56.1 \ + tensorboardX==2.0 \ + seaborn==0.10.1 \ + pandas==1.2.0 \ + requests==2.25.0 \ + xvfbwrapper==0.2.9 \ + torchdiffeq==0.2.1 \ + timm==0.5.4 \ + lmdb \ + Ninja \ + foolbox \ + torchsde \ + git+https://github.com/RobustBench/robustbench.git \ + numpy \ + sklearn \ + git+https://github.com/fra31/auto-attack \ + tensorflow \ No newline at end of file diff --git a/case_studies/diffpure/dp_utils.py b/case_studies/diffpure/dp_utils.py new file mode 100644 index 0000000..a4e717e --- /dev/null +++ b/case_studies/diffpure/dp_utils.py @@ -0,0 +1,301 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import sys +import argparse +from typing import Any + +import torch +import torch.nn as nn +import torchvision.models as models +from torch.utils.data import DataLoader +import torchvision.transforms as transforms + +from robustbench import load_model +import data + + +def compute_n_params(model, return_str=True): + tot = 0 + for p in model.parameters(): + w = 1 + for x in p.shape: + w *= x + tot += w + if return_str: + if tot >= 1e6: + return '{:.1f}M'.format(tot / 1e6) + else: + return '{:.1f}K'.format(tot / 1e3) + else: + return tot + + +class Logger(object): + """ + Redirect stderr to stdout, optionally print stdout to a file, + and optionally force flushing on both stdout and the file. + """ + + def __init__(self, file_name: str = None, file_mode: str = "w", should_flush: bool = True): + self.file = None + + if file_name is not None: + self.file = open(file_name, file_mode) + + self.should_flush = should_flush + self.stdout = sys.stdout + self.stderr = sys.stderr + + sys.stdout = self + sys.stderr = self + + def __enter__(self) -> "Logger": + return self + + def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: + self.close() + + def write(self, text: str) -> None: + """Write text to stdout (and a file) and optionally flush.""" + if len(text) == 0: # workaround for a bug in VSCode debugger: sys.stdout.write(''); sys.stdout.flush() => crash + return + + if self.file is not None: + self.file.write(text) + + self.stdout.write(text) + + if self.should_flush: + self.flush() + + def flush(self) -> None: + """Flush written text to both stdout and a file, if open.""" + if self.file is not None: + self.file.flush() + + self.stdout.flush() + + def close(self) -> None: + """Flush, close possible files, and remove stdout/stderr mirroring.""" + self.flush() + + # if using multiple loggers, prevent closing in wrong order + if sys.stdout is self: + sys.stdout = self.stdout + if sys.stderr is self: + sys.stderr = self.stderr + + if self.file is not None: + self.file.close() + + +def dict2namespace(config): + namespace = argparse.Namespace() + for key, value in config.items(): + if isinstance(value, dict): + new_value = dict2namespace(value) + else: + new_value = value + setattr(namespace, key, new_value) + return namespace + + +def str2bool(v): + if isinstance(v, bool): + return v + if v.lower() in ('yes', 'true', 't', 'y', '1'): + return True + elif v.lower() in ('no', 'false', 'f', 'n', '0'): + return False + else: + raise argparse.ArgumentTypeError('Boolean value expected.') + + +def update_state_dict(state_dict, idx_start=9): + + from collections import OrderedDict + new_state_dict = OrderedDict() + for k, v in state_dict.items(): + name = k[idx_start:] # remove 'module.0.' of dataparallel + new_state_dict[name]=v + + return new_state_dict + + +# ------------------------------------------------------------------------ +def get_accuracy(model, x_orig, y_orig, bs=64, device=torch.device('cuda:0')): + n_batches = x_orig.shape[0] // bs + acc = 0. + for counter in range(n_batches): + x = x_orig[counter * bs:min((counter + 1) * bs, x_orig.shape[0])].clone().to(device) + y = y_orig[counter * bs:min((counter + 1) * bs, x_orig.shape[0])].clone().to(device) + output = model(x) + acc += (output.max(1)[1] == y).float().sum() + + if isinstance(acc, torch.Tensor): + acc = acc.item() + + return acc / x_orig.shape[0] + + +def get_image_classifier(classifier_name): + class _Wrapper_ResNet(nn.Module): + def __init__(self, resnet): + super().__init__() + self.resnet = resnet + self.mu = torch.Tensor([0.485, 0.456, 0.406]).float().view(3, 1, 1) + self.sigma = torch.Tensor([0.229, 0.224, 0.225]).float().view(3, 1, 1) + + def forward(self, x): + x = (x - self.mu.to(x.device)) / self.sigma.to(x.device) + return self.resnet(x) + + if 'imagenet' in classifier_name: + if 'resnet18' in classifier_name: + print('using imagenet resnet18...') + model = models.resnet18(pretrained=True).eval() + elif 'resnet50' in classifier_name: + print('using imagenet resnet50...') + model = models.resnet50(pretrained=True).eval() + elif 'resnet101' in classifier_name: + print('using imagenet resnet101...') + model = models.resnet101(pretrained=True).eval() + elif 'wideresnet-50-2' in classifier_name: + print('using imagenet wideresnet-50-2...') + model = models.wide_resnet50_2(pretrained=True).eval() + elif 'deit-s' in classifier_name: + print('using imagenet deit-s...') + model = torch.hub.load('facebookresearch/deit:main', 'deit_small_patch16_224', pretrained=True).eval() + else: + raise NotImplementedError(f'unknown {classifier_name}') + + wrapper_resnet = _Wrapper_ResNet(model) + + elif 'cifar10' in classifier_name: + if 'wideresnet-28-10' in classifier_name: + print('using cifar10 wideresnet-28-10...') + model = load_model(model_name='Standard', dataset='cifar10', threat_model='Linf') # pixel in [0, 1] + + elif 'wrn-28-10-at0' in classifier_name: + print('using cifar10 wrn-28-10-at0...') + model = load_model(model_name='Gowal2021Improving_28_10_ddpm_100m', dataset='cifar10', + threat_model='Linf') # pixel in [0, 1] + + elif 'wrn-28-10-at1' in classifier_name: + print('using cifar10 wrn-28-10-at1...') + model = load_model(model_name='Gowal2020Uncovering_28_10_extra', dataset='cifar10', + threat_model='Linf') # pixel in [0, 1] + + elif 'wrn-70-16-at0' in classifier_name: + print('using cifar10 wrn-70-16-at0...') + model = load_model(model_name='Gowal2021Improving_70_16_ddpm_100m', dataset='cifar10', + threat_model='Linf') # pixel in [0, 1] + + elif 'wrn-70-16-at1' in classifier_name: + print('using cifar10 wrn-70-16-at1...') + model = load_model(model_name='Rebuffi2021Fixing_70_16_cutmix_extra', dataset='cifar10', + threat_model='Linf') # pixel in [0, 1] + + elif 'wrn-70-16-L2-at1' in classifier_name: + print('using cifar10 wrn-70-16-L2-at1...') + model = load_model(model_name='Rebuffi2021Fixing_70_16_cutmix_extra', dataset='cifar10', + threat_model='L2') # pixel in [0, 1] + + elif 'wideresnet-70-16' in classifier_name: + print('using cifar10 wideresnet-70-16 (dm_wrn-70-16)...') + from robustbench.model_zoo.architectures.dm_wide_resnet import DMWideResNet, Swish + model = DMWideResNet(num_classes=10, depth=70, width=16, activation_fn=Swish) # pixel in [0, 1] + + model_path = 'checkpoints/diffpure/cifar10/wresnet-76-10/weights-best.pt' + print(f"=> loading wideresnet-70-16 checkpoint '{model_path}'") + model.load_state_dict(update_state_dict(torch.load(model_path)['model_state_dict'])) + model.eval() + print(f"=> loaded wideresnet-70-16 checkpoint") + + elif 'resnet-50' in classifier_name: + print('using cifar10 resnet-50...') + from classifiers.cifar10_resnet import ResNet50 + model = ResNet50() # pixel in [0, 1] + + model_path = 'checkpoints/diffpure/cifar10/resnet-50/weights.pt' + print(f"=> loading resnet-50 checkpoint '{model_path}'") + model.load_state_dict(update_state_dict(torch.load(model_path), idx_start=7)) + model.eval() + print(f"=> loaded resnet-50 checkpoint") + + elif 'wrn-70-16-dropout' in classifier_name: + print('using cifar10 wrn-70-16-dropout (standard wrn-70-16-dropout)...') + from classifiers.cifar10_resnet import WideResNet_70_16_dropout + model = WideResNet_70_16_dropout() # pixel in [0, 1] + + model_path = 'checkpoints/diffpure/cifar10/wrn-70-16-dropout/weights.pt' + print(f"=> loading wrn-70-16-dropout checkpoint '{model_path}'") + model.load_state_dict(update_state_dict(torch.load(model_path), idx_start=7)) + model.eval() + print(f"=> loaded wrn-70-16-dropout checkpoint") + + else: + raise NotImplementedError(f'unknown {classifier_name}') + + wrapper_resnet = model + + elif 'celebahq' in classifier_name: + attribute = classifier_name.split('__')[-1] # `celebahq__Smiling` + ckpt_path = f'checkpoints/diffpure/celebahq/{attribute}/net_best.pth' + from classifiers.attribute_classifier import ClassifierWrapper + model = ClassifierWrapper(attribute, ckpt_path=ckpt_path) + wrapper_resnet = model + else: + raise NotImplementedError(f'unknown {classifier_name}') + + return wrapper_resnet + + +def load_data(args, adv_batch_size, binarization_test=False): + if 'imagenet' in args.domain: + val_dir = './dataset/imagenet_lmdb/val' # using imagenet lmdb data + val_transform = data.get_transform(args.domain, 'imval', base_size=224) + val_data = data.imagenet_lmdb_dataset_sub(val_dir, transform=val_transform, + num_sub=args.num_sub, data_seed=args.data_seed) + n_samples = len(val_data) + val_loader = DataLoader(val_data, batch_size=n_samples, shuffle=False, pin_memory=True, num_workers=4) + x_val, y_val = next(iter(val_loader)) + elif 'cifar10' in args.domain: + data_dir = './dataset' + transform = transforms.Compose([transforms.ToTensor()]) + + if binarization_test: + val_data = data.cifar10_dataset_sub( + data_dir, transform=transform, num_sub=10000, data_seed=args.data_seed) + val_loader = DataLoader(val_data, batch_size=args.test_samples_idx_end, shuffle=False) + x_val, y_val = next(iter(val_loader)) + x_val = x_val[args.test_samples_idx_start:args.test_samples_idx_end] + y_val = y_val[args.test_samples_idx_start:args.test_samples_idx_end] + else: + val_data = data.cifar10_dataset_sub(data_dir, transform=transform, + num_sub=args.num_sub, data_seed=args.data_seed) + n_samples = len(val_data) + val_loader = DataLoader(val_data, batch_size=n_samples, shuffle=False, pin_memory=True, num_workers=4) + x_val, y_val = next(iter(val_loader)) + elif 'celebahq' in args.domain: + data_dir = './dataset/celebahq' + attribute = args.classifier_name.split('__')[-1] # `celebahq__Smiling` + val_transform = data.get_transform('celebahq', 'imval') + clean_dset = data.get_dataset('celebahq', 'val', attribute, root=data_dir, transform=val_transform, + fraction=2, data_seed=args.data_seed) # data_seed randomizes here + loader = DataLoader(clean_dset, batch_size=adv_batch_size, shuffle=False, + pin_memory=True, num_workers=4) + x_val, y_val = next(iter(loader)) # [0, 1], 256x256 + else: + raise NotImplementedError(f'Unknown domain: {args.domain}!') + + print(f'x_val shape: {x_val.shape}') + x_val, y_val = x_val.contiguous().requires_grad_(True), y_val.contiguous() + print(f'x (min, max): ({x_val.min()}, {x_val.max()})') + + return x_val, y_val diff --git a/case_studies/diffpure/eval_sde_adv.py b/case_studies/diffpure/eval_sde_adv.py new file mode 100644 index 0000000..02d1a48 --- /dev/null +++ b/case_studies/diffpure/eval_sde_adv.py @@ -0,0 +1,570 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import argparse +import logging +import yaml +import os +import time + +import random +import numpy as np + +import torch +import torch.nn as nn +import torch.nn.functional as F + +from autoattack import AutoAttack +from attacks.autopgd import fix_autoattack as fix_autoattack_autopgd + +from active_tests import decision_boundary_binarization as dbb +from argparse_utils import DecisionBoundaryBinarizationSettings +from stadv_eot.attacks import StAdvAttack + +import dp_utils +import utils +from dp_utils import str2bool, get_accuracy, get_image_classifier, load_data + +from runners.diffpure_ddpm import Diffusion +from runners.diffpure_guided import GuidedDiffusion +from runners.diffpure_sde import RevGuidedDiffusion +from runners.diffpure_ode import OdeGuidedDiffusion +from runners.diffpure_ldsde import LDGuidedDiffusion + + +def patch_robustbench_models(): + import robustbench.model_zoo.architectures as arch + def wide_resnet_forward(self, x, features_only=False, features_and_logits=False): + out = self.conv1(x) + out = self.block1(out) + out = self.block2(out) + out = self.block3(out) + out = self.relu(self.bn1(out)) + out = F.avg_pool2d(out, 8) + out = out.view(-1, self.nChannels) + if features_only: + return out + l = self.fc(out) + if features_and_logits: + return out, l + return l + + def robust_wide_resnet_forward(self, x, features_only=False, features_and_logits=False): + out = self.stem_conv(x) + for i, block in enumerate(self.blocks): + out = block(out) + out = self.relu(self.bn1(out)) + out = self.global_pooling(out) + out = out.view(-1, self.fc_size) + if features_only: + return out + l = self.fc(out) + if features_and_logits: + return out, l + return out + + def cifar_resnext_forward(self, x, features_only=False, features_and_logits=False): + x = self.conv_1_3x3(x) + x = F.relu(self.bn_1(x), inplace=True) + x = self.stage_1(x) + x = self.stage_2(x) + x = self.stage_3(x) + x = self.avgpool(x) + x = x.view(x.size(0), -1) + if features_only: + return x + l = self.classifier(x) + if features_and_logits: + return x, l + return l + + def preact_resenet_forward(self, x, features_only=False, features_and_logits=False): + out = self.conv1(x) + out = self.layer1(out) + out = self.layer2(out) + out = self.layer3(out) + out = self.layer4(out) + if self.bn_before_fc: + out = F.relu(self.bn(out)) + out = F.avg_pool2d(out, 4) + out = out.view(out.size(0), -1) + if features_only: + return out + l = self.linear(out) + if features_and_logits: + return out, l + return l + + def resnet_forward(self, x, features_only=False, features_and_logits=False): + out = F.relu(self.bn1(self.conv1(x))) + out = self.layer1(out) + out = self.layer2(out) + out = self.layer3(out) + out = self.layer4(out) + out = F.avg_pool2d(out, 4) + out = out.view(out.size(0), -1) + if features_only: + return out + l = self.linear(out) + if features_and_logits: + out, l + return l + + def dm_preact_resnet_forward(self, x, features_only=False, features_and_logits=False): + if self.padding > 0: + x = F.pad(x, (self.padding,) * 4) + out = (x - self.mean) / self.std + out = self.conv_2d(out) + out = self.layer_0(out) + out = self.layer_1(out) + out = self.layer_2(out) + out = self.layer_3(out) + out = self.relu(self.batchnorm(out)) + out = F.avg_pool2d(out, 4) + out = out.view(out.size(0), -1) + if features_only: + return out + l = self.logits(out) + if features_and_logits: + return out, l + return l + + def dm_resnet_forward(self, x, features_only=False, features_and_logits=False): + if self.padding > 0: + x = F.pad(x, (self.padding,) * 4) + out = (x - self.mean) / self.std + out = self.init_conv(out) + out = self.layer(out) + out = self.relu(self.batchnorm(out)) + out = F.avg_pool2d(out, 8) + out = out.view(-1, self.num_channels) + if features_only: + return out + l = self.logits(out) + if features_and_logits: + return out, l + return l + + arch.wide_resnet.WideResNet.forward = wide_resnet_forward + arch.robust_wide_resnet.RobustWideResNet.forward = robust_wide_resnet_forward + arch.resnext.CifarResNeXt.forward = cifar_resnext_forward + arch.resnet.PreActResNet.forward = preact_resenet_forward + arch.resnet.ResNet.forward = resnet_forward + arch.dm_wide_resnet.DMPreActResNet.forward = dm_preact_resnet_forward + arch.dm_wide_resnet.DMWideResNet.forward = dm_resnet_forward + + print("Patched RobustBench classifiers.") + + +class SDE_Adv_Model(nn.Module): + def __init__(self, args, config): + super().__init__() + self.args = args + + # image classifier + self.classifier = get_image_classifier(args.classifier_name).to(config.device) + + # diffusion model + print(f'diffusion_type: {args.diffusion_type}') + if args.diffusion_type == 'ddpm': + self.runner = GuidedDiffusion(args, config, device=config.device) + elif args.diffusion_type == 'sde': + self.runner = RevGuidedDiffusion(args, config, device=config.device) + elif args.diffusion_type == 'ode': + self.runner = OdeGuidedDiffusion(args, config, device=config.device) + elif args.diffusion_type == 'ldsde': + self.runner = LDGuidedDiffusion(args, config, device=config.device) + elif args.diffusion_type == 'celebahq-ddpm': + self.runner = Diffusion(args, config, device=config.device) + else: + raise NotImplementedError('unknown diffusion type') + + self.register_buffer('counter', torch.zeros(1, device=config.device)) + self.tag = None + + def reset_counter(self): + self.counter = torch.zeros(1, dtype=torch.int, device=config.device) + + def set_tag(self, tag=None): + self.tag = tag + + def forward(self, x, features_only=False, features_and_logits=False): + counter = self.counter.item() + if counter % 10 == 0: + print(f'diffusion times: {counter}') + + # imagenet [3, 224, 224] -> [3, 256, 256] -> [3, 224, 224] + if 'imagenet' in self.args.domain: + x = F.interpolate(x, size=(256, 256), mode='bilinear', align_corners=False) + + start_time = time.time() + x_re = self.runner.image_editing_sample((x - 0.5) * 2, bs_id=counter, tag=self.tag) + minutes, seconds = divmod(time.time() - start_time, 60) + + if 'imagenet' in self.args.domain: + x_re = F.interpolate(x_re, size=(224, 224), mode='bilinear', align_corners=False) + + if counter % 10 == 0: + print(f'x shape (before diffusion models): {x.shape}') + print(f'x shape (before classifier): {x_re.shape}') + print("Sampling time per batch: {:0>2}:{:05.2f}".format(int(minutes), seconds)) + + out = self.classifier((x_re + 1) * 0.5, features_only=features_only, features_and_logits=features_and_logits) + + self.counter += 1 + + return out + + +def eval_autoattack(args, config, model, x_val, y_val, adv_batch_size, log_dir): + ngpus = torch.cuda.device_count() + model_ = model + if ngpus > 1: + model_ = model.module + + attack_version = args.attack_version # ['standard', 'rand', 'custom'] + if attack_version == 'standard': + attack_list = ['apgd-ce', 'apgd-t', 'fab-t', 'square'] + elif attack_version == 'rand': + attack_list = ['apgd-ce', 'apgd-dlr'] + elif attack_version == 'custom': + attack_list = args.attack_type.split(',') + else: + raise NotImplementedError(f'Unknown attack version: {attack_version}!') + print(f'attack_version: {attack_version}, attack_list: {attack_list}') # ['apgd-ce', 'apgd-t', 'fab-t', 'square'] + + # ---------------- apply the attack to classifier ---------------- + print(f'apply the attack to classifier [{args.lp_norm}]...') + classifier = get_image_classifier(args.classifier_name).to(config.device) + adversary_resnet = AutoAttack(classifier, norm=args.lp_norm, eps=args.adv_eps, + version=attack_version, attacks_to_run=attack_list, + log_path=f'{log_dir}/log_resnet.txt', device=config.device) + if attack_version == 'custom': + adversary_resnet.apgd.n_restarts = 1 + adversary_resnet.fab.n_restarts = 1 + adversary_resnet.apgd_targeted.n_restarts = 1 + adversary_resnet.fab.n_target_classes = 9 + adversary_resnet.apgd_targeted.n_target_classes = 9 + adversary_resnet.square.n_queries = 5000 + if attack_version == 'rand': + adversary_resnet.apgd.eot_iter = args.eot_iter + print(f'[classifier] rand version with eot_iter: {adversary_resnet.apgd.eot_iter}') + print(f'{args.lp_norm}, epsilon: {args.adv_eps}') + + x_adv_resnet = adversary_resnet.run_standard_evaluation(x_val, y_val, bs=adv_batch_size) + print(f'x_adv_resnet shape: {x_adv_resnet.shape}') + torch.save([x_adv_resnet, y_val], f'{log_dir}/x_adv_resnet_sd{args.seed}.pt') + + # ---------------- apply the attack to sde_adv ---------------- + print(f'apply the attack to sde_adv [{args.lp_norm}]...') + model_.reset_counter() + adversary_sde = AutoAttack(model, norm=args.lp_norm, eps=args.adv_eps, + version=attack_version, attacks_to_run=attack_list, + log_path=f'{log_dir}/log_sde_adv.txt', device=config.device) + if attack_version == 'custom': + adversary_sde.apgd.n_restarts = 1 + adversary_sde.fab.n_restarts = 1 + adversary_sde.apgd_targeted.n_restarts = 1 + adversary_sde.fab.n_target_classes = 9 + adversary_sde.apgd_targeted.n_target_classes = 9 + adversary_sde.square.n_queries = 5000 + if attack_version == 'rand': + adversary_sde.apgd.eot_iter = args.eot_iter + print(f'[adv_sde] rand version with eot_iter: {adversary_sde.apgd.eot_iter}') + print(f'{args.lp_norm}, epsilon: {args.adv_eps}') + + x_adv_sde = adversary_sde.run_standard_evaluation(x_val, y_val, bs=adv_batch_size) + print(f'x_adv_sde shape: {x_adv_sde.shape}') + torch.save([x_adv_sde, y_val], f'{log_dir}/x_adv_sde_sd{args.seed}.pt') + + +def eval_stadv(args, config, model, x_val, y_val, adv_batch_size, log_dir): + ngpus = torch.cuda.device_count() + model_ = model + if ngpus > 1: + model_ = model.module + + x_val, y_val = x_val.to(config.device), y_val.to(config.device) + print(f'bound: {args.adv_eps}') + + # apply the attack to resnet + print(f'apply the stadv attack to resnet...') + resnet = get_image_classifier(args.classifier_name).to(config.device) + + start_time = time.time() + init_acc = get_accuracy(resnet, x_val, y_val, bs=adv_batch_size) + print('initial accuracy: {:.2%}, time elapsed: {:.2f}s'.format(init_acc, time.time() - start_time)) + + adversary_resnet = StAdvAttack(resnet, bound=args.adv_eps, num_iterations=100, eot_iter=args.eot_iter) + + start_time = time.time() + x_adv_resnet = adversary_resnet(x_val, y_val) + + robust_acc = get_accuracy(resnet, x_adv_resnet, y_val, bs=adv_batch_size) + print('robust accuracy: {:.2%}, time elapsed: {:.2f}s'.format(robust_acc, time.time() - start_time)) + + print(f'x_adv_resnet shape: {x_adv_resnet.shape}') + torch.save([x_adv_resnet, y_val], f'{log_dir}/x_adv_resnet_sd{args.seed}.pt') + + # apply the attack to sde_adv + print(f'apply the stadv attack to sde_adv...') + + start_time = time.time() + model_.reset_counter() + model_.set_tag('no_adv') + init_acc = get_accuracy(model, x_val, y_val, bs=adv_batch_size) + print('initial accuracy: {:.2%}, time elapsed: {:.2f}s'.format(init_acc, time.time() - start_time)) + + adversary_sde = StAdvAttack(model, bound=args.adv_eps, num_iterations=100, eot_iter=args.eot_iter) + + start_time = time.time() + model_.reset_counter() + model_.set_tag() + x_adv_sde = adversary_sde(x_val, y_val) + + model_.reset_counter() + model_.set_tag('sde_adv') + robust_acc = get_accuracy(model, x_adv_sde, y_val, bs=adv_batch_size) + print('robust accuracy: {:.2%}, time elapsed: {:.2f}s'.format(robust_acc, time.time() - start_time)) + + print(f'x_adv_sde shape: {x_adv_sde.shape}') + torch.save([x_adv_sde, y_val], f'{log_dir}/x_adv_sde_sd{args.seed}.pt') + + +def binarization_eval(args, config): + print("Running binarization test.") + + middle_name = '_'.join([args.diffusion_type, args.attack_version]) if args.attack_version in ['stadv', 'standard', + 'rand'] \ + else '_'.join([args.diffusion_type, args.attack_version, args.attack_type]) + log_dir = os.path.join(args.image_folder, args.classifier_name, middle_name, + 'seed' + str(args.seed), 'data' + str(args.data_seed) + "_" + + str(args.test_samples_idx_start) + "_" + str(args.test_samples_idx_end)) + os.makedirs(log_dir, exist_ok=True) + args.log_dir = log_dir + + ngpus = torch.cuda.device_count() + adv_batch_size = args.adv_batch_size * ngpus + + # load model + print('starting the model and loader...') + model = SDE_Adv_Model(args, config) + if ngpus > 1: + model = torch.nn.DataParallel(model) + model = model.eval().to(config.device) + + # load data + x_val, y_val = load_data(args, adv_batch_size, binarization_test=True) + testloader = utils.build_dataloader_from_arrays(x_val.detach().cpu().numpy(), y_val.detach().cpu().numpy()) + adv_batch_size = args.adv_batch_size * ngpus + + print('adv_batch_size', adv_batch_size) + print('x_val', x_val.shape) + + if args.attack_version in ['standard', 'rand', 'custom']: + attack_version = args.attack_version # ['standard', 'rand', 'custom'] + if attack_version == 'standard': + attack_list = ['apgd-ce', 'apgd-t', 'fab-t', 'square'] + elif attack_version == 'rand': + attack_list = ['apgd-ce', 'apgd-dlr'] + elif attack_version == 'custom': + attack_list = args.attack_type.split(',') + else: + raise NotImplementedError(f'Unknown attack version: {attack_version}!') + print( + f'attack_version: {attack_version}, attack_list: {attack_list}') # ['apgd-ce', 'apgd-t', 'fab-t', 'square'] + print(f'{args.lp_norm}, epsilon: {args.adv_eps}') + elif args.attack_version == 'stadv': + print("Using StAdv attack.") + else: + raise NotImplementedError(f'unknown attack_version: {args.attack_version}') + + def eval(m, x, y): + model.reset_counter() + + if args.attack_version in ['standard', 'rand', 'custom']: + adversary_sde = AutoAttack(m, norm=args.lp_norm, eps=args.adv_eps, + version=attack_version, attacks_to_run=attack_list, + device=config.device) + # Fix loss functions of APGD such that they are properly defined for binary classification problems. + fix_autoattack_autopgd(adversary_sde) + if attack_version == 'custom': + adversary_sde.apgd.n_restarts = 1 + adversary_sde.fab.n_restarts = 1 + adversary_sde.apgd_targeted.n_restarts = 1 + adversary_sde.fab.n_target_classes = 1 + adversary_sde.apgd_targeted.n_target_classes = 1 + adversary_sde.square.n_queries = 5000 + if attack_version == 'rand': + adversary_sde.apgd.eot_iter = args.eot_iter + x_adv_sde = adversary_sde.run_standard_evaluation(x, y, bs=len(x)) + elif args.attack_version == 'stadv': + adversary_sde = StAdvAttack(m, bound=args.adv_eps, num_iterations=100, eot_iter=args.eot_iter) + x_adv_sde = adversary_sde(x, y) + else: + raise NotImplementedError(f'unknown attack_version: {args.attack_version}') + + x_adv_logits = m(x_adv_sde) + robust_acc = get_accuracy(m, x_adv_sde, y, bs=adv_batch_size) + + return robust_acc, (x_adv_sde, x_adv_logits) + + scores_logit_differences_and_validation_accuracies = dbb.interior_boundary_discrimination_attack( + model, + testloader, + attack_fn=lambda m, l, kwargs: eval(m, l.dataset.tensors[0].to(config.device), + l.dataset.tensors[1].to(config.device)), + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=args.adv_eps, + norm="linf", + lr=10000, + n_boundary_points=args.n_boundary_points, + n_inner_points=args.n_inner_points, + adversarial_attack_settings=None, + optimizer="sklearn" + ), + n_samples=len(x_val), + device=config.device, + n_samples_evaluation=200, # args.num_samples_test * 10, + n_samples_asr_evaluation=200, + batch_size=args.batch_size * ngpus, + rescale_logits="adaptive", + decision_boundary_closeness=0.999, + sample_training_data_from_corners=args.sample_from_corners + ) + + print(dbb.format_result(scores_logit_differences_and_validation_accuracies, len(x_val))) + + +def robustness_eval(args, config): + middle_name = '_'.join([args.diffusion_type, args.attack_version]) if args.attack_version in ['stadv', 'standard', 'rand'] \ + else '_'.join([args.diffusion_type, args.attack_version, args.attack_type]) + log_dir = os.path.join(args.image_folder, args.classifier_name, middle_name, + 'seed' + str(args.seed), 'data' + str(args.data_seed)) + os.makedirs(log_dir, exist_ok=True) + args.log_dir = log_dir + logger = dp_utils.Logger(file_name=f'{log_dir}/log.txt', file_mode="w+", should_flush=True) + + ngpus = torch.cuda.device_count() + adv_batch_size = args.adv_batch_size * ngpus + print(f'ngpus: {ngpus}, adv_batch_size: {adv_batch_size}') + + # load model + print('starting the model and loader...') + model = SDE_Adv_Model(args, config) + if ngpus > 1: + model = torch.nn.DataParallel(model) + model = model.eval().to(config.device) + + # load data + x_val, y_val = load_data(args, adv_batch_size) + + # eval classifier and sde_adv against attacks + if args.attack_version in ['standard', 'rand', 'custom']: + eval_autoattack(args, config, model, x_val, y_val, adv_batch_size, log_dir) + elif args.attack_version == 'stadv': + eval_stadv(args, config, model, x_val, y_val, adv_batch_size, log_dir) + else: + raise NotImplementedError(f'unknown attack_version: {args.attack_version}') + + logger.close() + + +def parse_args_and_config(): + parser = argparse.ArgumentParser(description=globals()['__doc__']) + # diffusion models + parser.add_argument('--config', type=str, required=True, help='Path to the config file') + parser.add_argument('--data_seed', type=int, default=0, help='Random seed') + parser.add_argument('--seed', type=int, default=1234, help='Random seed') + parser.add_argument('--exp', type=str, default='exp', help='Path for saving running related data.') + parser.add_argument('--verbose', type=str, default='info', help='Verbose level: info | debug | warning | critical') + parser.add_argument('-i', '--image_folder', type=str, default='images', help="The folder name of samples") + parser.add_argument('--ni', action='store_true', help="No interaction. Suitable for Slurm Job launcher") + parser.add_argument('--sample_step', type=int, default=1, help='Total sampling steps') + parser.add_argument('--t', type=int, default=400, help='Sampling noise scale') + parser.add_argument('--t_delta', type=int, default=15, help='Perturbation range of sampling noise scale') + parser.add_argument('--rand_t', type=str2bool, default=False, help='Decide if randomize sampling noise scale') + parser.add_argument('--diffusion_type', type=str, default='ddpm', help='[ddpm, sde]') + parser.add_argument('--score_type', type=str, default='guided_diffusion', help='[guided_diffusion, score_sde]') + parser.add_argument('--eot_iter', type=int, default=20, help='only for rand version of autoattack') + parser.add_argument('--use_bm', action='store_true', help='whether to use brownian motion') + + # LDSDE + parser.add_argument('--sigma2', type=float, default=1e-3, help='LDSDE sigma2') + parser.add_argument('--lambda_ld', type=float, default=1e-2, help='lambda_ld') + parser.add_argument('--eta', type=float, default=5., help='LDSDE eta') + parser.add_argument('--step_size', type=float, default=1e-2, help='step size for ODE Euler method') + + # adv + parser.add_argument('--domain', type=str, default='celebahq', help='which domain: celebahq, cat, car, imagenet') + parser.add_argument('--classifier_name', type=str, default='Eyeglasses', help='which classifier to use') + parser.add_argument('--partition', type=str, default='val') + parser.add_argument('--adv_batch_size', type=int, default=64) + parser.add_argument('--attack_type', type=str, default='square') + parser.add_argument('--lp_norm', type=str, default='Linf', choices=['Linf', 'L2']) + parser.add_argument('--attack_version', type=str, default='custom') + + parser.add_argument('--num_sub', type=int, default=1000, help='imagenet subset') + parser.add_argument('--adv_eps', type=float, default=0.07) + + # Binarization Test + parser.add_argument("--binarization-test", action="store_true") + parser.add_argument("--batch-size", default=64, type=int) + parser.add_argument("--n_inner_points", default=999, type=int) + parser.add_argument("--n_boundary_points", default=1, type=int) + parser.add_argument("--sample-from-corners", action="store_true") + parser.add_argument("--test-samples-idx-start", default=0, type=int) + parser.add_argument("--test-samples-idx-end", default=64, type=int) + # parser.add_argument('--gpu_ids', type=str, default='0') + + args = parser.parse_args() + + # parse config file + with open(args.config, 'r') as f: + config = yaml.safe_load(f) + new_config = dp_utils.dict2namespace(config) + + level = getattr(logging, args.verbose.upper(), None) + if not isinstance(level, int): + raise ValueError('level {} not supported'.format(args.verbose)) + + handler1 = logging.StreamHandler() + formatter = logging.Formatter('%(levelname)s - %(filename)s - %(asctime)s - %(message)s') + handler1.setFormatter(formatter) + logger = logging.getLogger() + logger.addHandler(handler1) + logger.setLevel(level) + + args.image_folder = os.path.join(args.exp, args.image_folder) + os.makedirs(args.image_folder, exist_ok=True) + + # add device + device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') + logging.info("Using device: {}".format(device)) + new_config.device = device + + # set random seed + torch.manual_seed(args.seed) + random.seed(args.seed) + np.random.seed(args.seed) + if torch.cuda.is_available(): + torch.cuda.manual_seed_all(args.seed) + + torch.backends.cudnn.benchmark = True + + return args, new_config + + +if __name__ == '__main__': + patch_robustbench_models() + args, config = parse_args_and_config() + # os.environ["CUDA_VISIBLE_DEVICES"] = args.gpu_ids + + if args.binarization_test: + binarization_eval(args, config) + else: + robustness_eval(args, config) diff --git a/case_studies/diffpure/eval_sde_adv_bpda.py b/case_studies/diffpure/eval_sde_adv_bpda.py new file mode 100644 index 0000000..7cb4996 --- /dev/null +++ b/case_studies/diffpure/eval_sde_adv_bpda.py @@ -0,0 +1,278 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import argparse +import logging +import yaml +import os +import time + +import random +import numpy as np + +import torch +import torch.nn as nn +import torch.nn.functional as F + +from bpda_eot.bpda_eot_attack import BPDA_EOT_Attack + +import utils +from utils import str2bool, get_accuracy, get_image_classifier, load_data + +from runners.diffpure_ddpm import Diffusion +from runners.diffpure_guided import GuidedDiffusion +from runners.diffpure_sde import RevGuidedDiffusion + + +class ResNet_Adv_Model(nn.Module): + def __init__(self, args, config): + super().__init__() + # image classifier + self.resnet = get_image_classifier(args.classifier_name).to(config.device) + + def purify(self, x): + return x + + def forward(self, x, mode='purify_and_classify'): + if mode == 'purify': + out = self.purify(x) + elif mode == 'classify': + out = self.resnet(x) # x in [0, 1] + elif mode == 'purify_and_classify': + x = self.purify(x) + out = self.resnet(x) # x in [0, 1] + else: + raise NotImplementedError(f'unknown mode: {mode}') + return out + + +class SDE_Adv_Model(nn.Module): + def __init__(self, args, config): + super().__init__() + self.args = args + + # image classifier + self.resnet = get_image_classifier(args.classifier_name).to(config.device) + + # diffusion model + print(f'diffusion_type: {args.diffusion_type}') + if args.diffusion_type == 'ddpm': + self.runner = GuidedDiffusion(args, config, device=config.device) + elif args.diffusion_type == 'sde': + self.runner = RevGuidedDiffusion(args, config, device=config.device) + elif args.diffusion_type == 'celebahq-ddpm': + self.runner = Diffusion(args, config, device=config.device) + else: + raise NotImplementedError('unknown diffusion type') + + self.register_buffer('counter', torch.zeros(1, device=config.device)) + self.tag = None + + def reset_counter(self): + self.counter = torch.zeros(1, dtype=torch.int, device=config.device) + + def set_tag(self, tag=None): + self.tag = tag + + def purify(self, x): + counter = self.counter.item() + if counter % 5 == 0: + print(f'diffusion times: {counter}') + + # imagenet [3, 224, 224] -> [3, 256, 256] -> [3, 224, 224] + if 'imagenet' in self.args.domain: + x = F.interpolate(x, size=(256, 256), mode='bilinear', align_corners=False) + + start_time = time.time() + x_re = self.runner.image_editing_sample((x - 0.5) * 2, bs_id=counter, tag=self.tag) + minutes, seconds = divmod(time.time() - start_time, 60) + + if 'imagenet' in self.args.domain: + x_re = F.interpolate(x_re, size=(224, 224), mode='bilinear', align_corners=False) + + if counter % 5 == 0: + print(f'x shape (before diffusion models): {x.shape}') + print(f'x shape (before resnet): {x_re.shape}') + print("Sampling time per batch: {:0>2}:{:05.2f}".format(int(minutes), seconds)) + + self.counter += 1 + + return (x_re + 1) * 0.5 + + def forward(self, x, mode='purify_and_classify'): + if mode == 'purify': + out = self.purify(x) + elif mode == 'classify': + out = self.resnet(x) # x in [0, 1] + elif mode == 'purify_and_classify': + x = self.purify(x) + out = self.resnet(x) # x in [0, 1] + else: + raise NotImplementedError(f'unknown mode: {mode}') + return out + + +def eval_bpda(args, config, model, x_val, y_val, adv_batch_size, log_dir): + ngpus = torch.cuda.device_count() + model_ = model + if ngpus > 1: + model_ = model.module + + x_val, y_val = x_val.to(config.device), y_val.to(config.device) + + # ------------------ apply the attack to resnet ------------------ + print(f'apply the bpda attack to resnet...') + resnet_bpda = ResNet_Adv_Model(args, config) + if ngpus > 1: + resnet_bpda = torch.nn.DataParallel(resnet_bpda) + + start_time = time.time() + init_acc = get_accuracy(resnet_bpda, x_val, y_val, bs=adv_batch_size) + print('initial accuracy: {:.2%}, time elapsed: {:.2f}s'.format(init_acc, time.time() - start_time)) + + adversary_resnet = BPDA_EOT_Attack(resnet_bpda, adv_eps=args.adv_eps, eot_defense_reps=args.eot_defense_reps, + eot_attack_reps=args.eot_attack_reps) + + start_time = time.time() + class_batch, ims_adv_batch = adversary_resnet.attack_all(x_val, y_val, batch_size=adv_batch_size) + init_acc = float(class_batch[0, :].sum()) / class_batch.shape[1] + robust_acc = float(class_batch[-1, :].sum()) / class_batch.shape[1] + + print('init acc: {:.2%}, robust acc: {:.2%}, time elapsed: {:.2f}s'.format(init_acc, robust_acc, time.time() - start_time)) + + print(f'x_adv_resnet shape: {ims_adv_batch.shape}') + torch.save([ims_adv_batch, y_val], f'{log_dir}/x_adv_resnet_sd{args.seed}.pt') + + # ------------------ apply the attack to sde_adv ------------------ + print(f'apply the bpda attack to sde_adv...') + + start_time = time.time() + model_.reset_counter() + model_.set_tag('no_adv') + init_acc = get_accuracy(model, x_val, y_val, bs=adv_batch_size) + print('initial accuracy: {:.2%}, time elapsed: {:.2f}s'.format(init_acc, time.time() - start_time)) + + adversary_sde = BPDA_EOT_Attack(model, adv_eps=args.adv_eps, eot_defense_reps=args.eot_defense_reps, + eot_attack_reps=args.eot_attack_reps) + + start_time = time.time() + model_.reset_counter() + model_.set_tag() + class_batch, ims_adv_batch = adversary_sde.attack_all(x_val, y_val, batch_size=adv_batch_size) + init_acc = float(class_batch[0, :].sum()) / class_batch.shape[1] + robust_acc = float(class_batch[-1, :].sum()) / class_batch.shape[1] + + print('init acc: {:.2%}, robust acc: {:.2%}, time elapsed: {:.2f}s'.format(init_acc, robust_acc, time.time() - start_time)) + + print(f'x_adv_sde shape: {ims_adv_batch.shape}') + torch.save([ims_adv_batch, y_val], f'{log_dir}/x_adv_sde_sd{args.seed}.pt') + + +def robustness_eval(args, config): + middle_name = '_'.join([args.diffusion_type, 'bpda']) + log_dir = os.path.join(args.image_folder, args.classifier_name, middle_name, + 'seed' + str(args.seed), 'data' + str(args.data_seed)) + os.makedirs(log_dir, exist_ok=True) + args.log_dir = log_dir + logger = utils.Logger(file_name=f'{log_dir}/log.txt', file_mode="w+", should_flush=True) + + ngpus = torch.cuda.device_count() + adv_batch_size = args.adv_batch_size * ngpus + print(f'ngpus: {ngpus}, adv_batch_size: {adv_batch_size}') + + # load model + print('starting the model and loader...') + model = SDE_Adv_Model(args, config) + if ngpus > 1: + model = torch.nn.DataParallel(model) + model = model.eval().to(config.device) + + # load data + x_val, y_val = load_data(args, adv_batch_size) + + # eval classifier and sde_adv against bpda attack + eval_bpda(args, config, model, x_val, y_val, adv_batch_size, log_dir) + + logger.close() + + +def parse_args_and_config(): + parser = argparse.ArgumentParser(description=globals()['__doc__']) + # diffusion models + parser.add_argument('--config', type=str, required=True, help='Path to the config file') + parser.add_argument('--data_seed', type=int, default=0, help='Random seed') + parser.add_argument('--seed', type=int, default=1234, help='Random seed') + parser.add_argument('--exp', type=str, default='exp', help='Path for saving running related data.') + parser.add_argument('--verbose', type=str, default='info', help='Verbose level: info | debug | warning | critical') + parser.add_argument('-i', '--image_folder', type=str, default='images', help="The folder name of samples") + parser.add_argument('--ni', action='store_true', help="No interaction. Suitable for Slurm Job launcher") + parser.add_argument('--sample_step', type=int, default=1, help='Total sampling steps') + parser.add_argument('--t', type=int, default=400, help='Sampling noise scale') + parser.add_argument('--t_delta', type=int, default=15, help='Perturbation range of sampling noise scale') + parser.add_argument('--rand_t', type=str2bool, default=False, help='Decide if randomize sampling noise scale') + parser.add_argument('--diffusion_type', type=str, default='ddpm', help='[ddpm, sde, celebahq-ddpm]') + parser.add_argument('--score_type', type=str, default='guided_diffusion', help='[guided_diffusion, score_sde]') + parser.add_argument('--eot_iter', type=int, default=20, help='only for rand version of autoattack') + parser.add_argument('--use_bm', action='store_true', help='whether to use brownian motion') + + parser.add_argument('--eot_defense_reps', type=int, default=150) + parser.add_argument('--eot_attack_reps', type=int, default=15) + + # adv + parser.add_argument('--domain', type=str, default='celebahq', help='which domain: celebahq, cat, car, imagenet') + parser.add_argument('--classifier_name', type=str, default='Eyeglasses', help='which classifier to use') + parser.add_argument('--partition', type=str, default='val') + parser.add_argument('--adv_batch_size', type=int, default=64) + + parser.add_argument('--num_sub', type=int, default=1000, help='imagenet subset') + parser.add_argument('--adv_eps', type=float, default=0.07) + parser.add_argument('--gpu_ids', type=str, default='0') + + args = parser.parse_args() + + # parse config file + with open(os.path.join('configs', args.config), 'r') as f: + config = yaml.safe_load(f) + new_config = utils.dict2namespace(config) + + level = getattr(logging, args.verbose.upper(), None) + if not isinstance(level, int): + raise ValueError('level {} not supported'.format(args.verbose)) + + handler1 = logging.StreamHandler() + formatter = logging.Formatter('%(levelname)s - %(filename)s - %(asctime)s - %(message)s') + handler1.setFormatter(formatter) + logger = logging.getLogger() + logger.addHandler(handler1) + logger.setLevel(level) + + args.image_folder = os.path.join(args.exp, args.image_folder) + os.makedirs(args.image_folder, exist_ok=True) + + # add device + device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') + logging.info("Using device: {}".format(device)) + new_config.device = device + + # set random seed + torch.manual_seed(args.seed) + random.seed(args.seed) + np.random.seed(args.seed) + if torch.cuda.is_available(): + torch.cuda.manual_seed_all(args.seed) + + torch.backends.cudnn.benchmark = True + + return args, new_config + + +if __name__ == '__main__': + args, config = parse_args_and_config() + os.environ["CUDA_VISIBLE_DEVICES"] = args.gpu_ids + robustness_eval(args, config) + + diff --git a/case_studies/diffpure/guided_diffusion/LICENSE_GUIDED_DIFFUSION b/case_studies/diffpure/guided_diffusion/LICENSE_GUIDED_DIFFUSION new file mode 100644 index 0000000..9e84fcb --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/LICENSE_GUIDED_DIFFUSION @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 OpenAI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/case_studies/diffpure/guided_diffusion/__init__.py b/case_studies/diffpure/guided_diffusion/__init__.py new file mode 100644 index 0000000..2edcdcf --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/__init__.py @@ -0,0 +1,11 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/__init__.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +""" +Codebase for "Improved Denoising Diffusion Probabilistic Models". +""" diff --git a/case_studies/diffpure/guided_diffusion/dist_util.py b/case_studies/diffpure/guided_diffusion/dist_util.py new file mode 100644 index 0000000..76406a6 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/dist_util.py @@ -0,0 +1,101 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/dist_util.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +""" +Helpers for distributed training. +""" + +import io +import os +import socket + +import blobfile as bf +from mpi4py import MPI +import torch as th +import torch.distributed as dist + +# Change this to reflect your cluster layout. +# The GPU for a given rank is (rank % GPUS_PER_NODE). +GPUS_PER_NODE = 8 + +SETUP_RETRY_COUNT = 3 + + +def setup_dist(): + """ + Setup a distributed process group. + """ + if dist.is_initialized(): + return + os.environ["CUDA_VISIBLE_DEVICES"] = f"{MPI.COMM_WORLD.Get_rank() % GPUS_PER_NODE}" + + comm = MPI.COMM_WORLD + backend = "gloo" if not th.cuda.is_available() else "nccl" + + if backend == "gloo": + hostname = "localhost" + else: + hostname = socket.gethostbyname(socket.getfqdn()) + os.environ["MASTER_ADDR"] = comm.bcast(hostname, root=0) + os.environ["RANK"] = str(comm.rank) + os.environ["WORLD_SIZE"] = str(comm.size) + + port = comm.bcast(_find_free_port(), root=0) + os.environ["MASTER_PORT"] = str(port) + dist.init_process_group(backend=backend, init_method="env://") + + +def dev(): + """ + Get the device to use for torch.distributed. + """ + if th.cuda.is_available(): + return th.device(f"cuda") + return th.device("cpu") + + +def load_state_dict(path, **kwargs): + """ + Load a PyTorch file without redundant fetches across MPI ranks. + """ + chunk_size = 2 ** 30 # MPI has a relatively small size limit + if MPI.COMM_WORLD.Get_rank() == 0: + with bf.BlobFile(path, "rb") as f: + data = f.read() + num_chunks = len(data) // chunk_size + if len(data) % chunk_size: + num_chunks += 1 + MPI.COMM_WORLD.bcast(num_chunks) + for i in range(0, len(data), chunk_size): + MPI.COMM_WORLD.bcast(data[i : i + chunk_size]) + else: + num_chunks = MPI.COMM_WORLD.bcast(None) + data = bytes() + for _ in range(num_chunks): + data += MPI.COMM_WORLD.bcast(None) + + return th.load(io.BytesIO(data), **kwargs) + + +def sync_params(params): + """ + Synchronize a sequence of Tensors across ranks from rank 0. + """ + for p in params: + with th.no_grad(): + dist.broadcast(p, 0) + + +def _find_free_port(): + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind(("", 0)) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + return s.getsockname()[1] + finally: + s.close() diff --git a/case_studies/diffpure/guided_diffusion/fp16_util.py b/case_studies/diffpure/guided_diffusion/fp16_util.py new file mode 100644 index 0000000..7560d12 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/fp16_util.py @@ -0,0 +1,244 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/fp16_util.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +""" +Helpers to train with 16-bit precision. +""" + +import numpy as np +import torch as th +import torch.nn as nn +from torch._utils import _flatten_dense_tensors, _unflatten_dense_tensors + +from . import logger + +INITIAL_LOG_LOSS_SCALE = 20.0 + + +def convert_module_to_f16(l): + """ + Convert primitive modules to float16. + """ + if isinstance(l, (nn.Conv1d, nn.Conv2d, nn.Conv3d)): + l.weight.data = l.weight.data.half() + if l.bias is not None: + l.bias.data = l.bias.data.half() + + +def convert_module_to_f32(l): + """ + Convert primitive modules to float32, undoing convert_module_to_f16(). + """ + if isinstance(l, (nn.Conv1d, nn.Conv2d, nn.Conv3d)): + l.weight.data = l.weight.data.float() + if l.bias is not None: + l.bias.data = l.bias.data.float() + + +def make_master_params(param_groups_and_shapes): + """ + Copy model parameters into a (differently-shaped) list of full-precision + parameters. + """ + master_params = [] + for param_group, shape in param_groups_and_shapes: + master_param = nn.Parameter( + _flatten_dense_tensors( + [param.detach().float() for (_, param) in param_group] + ).view(shape) + ) + master_param.requires_grad = True + master_params.append(master_param) + return master_params + + +def model_grads_to_master_grads(param_groups_and_shapes, master_params): + """ + Copy the gradients from the model parameters into the master parameters + from make_master_params(). + """ + for master_param, (param_group, shape) in zip( + master_params, param_groups_and_shapes + ): + master_param.grad = _flatten_dense_tensors( + [param_grad_or_zeros(param) for (_, param) in param_group] + ).view(shape) + + +def master_params_to_model_params(param_groups_and_shapes, master_params): + """ + Copy the master parameter data back into the model parameters. + """ + # Without copying to a list, if a generator is passed, this will + # silently not copy any parameters. + for master_param, (param_group, _) in zip(master_params, param_groups_and_shapes): + for (_, param), unflat_master_param in zip( + param_group, unflatten_master_params(param_group, master_param.view(-1)) + ): + param.detach().copy_(unflat_master_param) + + +def unflatten_master_params(param_group, master_param): + return _unflatten_dense_tensors(master_param, [param for (_, param) in param_group]) + + +def get_param_groups_and_shapes(named_model_params): + named_model_params = list(named_model_params) + scalar_vector_named_params = ( + [(n, p) for (n, p) in named_model_params if p.ndim <= 1], + (-1), + ) + matrix_named_params = ( + [(n, p) for (n, p) in named_model_params if p.ndim > 1], + (1, -1), + ) + return [scalar_vector_named_params, matrix_named_params] + + +def master_params_to_state_dict( + model, param_groups_and_shapes, master_params, use_fp16 +): + if use_fp16: + state_dict = model.state_dict() + for master_param, (param_group, _) in zip( + master_params, param_groups_and_shapes + ): + for (name, _), unflat_master_param in zip( + param_group, unflatten_master_params(param_group, master_param.view(-1)) + ): + assert name in state_dict + state_dict[name] = unflat_master_param + else: + state_dict = model.state_dict() + for i, (name, _value) in enumerate(model.named_parameters()): + assert name in state_dict + state_dict[name] = master_params[i] + return state_dict + + +def state_dict_to_master_params(model, state_dict, use_fp16): + if use_fp16: + named_model_params = [ + (name, state_dict[name]) for name, _ in model.named_parameters() + ] + param_groups_and_shapes = get_param_groups_and_shapes(named_model_params) + master_params = make_master_params(param_groups_and_shapes) + else: + master_params = [state_dict[name] for name, _ in model.named_parameters()] + return master_params + + +def zero_master_grads(master_params): + for param in master_params: + param.grad = None + + +def zero_grad(model_params): + for param in model_params: + # Taken from https://pytorch.org/docs/stable/_modules/torch/optim/optimizer.html#Optimizer.add_param_group + if param.grad is not None: + param.grad.detach_() + param.grad.zero_() + + +def param_grad_or_zeros(param): + if param.grad is not None: + return param.grad.data.detach() + else: + return th.zeros_like(param) + + +class MixedPrecisionTrainer: + def __init__( + self, + *, + model, + use_fp16=False, + fp16_scale_growth=1e-3, + initial_lg_loss_scale=INITIAL_LOG_LOSS_SCALE, + ): + self.model = model + self.use_fp16 = use_fp16 + self.fp16_scale_growth = fp16_scale_growth + + self.model_params = list(self.model.parameters()) + self.master_params = self.model_params + self.param_groups_and_shapes = None + self.lg_loss_scale = initial_lg_loss_scale + + if self.use_fp16: + self.param_groups_and_shapes = get_param_groups_and_shapes( + self.model.named_parameters() + ) + self.master_params = make_master_params(self.param_groups_and_shapes) + self.model.convert_to_fp16() + + def zero_grad(self): + zero_grad(self.model_params) + + def backward(self, loss: th.Tensor): + if self.use_fp16: + loss_scale = 2 ** self.lg_loss_scale + (loss * loss_scale).backward() + else: + loss.backward() + + def optimize(self, opt: th.optim.Optimizer): + if self.use_fp16: + return self._optimize_fp16(opt) + else: + return self._optimize_normal(opt) + + def _optimize_fp16(self, opt: th.optim.Optimizer): + logger.logkv_mean("lg_loss_scale", self.lg_loss_scale) + model_grads_to_master_grads(self.param_groups_and_shapes, self.master_params) + grad_norm, param_norm = self._compute_norms(grad_scale=2 ** self.lg_loss_scale) + if check_overflow(grad_norm): + self.lg_loss_scale -= 1 + logger.log(f"Found NaN, decreased lg_loss_scale to {self.lg_loss_scale}") + zero_master_grads(self.master_params) + return False + + logger.logkv_mean("grad_norm", grad_norm) + logger.logkv_mean("param_norm", param_norm) + + self.master_params[0].grad.mul_(1.0 / (2 ** self.lg_loss_scale)) + opt.step() + zero_master_grads(self.master_params) + master_params_to_model_params(self.param_groups_and_shapes, self.master_params) + self.lg_loss_scale += self.fp16_scale_growth + return True + + def _optimize_normal(self, opt: th.optim.Optimizer): + grad_norm, param_norm = self._compute_norms() + logger.logkv_mean("grad_norm", grad_norm) + logger.logkv_mean("param_norm", param_norm) + opt.step() + return True + + def _compute_norms(self, grad_scale=1.0): + grad_norm = 0.0 + param_norm = 0.0 + for p in self.master_params: + with th.no_grad(): + param_norm += th.norm(p, p=2, dtype=th.float32).item() ** 2 + if p.grad is not None: + grad_norm += th.norm(p.grad, p=2, dtype=th.float32).item() ** 2 + return np.sqrt(grad_norm) / grad_scale, np.sqrt(param_norm) + + def master_params_to_state_dict(self, master_params): + return master_params_to_state_dict( + self.model, self.param_groups_and_shapes, master_params, self.use_fp16 + ) + + def state_dict_to_master_params(self, state_dict): + return state_dict_to_master_params(self.model, state_dict, self.use_fp16) + + +def check_overflow(value): + return (value == float("inf")) or (value == -float("inf")) or (value != value) diff --git a/case_studies/diffpure/guided_diffusion/gaussian_diffusion.py b/case_studies/diffpure/guided_diffusion/gaussian_diffusion.py new file mode 100644 index 0000000..efbb3c6 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/gaussian_diffusion.py @@ -0,0 +1,916 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/gaussian_diffusion.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +""" +This code started out as a PyTorch port of Ho et al's diffusion models: +https://github.com/hojonathanho/diffusion/blob/1e0dceb3b3495bbe19116a5e1b3596cd0706c543/diffusion_tf/diffusion_utils_2.py + +Docstrings have been added, as well as DDIM sampling and a new collection of beta schedules. +""" + +import enum +import math + +import numpy as np +import torch as th + +from .nn import mean_flat +from .losses import normal_kl, discretized_gaussian_log_likelihood + + +def get_named_beta_schedule(schedule_name, num_diffusion_timesteps): + """ + Get a pre-defined beta schedule for the given name. + + The beta schedule library consists of beta schedules which remain similar + in the limit of num_diffusion_timesteps. + Beta schedules may be added, but should not be removed or changed once + they are committed to maintain backwards compatibility. + """ + if schedule_name == "linear": + # Linear schedule from Ho et al, extended to work for any number of + # diffusion steps. + scale = 1000 / num_diffusion_timesteps + beta_start = scale * 0.0001 + beta_end = scale * 0.02 + return np.linspace( + beta_start, beta_end, num_diffusion_timesteps, dtype=np.float64 + ) + elif schedule_name == "cosine": + return betas_for_alpha_bar( + num_diffusion_timesteps, + lambda t: math.cos((t + 0.008) / 1.008 * math.pi / 2) ** 2, + ) + else: + raise NotImplementedError(f"unknown beta schedule: {schedule_name}") + + +def betas_for_alpha_bar(num_diffusion_timesteps, alpha_bar, max_beta=0.999): + """ + Create a beta schedule that discretizes the given alpha_t_bar function, + which defines the cumulative product of (1-beta) over time from t = [0,1]. + + :param num_diffusion_timesteps: the number of betas to produce. + :param alpha_bar: a lambda that takes an argument t from 0 to 1 and + produces the cumulative product of (1-beta) up to that + part of the diffusion process. + :param max_beta: the maximum beta to use; use values lower than 1 to + prevent singularities. + """ + betas = [] + for i in range(num_diffusion_timesteps): + t1 = i / num_diffusion_timesteps + t2 = (i + 1) / num_diffusion_timesteps + betas.append(min(1 - alpha_bar(t2) / alpha_bar(t1), max_beta)) + return np.array(betas) + + +class ModelMeanType(enum.Enum): + """ + Which type of output the model predicts. + """ + + PREVIOUS_X = enum.auto() # the model predicts x_{t-1} + START_X = enum.auto() # the model predicts x_0 + EPSILON = enum.auto() # the model predicts epsilon + + +class ModelVarType(enum.Enum): + """ + What is used as the model's output variance. + + The LEARNED_RANGE option has been added to allow the model to predict + values between FIXED_SMALL and FIXED_LARGE, making its job easier. + """ + + LEARNED = enum.auto() + FIXED_SMALL = enum.auto() + FIXED_LARGE = enum.auto() + LEARNED_RANGE = enum.auto() + + +class LossType(enum.Enum): + MSE = enum.auto() # use raw MSE loss (and KL when learning variances) + RESCALED_MSE = ( + enum.auto() + ) # use raw MSE loss (with RESCALED_KL when learning variances) + KL = enum.auto() # use the variational lower-bound + RESCALED_KL = enum.auto() # like KL, but rescale to estimate the full VLB + + def is_vb(self): + return self == LossType.KL or self == LossType.RESCALED_KL + + +class GaussianDiffusion: + """ + Utilities for training and sampling diffusion models. + + Ported directly from here, and then adapted over time to further experimentation. + https://github.com/hojonathanho/diffusion/blob/1e0dceb3b3495bbe19116a5e1b3596cd0706c543/diffusion_tf/diffusion_utils_2.py#L42 + + :param betas: a 1-D numpy array of betas for each diffusion timestep, + starting at T and going to 1. + :param model_mean_type: a ModelMeanType determining what the model outputs. + :param model_var_type: a ModelVarType determining how variance is output. + :param loss_type: a LossType determining the loss function to use. + :param rescale_timesteps: if True, pass floating point timesteps into the + model so that they are always scaled like in the + original paper (0 to 1000). + """ + + def __init__( + self, + *, + betas, + model_mean_type, + model_var_type, + loss_type, + rescale_timesteps=False, + ): + self.model_mean_type = model_mean_type + self.model_var_type = model_var_type + self.loss_type = loss_type + self.rescale_timesteps = rescale_timesteps + + # Use float64 for accuracy. + betas = np.array(betas, dtype=np.float64) + self.betas = betas + assert len(betas.shape) == 1, "betas must be 1-D" + assert (betas > 0).all() and (betas <= 1).all() + + self.num_timesteps = int(betas.shape[0]) + + alphas = 1.0 - betas + self.alphas_cumprod = np.cumprod(alphas, axis=0) + self.alphas_cumprod_prev = np.append(1.0, self.alphas_cumprod[:-1]) + self.alphas_cumprod_next = np.append(self.alphas_cumprod[1:], 0.0) + assert self.alphas_cumprod_prev.shape == (self.num_timesteps,) + + # calculations for diffusion q(x_t | x_{t-1}) and others + self.sqrt_alphas_cumprod = np.sqrt(self.alphas_cumprod) + self.sqrt_one_minus_alphas_cumprod = np.sqrt(1.0 - self.alphas_cumprod) + self.log_one_minus_alphas_cumprod = np.log(1.0 - self.alphas_cumprod) + self.sqrt_recip_alphas_cumprod = np.sqrt(1.0 / self.alphas_cumprod) + self.sqrt_recipm1_alphas_cumprod = np.sqrt(1.0 / self.alphas_cumprod - 1) + + # calculations for posterior q(x_{t-1} | x_t, x_0) + self.posterior_variance = ( + betas * (1.0 - self.alphas_cumprod_prev) / (1.0 - self.alphas_cumprod) + ) + # log calculation clipped because the posterior variance is 0 at the + # beginning of the diffusion chain. + self.posterior_log_variance_clipped = np.log( + np.append(self.posterior_variance[1], self.posterior_variance[1:]) + ) + self.posterior_mean_coef1 = ( + betas * np.sqrt(self.alphas_cumprod_prev) / (1.0 - self.alphas_cumprod) + ) + self.posterior_mean_coef2 = ( + (1.0 - self.alphas_cumprod_prev) + * np.sqrt(alphas) + / (1.0 - self.alphas_cumprod) + ) + + def q_mean_variance(self, x_start, t): + """ + Get the distribution q(x_t | x_0). + + :param x_start: the [N x C x ...] tensor of noiseless inputs. + :param t: the number of diffusion steps (minus 1). Here, 0 means one step. + :return: A tuple (mean, variance, log_variance), all of x_start's shape. + """ + mean = ( + _extract_into_tensor(self.sqrt_alphas_cumprod, t, x_start.shape) * x_start + ) + variance = _extract_into_tensor(1.0 - self.alphas_cumprod, t, x_start.shape) + log_variance = _extract_into_tensor( + self.log_one_minus_alphas_cumprod, t, x_start.shape + ) + return mean, variance, log_variance + + def q_sample(self, x_start, t, noise=None): + """ + Diffuse the data for a given number of diffusion steps. + + In other words, sample from q(x_t | x_0). + + :param x_start: the initial data batch. + :param t: the number of diffusion steps (minus 1). Here, 0 means one step. + :param noise: if specified, the split-out normal noise. + :return: A noisy version of x_start. + """ + if noise is None: + noise = th.randn_like(x_start) + assert noise.shape == x_start.shape + return ( + _extract_into_tensor(self.sqrt_alphas_cumprod, t, x_start.shape) * x_start + + _extract_into_tensor(self.sqrt_one_minus_alphas_cumprod, t, x_start.shape) + * noise + ) + + def q_posterior_mean_variance(self, x_start, x_t, t): + """ + Compute the mean and variance of the diffusion posterior: + + q(x_{t-1} | x_t, x_0) + + """ + assert x_start.shape == x_t.shape + posterior_mean = ( + _extract_into_tensor(self.posterior_mean_coef1, t, x_t.shape) * x_start + + _extract_into_tensor(self.posterior_mean_coef2, t, x_t.shape) * x_t + ) + posterior_variance = _extract_into_tensor(self.posterior_variance, t, x_t.shape) + posterior_log_variance_clipped = _extract_into_tensor( + self.posterior_log_variance_clipped, t, x_t.shape + ) + assert ( + posterior_mean.shape[0] + == posterior_variance.shape[0] + == posterior_log_variance_clipped.shape[0] + == x_start.shape[0] + ) + return posterior_mean, posterior_variance, posterior_log_variance_clipped + + def p_mean_variance( + self, model, x, t, clip_denoised=True, denoised_fn=None, model_kwargs=None + ): + """ + Apply the model to get p(x_{t-1} | x_t), as well as a prediction of + the initial x, x_0. + + :param model: the model, which takes a signal and a batch of timesteps + as input. + :param x: the [N x C x ...] tensor at time t. + :param t: a 1-D Tensor of timesteps. + :param clip_denoised: if True, clip the denoised signal into [-1, 1]. + :param denoised_fn: if not None, a function which applies to the + x_start prediction before it is used to sample. Applies before + clip_denoised. + :param model_kwargs: if not None, a dict of extra keyword arguments to + pass to the model. This can be used for conditioning. + :return: a dict with the following keys: + - 'mean': the model mean output. + - 'variance': the model variance output. + - 'log_variance': the log of 'variance'. + - 'pred_xstart': the prediction for x_0. + """ + if model_kwargs is None: + model_kwargs = {} + + B, C = x.shape[:2] + assert t.shape == (B,) + model_output = model(x, self._scale_timesteps(t), **model_kwargs) + + if self.model_var_type in [ModelVarType.LEARNED, ModelVarType.LEARNED_RANGE]: + assert model_output.shape == (B, C * 2, *x.shape[2:]) + model_output, model_var_values = th.split(model_output, C, dim=1) + if self.model_var_type == ModelVarType.LEARNED: + model_log_variance = model_var_values + model_variance = th.exp(model_log_variance) + else: + min_log = _extract_into_tensor( + self.posterior_log_variance_clipped, t, x.shape + ) + max_log = _extract_into_tensor(np.log(self.betas), t, x.shape) + # The model_var_values is [-1, 1] for [min_var, max_var]. + frac = (model_var_values + 1) / 2 + model_log_variance = frac * max_log + (1 - frac) * min_log + model_variance = th.exp(model_log_variance) + else: + model_variance, model_log_variance = { + # for fixedlarge, we set the initial (log-)variance like so + # to get a better decoder log likelihood. + ModelVarType.FIXED_LARGE: ( + np.append(self.posterior_variance[1], self.betas[1:]), + np.log(np.append(self.posterior_variance[1], self.betas[1:])), + ), + ModelVarType.FIXED_SMALL: ( + self.posterior_variance, + self.posterior_log_variance_clipped, + ), + }[self.model_var_type] + model_variance = _extract_into_tensor(model_variance, t, x.shape) + model_log_variance = _extract_into_tensor(model_log_variance, t, x.shape) + + def process_xstart(x): + if denoised_fn is not None: + x = denoised_fn(x) + if clip_denoised: + return x.clamp(-1, 1) + return x + + if self.model_mean_type == ModelMeanType.PREVIOUS_X: + pred_xstart = process_xstart( + self._predict_xstart_from_xprev(x_t=x, t=t, xprev=model_output) + ) + model_mean = model_output + elif self.model_mean_type in [ModelMeanType.START_X, ModelMeanType.EPSILON]: + if self.model_mean_type == ModelMeanType.START_X: + pred_xstart = process_xstart(model_output) + else: + pred_xstart = process_xstart( + self._predict_xstart_from_eps(x_t=x, t=t, eps=model_output) + ) + model_mean, _, _ = self.q_posterior_mean_variance( + x_start=pred_xstart, x_t=x, t=t + ) + else: + raise NotImplementedError(self.model_mean_type) + + assert ( + model_mean.shape == model_log_variance.shape == pred_xstart.shape == x.shape + ) + return { + "mean": model_mean, + "variance": model_variance, + "log_variance": model_log_variance, + "pred_xstart": pred_xstart, + } + + def _predict_xstart_from_eps(self, x_t, t, eps): + assert x_t.shape == eps.shape + return ( + _extract_into_tensor(self.sqrt_recip_alphas_cumprod, t, x_t.shape) * x_t + - _extract_into_tensor(self.sqrt_recipm1_alphas_cumprod, t, x_t.shape) * eps + ) + + def _predict_xstart_from_xprev(self, x_t, t, xprev): + assert x_t.shape == xprev.shape + return ( # (xprev - coef2*x_t) / coef1 + _extract_into_tensor(1.0 / self.posterior_mean_coef1, t, x_t.shape) * xprev + - _extract_into_tensor( + self.posterior_mean_coef2 / self.posterior_mean_coef1, t, x_t.shape + ) + * x_t + ) + + def _predict_eps_from_xstart(self, x_t, t, pred_xstart): + return ( + _extract_into_tensor(self.sqrt_recip_alphas_cumprod, t, x_t.shape) * x_t + - pred_xstart + ) / _extract_into_tensor(self.sqrt_recipm1_alphas_cumprod, t, x_t.shape) + + def _scale_timesteps(self, t): + if self.rescale_timesteps: + return t.float() * (1000.0 / self.num_timesteps) + return t + + def condition_mean(self, cond_fn, p_mean_var, x, t, model_kwargs=None): + """ + Compute the mean for the previous step, given a function cond_fn that + computes the gradient of a conditional log probability with respect to + x. In particular, cond_fn computes grad(log(p(y|x))), and we want to + condition on y. + + This uses the conditioning strategy from Sohl-Dickstein et al. (2015). + """ + gradient = cond_fn(x, self._scale_timesteps(t), **model_kwargs) + new_mean = ( + p_mean_var["mean"].float() + p_mean_var["variance"] * gradient.float() + ) + return new_mean + + def condition_score(self, cond_fn, p_mean_var, x, t, model_kwargs=None): + """ + Compute what the p_mean_variance output would have been, should the + model's score function be conditioned by cond_fn. + + See condition_mean() for details on cond_fn. + + Unlike condition_mean(), this instead uses the conditioning strategy + from Song et al (2020). + """ + alpha_bar = _extract_into_tensor(self.alphas_cumprod, t, x.shape) + + eps = self._predict_eps_from_xstart(x, t, p_mean_var["pred_xstart"]) + eps = eps - (1 - alpha_bar).sqrt() * cond_fn( + x, self._scale_timesteps(t), **model_kwargs + ) + + out = p_mean_var.copy() + out["pred_xstart"] = self._predict_xstart_from_eps(x, t, eps) + out["mean"], _, _ = self.q_posterior_mean_variance( + x_start=out["pred_xstart"], x_t=x, t=t + ) + return out + + def p_sample( + self, + model, + x, + t, + clip_denoised=True, + denoised_fn=None, + cond_fn=None, + model_kwargs=None, + ): + """ + Sample x_{t-1} from the model at the given timestep. + + :param model: the model to sample from. + :param x: the current tensor at x_{t-1}. + :param t: the value of t, starting at 0 for the first diffusion step. + :param clip_denoised: if True, clip the x_start prediction to [-1, 1]. + :param denoised_fn: if not None, a function which applies to the + x_start prediction before it is used to sample. + :param cond_fn: if not None, this is a gradient function that acts + similarly to the model. + :param model_kwargs: if not None, a dict of extra keyword arguments to + pass to the model. This can be used for conditioning. + :return: a dict containing the following keys: + - 'sample': a random sample from the model. + - 'pred_xstart': a prediction of x_0. + """ + out = self.p_mean_variance( + model, + x, + t, + clip_denoised=clip_denoised, + denoised_fn=denoised_fn, + model_kwargs=model_kwargs, + ) + noise = th.randn_like(x) + nonzero_mask = ( + (t != 0).float().view(-1, *([1] * (len(x.shape) - 1))) + ) # no noise when t == 0 + if cond_fn is not None: + out["mean"] = self.condition_mean( + cond_fn, out, x, t, model_kwargs=model_kwargs + ) + sample = out["mean"] + nonzero_mask * th.exp(0.5 * out["log_variance"]) * noise + return {"sample": sample, "pred_xstart": out["pred_xstart"]} + + def p_sample_loop( + self, + model, + shape, + noise=None, + clip_denoised=True, + denoised_fn=None, + cond_fn=None, + model_kwargs=None, + device=None, + progress=False, + ): + """ + Generate samples from the model. + + :param model: the model module. + :param shape: the shape of the samples, (N, C, H, W). + :param noise: if specified, the noise from the encoder to sample. + Should be of the same shape as `shape`. + :param clip_denoised: if True, clip x_start predictions to [-1, 1]. + :param denoised_fn: if not None, a function which applies to the + x_start prediction before it is used to sample. + :param cond_fn: if not None, this is a gradient function that acts + similarly to the model. + :param model_kwargs: if not None, a dict of extra keyword arguments to + pass to the model. This can be used for conditioning. + :param device: if specified, the device to create the samples on. + If not specified, use a model parameter's device. + :param progress: if True, show a tqdm progress bar. + :return: a non-differentiable batch of samples. + """ + final = None + for sample in self.p_sample_loop_progressive( + model, + shape, + noise=noise, + clip_denoised=clip_denoised, + denoised_fn=denoised_fn, + cond_fn=cond_fn, + model_kwargs=model_kwargs, + device=device, + progress=progress, + ): + final = sample + return final["sample"] + + def p_sample_loop_progressive( + self, + model, + shape, + noise=None, + clip_denoised=True, + denoised_fn=None, + cond_fn=None, + model_kwargs=None, + device=None, + progress=False, + ): + """ + Generate samples from the model and yield intermediate samples from + each timestep of diffusion. + + Arguments are the same as p_sample_loop(). + Returns a generator over dicts, where each dict is the return value of + p_sample(). + """ + if device is None: + device = next(model.parameters()).device + assert isinstance(shape, (tuple, list)) + if noise is not None: + img = noise + else: + img = th.randn(*shape, device=device) + indices = list(range(self.num_timesteps))[::-1] + + if progress: + # Lazy import so that we don't depend on tqdm. + from tqdm.auto import tqdm + + indices = tqdm(indices) + + for i in indices: + t = th.tensor([i] * shape[0], device=device) + with th.no_grad(): + out = self.p_sample( + model, + img, + t, + clip_denoised=clip_denoised, + denoised_fn=denoised_fn, + cond_fn=cond_fn, + model_kwargs=model_kwargs, + ) + yield out + img = out["sample"] + + def ddim_sample( + self, + model, + x, + t, + clip_denoised=True, + denoised_fn=None, + cond_fn=None, + model_kwargs=None, + eta=0.0, + ): + """ + Sample x_{t-1} from the model using DDIM. + + Same usage as p_sample(). + """ + out = self.p_mean_variance( + model, + x, + t, + clip_denoised=clip_denoised, + denoised_fn=denoised_fn, + model_kwargs=model_kwargs, + ) + if cond_fn is not None: + out = self.condition_score(cond_fn, out, x, t, model_kwargs=model_kwargs) + + # Usually our model outputs epsilon, but we re-derive it + # in case we used x_start or x_prev prediction. + eps = self._predict_eps_from_xstart(x, t, out["pred_xstart"]) + + alpha_bar = _extract_into_tensor(self.alphas_cumprod, t, x.shape) + alpha_bar_prev = _extract_into_tensor(self.alphas_cumprod_prev, t, x.shape) + sigma = ( + eta + * th.sqrt((1 - alpha_bar_prev) / (1 - alpha_bar)) + * th.sqrt(1 - alpha_bar / alpha_bar_prev) + ) + # Equation 12. + noise = th.randn_like(x) + mean_pred = ( + out["pred_xstart"] * th.sqrt(alpha_bar_prev) + + th.sqrt(1 - alpha_bar_prev - sigma ** 2) * eps + ) + nonzero_mask = ( + (t != 0).float().view(-1, *([1] * (len(x.shape) - 1))) + ) # no noise when t == 0 + sample = mean_pred + nonzero_mask * sigma * noise + return {"sample": sample, "pred_xstart": out["pred_xstart"]} + + def ddim_reverse_sample( + self, + model, + x, + t, + clip_denoised=True, + denoised_fn=None, + model_kwargs=None, + eta=0.0, + ): + """ + Sample x_{t+1} from the model using DDIM reverse ODE. + """ + assert eta == 0.0, "Reverse ODE only for deterministic path" + out = self.p_mean_variance( + model, + x, + t, + clip_denoised=clip_denoised, + denoised_fn=denoised_fn, + model_kwargs=model_kwargs, + ) + # Usually our model outputs epsilon, but we re-derive it + # in case we used x_start or x_prev prediction. + eps = ( + _extract_into_tensor(self.sqrt_recip_alphas_cumprod, t, x.shape) * x + - out["pred_xstart"] + ) / _extract_into_tensor(self.sqrt_recipm1_alphas_cumprod, t, x.shape) + alpha_bar_next = _extract_into_tensor(self.alphas_cumprod_next, t, x.shape) + + # Equation 12. reversed + mean_pred = ( + out["pred_xstart"] * th.sqrt(alpha_bar_next) + + th.sqrt(1 - alpha_bar_next) * eps + ) + + return {"sample": mean_pred, "pred_xstart": out["pred_xstart"]} + + def ddim_sample_loop( + self, + model, + shape, + noise=None, + clip_denoised=True, + denoised_fn=None, + cond_fn=None, + model_kwargs=None, + device=None, + progress=False, + eta=0.0, + ): + """ + Generate samples from the model using DDIM. + + Same usage as p_sample_loop(). + """ + final = None + for sample in self.ddim_sample_loop_progressive( + model, + shape, + noise=noise, + clip_denoised=clip_denoised, + denoised_fn=denoised_fn, + cond_fn=cond_fn, + model_kwargs=model_kwargs, + device=device, + progress=progress, + eta=eta, + ): + final = sample + return final["sample"] + + def ddim_sample_loop_progressive( + self, + model, + shape, + noise=None, + clip_denoised=True, + denoised_fn=None, + cond_fn=None, + model_kwargs=None, + device=None, + progress=False, + eta=0.0, + ): + """ + Use DDIM to sample from the model and yield intermediate samples from + each timestep of DDIM. + + Same usage as p_sample_loop_progressive(). + """ + if device is None: + device = next(model.parameters()).device + assert isinstance(shape, (tuple, list)) + if noise is not None: + img = noise + else: + img = th.randn(*shape, device=device) + indices = list(range(self.num_timesteps))[::-1] + + if progress: + # Lazy import so that we don't depend on tqdm. + from tqdm.auto import tqdm + + indices = tqdm(indices) + + for i in indices: + t = th.tensor([i] * shape[0], device=device) + with th.no_grad(): + out = self.ddim_sample( + model, + img, + t, + clip_denoised=clip_denoised, + denoised_fn=denoised_fn, + cond_fn=cond_fn, + model_kwargs=model_kwargs, + eta=eta, + ) + yield out + img = out["sample"] + + def _vb_terms_bpd( + self, model, x_start, x_t, t, clip_denoised=True, model_kwargs=None + ): + """ + Get a term for the variational lower-bound. + + The resulting units are bits (rather than nats, as one might expect). + This allows for comparison to other papers. + + :return: a dict with the following keys: + - 'output': a shape [N] tensor of NLLs or KLs. + - 'pred_xstart': the x_0 predictions. + """ + true_mean, _, true_log_variance_clipped = self.q_posterior_mean_variance( + x_start=x_start, x_t=x_t, t=t + ) + out = self.p_mean_variance( + model, x_t, t, clip_denoised=clip_denoised, model_kwargs=model_kwargs + ) + kl = normal_kl( + true_mean, true_log_variance_clipped, out["mean"], out["log_variance"] + ) + kl = mean_flat(kl) / np.log(2.0) + + decoder_nll = -discretized_gaussian_log_likelihood( + x_start, means=out["mean"], log_scales=0.5 * out["log_variance"] + ) + assert decoder_nll.shape == x_start.shape + decoder_nll = mean_flat(decoder_nll) / np.log(2.0) + + # At the first timestep return the decoder NLL, + # otherwise return KL(q(x_{t-1}|x_t,x_0) || p(x_{t-1}|x_t)) + output = th.where((t == 0), decoder_nll, kl) + return {"output": output, "pred_xstart": out["pred_xstart"]} + + def training_losses(self, model, x_start, t, model_kwargs=None, noise=None): + """ + Compute training losses for a single timestep. + + :param model: the model to evaluate loss on. + :param x_start: the [N x C x ...] tensor of inputs. + :param t: a batch of timestep indices. + :param model_kwargs: if not None, a dict of extra keyword arguments to + pass to the model. This can be used for conditioning. + :param noise: if specified, the specific Gaussian noise to try to remove. + :return: a dict with the key "loss" containing a tensor of shape [N]. + Some mean or variance settings may also have other keys. + """ + if model_kwargs is None: + model_kwargs = {} + if noise is None: + noise = th.randn_like(x_start) + x_t = self.q_sample(x_start, t, noise=noise) + + terms = {} + + if self.loss_type == LossType.KL or self.loss_type == LossType.RESCALED_KL: + terms["loss"] = self._vb_terms_bpd( + model=model, + x_start=x_start, + x_t=x_t, + t=t, + clip_denoised=False, + model_kwargs=model_kwargs, + )["output"] + if self.loss_type == LossType.RESCALED_KL: + terms["loss"] *= self.num_timesteps + elif self.loss_type == LossType.MSE or self.loss_type == LossType.RESCALED_MSE: + model_output = model(x_t, self._scale_timesteps(t), **model_kwargs) + + if self.model_var_type in [ + ModelVarType.LEARNED, + ModelVarType.LEARNED_RANGE, + ]: + B, C = x_t.shape[:2] + assert model_output.shape == (B, C * 2, *x_t.shape[2:]) + model_output, model_var_values = th.split(model_output, C, dim=1) + # Learn the variance using the variational bound, but don't let + # it affect our mean prediction. + frozen_out = th.cat([model_output.detach(), model_var_values], dim=1) + terms["vb"] = self._vb_terms_bpd( + model=lambda *args, r=frozen_out: r, + x_start=x_start, + x_t=x_t, + t=t, + clip_denoised=False, + )["output"] + if self.loss_type == LossType.RESCALED_MSE: + # Divide by 1000 for equivalence with initial implementation. + # Without a factor of 1/1000, the VB term hurts the MSE term. + terms["vb"] *= self.num_timesteps / 1000.0 + + target = { + ModelMeanType.PREVIOUS_X: self.q_posterior_mean_variance( + x_start=x_start, x_t=x_t, t=t + )[0], + ModelMeanType.START_X: x_start, + ModelMeanType.EPSILON: noise, + }[self.model_mean_type] + assert model_output.shape == target.shape == x_start.shape + terms["mse"] = mean_flat((target - model_output) ** 2) + if "vb" in terms: + terms["loss"] = terms["mse"] + terms["vb"] + else: + terms["loss"] = terms["mse"] + else: + raise NotImplementedError(self.loss_type) + + return terms + + def _prior_bpd(self, x_start): + """ + Get the prior KL term for the variational lower-bound, measured in + bits-per-dim. + + This term can't be optimized, as it only depends on the encoder. + + :param x_start: the [N x C x ...] tensor of inputs. + :return: a batch of [N] KL values (in bits), one per batch element. + """ + batch_size = x_start.shape[0] + t = th.tensor([self.num_timesteps - 1] * batch_size, device=x_start.device) + qt_mean, _, qt_log_variance = self.q_mean_variance(x_start, t) + kl_prior = normal_kl( + mean1=qt_mean, logvar1=qt_log_variance, mean2=0.0, logvar2=0.0 + ) + return mean_flat(kl_prior) / np.log(2.0) + + def calc_bpd_loop(self, model, x_start, clip_denoised=True, model_kwargs=None): + """ + Compute the entire variational lower-bound, measured in bits-per-dim, + as well as other related quantities. + + :param model: the model to evaluate loss on. + :param x_start: the [N x C x ...] tensor of inputs. + :param clip_denoised: if True, clip denoised samples. + :param model_kwargs: if not None, a dict of extra keyword arguments to + pass to the model. This can be used for conditioning. + + :return: a dict containing the following keys: + - total_bpd: the total variational lower-bound, per batch element. + - prior_bpd: the prior term in the lower-bound. + - vb: an [N x T] tensor of terms in the lower-bound. + - xstart_mse: an [N x T] tensor of x_0 MSEs for each timestep. + - mse: an [N x T] tensor of epsilon MSEs for each timestep. + """ + device = x_start.device + batch_size = x_start.shape[0] + + vb = [] + xstart_mse = [] + mse = [] + for t in list(range(self.num_timesteps))[::-1]: + t_batch = th.tensor([t] * batch_size, device=device) + noise = th.randn_like(x_start) + x_t = self.q_sample(x_start=x_start, t=t_batch, noise=noise) + # Calculate VLB term at the current timestep + with th.no_grad(): + out = self._vb_terms_bpd( + model, + x_start=x_start, + x_t=x_t, + t=t_batch, + clip_denoised=clip_denoised, + model_kwargs=model_kwargs, + ) + vb.append(out["output"]) + xstart_mse.append(mean_flat((out["pred_xstart"] - x_start) ** 2)) + eps = self._predict_eps_from_xstart(x_t, t_batch, out["pred_xstart"]) + mse.append(mean_flat((eps - noise) ** 2)) + + vb = th.stack(vb, dim=1) + xstart_mse = th.stack(xstart_mse, dim=1) + mse = th.stack(mse, dim=1) + + prior_bpd = self._prior_bpd(x_start) + total_bpd = vb.sum(dim=1) + prior_bpd + return { + "total_bpd": total_bpd, + "prior_bpd": prior_bpd, + "vb": vb, + "xstart_mse": xstart_mse, + "mse": mse, + } + + +def _extract_into_tensor(arr, timesteps, broadcast_shape): + """ + Extract values from a 1-D numpy array for a batch of indices. + + :param arr: the 1-D numpy array. + :param timesteps: a tensor of indices into the array to extract. + :param broadcast_shape: a larger shape of K dimensions with the batch + dimension equal to the length of timesteps. + :return: a tensor of shape [batch_size, 1, ...] where the shape has K dims. + """ + res = th.from_numpy(arr).to(device=timesteps.device)[timesteps].float() + while len(res.shape) < len(broadcast_shape): + res = res[..., None] + return res.expand(broadcast_shape) diff --git a/case_studies/diffpure/guided_diffusion/image_datasets.py b/case_studies/diffpure/guided_diffusion/image_datasets.py new file mode 100644 index 0000000..cac5515 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/image_datasets.py @@ -0,0 +1,175 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/image_datasets.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +import math +import random + +from PIL import Image +import blobfile as bf +from mpi4py import MPI +import numpy as np +from torch.utils.data import DataLoader, Dataset + + +def load_data( + *, + data_dir, + batch_size, + image_size, + class_cond=False, + deterministic=False, + random_crop=False, + random_flip=True, +): + """ + For a dataset, create a generator over (images, kwargs) pairs. + + Each images is an NCHW float tensor, and the kwargs dict contains zero or + more keys, each of which map to a batched Tensor of their own. + The kwargs dict can be used for class labels, in which case the key is "y" + and the values are integer tensors of class labels. + + :param data_dir: a dataset directory. + :param batch_size: the batch size of each returned pair. + :param image_size: the size to which images are resized. + :param class_cond: if True, include a "y" key in returned dicts for class + label. If classes are not available and this is true, an + exception will be raised. + :param deterministic: if True, yield results in a deterministic order. + :param random_crop: if True, randomly crop the images for augmentation. + :param random_flip: if True, randomly flip the images for augmentation. + """ + if not data_dir: + raise ValueError("unspecified data directory") + all_files = _list_image_files_recursively(data_dir) + classes = None + if class_cond: + # Assume classes are the first part of the filename, + # before an underscore. + class_names = [bf.basename(path).split("_")[0] for path in all_files] + sorted_classes = {x: i for i, x in enumerate(sorted(set(class_names)))} + classes = [sorted_classes[x] for x in class_names] + dataset = ImageDataset( + image_size, + all_files, + classes=classes, + shard=MPI.COMM_WORLD.Get_rank(), + num_shards=MPI.COMM_WORLD.Get_size(), + random_crop=random_crop, + random_flip=random_flip, + ) + if deterministic: + loader = DataLoader( + dataset, batch_size=batch_size, shuffle=False, num_workers=1, drop_last=True + ) + else: + loader = DataLoader( + dataset, batch_size=batch_size, shuffle=True, num_workers=1, drop_last=True + ) + while True: + yield from loader + + +def _list_image_files_recursively(data_dir): + results = [] + for entry in sorted(bf.listdir(data_dir)): + full_path = bf.join(data_dir, entry) + ext = entry.split(".")[-1] + if "." in entry and ext.lower() in ["jpg", "jpeg", "png", "gif"]: + results.append(full_path) + elif bf.isdir(full_path): + results.extend(_list_image_files_recursively(full_path)) + return results + + +class ImageDataset(Dataset): + def __init__( + self, + resolution, + image_paths, + classes=None, + shard=0, + num_shards=1, + random_crop=False, + random_flip=True, + ): + super().__init__() + self.resolution = resolution + self.local_images = image_paths[shard:][::num_shards] + self.local_classes = None if classes is None else classes[shard:][::num_shards] + self.random_crop = random_crop + self.random_flip = random_flip + + def __len__(self): + return len(self.local_images) + + def __getitem__(self, idx): + path = self.local_images[idx] + with bf.BlobFile(path, "rb") as f: + pil_image = Image.open(f) + pil_image.load() + pil_image = pil_image.convert("RGB") + + if self.random_crop: + arr = random_crop_arr(pil_image, self.resolution) + else: + arr = center_crop_arr(pil_image, self.resolution) + + if self.random_flip and random.random() < 0.5: + arr = arr[:, ::-1] + + arr = arr.astype(np.float32) / 127.5 - 1 + + out_dict = {} + if self.local_classes is not None: + out_dict["y"] = np.array(self.local_classes[idx], dtype=np.int64) + return np.transpose(arr, [2, 0, 1]), out_dict + + +def center_crop_arr(pil_image, image_size): + # We are not on a new enough PIL to support the `reducing_gap` + # argument, which uses BOX downsampling at powers of two first. + # Thus, we do it by hand to improve downsample quality. + while min(*pil_image.size) >= 2 * image_size: + pil_image = pil_image.resize( + tuple(x // 2 for x in pil_image.size), resample=Image.BOX + ) + + scale = image_size / min(*pil_image.size) + pil_image = pil_image.resize( + tuple(round(x * scale) for x in pil_image.size), resample=Image.BICUBIC + ) + + arr = np.array(pil_image) + crop_y = (arr.shape[0] - image_size) // 2 + crop_x = (arr.shape[1] - image_size) // 2 + return arr[crop_y : crop_y + image_size, crop_x : crop_x + image_size] + + +def random_crop_arr(pil_image, image_size, min_crop_frac=0.8, max_crop_frac=1.0): + min_smaller_dim_size = math.ceil(image_size / max_crop_frac) + max_smaller_dim_size = math.ceil(image_size / min_crop_frac) + smaller_dim_size = random.randrange(min_smaller_dim_size, max_smaller_dim_size + 1) + + # We are not on a new enough PIL to support the `reducing_gap` + # argument, which uses BOX downsampling at powers of two first. + # Thus, we do it by hand to improve downsample quality. + while min(*pil_image.size) >= 2 * smaller_dim_size: + pil_image = pil_image.resize( + tuple(x // 2 for x in pil_image.size), resample=Image.BOX + ) + + scale = smaller_dim_size / min(*pil_image.size) + pil_image = pil_image.resize( + tuple(round(x * scale) for x in pil_image.size), resample=Image.BICUBIC + ) + + arr = np.array(pil_image) + crop_y = random.randrange(arr.shape[0] - image_size + 1) + crop_x = random.randrange(arr.shape[1] - image_size + 1) + return arr[crop_y : crop_y + image_size, crop_x : crop_x + image_size] diff --git a/case_studies/diffpure/guided_diffusion/logger.py b/case_studies/diffpure/guided_diffusion/logger.py new file mode 100644 index 0000000..cdd8176 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/logger.py @@ -0,0 +1,503 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/logger.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +""" +Logger copied from OpenAI baselines to avoid extra RL-based dependencies: +https://github.com/openai/baselines/blob/ea25b9e8b234e6ee1bca43083f8f3cf974143998/baselines/logger.py +""" + +import os +import sys +import shutil +import os.path as osp +import json +import time +import datetime +import tempfile +import warnings +from collections import defaultdict +from contextlib import contextmanager + +DEBUG = 10 +INFO = 20 +WARN = 30 +ERROR = 40 + +DISABLED = 50 + + +class KVWriter(object): + def writekvs(self, kvs): + raise NotImplementedError + + +class SeqWriter(object): + def writeseq(self, seq): + raise NotImplementedError + + +class HumanOutputFormat(KVWriter, SeqWriter): + def __init__(self, filename_or_file): + if isinstance(filename_or_file, str): + self.file = open(filename_or_file, "wt") + self.own_file = True + else: + assert hasattr(filename_or_file, "read"), ( + "expected file or str, got %s" % filename_or_file + ) + self.file = filename_or_file + self.own_file = False + + def writekvs(self, kvs): + # Create strings for printing + key2str = {} + for (key, val) in sorted(kvs.items()): + if hasattr(val, "__float__"): + valstr = "%-8.3g" % val + else: + valstr = str(val) + key2str[self._truncate(key)] = self._truncate(valstr) + + # Find max widths + if len(key2str) == 0: + print("WARNING: tried to write empty key-value dict") + return + else: + keywidth = max(map(len, key2str.keys())) + valwidth = max(map(len, key2str.values())) + + # Write out the data + dashes = "-" * (keywidth + valwidth + 7) + lines = [dashes] + for (key, val) in sorted(key2str.items(), key=lambda kv: kv[0].lower()): + lines.append( + "| %s%s | %s%s |" + % (key, " " * (keywidth - len(key)), val, " " * (valwidth - len(val))) + ) + lines.append(dashes) + self.file.write("\n".join(lines) + "\n") + + # Flush the output to the file + self.file.flush() + + def _truncate(self, s): + maxlen = 30 + return s[: maxlen - 3] + "..." if len(s) > maxlen else s + + def writeseq(self, seq): + seq = list(seq) + for (i, elem) in enumerate(seq): + self.file.write(elem) + if i < len(seq) - 1: # add space unless this is the last one + self.file.write(" ") + self.file.write("\n") + self.file.flush() + + def close(self): + if self.own_file: + self.file.close() + + +class JSONOutputFormat(KVWriter): + def __init__(self, filename): + self.file = open(filename, "wt") + + def writekvs(self, kvs): + for k, v in sorted(kvs.items()): + if hasattr(v, "dtype"): + kvs[k] = float(v) + self.file.write(json.dumps(kvs) + "\n") + self.file.flush() + + def close(self): + self.file.close() + + +class CSVOutputFormat(KVWriter): + def __init__(self, filename): + self.file = open(filename, "w+t") + self.keys = [] + self.sep = "," + + def writekvs(self, kvs): + # Add our current row to the history + extra_keys = list(kvs.keys() - self.keys) + extra_keys.sort() + if extra_keys: + self.keys.extend(extra_keys) + self.file.seek(0) + lines = self.file.readlines() + self.file.seek(0) + for (i, k) in enumerate(self.keys): + if i > 0: + self.file.write(",") + self.file.write(k) + self.file.write("\n") + for line in lines[1:]: + self.file.write(line[:-1]) + self.file.write(self.sep * len(extra_keys)) + self.file.write("\n") + for (i, k) in enumerate(self.keys): + if i > 0: + self.file.write(",") + v = kvs.get(k) + if v is not None: + self.file.write(str(v)) + self.file.write("\n") + self.file.flush() + + def close(self): + self.file.close() + + +class TensorBoardOutputFormat(KVWriter): + """ + Dumps key/value pairs into TensorBoard's numeric format. + """ + + def __init__(self, dir): + os.makedirs(dir, exist_ok=True) + self.dir = dir + self.step = 1 + prefix = "events" + path = osp.join(osp.abspath(dir), prefix) + import tensorflow as tf + from tensorflow.python import pywrap_tensorflow + from tensorflow.core.util import event_pb2 + from tensorflow.python.util import compat + + self.tf = tf + self.event_pb2 = event_pb2 + self.pywrap_tensorflow = pywrap_tensorflow + self.writer = pywrap_tensorflow.EventsWriter(compat.as_bytes(path)) + + def writekvs(self, kvs): + def summary_val(k, v): + kwargs = {"tag": k, "simple_value": float(v)} + return self.tf.Summary.Value(**kwargs) + + summary = self.tf.Summary(value=[summary_val(k, v) for k, v in kvs.items()]) + event = self.event_pb2.Event(wall_time=time.time(), summary=summary) + event.step = ( + self.step + ) # is there any reason why you'd want to specify the step? + self.writer.WriteEvent(event) + self.writer.Flush() + self.step += 1 + + def close(self): + if self.writer: + self.writer.Close() + self.writer = None + + +def make_output_format(format, ev_dir, log_suffix=""): + os.makedirs(ev_dir, exist_ok=True) + if format == "stdout": + return HumanOutputFormat(sys.stdout) + elif format == "log": + return HumanOutputFormat(osp.join(ev_dir, "log%s.txt" % log_suffix)) + elif format == "json": + return JSONOutputFormat(osp.join(ev_dir, "progress%s.json" % log_suffix)) + elif format == "csv": + return CSVOutputFormat(osp.join(ev_dir, "progress%s.csv" % log_suffix)) + elif format == "tensorboard": + return TensorBoardOutputFormat(osp.join(ev_dir, "tb%s" % log_suffix)) + else: + raise ValueError("Unknown format specified: %s" % (format,)) + + +# ================================================================ +# API +# ================================================================ + + +def logkv(key, val): + """ + Log a value of some diagnostic + Call this once for each diagnostic quantity, each iteration + If called many times, last value will be used. + """ + get_current().logkv(key, val) + + +def logkv_mean(key, val): + """ + The same as logkv(), but if called many times, values averaged. + """ + get_current().logkv_mean(key, val) + + +def logkvs(d): + """ + Log a dictionary of key-value pairs + """ + for (k, v) in d.items(): + logkv(k, v) + + +def dumpkvs(): + """ + Write all of the diagnostics from the current iteration + """ + return get_current().dumpkvs() + + +def getkvs(): + return get_current().name2val + + +def log(*args, level=INFO): + """ + Write the sequence of args, with no separators, to the console and output files (if you've configured an output file). + """ + get_current().log(*args, level=level) + + +def debug(*args): + log(*args, level=DEBUG) + + +def info(*args): + log(*args, level=INFO) + + +def warn(*args): + log(*args, level=WARN) + + +def error(*args): + log(*args, level=ERROR) + + +def set_level(level): + """ + Set logging threshold on current logger. + """ + get_current().set_level(level) + + +def set_comm(comm): + get_current().set_comm(comm) + + +def get_dir(): + """ + Get directory that log files are being written to. + will be None if there is no output directory (i.e., if you didn't call start) + """ + return get_current().get_dir() + + +record_tabular = logkv +dump_tabular = dumpkvs + + +@contextmanager +def profile_kv(scopename): + logkey = "wait_" + scopename + tstart = time.time() + try: + yield + finally: + get_current().name2val[logkey] += time.time() - tstart + + +def profile(n): + """ + Usage: + @profile("my_func") + def my_func(): code + """ + + def decorator_with_name(func): + def func_wrapper(*args, **kwargs): + with profile_kv(n): + return func(*args, **kwargs) + + return func_wrapper + + return decorator_with_name + + +# ================================================================ +# Backend +# ================================================================ + + +def get_current(): + if Logger.CURRENT is None: + _configure_default_logger() + + return Logger.CURRENT + + +class Logger(object): + DEFAULT = None # A logger with no output files. (See right below class definition) + # So that you can still log to the terminal without setting up any output files + CURRENT = None # Current logger being used by the free functions above + + def __init__(self, dir, output_formats, comm=None): + self.name2val = defaultdict(float) # values this iteration + self.name2cnt = defaultdict(int) + self.level = INFO + self.dir = dir + self.output_formats = output_formats + self.comm = comm + + # Logging API, forwarded + # ---------------------------------------- + def logkv(self, key, val): + self.name2val[key] = val + + def logkv_mean(self, key, val): + oldval, cnt = self.name2val[key], self.name2cnt[key] + self.name2val[key] = oldval * cnt / (cnt + 1) + val / (cnt + 1) + self.name2cnt[key] = cnt + 1 + + def dumpkvs(self): + if self.comm is None: + d = self.name2val + else: + d = mpi_weighted_mean( + self.comm, + { + name: (val, self.name2cnt.get(name, 1)) + for (name, val) in self.name2val.items() + }, + ) + if self.comm.rank != 0: + d["dummy"] = 1 # so we don't get a warning about empty dict + out = d.copy() # Return the dict for unit testing purposes + for fmt in self.output_formats: + if isinstance(fmt, KVWriter): + fmt.writekvs(d) + self.name2val.clear() + self.name2cnt.clear() + return out + + def log(self, *args, level=INFO): + if self.level <= level: + self._do_log(args) + + # Configuration + # ---------------------------------------- + def set_level(self, level): + self.level = level + + def set_comm(self, comm): + self.comm = comm + + def get_dir(self): + return self.dir + + def close(self): + for fmt in self.output_formats: + fmt.close() + + # Misc + # ---------------------------------------- + def _do_log(self, args): + for fmt in self.output_formats: + if isinstance(fmt, SeqWriter): + fmt.writeseq(map(str, args)) + + +def get_rank_without_mpi_import(): + # check environment variables here instead of importing mpi4py + # to avoid calling MPI_Init() when this module is imported + for varname in ["PMI_RANK", "OMPI_COMM_WORLD_RANK"]: + if varname in os.environ: + return int(os.environ[varname]) + return 0 + + +def mpi_weighted_mean(comm, local_name2valcount): + """ + Copied from: https://github.com/openai/baselines/blob/ea25b9e8b234e6ee1bca43083f8f3cf974143998/baselines/common/mpi_util.py#L110 + Perform a weighted average over dicts that are each on a different node + Input: local_name2valcount: dict mapping key -> (value, count) + Returns: key -> mean + """ + all_name2valcount = comm.gather(local_name2valcount) + if comm.rank == 0: + name2sum = defaultdict(float) + name2count = defaultdict(float) + for n2vc in all_name2valcount: + for (name, (val, count)) in n2vc.items(): + try: + val = float(val) + except ValueError: + if comm.rank == 0: + warnings.warn( + "WARNING: tried to compute mean on non-float {}={}".format( + name, val + ) + ) + else: + name2sum[name] += val * count + name2count[name] += count + return {name: name2sum[name] / name2count[name] for name in name2sum} + else: + return {} + + +def configure(dir=None, format_strs=None, comm=None, log_suffix=""): + """ + If comm is provided, average all numerical stats across that comm + """ + if dir is None: + dir = os.getenv("OPENAI_LOGDIR") + if dir is None: + dir = osp.join( + tempfile.gettempdir(), + datetime.datetime.now().strftime("openai-%Y-%m-%d-%H-%M-%S-%f"), + ) + assert isinstance(dir, str) + dir = os.path.expanduser(dir) + os.makedirs(os.path.expanduser(dir), exist_ok=True) + + rank = get_rank_without_mpi_import() + if rank > 0: + log_suffix = log_suffix + "-rank%03i" % rank + + if format_strs is None: + if rank == 0: + format_strs = os.getenv("OPENAI_LOG_FORMAT", "stdout,log,csv").split(",") + else: + format_strs = os.getenv("OPENAI_LOG_FORMAT_MPI", "log").split(",") + format_strs = filter(None, format_strs) + output_formats = [make_output_format(f, dir, log_suffix) for f in format_strs] + + Logger.CURRENT = Logger(dir=dir, output_formats=output_formats, comm=comm) + if output_formats: + log("Logging to %s" % dir) + + +def _configure_default_logger(): + configure() + Logger.DEFAULT = Logger.CURRENT + + +def reset(): + if Logger.CURRENT is not Logger.DEFAULT: + Logger.CURRENT.close() + Logger.CURRENT = Logger.DEFAULT + log("Reset logger") + + +@contextmanager +def scoped_configure(dir=None, format_strs=None, comm=None): + prevlogger = Logger.CURRENT + configure(dir=dir, format_strs=format_strs, comm=comm) + try: + yield + finally: + Logger.CURRENT.close() + Logger.CURRENT = prevlogger + diff --git a/case_studies/diffpure/guided_diffusion/losses.py b/case_studies/diffpure/guided_diffusion/losses.py new file mode 100644 index 0000000..a66e7a5 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/losses.py @@ -0,0 +1,85 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/losses.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +""" +Helpers for various likelihood-based losses. These are ported from the original +Ho et al. diffusion models codebase: +https://github.com/hojonathanho/diffusion/blob/1e0dceb3b3495bbe19116a5e1b3596cd0706c543/diffusion_tf/utils.py +""" + +import numpy as np + +import torch as th + + +def normal_kl(mean1, logvar1, mean2, logvar2): + """ + Compute the KL divergence between two gaussians. + + Shapes are automatically broadcasted, so batches can be compared to + scalars, among other use cases. + """ + tensor = None + for obj in (mean1, logvar1, mean2, logvar2): + if isinstance(obj, th.Tensor): + tensor = obj + break + assert tensor is not None, "at least one argument must be a Tensor" + + # Force variances to be Tensors. Broadcasting helps convert scalars to + # Tensors, but it does not work for th.exp(). + logvar1, logvar2 = [ + x if isinstance(x, th.Tensor) else th.tensor(x).to(tensor) + for x in (logvar1, logvar2) + ] + + return 0.5 * ( + -1.0 + + logvar2 + - logvar1 + + th.exp(logvar1 - logvar2) + + ((mean1 - mean2) ** 2) * th.exp(-logvar2) + ) + + +def approx_standard_normal_cdf(x): + """ + A fast approximation of the cumulative distribution function of the + standard normal. + """ + return 0.5 * (1.0 + th.tanh(np.sqrt(2.0 / np.pi) * (x + 0.044715 * th.pow(x, 3)))) + + +def discretized_gaussian_log_likelihood(x, *, means, log_scales): + """ + Compute the log-likelihood of a Gaussian distribution discretizing to a + given image. + + :param x: the target images. It is assumed that this was uint8 values, + rescaled to the range [-1, 1]. + :param means: the Gaussian mean Tensor. + :param log_scales: the Gaussian log stddev Tensor. + :return: a tensor like x of log probabilities (in nats). + """ + assert x.shape == means.shape == log_scales.shape + centered_x = x - means + inv_stdv = th.exp(-log_scales) + plus_in = inv_stdv * (centered_x + 1.0 / 255.0) + cdf_plus = approx_standard_normal_cdf(plus_in) + min_in = inv_stdv * (centered_x - 1.0 / 255.0) + cdf_min = approx_standard_normal_cdf(min_in) + log_cdf_plus = th.log(cdf_plus.clamp(min=1e-12)) + log_one_minus_cdf_min = th.log((1.0 - cdf_min).clamp(min=1e-12)) + cdf_delta = cdf_plus - cdf_min + log_probs = th.where( + x < -0.999, + log_cdf_plus, + th.where(x > 0.999, log_one_minus_cdf_min, th.log(cdf_delta.clamp(min=1e-12))), + ) + assert log_probs.shape == x.shape + return log_probs diff --git a/case_studies/diffpure/guided_diffusion/nn.py b/case_studies/diffpure/guided_diffusion/nn.py new file mode 100644 index 0000000..0655447 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/nn.py @@ -0,0 +1,178 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/nn.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +""" +Various utilities for neural networks. +""" + +import math + +import torch as th +import torch.nn as nn + + +# PyTorch 1.7 has SiLU, but we support PyTorch 1.5. +class SiLU(nn.Module): + def forward(self, x): + return x * th.sigmoid(x) + + +class GroupNorm32(nn.GroupNorm): + def forward(self, x): + return super().forward(x.float()).type(x.dtype) + + +def conv_nd(dims, *args, **kwargs): + """ + Create a 1D, 2D, or 3D convolution module. + """ + if dims == 1: + return nn.Conv1d(*args, **kwargs) + elif dims == 2: + return nn.Conv2d(*args, **kwargs) + elif dims == 3: + return nn.Conv3d(*args, **kwargs) + raise ValueError(f"unsupported dimensions: {dims}") + + +def linear(*args, **kwargs): + """ + Create a linear module. + """ + return nn.Linear(*args, **kwargs) + + +def avg_pool_nd(dims, *args, **kwargs): + """ + Create a 1D, 2D, or 3D average pooling module. + """ + if dims == 1: + return nn.AvgPool1d(*args, **kwargs) + elif dims == 2: + return nn.AvgPool2d(*args, **kwargs) + elif dims == 3: + return nn.AvgPool3d(*args, **kwargs) + raise ValueError(f"unsupported dimensions: {dims}") + + +def update_ema(target_params, source_params, rate=0.99): + """ + Update target parameters to be closer to those of source parameters using + an exponential moving average. + + :param target_params: the target parameter sequence. + :param source_params: the source parameter sequence. + :param rate: the EMA rate (closer to 1 means slower). + """ + for targ, src in zip(target_params, source_params): + targ.detach().mul_(rate).add_(src, alpha=1 - rate) + + +def zero_module(module): + """ + Zero out the parameters of a module and return it. + """ + for p in module.parameters(): + p.detach().zero_() + return module + + +def scale_module(module, scale): + """ + Scale the parameters of a module and return it. + """ + for p in module.parameters(): + p.detach().mul_(scale) + return module + + +def mean_flat(tensor): + """ + Take the mean over all non-batch dimensions. + """ + return tensor.mean(dim=list(range(1, len(tensor.shape)))) + + +def normalization(channels): + """ + Make a standard normalization layer. + + :param channels: number of input channels. + :return: an nn.Module for normalization. + """ + return GroupNorm32(32, channels) + + +def timestep_embedding(timesteps, dim, max_period=10000): + """ + Create sinusoidal timestep embeddings. + + :param timesteps: a 1-D Tensor of N indices, one per batch element. + These may be fractional. + :param dim: the dimension of the output. + :param max_period: controls the minimum frequency of the embeddings. + :return: an [N x dim] Tensor of positional embeddings. + """ + half = dim // 2 + freqs = th.exp( + -math.log(max_period) * th.arange(start=0, end=half, dtype=th.float32) / half + ).to(device=timesteps.device) + args = timesteps[:, None].float() * freqs[None] + embedding = th.cat([th.cos(args), th.sin(args)], dim=-1) + if dim % 2: + embedding = th.cat([embedding, th.zeros_like(embedding[:, :1])], dim=-1) + return embedding + + +def checkpoint(func, inputs, params, flag): + """ + Evaluate a function without caching intermediate activations, allowing for + reduced memory at the expense of extra compute in the backward pass. + + :param func: the function to evaluate. + :param inputs: the argument sequence to pass to `func`. + :param params: a sequence of parameters `func` depends on but does not + explicitly take as arguments. + :param flag: if False, disable gradient checkpointing. + """ + if flag: + args = tuple(inputs) + tuple(params) + return CheckpointFunction.apply(func, len(inputs), *args) + else: + return func(*inputs) + + +class CheckpointFunction(th.autograd.Function): + @staticmethod + def forward(ctx, run_function, length, *args): + ctx.run_function = run_function + ctx.input_tensors = list(args[:length]) + ctx.input_params = list(args[length:]) + with th.no_grad(): + output_tensors = ctx.run_function(*ctx.input_tensors) + return output_tensors + + @staticmethod + def backward(ctx, *output_grads): + ctx.input_tensors = [x.detach().requires_grad_(True) for x in ctx.input_tensors] + with th.enable_grad(): + # Fixes a bug where the first op in run_function modifies the + # Tensor storage in place, which is not allowed for detach()'d + # Tensors. + shallow_copies = [x.view_as(x) for x in ctx.input_tensors] + output_tensors = ctx.run_function(*shallow_copies) + input_grads = th.autograd.grad( + output_tensors, + ctx.input_tensors + ctx.input_params, + output_grads, + allow_unused=True, + ) + del ctx.input_tensors + del ctx.input_params + del output_tensors + return (None, None) + input_grads diff --git a/case_studies/diffpure/guided_diffusion/resample.py b/case_studies/diffpure/guided_diffusion/resample.py new file mode 100644 index 0000000..7afa05e --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/resample.py @@ -0,0 +1,162 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/resample.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +from abc import ABC, abstractmethod + +import numpy as np +import torch as th +import torch.distributed as dist + + +def create_named_schedule_sampler(name, diffusion): + """ + Create a ScheduleSampler from a library of pre-defined samplers. + + :param name: the name of the sampler. + :param diffusion: the diffusion object to sample for. + """ + if name == "uniform": + return UniformSampler(diffusion) + elif name == "loss-second-moment": + return LossSecondMomentResampler(diffusion) + else: + raise NotImplementedError(f"unknown schedule sampler: {name}") + + +class ScheduleSampler(ABC): + """ + A distribution over timesteps in the diffusion process, intended to reduce + variance of the objective. + + By default, samplers perform unbiased importance sampling, in which the + objective's mean is unchanged. + However, subclasses may override sample() to change how the resampled + terms are reweighted, allowing for actual changes in the objective. + """ + + @abstractmethod + def weights(self): + """ + Get a numpy array of weights, one per diffusion step. + + The weights needn't be normalized, but must be positive. + """ + + def sample(self, batch_size, device): + """ + Importance-sample timesteps for a batch. + + :param batch_size: the number of timesteps. + :param device: the torch device to save to. + :return: a tuple (timesteps, weights): + - timesteps: a tensor of timestep indices. + - weights: a tensor of weights to scale the resulting losses. + """ + w = self.weights() + p = w / np.sum(w) + indices_np = np.random.choice(len(p), size=(batch_size,), p=p) + indices = th.from_numpy(indices_np).long().to(device) + weights_np = 1 / (len(p) * p[indices_np]) + weights = th.from_numpy(weights_np).float().to(device) + return indices, weights + + +class UniformSampler(ScheduleSampler): + def __init__(self, diffusion): + self.diffusion = diffusion + self._weights = np.ones([diffusion.num_timesteps]) + + def weights(self): + return self._weights + + +class LossAwareSampler(ScheduleSampler): + def update_with_local_losses(self, local_ts, local_losses): + """ + Update the reweighting using losses from a model. + + Call this method from each rank with a batch of timesteps and the + corresponding losses for each of those timesteps. + This method will perform synchronization to make sure all of the ranks + maintain the exact same reweighting. + + :param local_ts: an integer Tensor of timesteps. + :param local_losses: a 1D Tensor of losses. + """ + batch_sizes = [ + th.tensor([0], dtype=th.int32, device=local_ts.device) + for _ in range(dist.get_world_size()) + ] + dist.all_gather( + batch_sizes, + th.tensor([len(local_ts)], dtype=th.int32, device=local_ts.device), + ) + + # Pad all_gather batches to be the maximum batch size. + batch_sizes = [x.item() for x in batch_sizes] + max_bs = max(batch_sizes) + + timestep_batches = [th.zeros(max_bs).to(local_ts) for bs in batch_sizes] + loss_batches = [th.zeros(max_bs).to(local_losses) for bs in batch_sizes] + dist.all_gather(timestep_batches, local_ts) + dist.all_gather(loss_batches, local_losses) + timesteps = [ + x.item() for y, bs in zip(timestep_batches, batch_sizes) for x in y[:bs] + ] + losses = [x.item() for y, bs in zip(loss_batches, batch_sizes) for x in y[:bs]] + self.update_with_all_losses(timesteps, losses) + + @abstractmethod + def update_with_all_losses(self, ts, losses): + """ + Update the reweighting using losses from a model. + + Sub-classes should override this method to update the reweighting + using losses from the model. + + This method directly updates the reweighting without synchronizing + between workers. It is called by update_with_local_losses from all + ranks with identical arguments. Thus, it should have deterministic + behavior to maintain state across workers. + + :param ts: a list of int timesteps. + :param losses: a list of float losses, one per timestep. + """ + + +class LossSecondMomentResampler(LossAwareSampler): + def __init__(self, diffusion, history_per_term=10, uniform_prob=0.001): + self.diffusion = diffusion + self.history_per_term = history_per_term + self.uniform_prob = uniform_prob + self._loss_history = np.zeros( + [diffusion.num_timesteps, history_per_term], dtype=np.float64 + ) + self._loss_counts = np.zeros([diffusion.num_timesteps], dtype=np.int) + + def weights(self): + if not self._warmed_up(): + return np.ones([self.diffusion.num_timesteps], dtype=np.float64) + weights = np.sqrt(np.mean(self._loss_history ** 2, axis=-1)) + weights /= np.sum(weights) + weights *= 1 - self.uniform_prob + weights += self.uniform_prob / len(weights) + return weights + + def update_with_all_losses(self, ts, losses): + for t, loss in zip(ts, losses): + if self._loss_counts[t] == self.history_per_term: + # Shift out the oldest loss term. + self._loss_history[t, :-1] = self._loss_history[t, 1:] + self._loss_history[t, -1] = loss + else: + self._loss_history[t, self._loss_counts[t]] = loss + self._loss_counts[t] += 1 + + def _warmed_up(self): + return (self._loss_counts == self.history_per_term).all() diff --git a/case_studies/diffpure/guided_diffusion/respace.py b/case_studies/diffpure/guided_diffusion/respace.py new file mode 100644 index 0000000..5d41637 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/respace.py @@ -0,0 +1,136 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/respace.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +import numpy as np +import torch as th + +from .gaussian_diffusion import GaussianDiffusion + + +def space_timesteps(num_timesteps, section_counts): + """ + Create a list of timesteps to use from an original diffusion process, + given the number of timesteps we want to take from equally-sized portions + of the original process. + + For example, if there's 300 timesteps and the section counts are [10,15,20] + then the first 100 timesteps are strided to be 10 timesteps, the second 100 + are strided to be 15 timesteps, and the final 100 are strided to be 20. + + If the stride is a string starting with "ddim", then the fixed striding + from the DDIM paper is used, and only one section is allowed. + + :param num_timesteps: the number of diffusion steps in the original + process to divide up. + :param section_counts: either a list of numbers, or a string containing + comma-separated numbers, indicating the step count + per section. As a special case, use "ddimN" where N + is a number of steps to use the striding from the + DDIM paper. + :return: a set of diffusion steps from the original process to use. + """ + if isinstance(section_counts, str): + if section_counts.startswith("ddim"): + desired_count = int(section_counts[len("ddim") :]) + for i in range(1, num_timesteps): + if len(range(0, num_timesteps, i)) == desired_count: + return set(range(0, num_timesteps, i)) + raise ValueError( + f"cannot create exactly {num_timesteps} steps with an integer stride" + ) + section_counts = [int(x) for x in section_counts.split(",")] + size_per = num_timesteps // len(section_counts) + extra = num_timesteps % len(section_counts) + start_idx = 0 + all_steps = [] + for i, section_count in enumerate(section_counts): + size = size_per + (1 if i < extra else 0) + if size < section_count: + raise ValueError( + f"cannot divide section of {size} steps into {section_count}" + ) + if section_count <= 1: + frac_stride = 1 + else: + frac_stride = (size - 1) / (section_count - 1) + cur_idx = 0.0 + taken_steps = [] + for _ in range(section_count): + taken_steps.append(start_idx + round(cur_idx)) + cur_idx += frac_stride + all_steps += taken_steps + start_idx += size + return set(all_steps) + + +class SpacedDiffusion(GaussianDiffusion): + """ + A diffusion process which can skip steps in a base diffusion process. + + :param use_timesteps: a collection (sequence or set) of timesteps from the + original diffusion process to retain. + :param kwargs: the kwargs to create the base diffusion process. + """ + + def __init__(self, use_timesteps, **kwargs): + self.use_timesteps = set(use_timesteps) + self.timestep_map = [] + self.original_num_steps = len(kwargs["betas"]) + + base_diffusion = GaussianDiffusion(**kwargs) # pylint: disable=missing-kwoa + last_alpha_cumprod = 1.0 + new_betas = [] + for i, alpha_cumprod in enumerate(base_diffusion.alphas_cumprod): + if i in self.use_timesteps: + new_betas.append(1 - alpha_cumprod / last_alpha_cumprod) + last_alpha_cumprod = alpha_cumprod + self.timestep_map.append(i) + kwargs["betas"] = np.array(new_betas) + super().__init__(**kwargs) + + def p_mean_variance( + self, model, *args, **kwargs + ): # pylint: disable=signature-differs + return super().p_mean_variance(self._wrap_model(model), *args, **kwargs) + + def training_losses( + self, model, *args, **kwargs + ): # pylint: disable=signature-differs + return super().training_losses(self._wrap_model(model), *args, **kwargs) + + def condition_mean(self, cond_fn, *args, **kwargs): + return super().condition_mean(self._wrap_model(cond_fn), *args, **kwargs) + + def condition_score(self, cond_fn, *args, **kwargs): + return super().condition_score(self._wrap_model(cond_fn), *args, **kwargs) + + def _wrap_model(self, model): + if isinstance(model, _WrappedModel): + return model + return _WrappedModel( + model, self.timestep_map, self.rescale_timesteps, self.original_num_steps + ) + + def _scale_timesteps(self, t): + # Scaling is done by the wrapped model. + return t + + +class _WrappedModel: + def __init__(self, model, timestep_map, rescale_timesteps, original_num_steps): + self.model = model + self.timestep_map = timestep_map + self.rescale_timesteps = rescale_timesteps + self.original_num_steps = original_num_steps + + def __call__(self, x, ts, **kwargs): + map_tensor = th.tensor(self.timestep_map, device=ts.device, dtype=ts.dtype) + new_ts = map_tensor[ts] + if self.rescale_timesteps: + new_ts = new_ts.float() * (1000.0 / self.original_num_steps) + return self.model(x, new_ts, **kwargs) diff --git a/case_studies/diffpure/guided_diffusion/script_util.py b/case_studies/diffpure/guided_diffusion/script_util.py new file mode 100644 index 0000000..7605693 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/script_util.py @@ -0,0 +1,460 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/script_util.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +import argparse +import inspect + +from . import gaussian_diffusion as gd +from .respace import SpacedDiffusion, space_timesteps +from .unet import SuperResModel, UNetModel, EncoderUNetModel + +NUM_CLASSES = 1000 + + +def diffusion_defaults(): + """ + Defaults for image and classifier training. + """ + return dict( + learn_sigma=False, + diffusion_steps=1000, + noise_schedule="linear", + timestep_respacing="", + use_kl=False, + predict_xstart=False, + rescale_timesteps=False, + rescale_learned_sigmas=False, + ) + + +def classifier_defaults(): + """ + Defaults for classifier models. + """ + return dict( + image_size=64, + classifier_use_fp16=False, + classifier_width=128, + classifier_depth=2, + classifier_attention_resolutions="32,16,8", # 16 + classifier_use_scale_shift_norm=True, # False + classifier_resblock_updown=True, # False + classifier_pool="attention", + ) + + +def model_and_diffusion_defaults(): + """ + Defaults for image training. + """ + res = dict( + image_size=64, + num_channels=128, + num_res_blocks=2, + num_heads=4, + num_heads_upsample=-1, + num_head_channels=-1, + attention_resolutions="16,8", + channel_mult="", + dropout=0.0, + class_cond=False, + use_checkpoint=False, + use_scale_shift_norm=True, + resblock_updown=False, + use_fp16=False, + use_new_attention_order=False, + ) + res.update(diffusion_defaults()) + return res + + +def classifier_and_diffusion_defaults(): + res = classifier_defaults() + res.update(diffusion_defaults()) + return res + + +def create_model_and_diffusion( + image_size, + class_cond, + learn_sigma, + num_channels, + num_res_blocks, + channel_mult, + num_heads, + num_head_channels, + num_heads_upsample, + attention_resolutions, + dropout, + diffusion_steps, + noise_schedule, + timestep_respacing, + use_kl, + predict_xstart, + rescale_timesteps, + rescale_learned_sigmas, + use_checkpoint, + use_scale_shift_norm, + resblock_updown, + use_fp16, + use_new_attention_order, +): + model = create_model( + image_size, + num_channels, + num_res_blocks, + channel_mult=channel_mult, + learn_sigma=learn_sigma, + class_cond=class_cond, + use_checkpoint=use_checkpoint, + attention_resolutions=attention_resolutions, + num_heads=num_heads, + num_head_channels=num_head_channels, + num_heads_upsample=num_heads_upsample, + use_scale_shift_norm=use_scale_shift_norm, + dropout=dropout, + resblock_updown=resblock_updown, + use_fp16=use_fp16, + use_new_attention_order=use_new_attention_order, + ) + diffusion = create_gaussian_diffusion( + steps=diffusion_steps, + learn_sigma=learn_sigma, + noise_schedule=noise_schedule, + use_kl=use_kl, + predict_xstart=predict_xstart, + rescale_timesteps=rescale_timesteps, + rescale_learned_sigmas=rescale_learned_sigmas, + timestep_respacing=timestep_respacing, + ) + return model, diffusion + + +def create_model( + image_size, + num_channels, + num_res_blocks, + channel_mult="", + learn_sigma=False, + class_cond=False, + use_checkpoint=False, + attention_resolutions="16", + num_heads=1, + num_head_channels=-1, + num_heads_upsample=-1, + use_scale_shift_norm=False, + dropout=0, + resblock_updown=False, + use_fp16=False, + use_new_attention_order=False, +): + if channel_mult == "": + if image_size == 512: + channel_mult = (0.5, 1, 1, 2, 2, 4, 4) + elif image_size == 256: + channel_mult = (1, 1, 2, 2, 4, 4) + elif image_size == 128: + channel_mult = (1, 1, 2, 3, 4) + elif image_size == 64: + channel_mult = (1, 2, 3, 4) + else: + raise ValueError(f"unsupported image size: {image_size}") + else: + channel_mult = tuple(int(ch_mult) for ch_mult in channel_mult.split(",")) + + attention_ds = [] + for res in attention_resolutions.split(","): + attention_ds.append(image_size // int(res)) + + return UNetModel( + image_size=image_size, + in_channels=3, + model_channels=num_channels, + out_channels=(3 if not learn_sigma else 6), + num_res_blocks=num_res_blocks, + attention_resolutions=tuple(attention_ds), + dropout=dropout, + channel_mult=channel_mult, + num_classes=(NUM_CLASSES if class_cond else None), + use_checkpoint=use_checkpoint, + use_fp16=use_fp16, + num_heads=num_heads, + num_head_channels=num_head_channels, + num_heads_upsample=num_heads_upsample, + use_scale_shift_norm=use_scale_shift_norm, + resblock_updown=resblock_updown, + use_new_attention_order=use_new_attention_order, + ) + + +def create_classifier_and_diffusion( + image_size, + classifier_use_fp16, + classifier_width, + classifier_depth, + classifier_attention_resolutions, + classifier_use_scale_shift_norm, + classifier_resblock_updown, + classifier_pool, + learn_sigma, + diffusion_steps, + noise_schedule, + timestep_respacing, + use_kl, + predict_xstart, + rescale_timesteps, + rescale_learned_sigmas, +): + classifier = create_classifier( + image_size, + classifier_use_fp16, + classifier_width, + classifier_depth, + classifier_attention_resolutions, + classifier_use_scale_shift_norm, + classifier_resblock_updown, + classifier_pool, + ) + diffusion = create_gaussian_diffusion( + steps=diffusion_steps, + learn_sigma=learn_sigma, + noise_schedule=noise_schedule, + use_kl=use_kl, + predict_xstart=predict_xstart, + rescale_timesteps=rescale_timesteps, + rescale_learned_sigmas=rescale_learned_sigmas, + timestep_respacing=timestep_respacing, + ) + return classifier, diffusion + + +def create_classifier( + image_size, + classifier_use_fp16, + classifier_width, + classifier_depth, + classifier_attention_resolutions, + classifier_use_scale_shift_norm, + classifier_resblock_updown, + classifier_pool, +): + if image_size == 512: + channel_mult = (0.5, 1, 1, 2, 2, 4, 4) + elif image_size == 256: + channel_mult = (1, 1, 2, 2, 4, 4) + elif image_size == 128: + channel_mult = (1, 1, 2, 3, 4) + elif image_size == 64: + channel_mult = (1, 2, 3, 4) + else: + raise ValueError(f"unsupported image size: {image_size}") + + attention_ds = [] + for res in classifier_attention_resolutions.split(","): + attention_ds.append(image_size // int(res)) + + return EncoderUNetModel( + image_size=image_size, + in_channels=3, + model_channels=classifier_width, + out_channels=1000, + num_res_blocks=classifier_depth, + attention_resolutions=tuple(attention_ds), + channel_mult=channel_mult, + use_fp16=classifier_use_fp16, + num_head_channels=64, + use_scale_shift_norm=classifier_use_scale_shift_norm, + resblock_updown=classifier_resblock_updown, + pool=classifier_pool, + ) + + +def sr_model_and_diffusion_defaults(): + res = model_and_diffusion_defaults() + res["large_size"] = 256 + res["small_size"] = 64 + arg_names = inspect.getfullargspec(sr_create_model_and_diffusion)[0] + for k in res.copy().keys(): + if k not in arg_names: + del res[k] + return res + + +def sr_create_model_and_diffusion( + large_size, + small_size, + class_cond, + learn_sigma, + num_channels, + num_res_blocks, + num_heads, + num_head_channels, + num_heads_upsample, + attention_resolutions, + dropout, + diffusion_steps, + noise_schedule, + timestep_respacing, + use_kl, + predict_xstart, + rescale_timesteps, + rescale_learned_sigmas, + use_checkpoint, + use_scale_shift_norm, + resblock_updown, + use_fp16, +): + model = sr_create_model( + large_size, + small_size, + num_channels, + num_res_blocks, + learn_sigma=learn_sigma, + class_cond=class_cond, + use_checkpoint=use_checkpoint, + attention_resolutions=attention_resolutions, + num_heads=num_heads, + num_head_channels=num_head_channels, + num_heads_upsample=num_heads_upsample, + use_scale_shift_norm=use_scale_shift_norm, + dropout=dropout, + resblock_updown=resblock_updown, + use_fp16=use_fp16, + ) + diffusion = create_gaussian_diffusion( + steps=diffusion_steps, + learn_sigma=learn_sigma, + noise_schedule=noise_schedule, + use_kl=use_kl, + predict_xstart=predict_xstart, + rescale_timesteps=rescale_timesteps, + rescale_learned_sigmas=rescale_learned_sigmas, + timestep_respacing=timestep_respacing, + ) + return model, diffusion + + +def sr_create_model( + large_size, + small_size, + num_channels, + num_res_blocks, + learn_sigma, + class_cond, + use_checkpoint, + attention_resolutions, + num_heads, + num_head_channels, + num_heads_upsample, + use_scale_shift_norm, + dropout, + resblock_updown, + use_fp16, +): + _ = small_size # hack to prevent unused variable + + if large_size == 512: + channel_mult = (1, 1, 2, 2, 4, 4) + elif large_size == 256: + channel_mult = (1, 1, 2, 2, 4, 4) + elif large_size == 64: + channel_mult = (1, 2, 3, 4) + else: + raise ValueError(f"unsupported large size: {large_size}") + + attention_ds = [] + for res in attention_resolutions.split(","): + attention_ds.append(large_size // int(res)) + + return SuperResModel( + image_size=large_size, + in_channels=3, + model_channels=num_channels, + out_channels=(3 if not learn_sigma else 6), + num_res_blocks=num_res_blocks, + attention_resolutions=tuple(attention_ds), + dropout=dropout, + channel_mult=channel_mult, + num_classes=(NUM_CLASSES if class_cond else None), + use_checkpoint=use_checkpoint, + num_heads=num_heads, + num_head_channels=num_head_channels, + num_heads_upsample=num_heads_upsample, + use_scale_shift_norm=use_scale_shift_norm, + resblock_updown=resblock_updown, + use_fp16=use_fp16, + ) + + +def create_gaussian_diffusion( + *, + steps=1000, + learn_sigma=False, + sigma_small=False, + noise_schedule="linear", + use_kl=False, + predict_xstart=False, + rescale_timesteps=False, + rescale_learned_sigmas=False, + timestep_respacing="", +): + betas = gd.get_named_beta_schedule(noise_schedule, steps) + if use_kl: + loss_type = gd.LossType.RESCALED_KL + elif rescale_learned_sigmas: + loss_type = gd.LossType.RESCALED_MSE + else: + loss_type = gd.LossType.MSE + if not timestep_respacing: + timestep_respacing = [steps] + return SpacedDiffusion( + use_timesteps=space_timesteps(steps, timestep_respacing), + betas=betas, + model_mean_type=( + gd.ModelMeanType.EPSILON if not predict_xstart else gd.ModelMeanType.START_X + ), + model_var_type=( + ( + gd.ModelVarType.FIXED_LARGE + if not sigma_small + else gd.ModelVarType.FIXED_SMALL + ) + if not learn_sigma + else gd.ModelVarType.LEARNED_RANGE + ), + loss_type=loss_type, + rescale_timesteps=rescale_timesteps, + ) + + +def add_dict_to_argparser(parser, default_dict): + for k, v in default_dict.items(): + v_type = type(v) + if v is None: + v_type = str + elif isinstance(v, bool): + v_type = str2bool + parser.add_argument(f"--{k}", default=v, type=v_type) + + +def args_to_dict(args, keys): + return {k: getattr(args, k) for k in keys} + + +def str2bool(v): + """ + https://stackoverflow.com/questions/15008758/parsing-boolean-values-with-argparse + """ + if isinstance(v, bool): + return v + if v.lower() in ("yes", "true", "t", "y", "1"): + return True + elif v.lower() in ("no", "false", "f", "n", "0"): + return False + else: + raise argparse.ArgumentTypeError("boolean value expected") diff --git a/case_studies/diffpure/guided_diffusion/train_util.py b/case_studies/diffpure/guided_diffusion/train_util.py new file mode 100644 index 0000000..1942f18 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/train_util.py @@ -0,0 +1,309 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/train_util.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +import copy +import functools +import os + +import blobfile as bf +import torch as th +import torch.distributed as dist +from torch.nn.parallel.distributed import DistributedDataParallel as DDP +from torch.optim import AdamW + +from . import dist_util, logger +from .fp16_util import MixedPrecisionTrainer +from .nn import update_ema +from .resample import LossAwareSampler, UniformSampler + +# For ImageNet experiments, this was a good default value. +# We found that the lg_loss_scale quickly climbed to +# 20-21 within the first ~1K steps of training. +INITIAL_LOG_LOSS_SCALE = 20.0 + + +class TrainLoop: + def __init__( + self, + *, + model, + diffusion, + data, + batch_size, + microbatch, + lr, + ema_rate, + log_interval, + save_interval, + resume_checkpoint, + use_fp16=False, + fp16_scale_growth=1e-3, + schedule_sampler=None, + weight_decay=0.0, + lr_anneal_steps=0, + ): + self.model = model + self.diffusion = diffusion + self.data = data + self.batch_size = batch_size + self.microbatch = microbatch if microbatch > 0 else batch_size + self.lr = lr + self.ema_rate = ( + [ema_rate] + if isinstance(ema_rate, float) + else [float(x) for x in ema_rate.split(",")] + ) + self.log_interval = log_interval + self.save_interval = save_interval + self.resume_checkpoint = resume_checkpoint + self.use_fp16 = use_fp16 + self.fp16_scale_growth = fp16_scale_growth + self.schedule_sampler = schedule_sampler or UniformSampler(diffusion) + self.weight_decay = weight_decay + self.lr_anneal_steps = lr_anneal_steps + + self.step = 0 + self.resume_step = 0 + self.global_batch = self.batch_size * dist.get_world_size() + + self.sync_cuda = th.cuda.is_available() + + self._load_and_sync_parameters() + self.mp_trainer = MixedPrecisionTrainer( + model=self.model, + use_fp16=self.use_fp16, + fp16_scale_growth=fp16_scale_growth, + ) + + self.opt = AdamW( + self.mp_trainer.master_params, lr=self.lr, weight_decay=self.weight_decay + ) + if self.resume_step: + self._load_optimizer_state() + # Model was resumed, either due to a restart or a checkpoint + # being specified at the command line. + self.ema_params = [ + self._load_ema_parameters(rate) for rate in self.ema_rate + ] + else: + self.ema_params = [ + copy.deepcopy(self.mp_trainer.master_params) + for _ in range(len(self.ema_rate)) + ] + + if th.cuda.is_available(): + self.use_ddp = True + self.ddp_model = DDP( + self.model, + device_ids=[dist_util.dev()], + output_device=dist_util.dev(), + broadcast_buffers=False, + bucket_cap_mb=128, + find_unused_parameters=False, + ) + else: + if dist.get_world_size() > 1: + logger.warn( + "Distributed training requires CUDA. " + "Gradients will not be synchronized properly!" + ) + self.use_ddp = False + self.ddp_model = self.model + + def _load_and_sync_parameters(self): + resume_checkpoint = find_resume_checkpoint() or self.resume_checkpoint + + if resume_checkpoint: + self.resume_step = parse_resume_step_from_filename(resume_checkpoint) + if dist.get_rank() == 0: + logger.log(f"loading model from checkpoint: {resume_checkpoint}...") + self.model.load_state_dict( + dist_util.load_state_dict( + resume_checkpoint, map_location=dist_util.dev() + ) + ) + + dist_util.sync_params(self.model.parameters()) + + def _load_ema_parameters(self, rate): + ema_params = copy.deepcopy(self.mp_trainer.master_params) + + main_checkpoint = find_resume_checkpoint() or self.resume_checkpoint + ema_checkpoint = find_ema_checkpoint(main_checkpoint, self.resume_step, rate) + if ema_checkpoint: + if dist.get_rank() == 0: + logger.log(f"loading EMA from checkpoint: {ema_checkpoint}...") + state_dict = dist_util.load_state_dict( + ema_checkpoint, map_location=dist_util.dev() + ) + ema_params = self.mp_trainer.state_dict_to_master_params(state_dict) + + dist_util.sync_params(ema_params) + return ema_params + + def _load_optimizer_state(self): + main_checkpoint = find_resume_checkpoint() or self.resume_checkpoint + opt_checkpoint = bf.join( + bf.dirname(main_checkpoint), f"opt{self.resume_step:06}.pt" + ) + if bf.exists(opt_checkpoint): + logger.log(f"loading optimizer state from checkpoint: {opt_checkpoint}") + state_dict = dist_util.load_state_dict( + opt_checkpoint, map_location=dist_util.dev() + ) + self.opt.load_state_dict(state_dict) + + def run_loop(self): + while ( + not self.lr_anneal_steps + or self.step + self.resume_step < self.lr_anneal_steps + ): + batch, cond = next(self.data) + self.run_step(batch, cond) + if self.step % self.log_interval == 0: + logger.dumpkvs() + if self.step % self.save_interval == 0: + self.save() + # Run for a finite amount of time in integration tests. + if os.environ.get("DIFFUSION_TRAINING_TEST", "") and self.step > 0: + return + self.step += 1 + # Save the last checkpoint if it wasn't already saved. + if (self.step - 1) % self.save_interval != 0: + self.save() + + def run_step(self, batch, cond): + self.forward_backward(batch, cond) + took_step = self.mp_trainer.optimize(self.opt) + if took_step: + self._update_ema() + self._anneal_lr() + self.log_step() + + def forward_backward(self, batch, cond): + self.mp_trainer.zero_grad() + for i in range(0, batch.shape[0], self.microbatch): + micro = batch[i : i + self.microbatch].to(dist_util.dev()) + micro_cond = { + k: v[i : i + self.microbatch].to(dist_util.dev()) + for k, v in cond.items() + } + last_batch = (i + self.microbatch) >= batch.shape[0] + t, weights = self.schedule_sampler.sample(micro.shape[0], dist_util.dev()) + + compute_losses = functools.partial( + self.diffusion.training_losses, + self.ddp_model, + micro, + t, + model_kwargs=micro_cond, + ) + + if last_batch or not self.use_ddp: + losses = compute_losses() + else: + with self.ddp_model.no_sync(): + losses = compute_losses() + + if isinstance(self.schedule_sampler, LossAwareSampler): + self.schedule_sampler.update_with_local_losses( + t, losses["loss"].detach() + ) + + loss = (losses["loss"] * weights).mean() + log_loss_dict( + self.diffusion, t, {k: v * weights for k, v in losses.items()} + ) + self.mp_trainer.backward(loss) + + def _update_ema(self): + for rate, params in zip(self.ema_rate, self.ema_params): + update_ema(params, self.mp_trainer.master_params, rate=rate) + + def _anneal_lr(self): + if not self.lr_anneal_steps: + return + frac_done = (self.step + self.resume_step) / self.lr_anneal_steps + lr = self.lr * (1 - frac_done) + for param_group in self.opt.param_groups: + param_group["lr"] = lr + + def log_step(self): + logger.logkv("step", self.step + self.resume_step) + logger.logkv("samples", (self.step + self.resume_step + 1) * self.global_batch) + + def save(self): + def save_checkpoint(rate, params): + state_dict = self.mp_trainer.master_params_to_state_dict(params) + if dist.get_rank() == 0: + logger.log(f"saving model {rate}...") + if not rate: + filename = f"model{(self.step+self.resume_step):06d}.pt" + else: + filename = f"ema_{rate}_{(self.step+self.resume_step):06d}.pt" + with bf.BlobFile(bf.join(get_blob_logdir(), filename), "wb") as f: + th.save(state_dict, f) + + save_checkpoint(0, self.mp_trainer.master_params) + for rate, params in zip(self.ema_rate, self.ema_params): + save_checkpoint(rate, params) + + if dist.get_rank() == 0: + with bf.BlobFile( + bf.join(get_blob_logdir(), f"opt{(self.step+self.resume_step):06d}.pt"), + "wb", + ) as f: + th.save(self.opt.state_dict(), f) + + dist.barrier() + + +def parse_resume_step_from_filename(filename): + """ + Parse filenames of the form path/to/modelNNNNNN.pt, where NNNNNN is the + checkpoint's number of steps. + """ + split = filename.split("model") + if len(split) < 2: + return 0 + split1 = split[-1].split(".")[0] + try: + return int(split1) + except ValueError: + return 0 + + +def get_blob_logdir(): + # You can change this to be a separate path to save checkpoints to + # a blobstore or some external drive. + return logger.get_dir() + + +def find_resume_checkpoint(): + # On your infrastructure, you may want to override this to automatically + # discover the latest checkpoint on your blob storage, etc. + return None + + +def find_ema_checkpoint(main_checkpoint, step, rate): + if main_checkpoint is None: + return None + filename = f"ema_{rate}_{(step):06d}.pt" + path = bf.join(bf.dirname(main_checkpoint), filename) + if bf.exists(path): + return path + return None + + +def log_loss_dict(diffusion, ts, losses): + for key, values in losses.items(): + logger.logkv_mean(key, values.mean().item()) + # Log the quantiles (four quartiles, in particular). + for sub_t, sub_loss in zip(ts.cpu().numpy(), values.detach().cpu().numpy()): + quartile = int(4 * sub_t / diffusion.num_timesteps) + logger.logkv_mean(f"{key}_q{quartile}", sub_loss) diff --git a/case_studies/diffpure/guided_diffusion/unet.py b/case_studies/diffpure/guided_diffusion/unet.py new file mode 100644 index 0000000..f25e8a7 --- /dev/null +++ b/case_studies/diffpure/guided_diffusion/unet.py @@ -0,0 +1,902 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/openai/guided-diffusion/blob/main/guided_diffusion/unet.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_GUIDED_DIFFUSION). +# --------------------------------------------------------------- + +from abc import abstractmethod + +import math + +import numpy as np +import torch as th +import torch.nn as nn +import torch.nn.functional as F + +from .fp16_util import convert_module_to_f16, convert_module_to_f32 +from .nn import ( + checkpoint, + conv_nd, + linear, + avg_pool_nd, + zero_module, + normalization, + timestep_embedding, +) + + +class AttentionPool2d(nn.Module): + """ + Adapted from CLIP: https://github.com/openai/CLIP/blob/main/clip/model.py + """ + + def __init__( + self, + spacial_dim: int, + embed_dim: int, + num_heads_channels: int, + output_dim: int = None, + ): + super().__init__() + self.positional_embedding = nn.Parameter( + th.randn(embed_dim, spacial_dim ** 2 + 1) / embed_dim ** 0.5 + ) + self.qkv_proj = conv_nd(1, embed_dim, 3 * embed_dim, 1) + self.c_proj = conv_nd(1, embed_dim, output_dim or embed_dim, 1) + self.num_heads = embed_dim // num_heads_channels + self.attention = QKVAttention(self.num_heads) + + def forward(self, x): + b, c, *_spatial = x.shape + x = x.reshape(b, c, -1) # NC(HW) + x = th.cat([x.mean(dim=-1, keepdim=True), x], dim=-1) # NC(HW+1) + x = x + self.positional_embedding[None, :, :].to(x.dtype) # NC(HW+1) + x = self.qkv_proj(x) + x = self.attention(x) + x = self.c_proj(x) + return x[:, :, 0] + + +class TimestepBlock(nn.Module): + """ + Any module where forward() takes timestep embeddings as a second argument. + """ + + @abstractmethod + def forward(self, x, emb): + """ + Apply the module to `x` given `emb` timestep embeddings. + """ + + +class TimestepEmbedSequential(nn.Sequential, TimestepBlock): + """ + A sequential module that passes timestep embeddings to the children that + support it as an extra input. + """ + + def forward(self, x, emb): + for layer in self: + if isinstance(layer, TimestepBlock): + x = layer(x, emb) + else: + x = layer(x) + return x + + +class Upsample(nn.Module): + """ + An upsampling layer with an optional convolution. + + :param channels: channels in the inputs and outputs. + :param use_conv: a bool determining if a convolution is applied. + :param dims: determines if the signal is 1D, 2D, or 3D. If 3D, then + upsampling occurs in the inner-two dimensions. + """ + + def __init__(self, channels, use_conv, dims=2, out_channels=None): + super().__init__() + self.channels = channels + self.out_channels = out_channels or channels + self.use_conv = use_conv + self.dims = dims + if use_conv: + self.conv = conv_nd(dims, self.channels, self.out_channels, 3, padding=1) + + def forward(self, x): + assert x.shape[1] == self.channels + if self.dims == 3: + x = F.interpolate( + x, (x.shape[2], x.shape[3] * 2, x.shape[4] * 2), mode="nearest" + ) + else: + x = F.interpolate(x, scale_factor=2, mode="nearest") + if self.use_conv: + x = self.conv(x) + return x + + +class Downsample(nn.Module): + """ + A downsampling layer with an optional convolution. + + :param channels: channels in the inputs and outputs. + :param use_conv: a bool determining if a convolution is applied. + :param dims: determines if the signal is 1D, 2D, or 3D. If 3D, then + downsampling occurs in the inner-two dimensions. + """ + + def __init__(self, channels, use_conv, dims=2, out_channels=None): + super().__init__() + self.channels = channels + self.out_channels = out_channels or channels + self.use_conv = use_conv + self.dims = dims + stride = 2 if dims != 3 else (1, 2, 2) + if use_conv: + self.op = conv_nd( + dims, self.channels, self.out_channels, 3, stride=stride, padding=1 + ) + else: + assert self.channels == self.out_channels + self.op = avg_pool_nd(dims, kernel_size=stride, stride=stride) + + def forward(self, x): + assert x.shape[1] == self.channels + return self.op(x) + + +class ResBlock(TimestepBlock): + """ + A residual block that can optionally change the number of channels. + + :param channels: the number of input channels. + :param emb_channels: the number of timestep embedding channels. + :param dropout: the rate of dropout. + :param out_channels: if specified, the number of out channels. + :param use_conv: if True and out_channels is specified, use a spatial + convolution instead of a smaller 1x1 convolution to change the + channels in the skip connection. + :param dims: determines if the signal is 1D, 2D, or 3D. + :param use_checkpoint: if True, use gradient checkpointing on this module. + :param up: if True, use this block for upsampling. + :param down: if True, use this block for downsampling. + """ + + def __init__( + self, + channels, + emb_channels, + dropout, + out_channels=None, + use_conv=False, + use_scale_shift_norm=False, + dims=2, + use_checkpoint=False, + up=False, + down=False, + ): + super().__init__() + self.channels = channels + self.emb_channels = emb_channels + self.dropout = dropout + self.out_channels = out_channels or channels + self.use_conv = use_conv + self.use_checkpoint = use_checkpoint + self.use_scale_shift_norm = use_scale_shift_norm + + self.in_layers = nn.Sequential( + normalization(channels), + nn.SiLU(), + conv_nd(dims, channels, self.out_channels, 3, padding=1), + ) + + self.updown = up or down + + if up: + self.h_upd = Upsample(channels, False, dims) + self.x_upd = Upsample(channels, False, dims) + elif down: + self.h_upd = Downsample(channels, False, dims) + self.x_upd = Downsample(channels, False, dims) + else: + self.h_upd = self.x_upd = nn.Identity() + + self.emb_layers = nn.Sequential( + nn.SiLU(), + linear( + emb_channels, + 2 * self.out_channels if use_scale_shift_norm else self.out_channels, + ), + ) + self.out_layers = nn.Sequential( + normalization(self.out_channels), + nn.SiLU(), + nn.Dropout(p=dropout), + zero_module( + conv_nd(dims, self.out_channels, self.out_channels, 3, padding=1) + ), + ) + + if self.out_channels == channels: + self.skip_connection = nn.Identity() + elif use_conv: + self.skip_connection = conv_nd( + dims, channels, self.out_channels, 3, padding=1 + ) + else: + self.skip_connection = conv_nd(dims, channels, self.out_channels, 1) + + def forward(self, x, emb): + """ + Apply the block to a Tensor, conditioned on a timestep embedding. + + :param x: an [N x C x ...] Tensor of features. + :param emb: an [N x emb_channels] Tensor of timestep embeddings. + :return: an [N x C x ...] Tensor of outputs. + """ + return checkpoint( + self._forward, (x, emb), self.parameters(), self.use_checkpoint + ) + + def _forward(self, x, emb): + if self.updown: + in_rest, in_conv = self.in_layers[:-1], self.in_layers[-1] + h = in_rest(x) + h = self.h_upd(h) + x = self.x_upd(x) + h = in_conv(h) + else: + h = self.in_layers(x) + emb_out = self.emb_layers(emb).type(h.dtype) + while len(emb_out.shape) < len(h.shape): + emb_out = emb_out[..., None] + if self.use_scale_shift_norm: + out_norm, out_rest = self.out_layers[0], self.out_layers[1:] + scale, shift = th.chunk(emb_out, 2, dim=1) + h = out_norm(h) * (1 + scale) + shift + h = out_rest(h) + else: + h = h + emb_out + h = self.out_layers(h) + return self.skip_connection(x) + h + + +class AttentionBlock(nn.Module): + """ + An attention block that allows spatial positions to attend to each other. + + Originally ported from here, but adapted to the N-d case. + https://github.com/hojonathanho/diffusion/blob/1e0dceb3b3495bbe19116a5e1b3596cd0706c543/diffusion_tf/models/unet.py#L66. + """ + + def __init__( + self, + channels, + num_heads=1, + num_head_channels=-1, + use_checkpoint=False, + use_new_attention_order=False, + ): + super().__init__() + self.channels = channels + if num_head_channels == -1: + self.num_heads = num_heads + else: + assert ( + channels % num_head_channels == 0 + ), f"q,k,v channels {channels} is not divisible by num_head_channels {num_head_channels}" + self.num_heads = channels // num_head_channels + self.use_checkpoint = use_checkpoint + self.norm = normalization(channels) + self.qkv = conv_nd(1, channels, channels * 3, 1) + if use_new_attention_order: + # split qkv before split heads + self.attention = QKVAttention(self.num_heads) + else: + # split heads before split qkv + self.attention = QKVAttentionLegacy(self.num_heads) + + self.proj_out = zero_module(conv_nd(1, channels, channels, 1)) + + def forward(self, x): + return checkpoint(self._forward, (x,), self.parameters(), True) + + def _forward(self, x): + b, c, *spatial = x.shape + x = x.reshape(b, c, -1) + qkv = self.qkv(self.norm(x)) + h = self.attention(qkv) + h = self.proj_out(h) + return (x + h).reshape(b, c, *spatial) + + +def count_flops_attn(model, _x, y): + """ + A counter for the `thop` package to count the operations in an + attention operation. + Meant to be used like: + macs, params = thop.profile( + model, + inputs=(inputs, timestamps), + custom_ops={QKVAttention: QKVAttention.count_flops}, + ) + """ + b, c, *spatial = y[0].shape + num_spatial = int(np.prod(spatial)) + # We perform two matmuls with the same number of ops. + # The first computes the weight matrix, the second computes + # the combination of the value vectors. + matmul_ops = 2 * b * (num_spatial ** 2) * c + model.total_ops += th.DoubleTensor([matmul_ops]) + + +class QKVAttentionLegacy(nn.Module): + """ + A module which performs QKV attention. Matches legacy QKVAttention + input/ouput heads shaping + """ + + def __init__(self, n_heads): + super().__init__() + self.n_heads = n_heads + + def forward(self, qkv): + """ + Apply QKV attention. + + :param qkv: an [N x (H * 3 * C) x T] tensor of Qs, Ks, and Vs. + :return: an [N x (H * C) x T] tensor after attention. + """ + bs, width, length = qkv.shape + assert width % (3 * self.n_heads) == 0 + ch = width // (3 * self.n_heads) + q, k, v = qkv.reshape(bs * self.n_heads, ch * 3, length).split(ch, dim=1) + scale = 1 / math.sqrt(math.sqrt(ch)) + weight = th.einsum( + "bct,bcs->bts", q * scale, k * scale + ) # More stable with f16 than dividing afterwards + weight = th.softmax(weight.float(), dim=-1).type(weight.dtype) + a = th.einsum("bts,bcs->bct", weight, v) + return a.reshape(bs, -1, length) + + @staticmethod + def count_flops(model, _x, y): + return count_flops_attn(model, _x, y) + + +class QKVAttention(nn.Module): + """ + A module which performs QKV attention and splits in a different order. + """ + + def __init__(self, n_heads): + super().__init__() + self.n_heads = n_heads + + def forward(self, qkv): + """ + Apply QKV attention. + + :param qkv: an [N x (3 * H * C) x T] tensor of Qs, Ks, and Vs. + :return: an [N x (H * C) x T] tensor after attention. + """ + bs, width, length = qkv.shape + assert width % (3 * self.n_heads) == 0 + ch = width // (3 * self.n_heads) + q, k, v = qkv.chunk(3, dim=1) + scale = 1 / math.sqrt(math.sqrt(ch)) + weight = th.einsum( + "bct,bcs->bts", + (q * scale).view(bs * self.n_heads, ch, length), + (k * scale).view(bs * self.n_heads, ch, length), + ) # More stable with f16 than dividing afterwards + weight = th.softmax(weight.float(), dim=-1).type(weight.dtype) + a = th.einsum("bts,bcs->bct", weight, v.reshape(bs * self.n_heads, ch, length)) + return a.reshape(bs, -1, length) + + @staticmethod + def count_flops(model, _x, y): + return count_flops_attn(model, _x, y) + + +class UNetModel(nn.Module): + """ + The full UNet model with attention and timestep embedding. + + :param in_channels: channels in the input Tensor. + :param model_channels: base channel count for the model. + :param out_channels: channels in the output Tensor. + :param num_res_blocks: number of residual blocks per downsample. + :param attention_resolutions: a collection of downsample rates at which + attention will take place. May be a set, list, or tuple. + For example, if this contains 4, then at 4x downsampling, attention + will be used. + :param dropout: the dropout probability. + :param channel_mult: channel multiplier for each level of the UNet. + :param conv_resample: if True, use learned convolutions for upsampling and + downsampling. + :param dims: determines if the signal is 1D, 2D, or 3D. + :param num_classes: if specified (as an int), then this model will be + class-conditional with `num_classes` classes. + :param use_checkpoint: use gradient checkpointing to reduce memory usage. + :param num_heads: the number of attention heads in each attention layer. + :param num_heads_channels: if specified, ignore num_heads and instead use + a fixed channel width per attention head. + :param num_heads_upsample: works with num_heads to set a different number + of heads for upsampling. Deprecated. + :param use_scale_shift_norm: use a FiLM-like conditioning mechanism. + :param resblock_updown: use residual blocks for up/downsampling. + :param use_new_attention_order: use a different attention pattern for potentially + increased efficiency. + """ + + def __init__( + self, + image_size, + in_channels, + model_channels, + out_channels, + num_res_blocks, + attention_resolutions, + dropout=0, + channel_mult=(1, 2, 4, 8), + conv_resample=True, + dims=2, + num_classes=None, + use_checkpoint=False, + use_fp16=False, + num_heads=1, + num_head_channels=-1, + num_heads_upsample=-1, + use_scale_shift_norm=False, + resblock_updown=False, + use_new_attention_order=False, + ): + super().__init__() + + if num_heads_upsample == -1: + num_heads_upsample = num_heads + + self.image_size = image_size + self.in_channels = in_channels + self.model_channels = model_channels + self.out_channels = out_channels + self.num_res_blocks = num_res_blocks + self.attention_resolutions = attention_resolutions + self.dropout = dropout + self.channel_mult = channel_mult + self.conv_resample = conv_resample + self.num_classes = num_classes + self.use_checkpoint = use_checkpoint + self.dtype = th.float16 if use_fp16 else th.float32 + self.num_heads = num_heads + self.num_head_channels = num_head_channels + self.num_heads_upsample = num_heads_upsample + + time_embed_dim = model_channels * 4 + self.time_embed = nn.Sequential( + linear(model_channels, time_embed_dim), + nn.SiLU(), + linear(time_embed_dim, time_embed_dim), + ) + + if self.num_classes is not None: + self.label_emb = nn.Embedding(num_classes, time_embed_dim) + + ch = input_ch = int(channel_mult[0] * model_channels) + self.input_blocks = nn.ModuleList( + [TimestepEmbedSequential(conv_nd(dims, in_channels, ch, 3, padding=1))] + ) + self._feature_size = ch + input_block_chans = [ch] + ds = 1 + for level, mult in enumerate(channel_mult): + for _ in range(num_res_blocks): + layers = [ + ResBlock( + ch, + time_embed_dim, + dropout, + out_channels=int(mult * model_channels), + dims=dims, + use_checkpoint=use_checkpoint, + use_scale_shift_norm=use_scale_shift_norm, + ) + ] + ch = int(mult * model_channels) + if ds in attention_resolutions: + layers.append( + AttentionBlock( + ch, + use_checkpoint=use_checkpoint, + num_heads=num_heads, + num_head_channels=num_head_channels, + use_new_attention_order=use_new_attention_order, + ) + ) + self.input_blocks.append(TimestepEmbedSequential(*layers)) + self._feature_size += ch + input_block_chans.append(ch) + if level != len(channel_mult) - 1: + out_ch = ch + self.input_blocks.append( + TimestepEmbedSequential( + ResBlock( + ch, + time_embed_dim, + dropout, + out_channels=out_ch, + dims=dims, + use_checkpoint=use_checkpoint, + use_scale_shift_norm=use_scale_shift_norm, + down=True, + ) + if resblock_updown + else Downsample( + ch, conv_resample, dims=dims, out_channels=out_ch + ) + ) + ) + ch = out_ch + input_block_chans.append(ch) + ds *= 2 + self._feature_size += ch + + self.middle_block = TimestepEmbedSequential( + ResBlock( + ch, + time_embed_dim, + dropout, + dims=dims, + use_checkpoint=use_checkpoint, + use_scale_shift_norm=use_scale_shift_norm, + ), + AttentionBlock( + ch, + use_checkpoint=use_checkpoint, + num_heads=num_heads, + num_head_channels=num_head_channels, + use_new_attention_order=use_new_attention_order, + ), + ResBlock( + ch, + time_embed_dim, + dropout, + dims=dims, + use_checkpoint=use_checkpoint, + use_scale_shift_norm=use_scale_shift_norm, + ), + ) + self._feature_size += ch + + self.output_blocks = nn.ModuleList([]) + for level, mult in list(enumerate(channel_mult))[::-1]: + for i in range(num_res_blocks + 1): + ich = input_block_chans.pop() + layers = [ + ResBlock( + ch + ich, + time_embed_dim, + dropout, + out_channels=int(model_channels * mult), + dims=dims, + use_checkpoint=use_checkpoint, + use_scale_shift_norm=use_scale_shift_norm, + ) + ] + ch = int(model_channels * mult) + if ds in attention_resolutions: + layers.append( + AttentionBlock( + ch, + use_checkpoint=use_checkpoint, + num_heads=num_heads_upsample, + num_head_channels=num_head_channels, + use_new_attention_order=use_new_attention_order, + ) + ) + if level and i == num_res_blocks: + out_ch = ch + layers.append( + ResBlock( + ch, + time_embed_dim, + dropout, + out_channels=out_ch, + dims=dims, + use_checkpoint=use_checkpoint, + use_scale_shift_norm=use_scale_shift_norm, + up=True, + ) + if resblock_updown + else Upsample(ch, conv_resample, dims=dims, out_channels=out_ch) + ) + ds //= 2 + self.output_blocks.append(TimestepEmbedSequential(*layers)) + self._feature_size += ch + + self.out = nn.Sequential( + normalization(ch), + nn.SiLU(), + zero_module(conv_nd(dims, input_ch, out_channels, 3, padding=1)), + ) + + def convert_to_fp16(self): + """ + Convert the torso of the model to float16. + """ + self.input_blocks.apply(convert_module_to_f16) + self.middle_block.apply(convert_module_to_f16) + self.output_blocks.apply(convert_module_to_f16) + + def convert_to_fp32(self): + """ + Convert the torso of the model to float32. + """ + self.input_blocks.apply(convert_module_to_f32) + self.middle_block.apply(convert_module_to_f32) + self.output_blocks.apply(convert_module_to_f32) + + def forward(self, x, timesteps, y=None): + """ + Apply the model to an input batch. + + :param x: an [N x C x ...] Tensor of inputs. + :param timesteps: a 1-D batch of timesteps. + :param y: an [N] Tensor of labels, if class-conditional. + :return: an [N x C x ...] Tensor of outputs. + """ + assert (y is not None) == ( + self.num_classes is not None + ), "must specify y if and only if the model is class-conditional" + + hs = [] + emb = self.time_embed(timestep_embedding(timesteps, self.model_channels)) + + if self.num_classes is not None: + assert y.shape == (x.shape[0],) + emb = emb + self.label_emb(y) + + h = x.type(self.dtype) + for module in self.input_blocks: + h = module(h, emb) + hs.append(h) + h = self.middle_block(h, emb) + for module in self.output_blocks: + h = th.cat([h, hs.pop()], dim=1) + h = module(h, emb) + h = h.type(x.dtype) + return self.out(h) + + +class SuperResModel(UNetModel): + """ + A UNetModel that performs super-resolution. + + Expects an extra kwarg `low_res` to condition on a low-resolution image. + """ + + def __init__(self, image_size, in_channels, *args, **kwargs): + super().__init__(image_size, in_channels * 2, *args, **kwargs) + + def forward(self, x, timesteps, low_res=None, **kwargs): + _, _, new_height, new_width = x.shape + upsampled = F.interpolate(low_res, (new_height, new_width), mode="bilinear") + x = th.cat([x, upsampled], dim=1) + return super().forward(x, timesteps, **kwargs) + + +class EncoderUNetModel(nn.Module): + """ + The half UNet model with attention and timestep embedding. + + For usage, see UNet. + """ + + def __init__( + self, + image_size, + in_channels, + model_channels, + out_channels, + num_res_blocks, + attention_resolutions, + dropout=0, + channel_mult=(1, 2, 4, 8), + conv_resample=True, + dims=2, + use_checkpoint=False, + use_fp16=False, + num_heads=1, + num_head_channels=-1, + num_heads_upsample=-1, + use_scale_shift_norm=False, + resblock_updown=False, + use_new_attention_order=False, + pool="adaptive", + ): + super().__init__() + + if num_heads_upsample == -1: + num_heads_upsample = num_heads + + self.in_channels = in_channels + self.model_channels = model_channels + self.out_channels = out_channels + self.num_res_blocks = num_res_blocks + self.attention_resolutions = attention_resolutions + self.dropout = dropout + self.channel_mult = channel_mult + self.conv_resample = conv_resample + self.use_checkpoint = use_checkpoint + self.dtype = th.float16 if use_fp16 else th.float32 + self.num_heads = num_heads + self.num_head_channels = num_head_channels + self.num_heads_upsample = num_heads_upsample + + time_embed_dim = model_channels * 4 + self.time_embed = nn.Sequential( + linear(model_channels, time_embed_dim), + nn.SiLU(), + linear(time_embed_dim, time_embed_dim), + ) + + ch = int(channel_mult[0] * model_channels) + self.input_blocks = nn.ModuleList( + [TimestepEmbedSequential(conv_nd(dims, in_channels, ch, 3, padding=1))] + ) + self._feature_size = ch + input_block_chans = [ch] + ds = 1 + for level, mult in enumerate(channel_mult): + for _ in range(num_res_blocks): + layers = [ + ResBlock( + ch, + time_embed_dim, + dropout, + out_channels=int(mult * model_channels), + dims=dims, + use_checkpoint=use_checkpoint, + use_scale_shift_norm=use_scale_shift_norm, + ) + ] + ch = int(mult * model_channels) + if ds in attention_resolutions: + layers.append( + AttentionBlock( + ch, + use_checkpoint=use_checkpoint, + num_heads=num_heads, + num_head_channels=num_head_channels, + use_new_attention_order=use_new_attention_order, + ) + ) + self.input_blocks.append(TimestepEmbedSequential(*layers)) + self._feature_size += ch + input_block_chans.append(ch) + if level != len(channel_mult) - 1: + out_ch = ch + self.input_blocks.append( + TimestepEmbedSequential( + ResBlock( + ch, + time_embed_dim, + dropout, + out_channels=out_ch, + dims=dims, + use_checkpoint=use_checkpoint, + use_scale_shift_norm=use_scale_shift_norm, + down=True, + ) + if resblock_updown + else Downsample( + ch, conv_resample, dims=dims, out_channels=out_ch + ) + ) + ) + ch = out_ch + input_block_chans.append(ch) + ds *= 2 + self._feature_size += ch + + self.middle_block = TimestepEmbedSequential( + ResBlock( + ch, + time_embed_dim, + dropout, + dims=dims, + use_checkpoint=use_checkpoint, + use_scale_shift_norm=use_scale_shift_norm, + ), + AttentionBlock( + ch, + use_checkpoint=use_checkpoint, + num_heads=num_heads, + num_head_channels=num_head_channels, + use_new_attention_order=use_new_attention_order, + ), + ResBlock( + ch, + time_embed_dim, + dropout, + dims=dims, + use_checkpoint=use_checkpoint, + use_scale_shift_norm=use_scale_shift_norm, + ), + ) + self._feature_size += ch + self.pool = pool + if pool == "adaptive": + self.out = nn.Sequential( + normalization(ch), + nn.SiLU(), + nn.AdaptiveAvgPool2d((1, 1)), + zero_module(conv_nd(dims, ch, out_channels, 1)), + nn.Flatten(), + ) + elif pool == "attention": + assert num_head_channels != -1 + self.out = nn.Sequential( + normalization(ch), + nn.SiLU(), + AttentionPool2d( + (image_size // ds), ch, num_head_channels, out_channels + ), + ) + elif pool == "spatial": + self.out = nn.Sequential( + nn.Linear(self._feature_size, 2048), + nn.ReLU(), + nn.Linear(2048, self.out_channels), + ) + elif pool == "spatial_v2": + self.out = nn.Sequential( + nn.Linear(self._feature_size, 2048), + normalization(2048), + nn.SiLU(), + nn.Linear(2048, self.out_channels), + ) + else: + raise NotImplementedError(f"Unexpected {pool} pooling") + + def convert_to_fp16(self): + """ + Convert the torso of the model to float16. + """ + self.input_blocks.apply(convert_module_to_f16) + self.middle_block.apply(convert_module_to_f16) + + def convert_to_fp32(self): + """ + Convert the torso of the model to float32. + """ + self.input_blocks.apply(convert_module_to_f32) + self.middle_block.apply(convert_module_to_f32) + + def forward(self, x, timesteps): + """ + Apply the model to an input batch. + + :param x: an [N x C x ...] Tensor of inputs. + :param timesteps: a 1-D batch of timesteps. + :return: an [N x K] Tensor of outputs. + """ + emb = self.time_embed(timestep_embedding(timesteps, self.model_channels)) + + results = [] + h = x.type(self.dtype) + for module in self.input_blocks: + h = module(h, emb) + if self.pool.startswith("spatial"): + results.append(h.type(x.dtype).mean(dim=(2, 3))) + h = self.middle_block(h, emb) + if self.pool.startswith("spatial"): + results.append(h.type(x.dtype).mean(dim=(2, 3))) + h = th.cat(results, axis=-1) + return self.out(h) + else: + h = h.type(x.dtype) + return self.out(h) diff --git a/case_studies/diffpure/run_scripts/celebahq/run_celebahq_bpda_glasses.sh b/case_studies/diffpure/run_scripts/celebahq/run_celebahq_bpda_glasses.sh new file mode 100644 index 0000000..ff5c80b --- /dev/null +++ b/case_studies/diffpure/run_scripts/celebahq/run_celebahq_bpda_glasses.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for classifier_name in celebahq__Eyeglasses; do + for t in 500; do + for adv_eps in 0.062745098; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0,1,2,3 python eval_sde_adv_bpda.py --exp ./exp_results --config celeba.yml \ + -i celebahq-adv-$t-eps$adv_eps-2x4-disc-bpda-rev \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 2 \ + --domain celebahq \ + --classifier_name $classifier_name \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type celebahq-ddpm \ + --eot_defense_reps 20 \ + --eot_attack_reps 15 \ + + done + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/celebahq/run_celebahq_bpda_smiling.sh b/case_studies/diffpure/run_scripts/celebahq/run_celebahq_bpda_smiling.sh new file mode 100644 index 0000000..147ab07 --- /dev/null +++ b/case_studies/diffpure/run_scripts/celebahq/run_celebahq_bpda_smiling.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for classifier_name in celebahq__Smiling; do + for t in 500; do + for adv_eps in 0.062745098; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0,1,2,3 python eval_sde_adv_bpda.py --exp ./exp_results --config celeba.yml \ + -i celebahq-adv-$t-eps$adv_eps-2x4-disc-bpda-rev \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 2 \ + --domain celebahq \ + --classifier_name $classifier_name \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type celebahq-ddpm \ + --eot_defense_reps 20 \ + --eot_attack_reps 15 \ + + done + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_bpda_eot.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_bpda_eot.sh new file mode 100644 index 0000000..c656bb4 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_bpda_eot.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +SEED1=$1 +SEED2=$2 + +for t in 100; do + for adv_eps in 0.031373; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + PYTHONPATH=$(pwd) python case_studies/diffpure/eval_sde_adv_bpda.py --exp ./case_studies/diffpure/exp_results \ + --config case_studies/diffpure/configs/cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-200x1-bm0-t0-end1e-5-cont-bpda \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 10 \ + --num_sub 200 \ + --domain cifar10 \ + --classifier_name cifar10-wideresnet-28-10 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2.sh new file mode 100644 index 0000000..16b3ea1 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 75; do + for adv_eps in 0.5; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0 python eval_sde_adv.py --exp ./exp_results --config cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-L2-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-wideresnet-28-10 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version rand \ + --eot_iter 20 \ + --lp_norm L2 \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2_70-16-dp.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2_70-16-dp.sh new file mode 100644 index 0000000..75da1fe --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2_70-16-dp.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 75; do + for adv_eps in 0.5; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0 python eval_sde_adv.py --exp ./exp_results --config cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-wres70-16-L2-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-wrn-70-16-dropout \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version rand \ + --eot_iter 20 \ + --lp_norm L2 \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2_rn50_eps1.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2_rn50_eps1.sh new file mode 100644 index 0000000..7393851 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_L2_rn50_eps1.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 125; do + for adv_eps in 1; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0 python eval_sde_adv.py --exp ./exp_results --config cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-L2-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-resnet-50 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version rand \ + --eot_iter 20 \ + --lp_norm L2 \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf.sh new file mode 100644 index 0000000..5392050 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +SEED1=$1 +SEED2=$2 + +for t in 100; do + for adv_eps in 0.031373; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + PYTHONPATH=$(pwd) python case_studies/diffpure/eval_sde_adv.py --exp ./case_studies/diffpure/exp_results \ + --config ./case_studies/diffpure/configs/cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 5 \ + --domain cifar10 \ + --classifier_name cifar10-wideresnet-28-10 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version rand \ + --eot_iter 20 \ + --batch-size 512 \ + --n_boundary_points=1 \ + --n_inner_points=999 + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_70-16-dp.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_70-16-dp.sh new file mode 100644 index 0000000..c10b52f --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_70-16-dp.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +SEED1=$1 +SEED2=$2 + +for t in 100; do + for adv_eps in 0.031373; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + PYTHONPATH=$(pwd) python case_studies/diffpure/eval_sde_adv.py --exp ./case_studies/diffpure/exp_results \ + --config case_studies/diffpure/configs/cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-wres70-16-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-wrn-70-16-dropout \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version rand \ + --eot_iter 20 + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_binarization_test.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_binarization_test.sh new file mode 100644 index 0000000..4567569 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_binarization_test.sh @@ -0,0 +1,27 @@ +seed=$1 +data_seed=$2 +sample_idx_start=$3 +sample_idx_end=$4 + +t=100 +adv_eps=0.031373 + +PYTHONPATH=$(pwd) python -u case_studies/diffpure/eval_sde_adv.py --exp ./case_studies/diffpure/exp_results \ + --config ./case_studies/diffpure/configs/cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 5 \ + --domain cifar10 \ + --classifier_name cifar10-wideresnet-28-10 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version rand \ + --eot_iter 20 \ + --batch-size 512 \ + --test-samples-idx-start=$sample_idx_start \ + --test-samples-idx-end=$sample_idx_end \ + --binarization-test \ No newline at end of file diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_rn50.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_rn50.sh new file mode 100644 index 0000000..40c2d71 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_rn50.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +SEED1=$1 +SEED2=$2 + +for t in 125; do + for adv_eps in 0.031373; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + PYTHONPATH=$(pwd) python case_studies/diffpure/eval_sde_adv.py --exp ./case_studies/diffpure/exp_results \ + --config case_studies/diffpure/configs/cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-resnet-50 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version rand \ + --eot_iter 20 + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_stadv_rn50.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stadv_rn50.sh new file mode 100644 index 0000000..b40917d --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stadv_rn50.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 125; do + for adv_eps in 0.05; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0 python eval_sde_adv.py --exp ./exp_results --config cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-stadv-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-resnet-50 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version stadv \ + --eot_iter 20 + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2.sh new file mode 100644 index 0000000..181deba --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 75; do + for adv_eps in 0.5; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0 python eval_sde_adv.py --exp ./exp_results --config cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-L2 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-wideresnet-28-10 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version standard \ + --lp_norm L2 \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2_70-16-dp.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2_70-16-dp.sh new file mode 100644 index 0000000..35338b8 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2_70-16-dp.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 75; do + for adv_eps in 0.5; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0 python eval_sde_adv.py --exp ./exp_results --config cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-L2-wres70-16 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-wrn-70-16-dropout \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version standard \ + --lp_norm L2 \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2_rn50_eps1.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2_rn50_eps1.sh new file mode 100644 index 0000000..f2f8d94 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_L2_rn50_eps1.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 125; do + for adv_eps in 1; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0 python eval_sde_adv.py --exp ./exp_results --config cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-L2 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-resnet-50 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version standard \ + --lp_norm L2 \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf.sh new file mode 100644 index 0000000..c6ebfc0 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 100; do + for adv_eps in 0.031373; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0 python eval_sde_adv.py --exp ./exp_results --config cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-wideresnet-28-10 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version standard \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf_70-16-dp.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf_70-16-dp.sh new file mode 100644 index 0000000..59e4a70 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf_70-16-dp.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 100; do + for adv_eps in 0.031373; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0 python eval_sde_adv.py --exp ./exp_results --config cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont-wres70-16 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-wrn-70-16-dropout \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version standard \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf_rn50.sh b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf_rn50.sh new file mode 100644 index 0000000..cae45d0 --- /dev/null +++ b/case_studies/diffpure/run_scripts/cifar10/run_cifar_stand_inf_rn50.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 125; do + for adv_eps in 0.031373; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0 python eval_sde_adv.py --exp ./exp_results --config cifar10.yml \ + -i cifar10-robust_adv-$t-eps$adv_eps-64x1-bm0-t0-end1e-5-cont \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 64 \ + --num_sub 64 \ + --domain cifar10 \ + --classifier_name cifar10-resnet-50 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --score_type score_sde \ + --attack_version standard \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf.sh b/case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf.sh new file mode 100644 index 0000000..eace779 --- /dev/null +++ b/case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 150; do + for adv_eps in 0.0157; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0,1,2,3 python eval_sde_adv.py --exp ./exp_results --config imagenet.yml \ + -i imagenet-robust_adv-$t-eps$adv_eps-4x4-bm0-t0-end1e-5-cont-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 4 \ + --num_sub 16 \ + --domain imagenet \ + --classifier_name imagenet-resnet50 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --attack_version rand \ + --eot_iter 20 + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf_50-2.sh b/case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf_50-2.sh new file mode 100644 index 0000000..6aab2d8 --- /dev/null +++ b/case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf_50-2.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 150; do + for adv_eps in 0.0157; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0,1,2,3 python eval_sde_adv.py --exp ./exp_results --config imagenet.yml \ + -i imagenet-robust_adv-$t-eps$adv_eps-4x4-bm0-t0-end1e-5-cont-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 4 \ + --num_sub 16 \ + --domain imagenet \ + --classifier_name imagenet-wideresnet-50-2 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --attack_version rand \ + --eot_iter 20 + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf_deits.sh b/case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf_deits.sh new file mode 100644 index 0000000..e46ec4d --- /dev/null +++ b/case_studies/diffpure/run_scripts/imagenet/run_in_rand_inf_deits.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 150; do + for adv_eps in 0.0157; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0,1,2,3 python eval_sde_adv.py --exp ./exp_results --config imagenet.yml \ + -i imagenet-robust_adv-$t-eps$adv_eps-4x4-bm0-t0-end1e-5-cont-eot20 \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 4 \ + --num_sub 16 \ + --domain imagenet \ + --classifier_name imagenet-deit-s \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --attack_version rand \ + --eot_iter 20 + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf.sh b/case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf.sh new file mode 100644 index 0000000..fe42784 --- /dev/null +++ b/case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 150; do + for adv_eps in 0.0157; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0,1,2,3 python eval_sde_adv.py --exp ./exp_results --config imagenet.yml \ + -i imagenet-robust_adv-$t-eps$adv_eps-4x4-bm0-t0-end1e-5-cont \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 4 \ + --num_sub 16 \ + --domain imagenet \ + --classifier_name imagenet-resnet50 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --attack_version standard \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf_50-2.sh b/case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf_50-2.sh new file mode 100644 index 0000000..b17c1de --- /dev/null +++ b/case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf_50-2.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 150; do + for adv_eps in 0.0157; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0,1,2,3 python eval_sde_adv.py --exp ./exp_results --config imagenet.yml \ + -i imagenet-robust_adv-$t-eps$adv_eps-4x4-bm0-t0-end1e-5-cont \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 4 \ + --num_sub 16 \ + --domain imagenet \ + --classifier_name imagenet-wideresnet-50-2 \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --attack_version standard \ + + done + done + done +done diff --git a/case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf_deits.sh b/case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf_deits.sh new file mode 100644 index 0000000..17337fd --- /dev/null +++ b/case_studies/diffpure/run_scripts/imagenet/run_in_stand_inf_deits.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +cd ../.. + +SEED1=$1 +SEED2=$2 + +for t in 150; do + for adv_eps in 0.0157; do + for seed in $SEED1; do + for data_seed in $SEED2; do + + CUDA_VISIBLE_DEVICES=0,1,2,3 python eval_sde_adv.py --exp ./exp_results --config imagenet.yml \ + -i imagenet-robust_adv-$t-eps$adv_eps-4x4-bm0-t0-end1e-5-cont \ + --t $t \ + --adv_eps $adv_eps \ + --adv_batch_size 4 \ + --num_sub 16 \ + --domain imagenet \ + --classifier_name imagenet-deit-s \ + --seed $seed \ + --data_seed $data_seed \ + --diffusion_type sde \ + --attack_version standard \ + + done + done + done +done diff --git a/case_studies/diffpure/runners/diffpure_ddpm.py b/case_studies/diffpure/runners/diffpure_ddpm.py new file mode 100644 index 0000000..4b88a44 --- /dev/null +++ b/case_studies/diffpure/runners/diffpure_ddpm.py @@ -0,0 +1,142 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import os +import random + +import numpy as np + +import torch +import torchvision.utils as tvu + +from ddpm.unet_ddpm import Model + + +def get_beta_schedule(*, beta_start, beta_end, num_diffusion_timesteps): + betas = np.linspace(beta_start, beta_end, + num_diffusion_timesteps, dtype=np.float64) + assert betas.shape == (num_diffusion_timesteps,) + return betas + + +def extract(a, t, x_shape): + """Extract coefficients from a based on t and reshape to make it + broadcastable with x_shape.""" + bs, = t.shape + assert x_shape[0] == bs + out = torch.gather(torch.tensor(a, dtype=torch.float, device=t.device), 0, t.long()) + assert out.shape == (bs,) + out = out.reshape((bs,) + (1,) * (len(x_shape) - 1)) + return out + + +def image_editing_denoising_step_flexible_mask(x, t, *, model, logvar, betas): + """ + Sample from p(x_{t-1} | x_t) + """ + alphas = 1.0 - betas + alphas_cumprod = alphas.cumprod(dim=0) + + model_output = model(x, t) + weighted_score = betas / torch.sqrt(1 - alphas_cumprod) + mean = extract(1 / torch.sqrt(alphas), t, x.shape) * (x - extract(weighted_score, t, x.shape) * model_output) + + logvar = extract(logvar, t, x.shape) + noise = torch.randn_like(x) + mask = 1 - (t == 0).float() + mask = mask.reshape((x.shape[0],) + (1,) * (len(x.shape) - 1)) + sample = mean + mask * torch.exp(0.5 * logvar) * noise + sample = sample.float() + return sample + + +class Diffusion(torch.nn.Module): + def __init__(self, args, config, device=None): + super().__init__() + self.args = args + self.config = config + if device is None: + device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") + self.device = device + + print("Loading model") + if self.config.data.dataset == "CelebA_HQ": + url = "https://image-editing-test-12345.s3-us-west-2.amazonaws.com/checkpoints/celeba_hq.ckpt" + else: + raise ValueError + + model = Model(self.config) + ckpt = torch.hub.load_state_dict_from_url(url, map_location='cpu') + model.load_state_dict(ckpt) + model.eval() + + self.model = model + + self.model_var_type = config.model.var_type + betas = get_beta_schedule( + beta_start=config.diffusion.beta_start, + beta_end=config.diffusion.beta_end, + num_diffusion_timesteps=config.diffusion.num_diffusion_timesteps + ) + self.betas = torch.from_numpy(betas).float() + self.num_timesteps = betas.shape[0] + + alphas = 1.0 - betas + alphas_cumprod = np.cumprod(alphas, axis=0) + alphas_cumprod_prev = np.append(1.0, alphas_cumprod[:-1]) + posterior_variance = betas * \ + (1.0 - alphas_cumprod_prev) / (1.0 - alphas_cumprod) + if self.model_var_type == "fixedlarge": + self.logvar = np.log(np.append(posterior_variance[1], betas[1:])) + + elif self.model_var_type == 'fixedsmall': + self.logvar = np.log(np.maximum(posterior_variance, 1e-20)) + + def image_editing_sample(self, img=None, bs_id=0, tag=None): + assert isinstance(img, torch.Tensor) + batch_size = img.shape[0] + + with torch.no_grad(): + if tag is None: + tag = 'rnd' + str(random.randint(0, 10000)) + out_dir = os.path.join(self.args.log_dir, 'bs' + str(bs_id) + '_' + tag) + + assert img.ndim == 4, img.ndim + x0 = img + + if bs_id < 2: + os.makedirs(out_dir, exist_ok=True) + tvu.save_image((x0 + 1) * 0.5, os.path.join(out_dir, f'original_input.png')) + + xs = [] + for it in range(self.args.sample_step): + e = torch.randn_like(x0) + total_noise_levels = self.args.t + a = (1 - self.betas).cumprod(dim=0).to(x0.device) + x = x0 * a[total_noise_levels - 1].sqrt() + e * (1.0 - a[total_noise_levels - 1]).sqrt() + + if bs_id < 2: + tvu.save_image((x + 1) * 0.5, os.path.join(out_dir, f'init_{it}.png')) + + for i in reversed(range(total_noise_levels)): + t = torch.tensor([i] * batch_size, device=img.device) + x = image_editing_denoising_step_flexible_mask(x, t=t, model=self.model, + logvar=self.logvar, + betas=self.betas.to(img.device)) + # added intermediate step vis + if (i - 49) % 50 == 0 and bs_id < 2: + tvu.save_image((x + 1) * 0.5, os.path.join(out_dir, f'noise_t_{i}_{it}.png')) + + x0 = x + + if bs_id < 2: + torch.save(x0, os.path.join(out_dir, f'samples_{it}.pth')) + tvu.save_image((x0 + 1) * 0.5, os.path.join(out_dir, f'samples_{it}.png')) + + xs.append(x0) + + return torch.cat(xs, dim=0) diff --git a/case_studies/diffpure/runners/diffpure_guided.py b/case_studies/diffpure/runners/diffpure_guided.py new file mode 100644 index 0000000..eb0eaf4 --- /dev/null +++ b/case_studies/diffpure/runners/diffpure_guided.py @@ -0,0 +1,89 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import os +import random + +import torch +import torchvision.utils as tvu + +from guided_diffusion.script_util import create_model_and_diffusion, model_and_diffusion_defaults + + +class GuidedDiffusion(torch.nn.Module): + def __init__(self, args, config, device=None, model_dir='checkpoints/diffpure/guided_diffusion'): + super().__init__() + self.args = args + self.config = config + if device is None: + device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") + self.device = device + + # load model + model_config = model_and_diffusion_defaults() + model_config.update(vars(self.config.model)) + print(f'model_config: {model_config}') + model, diffusion = create_model_and_diffusion(**model_config) + model.load_state_dict(torch.load(f'{model_dir}/256x256_diffusion_uncond.pt', map_location='cpu')) + model.requires_grad_(False).eval().to(self.device) + + if model_config['use_fp16']: + model.convert_to_fp16() + + self.model = model + self.diffusion = diffusion + self.betas = torch.from_numpy(diffusion.betas).float().to(self.device) + + def image_editing_sample(self, img, bs_id=0, tag=None): + with torch.no_grad(): + assert isinstance(img, torch.Tensor) + batch_size = img.shape[0] + + if tag is None: + tag = 'rnd' + str(random.randint(0, 10000)) + out_dir = os.path.join(self.args.log_dir, 'bs' + str(bs_id) + '_' + tag) + + assert img.ndim == 4, img.ndim + img = img.to(self.device) + x0 = img + + if bs_id < 2: + os.makedirs(out_dir, exist_ok=True) + tvu.save_image((x0 + 1) * 0.5, os.path.join(out_dir, f'original_input.png')) + + xs = [] + for it in range(self.args.sample_step): + e = torch.randn_like(x0) + total_noise_levels = self.args.t + a = (1 - self.betas).cumprod(dim=0) + x = x0 * a[total_noise_levels - 1].sqrt() + e * (1.0 - a[total_noise_levels - 1]).sqrt() + + if bs_id < 2: + tvu.save_image((x + 1) * 0.5, os.path.join(out_dir, f'init_{it}.png')) + + for i in reversed(range(total_noise_levels)): + t = torch.tensor([i] * batch_size, device=self.device) + + x = self.diffusion.p_sample(self.model, x, t, + clip_denoised=True, + denoised_fn=None, + cond_fn=None, + model_kwargs=None)["sample"] + + # added intermediate step vis + if (i - 99) % 100 == 0 and bs_id < 2: + tvu.save_image((x + 1) * 0.5, os.path.join(out_dir, f'noise_t_{i}_{it}.png')) + + x0 = x + + if bs_id < 2: + torch.save(x0, os.path.join(out_dir, f'samples_{it}.pth')) + tvu.save_image((x0 + 1) * 0.5, os.path.join(out_dir, f'samples_{it}.png')) + + xs.append(x0) + + return torch.cat(xs, dim=0) diff --git a/case_studies/diffpure/runners/diffpure_ldsde.py b/case_studies/diffpure/runners/diffpure_ldsde.py new file mode 100644 index 0000000..49c3882 --- /dev/null +++ b/case_studies/diffpure/runners/diffpure_ldsde.py @@ -0,0 +1,252 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import os +import random +import numpy as np + +import torch +import torchvision.utils as tvu +import torchsde + +from guided_diffusion.script_util import create_model_and_diffusion, model_and_diffusion_defaults +from score_sde.losses import get_optimizer +from score_sde.models import utils as mutils +from score_sde.models.ema import ExponentialMovingAverage +from score_sde import sde_lib + + +def _extract_into_tensor(arr_or_func, timesteps, broadcast_shape): + """ + Extract values from a 1-D numpy array for a batch of indices. + + :param arr: the 1-D numpy array or a func. + :param timesteps: a tensor of indices into the array to extract. + :param broadcast_shape: a larger shape of K dimensions with the batch + dimension equal to the length of timesteps. + :return: a tensor of shape [batch_size, 1, ...] where the shape has K dims. + """ + if callable(arr_or_func): + res = arr_or_func(timesteps).float() + else: + res = arr_or_func.to(device=timesteps.device)[timesteps].float() + while len(res.shape) < len(broadcast_shape): + res = res[..., None] + return res.expand(broadcast_shape) + + +def restore_checkpoint(ckpt_dir, state, device): + loaded_state = torch.load(ckpt_dir, map_location=device) + state['optimizer'].load_state_dict(loaded_state['optimizer']) + state['model'].load_state_dict(loaded_state['model'], strict=False) + state['ema'].load_state_dict(loaded_state['ema']) + state['step'] = loaded_state['step'] + + +class LDSDE(torch.nn.Module): + def __init__(self, model, x_init, score_type='guided_diffusion', beta_min=0.1, beta_max=20, N=1000, + img_shape=(3, 256, 256), sigma2=0.001, lambda_ld=0.01, eta=5, model_kwargs=None): + """Construct a Variance Preserving SDE. + + Args: + model: diffusion model + score_type: [guided_diffusion, score_sde, ddpm] + beta_min: value of beta(0) + beta_max: value of beta(1) + """ + super().__init__() + self.model = model + self.x_init = x_init + self.sigma2 = sigma2 + self.eta = eta + self.lambda_ld = lambda_ld # damping coefficient + self.score_type = score_type + self.model_kwargs = model_kwargs + self.img_shape = img_shape + + self.beta_0 = beta_min + self.beta_1 = beta_max + self.N = N + self.discrete_betas = torch.linspace(beta_min / N, beta_max / N, N) + self.alphas = 1. - self.discrete_betas + self.alphas_cumprod = torch.cumprod(self.alphas, dim=0) + self.sqrt_alphas_cumprod = torch.sqrt(self.alphas_cumprod) + self.sqrt_1m_alphas_cumprod = torch.sqrt(1. - self.alphas_cumprod) + + self.alphas_cumprod_cont = lambda t: torch.exp(-0.5 * (beta_max - beta_min) * t**2 - beta_min * t) + self.sqrt_1m_alphas_cumprod_neg_recip_cont = lambda t: -1. / torch.sqrt(1. - self.alphas_cumprod_cont(t)) + + self.noise_type = "diagonal" + self.sde_type = "ito" + + print(f'sigma2: {self.sigma2}, lambda_ld: {self.lambda_ld}, eta: {self.eta}') + + def _scale_timesteps(self, t): + assert torch.all(t <= 1) and torch.all(t >= 0), f't has to be in [0, 1], but get {t} with shape {t.shape}' + return (t.float() * self.N).long() + + def ldsde_fn(self, t, x, return_type='drift'): + """Create the drift and diffusion functions for the reverse SDE""" + t = torch.zeros_like(t, dtype=torch.float, device=t.device) + 1e-2 + + if return_type == 'drift': + + assert x.ndim == 2 and np.prod(self.img_shape) == x.shape[1], x.shape + x_img = x.view(-1, *self.img_shape) + + if self.score_type == 'guided_diffusion': + # model output is epsilon + if self.model_kwargs is None: + self.model_kwargs = {} + + disc_steps = self._scale_timesteps(t) # (batch_size, ), from float in [0,1] to int in [0, 1000] + model_output = self.model(x_img, disc_steps, **self.model_kwargs) + # with learned sigma, so model_output contains (mean, val) + model_output, _ = torch.split(model_output, self.img_shape[0], dim=1) + assert x_img.shape == model_output.shape, f'{x_img.shape}, {model_output.shape}' + model_output = model_output.view(x.shape[0], -1) + score = _extract_into_tensor(self.sqrt_1m_alphas_cumprod_neg_recip_cont, t, x.shape) * model_output + + elif self.score_type == 'score_sde': + # model output is epsilon + sde = sde_lib.VPSDE(beta_min=self.beta_0, beta_max=self.beta_1, N=self.N) + score_fn = mutils.get_score_fn(sde, self.model, train=False, continuous=True) + score = score_fn(x_img, t) + assert x_img.shape == score.shape, f'{x_img.shape}, {score.shape}' + score = score.view(x.shape[0], -1) + + else: + raise NotImplementedError(f'Unknown score type in RevVPSDE: {self.score_type}!') + + drift = -0.5 * (-score + (x - self.x_init) / self.sigma2) * self.lambda_ld # TODO + return drift + + else: + diffusion_coef = np.sqrt(self.lambda_ld) * self.eta + return torch.tensor([diffusion_coef], dtype=torch.float).expand(x.shape[0]).to(x.device) + + def f(self, t, x): + """Create the drift function f(x, t) + sdeint only support a 2D tensor (batch_size, c*h*w) + """ + t = t.expand(x.shape[0]) # (batch_size, ) + drift = self.ldsde_fn(t, x, return_type='drift') + assert drift.shape == x.shape + return drift + + def g(self, t, x): + """Create the diffusion function g(t) + sdeint only support a 2D tensor (batch_size, c*h*w) + """ + t = t.expand(x.shape[0]) # (batch_size, ) + diffusion = self.ldsde_fn(t, x, return_type='diffusion') + assert diffusion.shape == (x.shape[0], ) + return diffusion[:, None].expand(x.shape) + + +class LDGuidedDiffusion(torch.nn.Module): + def __init__(self, args, config, device=None): + super().__init__() + self.args = args + self.config = config + if device is None: + device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") + self.device = device + + # load model + if config.data.dataset == 'ImageNet': + img_shape = (3, 256, 256) + model_dir = 'checkpoints/diffpure/guided_diffusion' + model_config = model_and_diffusion_defaults() + model_config.update(vars(self.config.model)) + print(f'model_config: {model_config}') + model, _ = create_model_and_diffusion(**model_config) + model.load_state_dict(torch.load(f'{model_dir}/256x256_diffusion_uncond.pt', map_location='cpu')) + + if model_config['use_fp16']: + model.convert_to_fp16() + + elif config.data.dataset == 'CIFAR10': + img_shape = (3, 32, 32) + model_dir = 'checkpoints/diffpure/score_sde' + print(f'model_config: {config}') + model = mutils.create_model(config) + + optimizer = get_optimizer(config, model.parameters()) + ema = ExponentialMovingAverage(model.parameters(), decay=config.model.ema_rate) + state = dict(step=0, optimizer=optimizer, model=model, ema=ema) + restore_checkpoint(f'{model_dir}/checkpoint_8.pth', state, device) + ema.copy_to(model.parameters()) + + else: + raise NotImplementedError(f'Unknown dataset {config.data.dataset}!') + + model.eval().to(self.device) + + self.model = model + self.img_shape = img_shape + + print(f'use_bm: {args.use_bm}') + + self.args_dict = { + 'method': 'euler', # ["srk", "euler", None] + 'adaptive': False, + 'dt': 1e-2, + } + + print(f'args_dict: {self.args_dict}') + + def image_editing_sample(self, img, bs_id=0, tag=None): + assert isinstance(img, torch.Tensor) + batch_size = img.shape[0] + state_size = int(np.prod(img.shape[1:])) # c*h*w + + if tag is None: + tag = 'rnd' + str(random.randint(0, 10000)) + out_dir = os.path.join(self.args.log_dir, 'bs' + str(bs_id) + '_' + tag) + + assert img.ndim == 4, img.ndim + img = img.to(self.device) + x0 = img + + x0_ = x0.view(batch_size, -1) # (batch_size, state_size) + self.ldsde = LDSDE(model=self.model, x_init=x0_, score_type=self.args.score_type, img_shape=self.img_shape, + sigma2=self.args.sigma2, lambda_ld=self.args.lambda_ld, eta=self.args.eta, + model_kwargs=None).to(self.device) + self.betas = self.ldsde.discrete_betas.float().to(self.device) + + if bs_id < 2: + os.makedirs(out_dir, exist_ok=True) + tvu.save_image((x0 + 1) * 0.5, os.path.join(out_dir, f'original_input.png')) + + xs = [] + for it in range(self.args.sample_step): + x = x0 + + if bs_id < 2: + tvu.save_image((x + 1) * 0.5, os.path.join(out_dir, f'init_{it}.png')) + + epsilon_dt0, epsilon_dt1 = 0, 1e-5 + t0, t1 = 1 - self.args.t * 1. / 1000 + epsilon_dt0, 1 - epsilon_dt1 + t_size = 2 + ts = torch.linspace(t0, t1, t_size).to(self.device) + + x_ = x.view(batch_size, -1) # (batch_size, state_size) + if self.args.use_bm: + bm = torchsde.BrownianInterval(t0=t0, t1=t1, size=(batch_size, state_size), device=self.device) + xs_ = torchsde.sdeint_adjoint(self.ldsde, x_, ts, bm=bm, **self.args_dict) + else: + xs_ = torchsde.sdeint_adjoint(self.ldsde, x_, ts, **self.args_dict) + x0 = xs_[-1].view(x.shape) # (batch_size, c, h, w) + + if bs_id < 2: + torch.save(x0, os.path.join(out_dir, f'samples_{it}.pth')) + tvu.save_image((x0 + 1) * 0.5, os.path.join(out_dir, f'samples_{it}.png')) + + xs.append(x0) + + return torch.cat(xs, dim=0) diff --git a/case_studies/diffpure/runners/diffpure_ode.py b/case_studies/diffpure/runners/diffpure_ode.py new file mode 100644 index 0000000..9f0217b --- /dev/null +++ b/case_studies/diffpure/runners/diffpure_ode.py @@ -0,0 +1,249 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import os +import random +import numpy as np + +import torch +import torchvision.utils as tvu + +from torchdiffeq import odeint_adjoint + +from guided_diffusion.script_util import create_model_and_diffusion, model_and_diffusion_defaults +from score_sde.losses import get_optimizer +from score_sde.models import utils as mutils +from score_sde.models.ema import ExponentialMovingAverage +from score_sde import sde_lib + + +def _extract_into_tensor(arr_or_func, timesteps, broadcast_shape): + """ + Extract values from a 1-D numpy array for a batch of indices. + + :param arr: the 1-D numpy array or a func. + :param timesteps: a tensor of indices into the array to extract. + :param broadcast_shape: a larger shape of K dimensions with the batch + dimension equal to the length of timesteps. + :return: a tensor of shape [batch_size, 1, ...] where the shape has K dims. + """ + if callable(arr_or_func): + res = arr_or_func(timesteps).float() + else: + res = arr_or_func.to(device=timesteps.device)[timesteps].float() + while len(res.shape) < len(broadcast_shape): + res = res[..., None] + return res.expand(broadcast_shape) + + +def restore_checkpoint(ckpt_dir, state, device): + loaded_state = torch.load(ckpt_dir, map_location=device) + state['optimizer'].load_state_dict(loaded_state['optimizer']) + state['model'].load_state_dict(loaded_state['model'], strict=False) + state['ema'].load_state_dict(loaded_state['ema']) + state['step'] = loaded_state['step'] + + +class VPODE(torch.nn.Module): + def __init__(self, model, score_type='guided_diffusion', beta_min=0.1, beta_max=20, N=1000, + img_shape=(3, 256, 256), model_kwargs=None): + """Construct a Variance Preserving SDE. + + Args: + model: diffusion model + score_type: [guided_diffusion, score_sde, ddpm] + beta_min: value of beta(0) + beta_max: value of beta(1) + """ + super().__init__() + self.model = model + self.score_type = score_type + self.model_kwargs = model_kwargs + self.img_shape = img_shape + + self.beta_0 = beta_min + self.beta_1 = beta_max + self.N = N + self.discrete_betas = torch.linspace(beta_min / N, beta_max / N, N) + self.alphas = 1. - self.discrete_betas + self.alphas_cumprod = torch.cumprod(self.alphas, dim=0) + self.sqrt_alphas_cumprod = torch.sqrt(self.alphas_cumprod) + self.sqrt_1m_alphas_cumprod = torch.sqrt(1. - self.alphas_cumprod) + + self.alphas_cumprod_cont = lambda t: torch.exp(-0.5 * (beta_max - beta_min) * t**2 - beta_min * t) + self.sqrt_1m_alphas_cumprod_neg_recip_cont = lambda t: -1. / torch.sqrt(1. - self.alphas_cumprod_cont(t)) + + def _scale_timesteps(self, t): + assert torch.all(t <= 1) and torch.all(t >= 0), f't has to be in [0, 1], but get {t} with shape {t.shape}' + return (t.float() * self.N).long() + + def vpsde_fn(self, t, x): + beta_t = self.beta_0 + t * (self.beta_1 - self.beta_0) + drift = -0.5 * beta_t[:, None] * x + diffusion = torch.sqrt(beta_t) + return drift, diffusion + + def ode_fn(self, t, x): + """Create the drift and diffusion functions for the reverse SDE""" + drift, diffusion = self.vpsde_fn(t, x) + + assert x.ndim == 2 and np.prod(self.img_shape) == x.shape[1], x.shape + x_img = x.view(-1, *self.img_shape) + + if self.score_type == 'guided_diffusion': + # model output is epsilon + if self.model_kwargs is None: + self.model_kwargs = {} + + disc_steps = self._scale_timesteps(t) # (batch_size, ), from float in [0,1] to int in [0, 1000] + model_output = self.model(x_img, disc_steps, **self.model_kwargs) + # with learned sigma, so model_output contains (mean, val) + model_output, _ = torch.split(model_output, self.img_shape[0], dim=1) + assert x_img.shape == model_output.shape, f'{x_img.shape}, {model_output.shape}' + model_output = model_output.view(x.shape[0], -1) + score = _extract_into_tensor(self.sqrt_1m_alphas_cumprod_neg_recip_cont, t, x.shape) * model_output + + elif self.score_type == 'score_sde': + # model output is epsilon + sde = sde_lib.VPSDE(beta_min=self.beta_0, beta_max=self.beta_1, N=self.N) + score_fn = mutils.get_score_fn(sde, self.model, train=False, continuous=True) + score = score_fn(x_img, t) + assert x_img.shape == score.shape, f'{x_img.shape}, {score.shape}' + score = score.view(x.shape[0], -1) + + else: + raise NotImplementedError(f'Unknown score type in RevVPSDE: {self.score_type}!') + + ode_coef = drift - 0.5 * diffusion[:, None] ** 2 * score + return ode_coef + + def forward(self, t, states): + x = states[0] + + t = t.expand(x.shape[0]) # (batch_size, ) + dx_dt = self.ode_fn(t, x) + assert dx_dt.shape == x.shape + + return dx_dt, + + +class OdeGuidedDiffusion(torch.nn.Module): + def __init__(self, args, config, device=None): + super().__init__() + self.args = args + self.config = config + if device is None: + device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") + self.device = device + + # load model + if config.data.dataset == 'ImageNet': + img_shape = (3, 256, 256) + model_dir = 'checkpoints/diffpure/guided_diffusion' + model_config = model_and_diffusion_defaults() + model_config.update(vars(self.config.model)) + print(f'model_config: {model_config}') + model, _ = create_model_and_diffusion(**model_config) + model.load_state_dict(torch.load(f'{model_dir}/256x256_diffusion_uncond.pt', map_location='cpu')) + + if model_config['use_fp16']: + model.convert_to_fp16() + + elif config.data.dataset == 'CIFAR10': + img_shape = (3, 32, 32) + model_dir = 'checkpoints/diffpure/score_sde' + print(f'model_config: {config}') + model = mutils.create_model(config) + + optimizer = get_optimizer(config, model.parameters()) + ema = ExponentialMovingAverage(model.parameters(), decay=config.model.ema_rate) + state = dict(step=0, optimizer=optimizer, model=model, ema=ema) + restore_checkpoint(f'{model_dir}/checkpoint_8.pth', state, device) + ema.copy_to(model.parameters()) + + else: + raise NotImplementedError(f'Unknown dataset {config.data.dataset}!') + + model.eval().to(self.device) + + self.model = model + self.vpode = VPODE(model=model, score_type=args.score_type, img_shape=img_shape, + model_kwargs=None).to(self.device) + self.betas = self.vpode.discrete_betas.float().to(self.device) + + self.atol, self.rtol = 1e-3, 1e-3 + self.method = 'euler' + + print(f'method: {self.method}, atol: {self.atol}, rtol: {self.rtol}, step_size: {self.args.step_size}') + + def image_editing_sample(self, img, bs_id=0, tag=None): + assert isinstance(img, torch.Tensor) + batch_size = img.shape[0] + + if tag is None: + tag = 'rnd' + str(random.randint(0, 10000)) + out_dir = os.path.join(self.args.log_dir, 'bs' + str(bs_id) + '_' + tag) + + assert img.ndim == 4, img.ndim + img = img.to(self.device) + x0 = img + + if bs_id < 2: + os.makedirs(out_dir, exist_ok=True) + tvu.save_image((x0 + 1) * 0.5, os.path.join(out_dir, f'original_input.png')) + + xs = [] + for it in range(self.args.sample_step): + + if self.args.fix_rand: + # fix initial randomness + noise_fixed = torch.FloatTensor(1, *x0.shape[1:]).\ + normal_(0, 1, generator=torch.manual_seed(self.args.seed)).to(self.device) + print(f'noise_fixed: {noise_fixed[0, 0, 0, :3]}') + e = noise_fixed.repeat(x0.shape[0], 1, 1, 1) + else: + e = torch.randn_like(x0).to(self.device) + + assert e.shape == x0.shape + + total_noise_levels = self.args.t + a = (1 - self.betas).cumprod(dim=0).to(self.device) + x = x0 * a[total_noise_levels - 1].sqrt() + e * (1.0 - a[total_noise_levels - 1]).sqrt() + + if bs_id < 2: + tvu.save_image((x + 1) * 0.5, os.path.join(out_dir, f'init_{it}.png')) + + epsilon_dt0, epsilon_dt1 = 0, 1e-5 + t0, t1 = self.args.t * 1. / 1000 - epsilon_dt0, epsilon_dt1 + t_size = 2 + ts = torch.linspace(t0, t1, t_size).to(self.device) + + x_ = x.view(batch_size, -1) # (batch_size, state_size) + states = (x_, ) + + # ODE solver + odeint = odeint_adjoint + state_t = odeint( + self.vpode, + states, + ts, + atol=self.atol, + rtol=self.rtol, + method=self.method, + options=None if self.method != 'euler' else dict(step_size=self.args.step_size) # only used for fixed-point method + ) # 'euler', 'dopri5' + + x0_ = state_t[0][-1] + x0 = x0_.view(x.shape) # (batch_size, c, h, w) + + if bs_id < 2: + torch.save(x0, os.path.join(out_dir, f'samples_{it}.pth')) + tvu.save_image((x0 + 1) * 0.5, os.path.join(out_dir, f'samples_{it}.png')) + + xs.append(x0) + + return torch.cat(xs, dim=0) diff --git a/case_studies/diffpure/runners/diffpure_sde.py b/case_studies/diffpure/runners/diffpure_sde.py new file mode 100644 index 0000000..882aef0 --- /dev/null +++ b/case_studies/diffpure/runners/diffpure_sde.py @@ -0,0 +1,247 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import os +import random +import numpy as np + +import torch +import torchvision.utils as tvu +import torchsde + +from guided_diffusion.script_util import create_model_and_diffusion, model_and_diffusion_defaults +from score_sde.losses import get_optimizer +from score_sde.models import utils as mutils +from score_sde.models.ema import ExponentialMovingAverage +from score_sde import sde_lib + + +def _extract_into_tensor(arr_or_func, timesteps, broadcast_shape): + """ + Extract values from a 1-D numpy array for a batch of indices. + + :param arr: the 1-D numpy array or a func. + :param timesteps: a tensor of indices into the array to extract. + :param broadcast_shape: a larger shape of K dimensions with the batch + dimension equal to the length of timesteps. + :return: a tensor of shape [batch_size, 1, ...] where the shape has K dims. + """ + if callable(arr_or_func): + res = arr_or_func(timesteps).float() + else: + res = arr_or_func.to(device=timesteps.device)[timesteps].float() + while len(res.shape) < len(broadcast_shape): + res = res[..., None] + return res.expand(broadcast_shape) + + +def restore_checkpoint(ckpt_dir, state, device): + loaded_state = torch.load(ckpt_dir, map_location=device) + state['optimizer'].load_state_dict(loaded_state['optimizer']) + state['model'].load_state_dict(loaded_state['model'], strict=False) + state['ema'].load_state_dict(loaded_state['ema']) + state['step'] = loaded_state['step'] + + +class RevVPSDE(torch.nn.Module): + def __init__(self, model, score_type='guided_diffusion', beta_min=0.1, beta_max=20, N=1000, + img_shape=(3, 256, 256), model_kwargs=None): + """Construct a Variance Preserving SDE. + + Args: + model: diffusion model + score_type: [guided_diffusion, score_sde, ddpm] + beta_min: value of beta(0) + beta_max: value of beta(1) + """ + super().__init__() + self.model = model + self.score_type = score_type + self.model_kwargs = model_kwargs + self.img_shape = img_shape + + self.beta_0 = beta_min + self.beta_1 = beta_max + self.N = N + self.discrete_betas = torch.linspace(beta_min / N, beta_max / N, N) + self.alphas = 1. - self.discrete_betas + self.alphas_cumprod = torch.cumprod(self.alphas, dim=0) + self.sqrt_alphas_cumprod = torch.sqrt(self.alphas_cumprod) + self.sqrt_1m_alphas_cumprod = torch.sqrt(1. - self.alphas_cumprod) + + self.alphas_cumprod_cont = lambda t: torch.exp(-0.5 * (beta_max - beta_min) * t**2 - beta_min * t) + self.sqrt_1m_alphas_cumprod_neg_recip_cont = lambda t: -1. / torch.sqrt(1. - self.alphas_cumprod_cont(t)) + + self.noise_type = "diagonal" + self.sde_type = "ito" + + def _scale_timesteps(self, t): + assert torch.all(t <= 1) and torch.all(t >= 0), f't has to be in [0, 1], but get {t} with shape {t.shape}' + return (t.float() * self.N).long() + + def vpsde_fn(self, t, x): + beta_t = self.beta_0 + t * (self.beta_1 - self.beta_0) + drift = -0.5 * beta_t[:, None] * x + diffusion = torch.sqrt(beta_t) + return drift, diffusion + + def rvpsde_fn(self, t, x, return_type='drift'): + """Create the drift and diffusion functions for the reverse SDE""" + drift, diffusion = self.vpsde_fn(t, x) + + if return_type == 'drift': + + assert x.ndim == 2 and np.prod(self.img_shape) == x.shape[1], x.shape + x_img = x.view(-1, *self.img_shape) + + if self.score_type == 'guided_diffusion': + # model output is epsilon + if self.model_kwargs is None: + self.model_kwargs = {} + + disc_steps = self._scale_timesteps(t) # (batch_size, ), from float in [0,1] to int in [0, 1000] + model_output = self.model(x_img, disc_steps, **self.model_kwargs) + # with learned sigma, so model_output contains (mean, val) + model_output, _ = torch.split(model_output, self.img_shape[0], dim=1) + assert x_img.shape == model_output.shape, f'{x_img.shape}, {model_output.shape}' + model_output = model_output.view(x.shape[0], -1) + score = _extract_into_tensor(self.sqrt_1m_alphas_cumprod_neg_recip_cont, t, x.shape) * model_output + + elif self.score_type == 'score_sde': + # model output is epsilon + sde = sde_lib.VPSDE(beta_min=self.beta_0, beta_max=self.beta_1, N=self.N) + score_fn = mutils.get_score_fn(sde, self.model, train=False, continuous=True) + score = score_fn(x_img, t) + assert x_img.shape == score.shape, f'{x_img.shape}, {score.shape}' + score = score.view(x.shape[0], -1) + + else: + raise NotImplementedError(f'Unknown score type in RevVPSDE: {self.score_type}!') + + drift = drift - diffusion[:, None] ** 2 * score + return drift + + else: + return diffusion + + def f(self, t, x): + """Create the drift function -f(x, 1-t) (by t' = 1 - t) + sdeint only support a 2D tensor (batch_size, c*h*w) + """ + t = t.expand(x.shape[0]) # (batch_size, ) + drift = self.rvpsde_fn(1 - t, x, return_type='drift') + assert drift.shape == x.shape + return -drift + + def g(self, t, x): + """Create the diffusion function g(1-t) (by t' = 1 - t) + sdeint only support a 2D tensor (batch_size, c*h*w) + """ + t = t.expand(x.shape[0]) # (batch_size, ) + diffusion = self.rvpsde_fn(1 - t, x, return_type='diffusion') + assert diffusion.shape == (x.shape[0], ) + return diffusion[:, None].expand(x.shape) + + +class RevGuidedDiffusion(torch.nn.Module): + def __init__(self, args, config, device=None): + super().__init__() + self.args = args + self.config = config + if device is None: + device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") + self.device = device + + # load model + if config.data.dataset == 'ImageNet': + img_shape = (3, 256, 256) + model_dir = 'checkpoints/diffpure/guided_diffusion' + model_config = model_and_diffusion_defaults() + model_config.update(vars(self.config.model)) + print(f'model_config: {model_config}') + model, _ = create_model_and_diffusion(**model_config) + model.load_state_dict(torch.load(f'{model_dir}/256x256_diffusion_uncond.pt', map_location='cpu')) + + if model_config['use_fp16']: + model.convert_to_fp16() + + elif config.data.dataset == 'CIFAR10': + img_shape = (3, 32, 32) + model_dir = 'checkpoints/diffpure/score_sde' + print(f'model_config: {config}') + model = mutils.create_model(config) + + optimizer = get_optimizer(config, model.parameters()) + ema = ExponentialMovingAverage(model.parameters(), decay=config.model.ema_rate) + state = dict(step=0, optimizer=optimizer, model=model, ema=ema) + restore_checkpoint(f'{model_dir}/checkpoint_8.pth', state, device) + ema.copy_to(model.parameters()) + + else: + raise NotImplementedError(f'Unknown dataset {config.data.dataset}!') + + model.eval().to(self.device) + + self.model = model + self.rev_vpsde = RevVPSDE(model=model, score_type=args.score_type, img_shape=img_shape, + model_kwargs=None).to(self.device) + self.betas = self.rev_vpsde.discrete_betas.float().to(self.device) + + print(f't: {args.t}, rand_t: {args.rand_t}, t_delta: {args.t_delta}') + print(f'use_bm: {args.use_bm}') + + def image_editing_sample(self, img, bs_id=0, tag=None): + assert isinstance(img, torch.Tensor) + batch_size = img.shape[0] + state_size = int(np.prod(img.shape[1:])) # c*h*w + + if tag is None: + tag = 'rnd' + str(random.randint(0, 10000)) + out_dir = os.path.join(self.args.log_dir, 'bs' + str(bs_id) + '_' + tag) + + assert img.ndim == 4, img.ndim + img = img.to(self.device) + x0 = img + + if bs_id < 2: + os.makedirs(out_dir, exist_ok=True) + tvu.save_image((x0 + 1) * 0.5, os.path.join(out_dir, f'original_input.png')) + + xs = [] + for it in range(self.args.sample_step): + + e = torch.randn_like(x0).to(self.device) + total_noise_levels = self.args.t + if self.args.rand_t: + total_noise_levels = self.args.t + np.random.randint(-self.args.t_delta, self.args.t_delta) + print(f'total_noise_levels: {total_noise_levels}') + a = (1 - self.betas).cumprod(dim=0).to(self.device) + x = x0 * a[total_noise_levels - 1].sqrt() + e * (1.0 - a[total_noise_levels - 1]).sqrt() + + if bs_id < 2: + tvu.save_image((x + 1) * 0.5, os.path.join(out_dir, f'init_{it}.png')) + + epsilon_dt0, epsilon_dt1 = 0, 1e-5 + t0, t1 = 1 - self.args.t * 1. / 1000 + epsilon_dt0, 1 - epsilon_dt1 + t_size = 2 + ts = torch.linspace(t0, t1, t_size).to(self.device) + + x_ = x.view(batch_size, -1) # (batch_size, state_size) + if self.args.use_bm: + bm = torchsde.BrownianInterval(t0=t0, t1=t1, size=(batch_size, state_size), device=self.device) + xs_ = torchsde.sdeint_adjoint(self.rev_vpsde, x_, ts, method='euler', bm=bm) + else: + xs_ = torchsde.sdeint_adjoint(self.rev_vpsde, x_, ts, method='euler') + x0 = xs_[-1].view(x.shape) # (batch_size, c, h, w) + + if bs_id < 2: + torch.save(x0, os.path.join(out_dir, f'samples_{it}.pth')) + tvu.save_image((x0 + 1) * 0.5, os.path.join(out_dir, f'samples_{it}.png')) + + xs.append(x0) + + return torch.cat(xs, dim=0) diff --git a/case_studies/diffpure/score_sde/LICENSE_SCORE_SDE b/case_studies/diffpure/score_sde/LICENSE_SCORE_SDE new file mode 100644 index 0000000..f49a4e1 --- /dev/null +++ b/case_studies/diffpure/score_sde/LICENSE_SCORE_SDE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/case_studies/diffpure/score_sde/losses.py b/case_studies/diffpure/score_sde/losses.py new file mode 100644 index 0000000..9b3931b --- /dev/null +++ b/case_studies/diffpure/score_sde/losses.py @@ -0,0 +1,210 @@ +# coding=utf-8 +# Copyright 2020 The Google Research Authors. +# +# 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. + +"""All functions related to loss computation and optimization. +""" + +import torch +import torch.optim as optim +import numpy as np +from .models import utils as mutils +from .sde_lib import VESDE, VPSDE + + +def get_optimizer(config, params): + """Returns a flax optimizer object based on `config`.""" + if config.optim.optimizer == 'Adam': + optimizer = optim.Adam(params, lr=config.optim.lr, betas=(config.optim.beta1, 0.999), eps=config.optim.eps, + weight_decay=config.optim.weight_decay) + else: + raise NotImplementedError( + f'Optimizer {config.optim.optimizer} not supported yet!') + + return optimizer + + +def optimization_manager(config): + """Returns an optimize_fn based on `config`.""" + + def optimize_fn(optimizer, params, step, lr=config.optim.lr, + warmup=config.optim.warmup, + grad_clip=config.optim.grad_clip): + """Optimizes with warmup and gradient clipping (disabled if negative).""" + if warmup > 0: + for g in optimizer.param_groups: + g['lr'] = lr * np.minimum(step / warmup, 1.0) + if grad_clip >= 0: + torch.nn.utils.clip_grad_norm_(params, max_norm=grad_clip) + optimizer.step() + + return optimize_fn + + +def get_sde_loss_fn(sde, train, reduce_mean=True, continuous=True, likelihood_weighting=True, eps=1e-5): + """Create a loss function for training with arbirary SDEs. + + Args: + sde: An `sde_lib.SDE` object that represents the forward SDE. + train: `True` for training loss and `False` for evaluation loss. + reduce_mean: If `True`, average the loss across data dimensions. Otherwise sum the loss across data dimensions. + continuous: `True` indicates that the model is defined to take continuous time steps. Otherwise it requires + ad-hoc interpolation to take continuous time steps. + likelihood_weighting: If `True`, weight the mixture of score matching losses + according to https://arxiv.org/abs/2101.09258; otherwise use the weighting recommended in our paper. + eps: A `float` number. The smallest time step to sample from. + + Returns: + A loss function. + """ + reduce_op = torch.mean if reduce_mean else lambda *args, **kwargs: 0.5 * torch.sum(*args, **kwargs) + + def loss_fn(model, batch): + """Compute the loss function. + + Args: + model: A score model. + batch: A mini-batch of training data. + + Returns: + loss: A scalar that represents the average loss value across the mini-batch. + """ + score_fn = mutils.get_score_fn(sde, model, train=train, continuous=continuous) + t = torch.rand(batch.shape[0], device=batch.device) * (sde.T - eps) + eps + z = torch.randn_like(batch) + mean, std = sde.marginal_prob(batch, t) + perturbed_data = mean + std[:, None, None, None] * z + score = score_fn(perturbed_data, t) + + if not likelihood_weighting: + losses = torch.square(score * std[:, None, None, None] + z) + losses = reduce_op(losses.reshape(losses.shape[0], -1), dim=-1) + else: + g2 = sde.sde(torch.zeros_like(batch), t)[1] ** 2 + losses = torch.square(score + z / std[:, None, None, None]) + losses = reduce_op(losses.reshape(losses.shape[0], -1), dim=-1) * g2 + + loss = torch.mean(losses) + return loss + + return loss_fn + + +def get_smld_loss_fn(vesde, train, reduce_mean=False): + """Legacy code to reproduce previous results on SMLD(NCSN). Not recommended for new work.""" + assert isinstance(vesde, VESDE), "SMLD training only works for VESDEs." + + # Previous SMLD models assume descending sigmas + smld_sigma_array = torch.flip(vesde.discrete_sigmas, dims=(0,)) + reduce_op = torch.mean if reduce_mean else lambda *args, **kwargs: 0.5 * torch.sum(*args, **kwargs) + + def loss_fn(model, batch): + model_fn = mutils.get_model_fn(model, train=train) + labels = torch.randint(0, vesde.N, (batch.shape[0],), device=batch.device) + sigmas = smld_sigma_array.to(batch.device)[labels] + noise = torch.randn_like(batch) * sigmas[:, None, None, None] + perturbed_data = noise + batch + score = model_fn(perturbed_data, labels) + target = -noise / (sigmas ** 2)[:, None, None, None] + losses = torch.square(score - target) + losses = reduce_op(losses.reshape(losses.shape[0], -1), dim=-1) * sigmas ** 2 + loss = torch.mean(losses) + return loss + + return loss_fn + + +def get_ddpm_loss_fn(vpsde, train, reduce_mean=True): + """Legacy code to reproduce previous results on DDPM. Not recommended for new work.""" + assert isinstance(vpsde, VPSDE), "DDPM training only works for VPSDEs." + + reduce_op = torch.mean if reduce_mean else lambda *args, **kwargs: 0.5 * torch.sum(*args, **kwargs) + + def loss_fn(model, batch): + model_fn = mutils.get_model_fn(model, train=train) + labels = torch.randint(0, vpsde.N, (batch.shape[0],), device=batch.device) + sqrt_alphas_cumprod = vpsde.sqrt_alphas_cumprod.to(batch.device) + sqrt_1m_alphas_cumprod = vpsde.sqrt_1m_alphas_cumprod.to(batch.device) + noise = torch.randn_like(batch) + perturbed_data = sqrt_alphas_cumprod[labels, None, None, None] * batch + \ + sqrt_1m_alphas_cumprod[labels, None, None, None] * noise + score = model_fn(perturbed_data, labels) + losses = torch.square(score - noise) + losses = reduce_op(losses.reshape(losses.shape[0], -1), dim=-1) + loss = torch.mean(losses) + return loss + + return loss_fn + + +def get_step_fn(sde, train, optimize_fn=None, reduce_mean=False, continuous=True, likelihood_weighting=False): + """Create a one-step training/evaluation function. + + Args: + sde: An `sde_lib.SDE` object that represents the forward SDE. + optimize_fn: An optimization function. + reduce_mean: If `True`, average the loss across data dimensions. Otherwise sum the loss across data dimensions. + continuous: `True` indicates that the model is defined to take continuous time steps. + likelihood_weighting: If `True`, weight the mixture of score matching losses according to + https://arxiv.org/abs/2101.09258; otherwise use the weighting recommended by our paper. + + Returns: + A one-step function for training or evaluation. + """ + if continuous: + loss_fn = get_sde_loss_fn(sde, train, reduce_mean=reduce_mean, + continuous=True, likelihood_weighting=likelihood_weighting) + else: + assert not likelihood_weighting, "Likelihood weighting is not supported for original SMLD/DDPM training." + if isinstance(sde, VESDE): + loss_fn = get_smld_loss_fn(sde, train, reduce_mean=reduce_mean) + elif isinstance(sde, VPSDE): + loss_fn = get_ddpm_loss_fn(sde, train, reduce_mean=reduce_mean) + else: + raise ValueError(f"Discrete training for {sde.__class__.__name__} is not recommended.") + + def step_fn(state, batch): + """Running one step of training or evaluation. + + This function will undergo `jax.lax.scan` so that multiple steps can be pmapped and jit-compiled together + for faster execution. + + Args: + state: A dictionary of training information, containing the score model, optimizer, + EMA status, and number of optimization steps. + batch: A mini-batch of training/evaluation data. + + Returns: + loss: The average loss value of this state. + """ + model = state['model'] + if train: + optimizer = state['optimizer'] + optimizer.zero_grad() + loss = loss_fn(model, batch) + loss.backward() + optimize_fn(optimizer, model.parameters(), step=state['step']) + state['step'] += 1 + state['ema'].update(model.parameters()) + else: + with torch.no_grad(): + ema = state['ema'] + ema.store(model.parameters()) + ema.copy_to(model.parameters()) + loss = loss_fn(model, batch) + ema.restore(model.parameters()) + + return loss + + return step_fn diff --git a/case_studies/diffpure/score_sde/models/__init__.py b/case_studies/diffpure/score_sde/models/__init__.py new file mode 100644 index 0000000..4b0b4f2 --- /dev/null +++ b/case_studies/diffpure/score_sde/models/__init__.py @@ -0,0 +1,15 @@ +# coding=utf-8 +# Copyright 2020 The Google Research Authors. +# +# 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. +from . import ncsnpp diff --git a/case_studies/diffpure/score_sde/models/ddpm.py b/case_studies/diffpure/score_sde/models/ddpm.py new file mode 100644 index 0000000..2c2a394 --- /dev/null +++ b/case_studies/diffpure/score_sde/models/ddpm.py @@ -0,0 +1,181 @@ +# coding=utf-8 +# Copyright 2020 The Google Research Authors. +# +# 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. + +# pylint: skip-file +"""DDPM model. + +This code is the pytorch equivalent of: +https://github.com/hojonathanho/diffusion/blob/master/diffusion_tf/models/unet.py +""" +import torch +import torch.nn as nn +import functools + +from . import utils, layers, normalization + +RefineBlock = layers.RefineBlock +ResidualBlock = layers.ResidualBlock +ResnetBlockDDPM = layers.ResnetBlockDDPM +Upsample = layers.Upsample +Downsample = layers.Downsample +conv3x3 = layers.ddpm_conv3x3 +get_act = layers.get_act +get_normalization = normalization.get_normalization +default_initializer = layers.default_init + + +@utils.register_model(name='ddpm') +class DDPM(nn.Module): + def __init__(self, config): + super().__init__() + self.act = act = get_act(config) + self.register_buffer('sigmas', torch.tensor(utils.get_sigmas(config))) + + self.nf = nf = config.model.nf + ch_mult = config.model.ch_mult + self.num_res_blocks = num_res_blocks = config.model.num_res_blocks + self.attn_resolutions = attn_resolutions = config.model.attn_resolutions + dropout = config.model.dropout + resamp_with_conv = config.model.resamp_with_conv + self.num_resolutions = num_resolutions = len(ch_mult) + self.all_resolutions = all_resolutions = [config.data.image_size // (2 ** i) for i in range(num_resolutions)] + + AttnBlock = functools.partial(layers.AttnBlock) + self.conditional = conditional = config.model.conditional + ResnetBlock = functools.partial(ResnetBlockDDPM, act=act, temb_dim=4 * nf, dropout=dropout) + if conditional: + # Condition on noise levels. + modules = [nn.Linear(nf, nf * 4)] + modules[0].weight.data = default_initializer()(modules[0].weight.data.shape) + nn.init.zeros_(modules[0].bias) + modules.append(nn.Linear(nf * 4, nf * 4)) + modules[1].weight.data = default_initializer()(modules[1].weight.data.shape) + nn.init.zeros_(modules[1].bias) + + self.centered = config.data.centered + channels = config.data.num_channels + + # Downsampling block + modules.append(conv3x3(channels, nf)) + hs_c = [nf] + in_ch = nf + for i_level in range(num_resolutions): + # Residual blocks for this resolution + for i_block in range(num_res_blocks): + out_ch = nf * ch_mult[i_level] + modules.append(ResnetBlock(in_ch=in_ch, out_ch=out_ch)) + in_ch = out_ch + if all_resolutions[i_level] in attn_resolutions: + modules.append(AttnBlock(channels=in_ch)) + hs_c.append(in_ch) + if i_level != num_resolutions - 1: + modules.append(Downsample(channels=in_ch, with_conv=resamp_with_conv)) + hs_c.append(in_ch) + + in_ch = hs_c[-1] + modules.append(ResnetBlock(in_ch=in_ch)) + modules.append(AttnBlock(channels=in_ch)) + modules.append(ResnetBlock(in_ch=in_ch)) + + # Upsampling block + for i_level in reversed(range(num_resolutions)): + for i_block in range(num_res_blocks + 1): + out_ch = nf * ch_mult[i_level] + modules.append(ResnetBlock(in_ch=in_ch + hs_c.pop(), out_ch=out_ch)) + in_ch = out_ch + if all_resolutions[i_level] in attn_resolutions: + modules.append(AttnBlock(channels=in_ch)) + if i_level != 0: + modules.append(Upsample(channels=in_ch, with_conv=resamp_with_conv)) + + assert not hs_c + modules.append(nn.GroupNorm(num_channels=in_ch, num_groups=32, eps=1e-6)) + modules.append(conv3x3(in_ch, channels, init_scale=0.)) + self.all_modules = nn.ModuleList(modules) + + self.scale_by_sigma = config.model.scale_by_sigma + + def forward(self, x, labels): + modules = self.all_modules + m_idx = 0 + if self.conditional: + # timestep/scale embedding + timesteps = labels + temb = layers.get_timestep_embedding(timesteps, self.nf) + temb = modules[m_idx](temb) + m_idx += 1 + temb = modules[m_idx](self.act(temb)) + m_idx += 1 + else: + temb = None + + if self.centered: + # Input is in [-1, 1] + h = x + else: + # Input is in [0, 1] + h = 2 * x - 1. + + # Downsampling block + hs = [modules[m_idx](h)] + m_idx += 1 + for i_level in range(self.num_resolutions): + # Residual blocks for this resolution + for i_block in range(self.num_res_blocks): + h = modules[m_idx](hs[-1], temb) + m_idx += 1 + if h.shape[-1] in self.attn_resolutions: + h = modules[m_idx](h) + m_idx += 1 + hs.append(h) + if i_level != self.num_resolutions - 1: + hs.append(modules[m_idx](hs[-1])) + m_idx += 1 + + h = hs[-1] + h = modules[m_idx](h, temb) + m_idx += 1 + h = modules[m_idx](h) + m_idx += 1 + h = modules[m_idx](h, temb) + m_idx += 1 + + # Upsampling block + for i_level in reversed(range(self.num_resolutions)): + for i_block in range(self.num_res_blocks + 1): + h = modules[m_idx](torch.cat([h, hs.pop()], dim=1), temb) + m_idx += 1 + if h.shape[-1] in self.attn_resolutions: + h = modules[m_idx](h) + m_idx += 1 + if i_level != 0: + h = modules[m_idx](h) + m_idx += 1 + + assert not hs + h = self.act(modules[m_idx](h)) + m_idx += 1 + h = modules[m_idx](h) + m_idx += 1 + assert m_idx == len(modules) + + if self.scale_by_sigma: + # Divide the output by sigmas. Useful for training with the NCSN loss. + # The DDPM loss scales the network output by sigma in the loss function, + # so no need of doing it here. + used_sigmas = self.sigmas[labels, None, None, None] + h = h / used_sigmas + + return h diff --git a/case_studies/diffpure/score_sde/models/ema.py b/case_studies/diffpure/score_sde/models/ema.py new file mode 100644 index 0000000..84c5932 --- /dev/null +++ b/case_studies/diffpure/score_sde/models/ema.py @@ -0,0 +1,106 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/yang-song/score_sde_pytorch/blob/main/models/ema.py +# +# The license for the original version of this file can be +# found in the `score_sde` directory (LICENSE_SCORE_SDE). +# --------------------------------------------------------------- + +# Modified from https://raw.githubusercontent.com/fadel/pytorch_ema/master/torch_ema/ema.py + +from __future__ import division +from __future__ import unicode_literals + +import torch + + +# Partially based on: https://github.com/tensorflow/tensorflow/blob/r1.13/tensorflow/python/training/moving_averages.py +class ExponentialMovingAverage: + """ + Maintains (exponential) moving average of a set of parameters. + """ + + def __init__(self, parameters, decay, use_num_updates=True): + """ + Args: + parameters: Iterable of `torch.nn.Parameter`; usually the result of + `model.parameters()`. + decay: The exponential decay. + use_num_updates: Whether to use number of updates when computing + averages. + """ + if decay < 0.0 or decay > 1.0: + raise ValueError('Decay must be between 0 and 1') + self.decay = decay + self.num_updates = 0 if use_num_updates else None + self.shadow_params = [p.clone().detach() + for p in parameters if p.requires_grad] + self.collected_params = [] + + def update(self, parameters): + """ + Update currently maintained parameters. + + Call this every time the parameters are updated, such as the result of + the `optimizer.step()` call. + + Args: + parameters: Iterable of `torch.nn.Parameter`; usually the same set of + parameters used to initialize this object. + """ + decay = self.decay + if self.num_updates is not None: + self.num_updates += 1 + decay = min(decay, (1 + self.num_updates) / (10 + self.num_updates)) + one_minus_decay = 1.0 - decay + with torch.no_grad(): + parameters = [p for p in parameters if p.requires_grad] + for s_param, param in zip(self.shadow_params, parameters): + s_param.sub_(one_minus_decay * (s_param - param)) + + def copy_to(self, parameters): + """ + Copy current parameters into given collection of parameters. + + Args: + parameters: Iterable of `torch.nn.Parameter`; the parameters to be + updated with the stored moving averages. + """ + parameters = [p for p in parameters if p.requires_grad] + for s_param, param in zip(self.shadow_params, parameters): + if param.requires_grad: + param.data.copy_(s_param.data) + + def store(self, parameters): + """ + Save the current parameters for restoring later. + + Args: + parameters: Iterable of `torch.nn.Parameter`; the parameters to be + temporarily stored. + """ + self.collected_params = [param.clone() for param in parameters] + + def restore(self, parameters): + """ + Restore the parameters stored with the `store` method. + Useful to validate the model with EMA parameters without affecting the + original optimization process. Store the parameters before the + `copy_to` method. After validation (or model saving), use this to + restore the former parameters. + + Args: + parameters: Iterable of `torch.nn.Parameter`; the parameters to be + updated with the stored parameters. + """ + for c_param, param in zip(self.collected_params, parameters): + param.data.copy_(c_param.data) + + def state_dict(self): + return dict(decay=self.decay, num_updates=self.num_updates, + shadow_params=self.shadow_params) + + def load_state_dict(self, state_dict): + self.decay = state_dict['decay'] + self.num_updates = state_dict['num_updates'] + self.shadow_params = state_dict['shadow_params'] \ No newline at end of file diff --git a/case_studies/diffpure/score_sde/models/layers.py b/case_studies/diffpure/score_sde/models/layers.py new file mode 100644 index 0000000..296a2a0 --- /dev/null +++ b/case_studies/diffpure/score_sde/models/layers.py @@ -0,0 +1,662 @@ +# coding=utf-8 +# Copyright 2020 The Google Research Authors. +# +# 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. + +# pylint: skip-file +"""Common layers for defining score networks. +""" +import math +import string +from functools import partial +import torch.nn as nn +import torch +import torch.nn.functional as F +import numpy as np +from .normalization import ConditionalInstanceNorm2dPlus + + +def get_act(config): + """Get activation functions from the config file.""" + + if config.model.nonlinearity.lower() == 'elu': + return nn.ELU() + elif config.model.nonlinearity.lower() == 'relu': + return nn.ReLU() + elif config.model.nonlinearity.lower() == 'lrelu': + return nn.LeakyReLU(negative_slope=0.2) + elif config.model.nonlinearity.lower() == 'swish': + return nn.SiLU() + else: + raise NotImplementedError('activation function does not exist!') + + +def ncsn_conv1x1(in_planes, out_planes, stride=1, bias=True, dilation=1, init_scale=1., padding=0): + """1x1 convolution. Same as NCSNv1/v2.""" + conv = nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=bias, dilation=dilation, + padding=padding) + init_scale = 1e-10 if init_scale == 0 else init_scale + conv.weight.data *= init_scale + conv.bias.data *= init_scale + return conv + + +def variance_scaling(scale, mode, distribution, + in_axis=1, out_axis=0, + dtype=torch.float32, + device='cpu'): + """Ported from JAX. """ + + def _compute_fans(shape, in_axis=1, out_axis=0): + receptive_field_size = np.prod(shape) / shape[in_axis] / shape[out_axis] + fan_in = shape[in_axis] * receptive_field_size + fan_out = shape[out_axis] * receptive_field_size + return fan_in, fan_out + + def init(shape, dtype=dtype, device=device): + fan_in, fan_out = _compute_fans(shape, in_axis, out_axis) + if mode == "fan_in": + denominator = fan_in + elif mode == "fan_out": + denominator = fan_out + elif mode == "fan_avg": + denominator = (fan_in + fan_out) / 2 + else: + raise ValueError( + "invalid mode for variance scaling initializer: {}".format(mode)) + variance = scale / denominator + if distribution == "normal": + return torch.randn(*shape, dtype=dtype, device=device) * np.sqrt(variance) + elif distribution == "uniform": + return (torch.rand(*shape, dtype=dtype, device=device) * 2. - 1.) * np.sqrt(3 * variance) + else: + raise ValueError("invalid distribution for variance scaling initializer") + + return init + + +def default_init(scale=1.): + """The same initialization used in DDPM.""" + scale = 1e-10 if scale == 0 else scale + return variance_scaling(scale, 'fan_avg', 'uniform') + + +class Dense(nn.Module): + """Linear layer with `default_init`.""" + def __init__(self): + super().__init__() + + +def ddpm_conv1x1(in_planes, out_planes, stride=1, bias=True, init_scale=1., padding=0): + """1x1 convolution with DDPM initialization.""" + conv = nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, padding=padding, bias=bias) + conv.weight.data = default_init(init_scale)(conv.weight.data.shape) + nn.init.zeros_(conv.bias) + return conv + + +def ncsn_conv3x3(in_planes, out_planes, stride=1, bias=True, dilation=1, init_scale=1., padding=1): + """3x3 convolution with PyTorch initialization. Same as NCSNv1/NCSNv2.""" + init_scale = 1e-10 if init_scale == 0 else init_scale + conv = nn.Conv2d(in_planes, out_planes, stride=stride, bias=bias, + dilation=dilation, padding=padding, kernel_size=3) + conv.weight.data *= init_scale + conv.bias.data *= init_scale + return conv + + +def ddpm_conv3x3(in_planes, out_planes, stride=1, bias=True, dilation=1, init_scale=1., padding=1): + """3x3 convolution with DDPM initialization.""" + conv = nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, padding=padding, + dilation=dilation, bias=bias) + conv.weight.data = default_init(init_scale)(conv.weight.data.shape) + nn.init.zeros_(conv.bias) + return conv + + ########################################################################### + # Functions below are ported over from the NCSNv1/NCSNv2 codebase: + # https://github.com/ermongroup/ncsn + # https://github.com/ermongroup/ncsnv2 + ########################################################################### + + +class CRPBlock(nn.Module): + def __init__(self, features, n_stages, act=nn.ReLU(), maxpool=True): + super().__init__() + self.convs = nn.ModuleList() + for i in range(n_stages): + self.convs.append(ncsn_conv3x3(features, features, stride=1, bias=False)) + self.n_stages = n_stages + if maxpool: + self.pool = nn.MaxPool2d(kernel_size=5, stride=1, padding=2) + else: + self.pool = nn.AvgPool2d(kernel_size=5, stride=1, padding=2) + + self.act = act + + def forward(self, x): + x = self.act(x) + path = x + for i in range(self.n_stages): + path = self.pool(path) + path = self.convs[i](path) + x = path + x + return x + + +class CondCRPBlock(nn.Module): + def __init__(self, features, n_stages, num_classes, normalizer, act=nn.ReLU()): + super().__init__() + self.convs = nn.ModuleList() + self.norms = nn.ModuleList() + self.normalizer = normalizer + for i in range(n_stages): + self.norms.append(normalizer(features, num_classes, bias=True)) + self.convs.append(ncsn_conv3x3(features, features, stride=1, bias=False)) + + self.n_stages = n_stages + self.pool = nn.AvgPool2d(kernel_size=5, stride=1, padding=2) + self.act = act + + def forward(self, x, y): + x = self.act(x) + path = x + for i in range(self.n_stages): + path = self.norms[i](path, y) + path = self.pool(path) + path = self.convs[i](path) + + x = path + x + return x + + +class RCUBlock(nn.Module): + def __init__(self, features, n_blocks, n_stages, act=nn.ReLU()): + super().__init__() + + for i in range(n_blocks): + for j in range(n_stages): + setattr(self, '{}_{}_conv'.format(i + 1, j + 1), ncsn_conv3x3(features, features, stride=1, bias=False)) + + self.stride = 1 + self.n_blocks = n_blocks + self.n_stages = n_stages + self.act = act + + def forward(self, x): + for i in range(self.n_blocks): + residual = x + for j in range(self.n_stages): + x = self.act(x) + x = getattr(self, '{}_{}_conv'.format(i + 1, j + 1))(x) + + x += residual + return x + + +class CondRCUBlock(nn.Module): + def __init__(self, features, n_blocks, n_stages, num_classes, normalizer, act=nn.ReLU()): + super().__init__() + + for i in range(n_blocks): + for j in range(n_stages): + setattr(self, '{}_{}_norm'.format(i + 1, j + 1), normalizer(features, num_classes, bias=True)) + setattr(self, '{}_{}_conv'.format(i + 1, j + 1), ncsn_conv3x3(features, features, stride=1, bias=False)) + + self.stride = 1 + self.n_blocks = n_blocks + self.n_stages = n_stages + self.act = act + self.normalizer = normalizer + + def forward(self, x, y): + for i in range(self.n_blocks): + residual = x + for j in range(self.n_stages): + x = getattr(self, '{}_{}_norm'.format(i + 1, j + 1))(x, y) + x = self.act(x) + x = getattr(self, '{}_{}_conv'.format(i + 1, j + 1))(x) + + x += residual + return x + + +class MSFBlock(nn.Module): + def __init__(self, in_planes, features): + super().__init__() + assert isinstance(in_planes, list) or isinstance(in_planes, tuple) + self.convs = nn.ModuleList() + self.features = features + + for i in range(len(in_planes)): + self.convs.append(ncsn_conv3x3(in_planes[i], features, stride=1, bias=True)) + + def forward(self, xs, shape): + sums = torch.zeros(xs[0].shape[0], self.features, *shape, device=xs[0].device) + for i in range(len(self.convs)): + h = self.convs[i](xs[i]) + h = F.interpolate(h, size=shape, mode='bilinear', align_corners=True) + sums += h + return sums + + +class CondMSFBlock(nn.Module): + def __init__(self, in_planes, features, num_classes, normalizer): + super().__init__() + assert isinstance(in_planes, list) or isinstance(in_planes, tuple) + + self.convs = nn.ModuleList() + self.norms = nn.ModuleList() + self.features = features + self.normalizer = normalizer + + for i in range(len(in_planes)): + self.convs.append(ncsn_conv3x3(in_planes[i], features, stride=1, bias=True)) + self.norms.append(normalizer(in_planes[i], num_classes, bias=True)) + + def forward(self, xs, y, shape): + sums = torch.zeros(xs[0].shape[0], self.features, *shape, device=xs[0].device) + for i in range(len(self.convs)): + h = self.norms[i](xs[i], y) + h = self.convs[i](h) + h = F.interpolate(h, size=shape, mode='bilinear', align_corners=True) + sums += h + return sums + + +class RefineBlock(nn.Module): + def __init__(self, in_planes, features, act=nn.ReLU(), start=False, end=False, maxpool=True): + super().__init__() + + assert isinstance(in_planes, tuple) or isinstance(in_planes, list) + self.n_blocks = n_blocks = len(in_planes) + + self.adapt_convs = nn.ModuleList() + for i in range(n_blocks): + self.adapt_convs.append(RCUBlock(in_planes[i], 2, 2, act)) + + self.output_convs = RCUBlock(features, 3 if end else 1, 2, act) + + if not start: + self.msf = MSFBlock(in_planes, features) + + self.crp = CRPBlock(features, 2, act, maxpool=maxpool) + + def forward(self, xs, output_shape): + assert isinstance(xs, tuple) or isinstance(xs, list) + hs = [] + for i in range(len(xs)): + h = self.adapt_convs[i](xs[i]) + hs.append(h) + + if self.n_blocks > 1: + h = self.msf(hs, output_shape) + else: + h = hs[0] + + h = self.crp(h) + h = self.output_convs(h) + + return h + + +class CondRefineBlock(nn.Module): + def __init__(self, in_planes, features, num_classes, normalizer, act=nn.ReLU(), start=False, end=False): + super().__init__() + + assert isinstance(in_planes, tuple) or isinstance(in_planes, list) + self.n_blocks = n_blocks = len(in_planes) + + self.adapt_convs = nn.ModuleList() + for i in range(n_blocks): + self.adapt_convs.append( + CondRCUBlock(in_planes[i], 2, 2, num_classes, normalizer, act) + ) + + self.output_convs = CondRCUBlock(features, 3 if end else 1, 2, num_classes, normalizer, act) + + if not start: + self.msf = CondMSFBlock(in_planes, features, num_classes, normalizer) + + self.crp = CondCRPBlock(features, 2, num_classes, normalizer, act) + + def forward(self, xs, y, output_shape): + assert isinstance(xs, tuple) or isinstance(xs, list) + hs = [] + for i in range(len(xs)): + h = self.adapt_convs[i](xs[i], y) + hs.append(h) + + if self.n_blocks > 1: + h = self.msf(hs, y, output_shape) + else: + h = hs[0] + + h = self.crp(h, y) + h = self.output_convs(h, y) + + return h + + +class ConvMeanPool(nn.Module): + def __init__(self, input_dim, output_dim, kernel_size=3, biases=True, adjust_padding=False): + super().__init__() + if not adjust_padding: + conv = nn.Conv2d(input_dim, output_dim, kernel_size, stride=1, padding=kernel_size // 2, bias=biases) + self.conv = conv + else: + conv = nn.Conv2d(input_dim, output_dim, kernel_size, stride=1, padding=kernel_size // 2, bias=biases) + + self.conv = nn.Sequential( + nn.ZeroPad2d((1, 0, 1, 0)), + conv + ) + + def forward(self, inputs): + output = self.conv(inputs) + output = sum([output[:, :, ::2, ::2], output[:, :, 1::2, ::2], + output[:, :, ::2, 1::2], output[:, :, 1::2, 1::2]]) / 4. + return output + + +class MeanPoolConv(nn.Module): + def __init__(self, input_dim, output_dim, kernel_size=3, biases=True): + super().__init__() + self.conv = nn.Conv2d(input_dim, output_dim, kernel_size, stride=1, padding=kernel_size // 2, bias=biases) + + def forward(self, inputs): + output = inputs + output = sum([output[:, :, ::2, ::2], output[:, :, 1::2, ::2], + output[:, :, ::2, 1::2], output[:, :, 1::2, 1::2]]) / 4. + return self.conv(output) + + +class UpsampleConv(nn.Module): + def __init__(self, input_dim, output_dim, kernel_size=3, biases=True): + super().__init__() + self.conv = nn.Conv2d(input_dim, output_dim, kernel_size, stride=1, padding=kernel_size // 2, bias=biases) + self.pixelshuffle = nn.PixelShuffle(upscale_factor=2) + + def forward(self, inputs): + output = inputs + output = torch.cat([output, output, output, output], dim=1) + output = self.pixelshuffle(output) + return self.conv(output) + + +class ConditionalResidualBlock(nn.Module): + def __init__(self, input_dim, output_dim, num_classes, resample=1, act=nn.ELU(), + normalization=ConditionalInstanceNorm2dPlus, adjust_padding=False, dilation=None): + super().__init__() + self.non_linearity = act + self.input_dim = input_dim + self.output_dim = output_dim + self.resample = resample + self.normalization = normalization + if resample == 'down': + if dilation > 1: + self.conv1 = ncsn_conv3x3(input_dim, input_dim, dilation=dilation) + self.normalize2 = normalization(input_dim, num_classes) + self.conv2 = ncsn_conv3x3(input_dim, output_dim, dilation=dilation) + conv_shortcut = partial(ncsn_conv3x3, dilation=dilation) + else: + self.conv1 = ncsn_conv3x3(input_dim, input_dim) + self.normalize2 = normalization(input_dim, num_classes) + self.conv2 = ConvMeanPool(input_dim, output_dim, 3, adjust_padding=adjust_padding) + conv_shortcut = partial(ConvMeanPool, kernel_size=1, adjust_padding=adjust_padding) + + elif resample is None: + if dilation > 1: + conv_shortcut = partial(ncsn_conv3x3, dilation=dilation) + self.conv1 = ncsn_conv3x3(input_dim, output_dim, dilation=dilation) + self.normalize2 = normalization(output_dim, num_classes) + self.conv2 = ncsn_conv3x3(output_dim, output_dim, dilation=dilation) + else: + conv_shortcut = nn.Conv2d + self.conv1 = ncsn_conv3x3(input_dim, output_dim) + self.normalize2 = normalization(output_dim, num_classes) + self.conv2 = ncsn_conv3x3(output_dim, output_dim) + else: + raise Exception('invalid resample value') + + if output_dim != input_dim or resample is not None: + self.shortcut = conv_shortcut(input_dim, output_dim) + + self.normalize1 = normalization(input_dim, num_classes) + + def forward(self, x, y): + output = self.normalize1(x, y) + output = self.non_linearity(output) + output = self.conv1(output) + output = self.normalize2(output, y) + output = self.non_linearity(output) + output = self.conv2(output) + + if self.output_dim == self.input_dim and self.resample is None: + shortcut = x + else: + shortcut = self.shortcut(x) + + return shortcut + output + + +class ResidualBlock(nn.Module): + def __init__(self, input_dim, output_dim, resample=None, act=nn.ELU(), + normalization=nn.InstanceNorm2d, adjust_padding=False, dilation=1): + super().__init__() + self.non_linearity = act + self.input_dim = input_dim + self.output_dim = output_dim + self.resample = resample + self.normalization = normalization + if resample == 'down': + if dilation > 1: + self.conv1 = ncsn_conv3x3(input_dim, input_dim, dilation=dilation) + self.normalize2 = normalization(input_dim) + self.conv2 = ncsn_conv3x3(input_dim, output_dim, dilation=dilation) + conv_shortcut = partial(ncsn_conv3x3, dilation=dilation) + else: + self.conv1 = ncsn_conv3x3(input_dim, input_dim) + self.normalize2 = normalization(input_dim) + self.conv2 = ConvMeanPool(input_dim, output_dim, 3, adjust_padding=adjust_padding) + conv_shortcut = partial(ConvMeanPool, kernel_size=1, adjust_padding=adjust_padding) + + elif resample is None: + if dilation > 1: + conv_shortcut = partial(ncsn_conv3x3, dilation=dilation) + self.conv1 = ncsn_conv3x3(input_dim, output_dim, dilation=dilation) + self.normalize2 = normalization(output_dim) + self.conv2 = ncsn_conv3x3(output_dim, output_dim, dilation=dilation) + else: + # conv_shortcut = nn.Conv2d ### Something wierd here. + conv_shortcut = partial(ncsn_conv1x1) + self.conv1 = ncsn_conv3x3(input_dim, output_dim) + self.normalize2 = normalization(output_dim) + self.conv2 = ncsn_conv3x3(output_dim, output_dim) + else: + raise Exception('invalid resample value') + + if output_dim != input_dim or resample is not None: + self.shortcut = conv_shortcut(input_dim, output_dim) + + self.normalize1 = normalization(input_dim) + + def forward(self, x): + output = self.normalize1(x) + output = self.non_linearity(output) + output = self.conv1(output) + output = self.normalize2(output) + output = self.non_linearity(output) + output = self.conv2(output) + + if self.output_dim == self.input_dim and self.resample is None: + shortcut = x + else: + shortcut = self.shortcut(x) + + return shortcut + output + + +########################################################################### +# Functions below are ported over from the DDPM codebase: +# https://github.com/hojonathanho/diffusion/blob/master/diffusion_tf/nn.py +########################################################################### + +def get_timestep_embedding(timesteps, embedding_dim, max_positions=10000): + assert len(timesteps.shape) == 1 # and timesteps.dtype == tf.int32 + half_dim = embedding_dim // 2 + # magic number 10000 is from transformers + emb = math.log(max_positions) / (half_dim - 1) + # emb = math.log(2.) / (half_dim - 1) + emb = torch.exp(torch.arange(half_dim, dtype=torch.float32, device=timesteps.device) * -emb) + # emb = tf.range(num_embeddings, dtype=jnp.float32)[:, None] * emb[None, :] + # emb = tf.cast(timesteps, dtype=jnp.float32)[:, None] * emb[None, :] + emb = timesteps.float()[:, None] * emb[None, :] + emb = torch.cat([torch.sin(emb), torch.cos(emb)], dim=1) + if embedding_dim % 2 == 1: # zero pad + emb = F.pad(emb, (0, 1), mode='constant') + assert emb.shape == (timesteps.shape[0], embedding_dim) + return emb + + +def _einsum(a, b, c, x, y): + einsum_str = '{},{}->{}'.format(''.join(a), ''.join(b), ''.join(c)) + return torch.einsum(einsum_str, x, y) + + +def contract_inner(x, y): + """tensordot(x, y, 1).""" + x_chars = list(string.ascii_lowercase[:len(x.shape)]) + y_chars = list(string.ascii_lowercase[len(x.shape):len(y.shape) + len(x.shape)]) + y_chars[0] = x_chars[-1] # first axis of y and last of x get summed + out_chars = x_chars[:-1] + y_chars[1:] + return _einsum(x_chars, y_chars, out_chars, x, y) + + +class NIN(nn.Module): + def __init__(self, in_dim, num_units, init_scale=0.1): + super().__init__() + self.W = nn.Parameter(default_init(scale=init_scale)((in_dim, num_units)), requires_grad=True) + self.b = nn.Parameter(torch.zeros(num_units), requires_grad=True) + + def forward(self, x): + x = x.permute(0, 2, 3, 1) + y = contract_inner(x, self.W) + self.b + return y.permute(0, 3, 1, 2) + + +class AttnBlock(nn.Module): + """Channel-wise self-attention block.""" + def __init__(self, channels): + super().__init__() + self.GroupNorm_0 = nn.GroupNorm(num_groups=32, num_channels=channels, eps=1e-6) + self.NIN_0 = NIN(channels, channels) + self.NIN_1 = NIN(channels, channels) + self.NIN_2 = NIN(channels, channels) + self.NIN_3 = NIN(channels, channels, init_scale=0.) + + def forward(self, x): + B, C, H, W = x.shape + h = self.GroupNorm_0(x) + q = self.NIN_0(h) + k = self.NIN_1(h) + v = self.NIN_2(h) + + w = torch.einsum('bchw,bcij->bhwij', q, k) * (int(C) ** (-0.5)) + w = torch.reshape(w, (B, H, W, H * W)) + w = F.softmax(w, dim=-1) + w = torch.reshape(w, (B, H, W, H, W)) + h = torch.einsum('bhwij,bcij->bchw', w, v) + h = self.NIN_3(h) + return x + h + + +class Upsample(nn.Module): + def __init__(self, channels, with_conv=False): + super().__init__() + if with_conv: + self.Conv_0 = ddpm_conv3x3(channels, channels) + self.with_conv = with_conv + + def forward(self, x): + B, C, H, W = x.shape + h = F.interpolate(x, (H * 2, W * 2), mode='nearest') + if self.with_conv: + h = self.Conv_0(h) + return h + + +class Downsample(nn.Module): + def __init__(self, channels, with_conv=False): + super().__init__() + if with_conv: + self.Conv_0 = ddpm_conv3x3(channels, channels, stride=2, padding=0) + self.with_conv = with_conv + + def forward(self, x): + B, C, H, W = x.shape + # Emulate 'SAME' padding + if self.with_conv: + x = F.pad(x, (0, 1, 0, 1)) + x = self.Conv_0(x) + else: + x = F.avg_pool2d(x, kernel_size=2, stride=2, padding=0) + + assert x.shape == (B, C, H // 2, W // 2) + return x + + +class ResnetBlockDDPM(nn.Module): + """The ResNet Blocks used in DDPM.""" + def __init__(self, act, in_ch, out_ch=None, temb_dim=None, conv_shortcut=False, dropout=0.1): + super().__init__() + if out_ch is None: + out_ch = in_ch + self.GroupNorm_0 = nn.GroupNorm(num_groups=32, num_channels=in_ch, eps=1e-6) + self.act = act + self.Conv_0 = ddpm_conv3x3(in_ch, out_ch) + if temb_dim is not None: + self.Dense_0 = nn.Linear(temb_dim, out_ch) + self.Dense_0.weight.data = default_init()(self.Dense_0.weight.data.shape) + nn.init.zeros_(self.Dense_0.bias) + + self.GroupNorm_1 = nn.GroupNorm(num_groups=32, num_channels=out_ch, eps=1e-6) + self.Dropout_0 = nn.Dropout(dropout) + self.Conv_1 = ddpm_conv3x3(out_ch, out_ch, init_scale=0.) + if in_ch != out_ch: + if conv_shortcut: + self.Conv_2 = ddpm_conv3x3(in_ch, out_ch) + else: + self.NIN_0 = NIN(in_ch, out_ch) + self.out_ch = out_ch + self.in_ch = in_ch + self.conv_shortcut = conv_shortcut + + def forward(self, x, temb=None): + B, C, H, W = x.shape + assert C == self.in_ch + out_ch = self.out_ch if self.out_ch else self.in_ch + h = self.act(self.GroupNorm_0(x)) + h = self.Conv_0(h) + # Add bias to each feature map conditioned on the time embedding + if temb is not None: + h += self.Dense_0(self.act(temb))[:, :, None, None] + h = self.act(self.GroupNorm_1(h)) + h = self.Dropout_0(h) + h = self.Conv_1(h) + if C != out_ch: + if self.conv_shortcut: + x = self.Conv_2(x) + else: + x = self.NIN_0(x) + return x + h \ No newline at end of file diff --git a/case_studies/diffpure/score_sde/models/layerspp.py b/case_studies/diffpure/score_sde/models/layerspp.py new file mode 100644 index 0000000..948b068 --- /dev/null +++ b/case_studies/diffpure/score_sde/models/layerspp.py @@ -0,0 +1,274 @@ +# coding=utf-8 +# Copyright 2020 The Google Research Authors. +# +# 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. + +# pylint: skip-file +"""Layers for defining NCSN++. +""" +from . import layers +from . import up_or_down_sampling +import torch.nn as nn +import torch +import torch.nn.functional as F +import numpy as np + +conv1x1 = layers.ddpm_conv1x1 +conv3x3 = layers.ddpm_conv3x3 +NIN = layers.NIN +default_init = layers.default_init + + +class GaussianFourierProjection(nn.Module): + """Gaussian Fourier embeddings for noise levels.""" + + def __init__(self, embedding_size=256, scale=1.0): + super().__init__() + self.W = nn.Parameter(torch.randn(embedding_size) * scale, requires_grad=False) + + def forward(self, x): + x_proj = x[:, None] * self.W[None, :] * 2 * np.pi + return torch.cat([torch.sin(x_proj), torch.cos(x_proj)], dim=-1) + + +class Combine(nn.Module): + """Combine information from skip connections.""" + + def __init__(self, dim1, dim2, method='cat'): + super().__init__() + self.Conv_0 = conv1x1(dim1, dim2) + self.method = method + + def forward(self, x, y): + h = self.Conv_0(x) + if self.method == 'cat': + return torch.cat([h, y], dim=1) + elif self.method == 'sum': + return h + y + else: + raise ValueError(f'Method {self.method} not recognized.') + + +class AttnBlockpp(nn.Module): + """Channel-wise self-attention block. Modified from DDPM.""" + + def __init__(self, channels, skip_rescale=False, init_scale=0.): + super().__init__() + self.GroupNorm_0 = nn.GroupNorm(num_groups=min(channels // 4, 32), num_channels=channels, + eps=1e-6) + self.NIN_0 = NIN(channels, channels) + self.NIN_1 = NIN(channels, channels) + self.NIN_2 = NIN(channels, channels) + self.NIN_3 = NIN(channels, channels, init_scale=init_scale) + self.skip_rescale = skip_rescale + + def forward(self, x): + B, C, H, W = x.shape + h = self.GroupNorm_0(x) + q = self.NIN_0(h) + k = self.NIN_1(h) + v = self.NIN_2(h) + + w = torch.einsum('bchw,bcij->bhwij', q, k) * (int(C) ** (-0.5)) + w = torch.reshape(w, (B, H, W, H * W)) + w = F.softmax(w, dim=-1) + w = torch.reshape(w, (B, H, W, H, W)) + h = torch.einsum('bhwij,bcij->bchw', w, v) + h = self.NIN_3(h) + if not self.skip_rescale: + return x + h + else: + return (x + h) / np.sqrt(2.) + + +class Upsample(nn.Module): + def __init__(self, in_ch=None, out_ch=None, with_conv=False, fir=False, + fir_kernel=(1, 3, 3, 1)): + super().__init__() + out_ch = out_ch if out_ch else in_ch + if not fir: + if with_conv: + self.Conv_0 = conv3x3(in_ch, out_ch) + else: + if with_conv: + self.Conv2d_0 = up_or_down_sampling.Conv2d(in_ch, out_ch, + kernel=3, up=True, + resample_kernel=fir_kernel, + use_bias=True, + kernel_init=default_init()) + self.fir = fir + self.with_conv = with_conv + self.fir_kernel = fir_kernel + self.out_ch = out_ch + + def forward(self, x): + B, C, H, W = x.shape + if not self.fir: + h = F.interpolate(x, (H * 2, W * 2), 'nearest') + if self.with_conv: + h = self.Conv_0(h) + else: + if not self.with_conv: + h = up_or_down_sampling.upsample_2d(x, self.fir_kernel, factor=2) + else: + h = self.Conv2d_0(x) + + return h + + +class Downsample(nn.Module): + def __init__(self, in_ch=None, out_ch=None, with_conv=False, fir=False, + fir_kernel=(1, 3, 3, 1)): + super().__init__() + out_ch = out_ch if out_ch else in_ch + if not fir: + if with_conv: + self.Conv_0 = conv3x3(in_ch, out_ch, stride=2, padding=0) + else: + if with_conv: + self.Conv2d_0 = up_or_down_sampling.Conv2d(in_ch, out_ch, + kernel=3, down=True, + resample_kernel=fir_kernel, + use_bias=True, + kernel_init=default_init()) + self.fir = fir + self.fir_kernel = fir_kernel + self.with_conv = with_conv + self.out_ch = out_ch + + def forward(self, x): + B, C, H, W = x.shape + if not self.fir: + if self.with_conv: + x = F.pad(x, (0, 1, 0, 1)) + x = self.Conv_0(x) + else: + x = F.avg_pool2d(x, 2, stride=2) + else: + if not self.with_conv: + x = up_or_down_sampling.downsample_2d(x, self.fir_kernel, factor=2) + else: + x = self.Conv2d_0(x) + + return x + + +class ResnetBlockDDPMpp(nn.Module): + """ResBlock adapted from DDPM.""" + + def __init__(self, act, in_ch, out_ch=None, temb_dim=None, conv_shortcut=False, + dropout=0.1, skip_rescale=False, init_scale=0.): + super().__init__() + out_ch = out_ch if out_ch else in_ch + self.GroupNorm_0 = nn.GroupNorm(num_groups=min(in_ch // 4, 32), num_channels=in_ch, eps=1e-6) + self.Conv_0 = conv3x3(in_ch, out_ch) + if temb_dim is not None: + self.Dense_0 = nn.Linear(temb_dim, out_ch) + self.Dense_0.weight.data = default_init()(self.Dense_0.weight.data.shape) + nn.init.zeros_(self.Dense_0.bias) + self.GroupNorm_1 = nn.GroupNorm(num_groups=min(out_ch // 4, 32), num_channels=out_ch, eps=1e-6) + self.Dropout_0 = nn.Dropout(dropout) + self.Conv_1 = conv3x3(out_ch, out_ch, init_scale=init_scale) + if in_ch != out_ch: + if conv_shortcut: + self.Conv_2 = conv3x3(in_ch, out_ch) + else: + self.NIN_0 = NIN(in_ch, out_ch) + + self.skip_rescale = skip_rescale + self.act = act + self.out_ch = out_ch + self.conv_shortcut = conv_shortcut + + def forward(self, x, temb=None): + h = self.act(self.GroupNorm_0(x)) + h = self.Conv_0(h) + if temb is not None: + h += self.Dense_0(self.act(temb))[:, :, None, None] + h = self.act(self.GroupNorm_1(h)) + h = self.Dropout_0(h) + h = self.Conv_1(h) + if x.shape[1] != self.out_ch: + if self.conv_shortcut: + x = self.Conv_2(x) + else: + x = self.NIN_0(x) + if not self.skip_rescale: + return x + h + else: + return (x + h) / np.sqrt(2.) + + +class ResnetBlockBigGANpp(nn.Module): + def __init__(self, act, in_ch, out_ch=None, temb_dim=None, up=False, down=False, + dropout=0.1, fir=False, fir_kernel=(1, 3, 3, 1), + skip_rescale=True, init_scale=0.): + super().__init__() + + out_ch = out_ch if out_ch else in_ch + self.GroupNorm_0 = nn.GroupNorm(num_groups=min(in_ch // 4, 32), num_channels=in_ch, eps=1e-6) + self.up = up + self.down = down + self.fir = fir + self.fir_kernel = fir_kernel + + self.Conv_0 = conv3x3(in_ch, out_ch) + if temb_dim is not None: + self.Dense_0 = nn.Linear(temb_dim, out_ch) + self.Dense_0.weight.data = default_init()(self.Dense_0.weight.shape) + nn.init.zeros_(self.Dense_0.bias) + + self.GroupNorm_1 = nn.GroupNorm(num_groups=min(out_ch // 4, 32), num_channels=out_ch, eps=1e-6) + self.Dropout_0 = nn.Dropout(dropout) + self.Conv_1 = conv3x3(out_ch, out_ch, init_scale=init_scale) + if in_ch != out_ch or up or down: + self.Conv_2 = conv1x1(in_ch, out_ch) + + self.skip_rescale = skip_rescale + self.act = act + self.in_ch = in_ch + self.out_ch = out_ch + + def forward(self, x, temb=None): + h = self.act(self.GroupNorm_0(x)) + + if self.up: + if self.fir: + h = up_or_down_sampling.upsample_2d(h, self.fir_kernel, factor=2) + x = up_or_down_sampling.upsample_2d(x, self.fir_kernel, factor=2) + else: + h = up_or_down_sampling.naive_upsample_2d(h, factor=2) + x = up_or_down_sampling.naive_upsample_2d(x, factor=2) + elif self.down: + if self.fir: + h = up_or_down_sampling.downsample_2d(h, self.fir_kernel, factor=2) + x = up_or_down_sampling.downsample_2d(x, self.fir_kernel, factor=2) + else: + h = up_or_down_sampling.naive_downsample_2d(h, factor=2) + x = up_or_down_sampling.naive_downsample_2d(x, factor=2) + + h = self.Conv_0(h) + # Add bias to each feature map conditioned on the time embedding + if temb is not None: + h += self.Dense_0(self.act(temb))[:, :, None, None] + h = self.act(self.GroupNorm_1(h)) + h = self.Dropout_0(h) + h = self.Conv_1(h) + + if self.in_ch != self.out_ch or self.up or self.down: + x = self.Conv_2(x) + + if not self.skip_rescale: + return x + h + else: + return (x + h) / np.sqrt(2.) diff --git a/case_studies/diffpure/score_sde/models/ncsnpp.py b/case_studies/diffpure/score_sde/models/ncsnpp.py new file mode 100644 index 0000000..0557eb0 --- /dev/null +++ b/case_studies/diffpure/score_sde/models/ncsnpp.py @@ -0,0 +1,381 @@ +# coding=utf-8 +# Copyright 2020 The Google Research Authors. +# +# 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. + +# pylint: skip-file + +from . import utils, layers, layerspp, normalization +import torch.nn as nn +import functools +import torch +import numpy as np + +ResnetBlockDDPM = layerspp.ResnetBlockDDPMpp +ResnetBlockBigGAN = layerspp.ResnetBlockBigGANpp +Combine = layerspp.Combine +conv3x3 = layerspp.conv3x3 +conv1x1 = layerspp.conv1x1 +get_act = layers.get_act +get_normalization = normalization.get_normalization +default_initializer = layers.default_init + + +@utils.register_model(name='ncsnpp') +class NCSNpp(nn.Module): + """NCSN++ model""" + + def __init__(self, config): + super().__init__() + self.config = config + self.act = act = get_act(config) + self.register_buffer('sigmas', torch.tensor(utils.get_sigmas(config))) + + self.nf = nf = config.model.nf + ch_mult = config.model.ch_mult + self.num_res_blocks = num_res_blocks = config.model.num_res_blocks + self.attn_resolutions = attn_resolutions = config.model.attn_resolutions + dropout = config.model.dropout + resamp_with_conv = config.model.resamp_with_conv + self.num_resolutions = num_resolutions = len(ch_mult) + self.all_resolutions = all_resolutions = [config.data.image_size // (2 ** i) for i in range(num_resolutions)] + + self.conditional = conditional = config.model.conditional # noise-conditional + fir = config.model.fir + fir_kernel = config.model.fir_kernel + self.skip_rescale = skip_rescale = config.model.skip_rescale + self.resblock_type = resblock_type = config.model.resblock_type.lower() + self.progressive = progressive = config.model.progressive.lower() + self.progressive_input = progressive_input = config.model.progressive_input.lower() + self.embedding_type = embedding_type = config.model.embedding_type.lower() + init_scale = config.model.init_scale + assert progressive in ['none', 'output_skip', 'residual'] + assert progressive_input in ['none', 'input_skip', 'residual'] + assert embedding_type in ['fourier', 'positional'] + combine_method = config.model.progressive_combine.lower() + combiner = functools.partial(Combine, method=combine_method) + + modules = [] + # timestep/noise_level embedding; only for continuous training + if embedding_type == 'fourier': + # Gaussian Fourier features embeddings. + assert config.training.continuous, "Fourier features are only used for continuous training." + + modules.append(layerspp.GaussianFourierProjection( + embedding_size=nf, scale=config.model.fourier_scale + )) + embed_dim = 2 * nf + + elif embedding_type == 'positional': + embed_dim = nf + + else: + raise ValueError(f'embedding type {embedding_type} unknown.') + + if conditional: + modules.append(nn.Linear(embed_dim, nf * 4)) + modules[-1].weight.data = default_initializer()(modules[-1].weight.shape) + nn.init.zeros_(modules[-1].bias) + modules.append(nn.Linear(nf * 4, nf * 4)) + modules[-1].weight.data = default_initializer()(modules[-1].weight.shape) + nn.init.zeros_(modules[-1].bias) + + AttnBlock = functools.partial(layerspp.AttnBlockpp, + init_scale=init_scale, + skip_rescale=skip_rescale) + + Upsample = functools.partial(layerspp.Upsample, + with_conv=resamp_with_conv, fir=fir, fir_kernel=fir_kernel) + + if progressive == 'output_skip': + self.pyramid_upsample = layerspp.Upsample(fir=fir, fir_kernel=fir_kernel, with_conv=False) + elif progressive == 'residual': + pyramid_upsample = functools.partial(layerspp.Upsample, + fir=fir, fir_kernel=fir_kernel, with_conv=True) + + Downsample = functools.partial(layerspp.Downsample, + with_conv=resamp_with_conv, fir=fir, fir_kernel=fir_kernel) + + if progressive_input == 'input_skip': + self.pyramid_downsample = layerspp.Downsample(fir=fir, fir_kernel=fir_kernel, with_conv=False) + elif progressive_input == 'residual': + pyramid_downsample = functools.partial(layerspp.Downsample, + fir=fir, fir_kernel=fir_kernel, with_conv=True) + + if resblock_type == 'ddpm': + ResnetBlock = functools.partial(ResnetBlockDDPM, + act=act, + dropout=dropout, + init_scale=init_scale, + skip_rescale=skip_rescale, + temb_dim=nf * 4) + + elif resblock_type == 'biggan': + ResnetBlock = functools.partial(ResnetBlockBigGAN, + act=act, + dropout=dropout, + fir=fir, + fir_kernel=fir_kernel, + init_scale=init_scale, + skip_rescale=skip_rescale, + temb_dim=nf * 4) + + else: + raise ValueError(f'resblock type {resblock_type} unrecognized.') + + # Downsampling block + + channels = config.data.num_channels + if progressive_input != 'none': + input_pyramid_ch = channels + + modules.append(conv3x3(channels, nf)) + hs_c = [nf] + + in_ch = nf + for i_level in range(num_resolutions): + # Residual blocks for this resolution + for i_block in range(num_res_blocks): + out_ch = nf * ch_mult[i_level] + modules.append(ResnetBlock(in_ch=in_ch, out_ch=out_ch)) + in_ch = out_ch + + if all_resolutions[i_level] in attn_resolutions: + modules.append(AttnBlock(channels=in_ch)) + hs_c.append(in_ch) + + if i_level != num_resolutions - 1: + if resblock_type == 'ddpm': + modules.append(Downsample(in_ch=in_ch)) + else: + modules.append(ResnetBlock(down=True, in_ch=in_ch)) + + if progressive_input == 'input_skip': + modules.append(combiner(dim1=input_pyramid_ch, dim2=in_ch)) + if combine_method == 'cat': + in_ch *= 2 + + elif progressive_input == 'residual': + modules.append(pyramid_downsample(in_ch=input_pyramid_ch, out_ch=in_ch)) + input_pyramid_ch = in_ch + + hs_c.append(in_ch) + + in_ch = hs_c[-1] + modules.append(ResnetBlock(in_ch=in_ch)) + modules.append(AttnBlock(channels=in_ch)) + modules.append(ResnetBlock(in_ch=in_ch)) + + pyramid_ch = 0 + # Upsampling block + for i_level in reversed(range(num_resolutions)): + for i_block in range(num_res_blocks + 1): + out_ch = nf * ch_mult[i_level] + modules.append(ResnetBlock(in_ch=in_ch + hs_c.pop(), + out_ch=out_ch)) + in_ch = out_ch + + if all_resolutions[i_level] in attn_resolutions: + modules.append(AttnBlock(channels=in_ch)) + + if progressive != 'none': + if i_level == num_resolutions - 1: + if progressive == 'output_skip': + modules.append(nn.GroupNorm(num_groups=min(in_ch // 4, 32), + num_channels=in_ch, eps=1e-6)) + modules.append(conv3x3(in_ch, channels, init_scale=init_scale)) + pyramid_ch = channels + elif progressive == 'residual': + modules.append(nn.GroupNorm(num_groups=min(in_ch // 4, 32), + num_channels=in_ch, eps=1e-6)) + modules.append(conv3x3(in_ch, in_ch, bias=True)) + pyramid_ch = in_ch + else: + raise ValueError(f'{progressive} is not a valid name.') + else: + if progressive == 'output_skip': + modules.append(nn.GroupNorm(num_groups=min(in_ch // 4, 32), + num_channels=in_ch, eps=1e-6)) + modules.append(conv3x3(in_ch, channels, bias=True, init_scale=init_scale)) + pyramid_ch = channels + elif progressive == 'residual': + modules.append(pyramid_upsample(in_ch=pyramid_ch, out_ch=in_ch)) + pyramid_ch = in_ch + else: + raise ValueError(f'{progressive} is not a valid name') + + if i_level != 0: + if resblock_type == 'ddpm': + modules.append(Upsample(in_ch=in_ch)) + else: + modules.append(ResnetBlock(in_ch=in_ch, up=True)) + + assert not hs_c + + if progressive != 'output_skip': + modules.append(nn.GroupNorm(num_groups=min(in_ch // 4, 32), + num_channels=in_ch, eps=1e-6)) + modules.append(conv3x3(in_ch, channels, init_scale=init_scale)) + + self.all_modules = nn.ModuleList(modules) + + def forward(self, x, time_cond): + # timestep/noise_level embedding; only for continuous training + modules = self.all_modules + m_idx = 0 + if self.embedding_type == 'fourier': + # Gaussian Fourier features embeddings. + used_sigmas = time_cond + temb = modules[m_idx](torch.log(used_sigmas)) + m_idx += 1 + + elif self.embedding_type == 'positional': + # Sinusoidal positional embeddings. + timesteps = time_cond + used_sigmas = self.sigmas[time_cond.long()] + temb = layers.get_timestep_embedding(timesteps, self.nf) + + else: + raise ValueError(f'embedding type {self.embedding_type} unknown.') + + if self.conditional: + temb = modules[m_idx](temb) + m_idx += 1 + temb = modules[m_idx](self.act(temb)) + m_idx += 1 + else: + temb = None + + if not self.config.data.centered: + # If input data is in [0, 1] + x = 2 * x - 1. + + # Downsampling block + input_pyramid = None + if self.progressive_input != 'none': + input_pyramid = x + + hs = [modules[m_idx](x)] + m_idx += 1 + for i_level in range(self.num_resolutions): + # Residual blocks for this resolution + for i_block in range(self.num_res_blocks): + h = modules[m_idx](hs[-1], temb) + m_idx += 1 + if h.shape[-1] in self.attn_resolutions: + h = modules[m_idx](h) + m_idx += 1 + + hs.append(h) + + if i_level != self.num_resolutions - 1: + if self.resblock_type == 'ddpm': + h = modules[m_idx](hs[-1]) + m_idx += 1 + else: + h = modules[m_idx](hs[-1], temb) + m_idx += 1 + + if self.progressive_input == 'input_skip': + input_pyramid = self.pyramid_downsample(input_pyramid) + h = modules[m_idx](input_pyramid, h) + m_idx += 1 + + elif self.progressive_input == 'residual': + input_pyramid = modules[m_idx](input_pyramid) + m_idx += 1 + if self.skip_rescale: + input_pyramid = (input_pyramid + h) / np.sqrt(2.) + else: + input_pyramid = input_pyramid + h + h = input_pyramid + + hs.append(h) + + h = hs[-1] + h = modules[m_idx](h, temb) + m_idx += 1 + h = modules[m_idx](h) + m_idx += 1 + h = modules[m_idx](h, temb) + m_idx += 1 + + pyramid = None + + # Upsampling block + for i_level in reversed(range(self.num_resolutions)): + for i_block in range(self.num_res_blocks + 1): + h = modules[m_idx](torch.cat([h, hs.pop()], dim=1), temb) + m_idx += 1 + + if h.shape[-1] in self.attn_resolutions: + h = modules[m_idx](h) + m_idx += 1 + + if self.progressive != 'none': + if i_level == self.num_resolutions - 1: + if self.progressive == 'output_skip': + pyramid = self.act(modules[m_idx](h)) + m_idx += 1 + pyramid = modules[m_idx](pyramid) + m_idx += 1 + elif self.progressive == 'residual': + pyramid = self.act(modules[m_idx](h)) + m_idx += 1 + pyramid = modules[m_idx](pyramid) + m_idx += 1 + else: + raise ValueError(f'{self.progressive} is not a valid name.') + else: + if self.progressive == 'output_skip': + pyramid = self.pyramid_upsample(pyramid) + pyramid_h = self.act(modules[m_idx](h)) + m_idx += 1 + pyramid_h = modules[m_idx](pyramid_h) + m_idx += 1 + pyramid = pyramid + pyramid_h + elif self.progressive == 'residual': + pyramid = modules[m_idx](pyramid) + m_idx += 1 + if self.skip_rescale: + pyramid = (pyramid + h) / np.sqrt(2.) + else: + pyramid = pyramid + h + h = pyramid + else: + raise ValueError(f'{self.progressive} is not a valid name') + + if i_level != 0: + if self.resblock_type == 'ddpm': + h = modules[m_idx](h) + m_idx += 1 + else: + h = modules[m_idx](h, temb) + m_idx += 1 + + assert not hs + + if self.progressive == 'output_skip': + h = pyramid + else: + h = self.act(modules[m_idx](h)) + m_idx += 1 + h = modules[m_idx](h) + m_idx += 1 + + assert m_idx == len(modules) + if self.config.model.scale_by_sigma: + used_sigmas = used_sigmas.reshape((x.shape[0], *([1] * len(x.shape[1:])))) + h = h / used_sigmas + + return h diff --git a/case_studies/diffpure/score_sde/models/ncsnv2.py b/case_studies/diffpure/score_sde/models/ncsnv2.py new file mode 100644 index 0000000..5302cc9 --- /dev/null +++ b/case_studies/diffpure/score_sde/models/ncsnv2.py @@ -0,0 +1,416 @@ +# coding=utf-8 +# Copyright 2020 The Google Research Authors. +# +# 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. + +# pylint: skip-file +"""The NCSNv2 model.""" +import torch +import torch.nn as nn +import functools + +from .utils import get_sigmas, register_model +from .layers import (CondRefineBlock, RefineBlock, ResidualBlock, ncsn_conv3x3, + ConditionalResidualBlock, get_act) +from .normalization import get_normalization + +CondResidualBlock = ConditionalResidualBlock +conv3x3 = ncsn_conv3x3 + + +def get_network(config): + if config.data.image_size < 96: + return functools.partial(NCSNv2, config=config) + elif 96 <= config.data.image_size <= 128: + return functools.partial(NCSNv2_128, config=config) + elif 128 < config.data.image_size <= 256: + return functools.partial(NCSNv2_256, config=config) + else: + raise NotImplementedError( + f'No network suitable for {config.data.image_size}px implemented yet.') + + +@register_model(name='ncsnv2_64') +class NCSNv2(nn.Module): + def __init__(self, config): + super().__init__() + self.centered = config.data.centered + self.norm = get_normalization(config) + self.nf = nf = config.model.nf + + self.act = act = get_act(config) + self.register_buffer('sigmas', torch.tensor(get_sigmas(config))) + self.config = config + + self.begin_conv = nn.Conv2d(config.data.channels, nf, 3, stride=1, padding=1) + + self.normalizer = self.norm(nf, config.model.num_scales) + self.end_conv = nn.Conv2d(nf, config.data.channels, 3, stride=1, padding=1) + + self.res1 = nn.ModuleList([ + ResidualBlock(self.nf, self.nf, resample=None, act=act, + normalization=self.norm), + ResidualBlock(self.nf, self.nf, resample=None, act=act, + normalization=self.norm)] + ) + + self.res2 = nn.ModuleList([ + ResidualBlock(self.nf, 2 * self.nf, resample='down', act=act, + normalization=self.norm), + ResidualBlock(2 * self.nf, 2 * self.nf, resample=None, act=act, + normalization=self.norm)] + ) + + self.res3 = nn.ModuleList([ + ResidualBlock(2 * self.nf, 2 * self.nf, resample='down', act=act, + normalization=self.norm, dilation=2), + ResidualBlock(2 * self.nf, 2 * self.nf, resample=None, act=act, + normalization=self.norm, dilation=2)] + ) + + if config.data.image_size == 28: + self.res4 = nn.ModuleList([ + ResidualBlock(2 * self.nf, 2 * self.nf, resample='down', act=act, + normalization=self.norm, adjust_padding=True, dilation=4), + ResidualBlock(2 * self.nf, 2 * self.nf, resample=None, act=act, + normalization=self.norm, dilation=4)] + ) + else: + self.res4 = nn.ModuleList([ + ResidualBlock(2 * self.nf, 2 * self.nf, resample='down', act=act, + normalization=self.norm, adjust_padding=False, dilation=4), + ResidualBlock(2 * self.nf, 2 * self.nf, resample=None, act=act, + normalization=self.norm, dilation=4)] + ) + + self.refine1 = RefineBlock([2 * self.nf], 2 * self.nf, act=act, start=True) + self.refine2 = RefineBlock([2 * self.nf, 2 * self.nf], 2 * self.nf, act=act) + self.refine3 = RefineBlock([2 * self.nf, 2 * self.nf], self.nf, act=act) + self.refine4 = RefineBlock([self.nf, self.nf], self.nf, act=act, end=True) + + def _compute_cond_module(self, module, x): + for m in module: + x = m(x) + return x + + def forward(self, x, y): + if not self.centered: + h = 2 * x - 1. + else: + h = x + + output = self.begin_conv(h) + + layer1 = self._compute_cond_module(self.res1, output) + layer2 = self._compute_cond_module(self.res2, layer1) + layer3 = self._compute_cond_module(self.res3, layer2) + layer4 = self._compute_cond_module(self.res4, layer3) + + ref1 = self.refine1([layer4], layer4.shape[2:]) + ref2 = self.refine2([layer3, ref1], layer3.shape[2:]) + ref3 = self.refine3([layer2, ref2], layer2.shape[2:]) + output = self.refine4([layer1, ref3], layer1.shape[2:]) + + output = self.normalizer(output) + output = self.act(output) + output = self.end_conv(output) + + used_sigmas = self.sigmas[y].view(x.shape[0], *([1] * len(x.shape[1:]))) + + output = output / used_sigmas + + return output + + +@register_model(name='ncsn') +class NCSN(nn.Module): + def __init__(self, config): + super().__init__() + self.centered = config.data.centered + self.norm = get_normalization(config) + self.nf = nf = config.model.nf + self.act = act = get_act(config) + self.config = config + + self.begin_conv = nn.Conv2d(config.data.channels, nf, 3, stride=1, padding=1) + + self.normalizer = self.norm(nf, config.model.num_scales) + self.end_conv = nn.Conv2d(nf, config.data.channels, 3, stride=1, padding=1) + + self.res1 = nn.ModuleList([ + ConditionalResidualBlock(self.nf, self.nf, config.model.num_scales, resample=None, act=act, + normalization=self.norm), + ConditionalResidualBlock(self.nf, self.nf, config.model.num_scales, resample=None, act=act, + normalization=self.norm)] + ) + + self.res2 = nn.ModuleList([ + ConditionalResidualBlock(self.nf, 2 * self.nf, config.model.num_scales, resample='down', act=act, + normalization=self.norm), + ConditionalResidualBlock(2 * self.nf, 2 * self.nf, config.model.num_scales, resample=None, act=act, + normalization=self.norm)] + ) + + self.res3 = nn.ModuleList([ + ConditionalResidualBlock(2 * self.nf, 2 * self.nf, config.model.num_scales, resample='down', act=act, + normalization=self.norm, dilation=2), + ConditionalResidualBlock(2 * self.nf, 2 * self.nf, config.model.num_scales, resample=None, act=act, + normalization=self.norm, dilation=2)] + ) + + if config.data.image_size == 28: + self.res4 = nn.ModuleList([ + ConditionalResidualBlock(2 * self.nf, 2 * self.nf, config.model.num_scales, resample='down', act=act, + normalization=self.norm, adjust_padding=True, dilation=4), + ConditionalResidualBlock(2 * self.nf, 2 * self.nf, config.model.num_scales, resample=None, act=act, + normalization=self.norm, dilation=4)] + ) + else: + self.res4 = nn.ModuleList([ + ConditionalResidualBlock(2 * self.nf, 2 * self.nf, config.model.num_scales, resample='down', act=act, + normalization=self.norm, adjust_padding=False, dilation=4), + ConditionalResidualBlock(2 * self.nf, 2 * self.nf, config.model.num_scales, resample=None, act=act, + normalization=self.norm, dilation=4)] + ) + + self.refine1 = CondRefineBlock([2 * self.nf], 2 * self.nf, config.model.num_scales, self.norm, act=act, start=True) + self.refine2 = CondRefineBlock([2 * self.nf, 2 * self.nf], 2 * self.nf, config.model.num_scales, self.norm, act=act) + self.refine3 = CondRefineBlock([2 * self.nf, 2 * self.nf], self.nf, config.model.num_scales, self.norm, act=act) + self.refine4 = CondRefineBlock([self.nf, self.nf], self.nf, config.model.num_scales, self.norm, act=act, end=True) + + def _compute_cond_module(self, module, x, y): + for m in module: + x = m(x, y) + return x + + def forward(self, x, y): + if not self.centered: + h = 2 * x - 1. + else: + h = x + + output = self.begin_conv(h) + + layer1 = self._compute_cond_module(self.res1, output, y) + layer2 = self._compute_cond_module(self.res2, layer1, y) + layer3 = self._compute_cond_module(self.res3, layer2, y) + layer4 = self._compute_cond_module(self.res4, layer3, y) + + ref1 = self.refine1([layer4], y, layer4.shape[2:]) + ref2 = self.refine2([layer3, ref1], y, layer3.shape[2:]) + ref3 = self.refine3([layer2, ref2], y, layer2.shape[2:]) + output = self.refine4([layer1, ref3], y, layer1.shape[2:]) + + output = self.normalizer(output, y) + output = self.act(output) + output = self.end_conv(output) + + return output + + +@register_model(name='ncsnv2_128') +class NCSNv2_128(nn.Module): + """NCSNv2 model architecture for 128px images.""" + def __init__(self, config): + super().__init__() + self.centered = config.data.centered + self.norm = get_normalization(config) + self.nf = nf = config.model.nf + self.act = act = get_act(config) + self.register_buffer('sigmas', torch.tensor(get_sigmas(config))) + self.config = config + + self.begin_conv = nn.Conv2d(config.data.channels, nf, 3, stride=1, padding=1) + self.normalizer = self.norm(nf, config.model.num_scales) + + self.end_conv = nn.Conv2d(nf, config.data.channels, 3, stride=1, padding=1) + + self.res1 = nn.ModuleList([ + ResidualBlock(self.nf, self.nf, resample=None, act=act, + normalization=self.norm), + ResidualBlock(self.nf, self.nf, resample=None, act=act, + normalization=self.norm)] + ) + + self.res2 = nn.ModuleList([ + ResidualBlock(self.nf, 2 * self.nf, resample='down', act=act, + normalization=self.norm), + ResidualBlock(2 * self.nf, 2 * self.nf, resample=None, act=act, + normalization=self.norm)] + ) + + self.res3 = nn.ModuleList([ + ResidualBlock(2 * self.nf, 2 * self.nf, resample='down', act=act, + normalization=self.norm), + ResidualBlock(2 * self.nf, 2 * self.nf, resample=None, act=act, + normalization=self.norm)] + ) + + self.res4 = nn.ModuleList([ + ResidualBlock(2 * self.nf, 4 * self.nf, resample='down', act=act, + normalization=self.norm, dilation=2), + ResidualBlock(4 * self.nf, 4 * self.nf, resample=None, act=act, + normalization=self.norm, dilation=2)] + ) + + self.res5 = nn.ModuleList([ + ResidualBlock(4 * self.nf, 4 * self.nf, resample='down', act=act, + normalization=self.norm, dilation=4), + ResidualBlock(4 * self.nf, 4 * self.nf, resample=None, act=act, + normalization=self.norm, dilation=4)] + ) + + self.refine1 = RefineBlock([4 * self.nf], 4 * self.nf, act=act, start=True) + self.refine2 = RefineBlock([4 * self.nf, 4 * self.nf], 2 * self.nf, act=act) + self.refine3 = RefineBlock([2 * self.nf, 2 * self.nf], 2 * self.nf, act=act) + self.refine4 = RefineBlock([2 * self.nf, 2 * self.nf], self.nf, act=act) + self.refine5 = RefineBlock([self.nf, self.nf], self.nf, act=act, end=True) + + def _compute_cond_module(self, module, x): + for m in module: + x = m(x) + return x + + def forward(self, x, y): + if not self.centered: + h = 2 * x - 1. + else: + h = x + + output = self.begin_conv(h) + + layer1 = self._compute_cond_module(self.res1, output) + layer2 = self._compute_cond_module(self.res2, layer1) + layer3 = self._compute_cond_module(self.res3, layer2) + layer4 = self._compute_cond_module(self.res4, layer3) + layer5 = self._compute_cond_module(self.res5, layer4) + + ref1 = self.refine1([layer5], layer5.shape[2:]) + ref2 = self.refine2([layer4, ref1], layer4.shape[2:]) + ref3 = self.refine3([layer3, ref2], layer3.shape[2:]) + ref4 = self.refine4([layer2, ref3], layer2.shape[2:]) + output = self.refine5([layer1, ref4], layer1.shape[2:]) + + output = self.normalizer(output) + output = self.act(output) + output = self.end_conv(output) + + used_sigmas = self.sigmas[y].view(x.shape[0], *([1] * len(x.shape[1:]))) + + output = output / used_sigmas + + return output + + +@register_model(name='ncsnv2_256') +class NCSNv2_256(nn.Module): + """NCSNv2 model architecture for 256px images.""" + def __init__(self, config): + super().__init__() + self.centered = config.data.centered + self.norm = get_normalization(config) + self.nf = nf = config.model.nf + self.act = act = get_act(config) + self.register_buffer('sigmas', torch.tensor(get_sigmas(config))) + self.config = config + + self.begin_conv = nn.Conv2d(config.data.channels, nf, 3, stride=1, padding=1) + self.normalizer = self.norm(nf, config.model.num_scales) + + self.end_conv = nn.Conv2d(nf, config.data.channels, 3, stride=1, padding=1) + + self.res1 = nn.ModuleList([ + ResidualBlock(self.nf, self.nf, resample=None, act=act, + normalization=self.norm), + ResidualBlock(self.nf, self.nf, resample=None, act=act, + normalization=self.norm)] + ) + + self.res2 = nn.ModuleList([ + ResidualBlock(self.nf, 2 * self.nf, resample='down', act=act, + normalization=self.norm), + ResidualBlock(2 * self.nf, 2 * self.nf, resample=None, act=act, + normalization=self.norm)] + ) + + self.res3 = nn.ModuleList([ + ResidualBlock(2 * self.nf, 2 * self.nf, resample='down', act=act, + normalization=self.norm), + ResidualBlock(2 * self.nf, 2 * self.nf, resample=None, act=act, + normalization=self.norm)] + ) + + self.res31 = nn.ModuleList([ + ResidualBlock(2 * self.nf, 2 * self.nf, resample='down', act=act, + normalization=self.norm), + ResidualBlock(2 * self.nf, 2 * self.nf, resample=None, act=act, + normalization=self.norm)] + ) + + self.res4 = nn.ModuleList([ + ResidualBlock(2 * self.nf, 4 * self.nf, resample='down', act=act, + normalization=self.norm, dilation=2), + ResidualBlock(4 * self.nf, 4 * self.nf, resample=None, act=act, + normalization=self.norm, dilation=2)] + ) + + self.res5 = nn.ModuleList([ + ResidualBlock(4 * self.nf, 4 * self.nf, resample='down', act=act, + normalization=self.norm, dilation=4), + ResidualBlock(4 * self.nf, 4 * self.nf, resample=None, act=act, + normalization=self.norm, dilation=4)] + ) + + self.refine1 = RefineBlock([4 * self.nf], 4 * self.nf, act=act, start=True) + self.refine2 = RefineBlock([4 * self.nf, 4 * self.nf], 2 * self.nf, act=act) + self.refine3 = RefineBlock([2 * self.nf, 2 * self.nf], 2 * self.nf, act=act) + self.refine31 = RefineBlock([2 * self.nf, 2 * self.nf], 2 * self.nf, act=act) + self.refine4 = RefineBlock([2 * self.nf, 2 * self.nf], self.nf, act=act) + self.refine5 = RefineBlock([self.nf, self.nf], self.nf, act=act, end=True) + + def _compute_cond_module(self, module, x): + for m in module: + x = m(x) + return x + + def forward(self, x, y): + if not self.centered: + h = 2 * x - 1. + else: + h = x + + output = self.begin_conv(h) + + layer1 = self._compute_cond_module(self.res1, output) + layer2 = self._compute_cond_module(self.res2, layer1) + layer3 = self._compute_cond_module(self.res3, layer2) + layer31 = self._compute_cond_module(self.res31, layer3) + layer4 = self._compute_cond_module(self.res4, layer31) + layer5 = self._compute_cond_module(self.res5, layer4) + + ref1 = self.refine1([layer5], layer5.shape[2:]) + ref2 = self.refine2([layer4, ref1], layer4.shape[2:]) + ref31 = self.refine31([layer31, ref2], layer31.shape[2:]) + ref3 = self.refine3([layer3, ref31], layer3.shape[2:]) + ref4 = self.refine4([layer2, ref3], layer2.shape[2:]) + output = self.refine5([layer1, ref4], layer1.shape[2:]) + + output = self.normalizer(output) + output = self.act(output) + output = self.end_conv(output) + + used_sigmas = self.sigmas[y].view(x.shape[0], *([1] * len(x.shape[1:]))) + + output = output / used_sigmas + + return output \ No newline at end of file diff --git a/case_studies/diffpure/score_sde/models/normalization.py b/case_studies/diffpure/score_sde/models/normalization.py new file mode 100644 index 0000000..9a23204 --- /dev/null +++ b/case_studies/diffpure/score_sde/models/normalization.py @@ -0,0 +1,215 @@ +# coding=utf-8 +# Copyright 2020 The Google Research Authors. +# +# 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. + +"""Normalization layers.""" +import torch.nn as nn +import torch +import functools + + +def get_normalization(config, conditional=False): + """Obtain normalization modules from the config file.""" + norm = config.model.normalization + if conditional: + if norm == 'InstanceNorm++': + return functools.partial(ConditionalInstanceNorm2dPlus, num_classes=config.model.num_classes) + else: + raise NotImplementedError(f'{norm} not implemented yet.') + else: + if norm == 'InstanceNorm': + return nn.InstanceNorm2d + elif norm == 'InstanceNorm++': + return InstanceNorm2dPlus + elif norm == 'VarianceNorm': + return VarianceNorm2d + elif norm == 'GroupNorm': + return nn.GroupNorm + else: + raise ValueError('Unknown normalization: %s' % norm) + + +class ConditionalBatchNorm2d(nn.Module): + def __init__(self, num_features, num_classes, bias=True): + super().__init__() + self.num_features = num_features + self.bias = bias + self.bn = nn.BatchNorm2d(num_features, affine=False) + if self.bias: + self.embed = nn.Embedding(num_classes, num_features * 2) + self.embed.weight.data[:, :num_features].uniform_() # Initialise scale at N(1, 0.02) + self.embed.weight.data[:, num_features:].zero_() # Initialise bias at 0 + else: + self.embed = nn.Embedding(num_classes, num_features) + self.embed.weight.data.uniform_() + + def forward(self, x, y): + out = self.bn(x) + if self.bias: + gamma, beta = self.embed(y).chunk(2, dim=1) + out = gamma.view(-1, self.num_features, 1, 1) * out + beta.view(-1, self.num_features, 1, 1) + else: + gamma = self.embed(y) + out = gamma.view(-1, self.num_features, 1, 1) * out + return out + + +class ConditionalInstanceNorm2d(nn.Module): + def __init__(self, num_features, num_classes, bias=True): + super().__init__() + self.num_features = num_features + self.bias = bias + self.instance_norm = nn.InstanceNorm2d(num_features, affine=False, track_running_stats=False) + if bias: + self.embed = nn.Embedding(num_classes, num_features * 2) + self.embed.weight.data[:, :num_features].uniform_() # Initialise scale at N(1, 0.02) + self.embed.weight.data[:, num_features:].zero_() # Initialise bias at 0 + else: + self.embed = nn.Embedding(num_classes, num_features) + self.embed.weight.data.uniform_() + + def forward(self, x, y): + h = self.instance_norm(x) + if self.bias: + gamma, beta = self.embed(y).chunk(2, dim=-1) + out = gamma.view(-1, self.num_features, 1, 1) * h + beta.view(-1, self.num_features, 1, 1) + else: + gamma = self.embed(y) + out = gamma.view(-1, self.num_features, 1, 1) * h + return out + + +class ConditionalVarianceNorm2d(nn.Module): + def __init__(self, num_features, num_classes, bias=False): + super().__init__() + self.num_features = num_features + self.bias = bias + self.embed = nn.Embedding(num_classes, num_features) + self.embed.weight.data.normal_(1, 0.02) + + def forward(self, x, y): + vars = torch.var(x, dim=(2, 3), keepdim=True) + h = x / torch.sqrt(vars + 1e-5) + + gamma = self.embed(y) + out = gamma.view(-1, self.num_features, 1, 1) * h + return out + + +class VarianceNorm2d(nn.Module): + def __init__(self, num_features, bias=False): + super().__init__() + self.num_features = num_features + self.bias = bias + self.alpha = nn.Parameter(torch.zeros(num_features)) + self.alpha.data.normal_(1, 0.02) + + def forward(self, x): + vars = torch.var(x, dim=(2, 3), keepdim=True) + h = x / torch.sqrt(vars + 1e-5) + + out = self.alpha.view(-1, self.num_features, 1, 1) * h + return out + + +class ConditionalNoneNorm2d(nn.Module): + def __init__(self, num_features, num_classes, bias=True): + super().__init__() + self.num_features = num_features + self.bias = bias + if bias: + self.embed = nn.Embedding(num_classes, num_features * 2) + self.embed.weight.data[:, :num_features].uniform_() # Initialise scale at N(1, 0.02) + self.embed.weight.data[:, num_features:].zero_() # Initialise bias at 0 + else: + self.embed = nn.Embedding(num_classes, num_features) + self.embed.weight.data.uniform_() + + def forward(self, x, y): + if self.bias: + gamma, beta = self.embed(y).chunk(2, dim=-1) + out = gamma.view(-1, self.num_features, 1, 1) * x + beta.view(-1, self.num_features, 1, 1) + else: + gamma = self.embed(y) + out = gamma.view(-1, self.num_features, 1, 1) * x + return out + + +class NoneNorm2d(nn.Module): + def __init__(self, num_features, bias=True): + super().__init__() + + def forward(self, x): + return x + + +class InstanceNorm2dPlus(nn.Module): + def __init__(self, num_features, bias=True): + super().__init__() + self.num_features = num_features + self.bias = bias + self.instance_norm = nn.InstanceNorm2d(num_features, affine=False, track_running_stats=False) + self.alpha = nn.Parameter(torch.zeros(num_features)) + self.gamma = nn.Parameter(torch.zeros(num_features)) + self.alpha.data.normal_(1, 0.02) + self.gamma.data.normal_(1, 0.02) + if bias: + self.beta = nn.Parameter(torch.zeros(num_features)) + + def forward(self, x): + means = torch.mean(x, dim=(2, 3)) + m = torch.mean(means, dim=-1, keepdim=True) + v = torch.var(means, dim=-1, keepdim=True) + means = (means - m) / (torch.sqrt(v + 1e-5)) + h = self.instance_norm(x) + + if self.bias: + h = h + means[..., None, None] * self.alpha[..., None, None] + out = self.gamma.view(-1, self.num_features, 1, 1) * h + self.beta.view(-1, self.num_features, 1, 1) + else: + h = h + means[..., None, None] * self.alpha[..., None, None] + out = self.gamma.view(-1, self.num_features, 1, 1) * h + return out + + +class ConditionalInstanceNorm2dPlus(nn.Module): + def __init__(self, num_features, num_classes, bias=True): + super().__init__() + self.num_features = num_features + self.bias = bias + self.instance_norm = nn.InstanceNorm2d(num_features, affine=False, track_running_stats=False) + if bias: + self.embed = nn.Embedding(num_classes, num_features * 3) + self.embed.weight.data[:, :2 * num_features].normal_(1, 0.02) # Initialise scale at N(1, 0.02) + self.embed.weight.data[:, 2 * num_features:].zero_() # Initialise bias at 0 + else: + self.embed = nn.Embedding(num_classes, 2 * num_features) + self.embed.weight.data.normal_(1, 0.02) + + def forward(self, x, y): + means = torch.mean(x, dim=(2, 3)) + m = torch.mean(means, dim=-1, keepdim=True) + v = torch.var(means, dim=-1, keepdim=True) + means = (means - m) / (torch.sqrt(v + 1e-5)) + h = self.instance_norm(x) + + if self.bias: + gamma, alpha, beta = self.embed(y).chunk(3, dim=-1) + h = h + means[..., None, None] * alpha[..., None, None] + out = gamma.view(-1, self.num_features, 1, 1) * h + beta.view(-1, self.num_features, 1, 1) + else: + gamma, alpha = self.embed(y).chunk(2, dim=-1) + h = h + means[..., None, None] * alpha[..., None, None] + out = gamma.view(-1, self.num_features, 1, 1) * h + return out diff --git a/case_studies/diffpure/score_sde/models/up_or_down_sampling.py b/case_studies/diffpure/score_sde/models/up_or_down_sampling.py new file mode 100644 index 0000000..e5a88d5 --- /dev/null +++ b/case_studies/diffpure/score_sde/models/up_or_down_sampling.py @@ -0,0 +1,265 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/yang-song/score_sde_pytorch/blob/main/models/up_or_down_sampling.py +# +# The license for the original version of this file can be +# found in the `score_sde` directory (LICENSE_SCORE_SDE). +# --------------------------------------------------------------- + +"""Layers used for up-sampling or down-sampling images. + +Many functions are ported from https://github.com/NVlabs/stylegan2. +""" + +import torch.nn as nn +import torch +import torch.nn.functional as F +import numpy as np +from ..op import upfirdn2d + + +# Function ported from StyleGAN2 +def get_weight(module, + shape, + weight_var='weight', + kernel_init=None): + """Get/create weight tensor for a convolution or fully-connected layer.""" + + return module.param(weight_var, kernel_init, shape) + + +class Conv2d(nn.Module): + """Conv2d layer with optimal upsampling and downsampling (StyleGAN2).""" + + def __init__(self, in_ch, out_ch, kernel, up=False, down=False, + resample_kernel=(1, 3, 3, 1), + use_bias=True, + kernel_init=None): + super().__init__() + assert not (up and down) + assert kernel >= 1 and kernel % 2 == 1 + self.weight = nn.Parameter(torch.zeros(out_ch, in_ch, kernel, kernel)) + if kernel_init is not None: + self.weight.data = kernel_init(self.weight.data.shape) + if use_bias: + self.bias = nn.Parameter(torch.zeros(out_ch)) + + self.up = up + self.down = down + self.resample_kernel = resample_kernel + self.kernel = kernel + self.use_bias = use_bias + + def forward(self, x): + if self.up: + x = upsample_conv_2d(x, self.weight, k=self.resample_kernel) + elif self.down: + x = conv_downsample_2d(x, self.weight, k=self.resample_kernel) + else: + x = F.conv2d(x, self.weight, stride=1, padding=self.kernel // 2) + + if self.use_bias: + x = x + self.bias.reshape(1, -1, 1, 1) + + return x + + +def naive_upsample_2d(x, factor=2): + _N, C, H, W = x.shape + x = torch.reshape(x, (-1, C, H, 1, W, 1)) + x = x.repeat(1, 1, 1, factor, 1, factor) + return torch.reshape(x, (-1, C, H * factor, W * factor)) + + +def naive_downsample_2d(x, factor=2): + _N, C, H, W = x.shape + x = torch.reshape(x, (-1, C, H // factor, factor, W // factor, factor)) + return torch.mean(x, dim=(3, 5)) + + +def upsample_conv_2d(x, w, k=None, factor=2, gain=1): + """Fused `upsample_2d()` followed by `tf.nn.conv2d()`. + + Padding is performed only once at the beginning, not between the + operations. + The fused op is considerably more efficient than performing the same + calculation + using standard TensorFlow ops. It supports gradients of arbitrary order. + Args: + x: Input tensor of the shape `[N, C, H, W]` or `[N, H, W, + C]`. + w: Weight tensor of the shape `[filterH, filterW, inChannels, + outChannels]`. Grouped convolution can be performed by `inChannels = + x.shape[0] // numGroups`. + k: FIR filter of the shape `[firH, firW]` or `[firN]` + (separable). The default is `[1] * factor`, which corresponds to + nearest-neighbor upsampling. + factor: Integer upsampling factor (default: 2). + gain: Scaling factor for signal magnitude (default: 1.0). + + Returns: + Tensor of the shape `[N, C, H * factor, W * factor]` or + `[N, H * factor, W * factor, C]`, and same datatype as `x`. + """ + + assert isinstance(factor, int) and factor >= 1 + + # Check weight shape. + assert len(w.shape) == 4 + convH = w.shape[2] + convW = w.shape[3] + inC = w.shape[1] + outC = w.shape[0] + + assert convW == convH + + # Setup filter kernel. + if k is None: + k = [1] * factor + k = _setup_kernel(k) * (gain * (factor ** 2)) + p = (k.shape[0] - factor) - (convW - 1) + + stride = (factor, factor) + + # Determine data dimensions. + stride = [1, 1, factor, factor] + output_shape = ((_shape(x, 2) - 1) * factor + convH, (_shape(x, 3) - 1) * factor + convW) + output_padding = (output_shape[0] - (_shape(x, 2) - 1) * stride[0] - convH, + output_shape[1] - (_shape(x, 3) - 1) * stride[1] - convW) + assert output_padding[0] >= 0 and output_padding[1] >= 0 + num_groups = _shape(x, 1) // inC + + # Transpose weights. + w = torch.reshape(w, (num_groups, -1, inC, convH, convW)) + w = w[..., ::-1, ::-1].permute(0, 2, 1, 3, 4) + w = torch.reshape(w, (num_groups * inC, -1, convH, convW)) + + x = F.conv_transpose2d(x, w, stride=stride, output_padding=output_padding, padding=0) + ## Original TF code. + # x = tf.nn.conv2d_transpose( + # x, + # w, + # output_shape=output_shape, + # strides=stride, + # padding='VALID', + # data_format=data_format) + ## JAX equivalent + + return upfirdn2d(x, torch.tensor(k, device=x.device), + pad=((p + 1) // 2 + factor - 1, p // 2 + 1)) + + +def conv_downsample_2d(x, w, k=None, factor=2, gain=1): + """Fused `tf.nn.conv2d()` followed by `downsample_2d()`. + + Padding is performed only once at the beginning, not between the operations. + The fused op is considerably more efficient than performing the same + calculation + using standard TensorFlow ops. It supports gradients of arbitrary order. + Args: + x: Input tensor of the shape `[N, C, H, W]` or `[N, H, W, + C]`. + w: Weight tensor of the shape `[filterH, filterW, inChannels, + outChannels]`. Grouped convolution can be performed by `inChannels = + x.shape[0] // numGroups`. + k: FIR filter of the shape `[firH, firW]` or `[firN]` + (separable). The default is `[1] * factor`, which corresponds to + average pooling. + factor: Integer downsampling factor (default: 2). + gain: Scaling factor for signal magnitude (default: 1.0). + + Returns: + Tensor of the shape `[N, C, H // factor, W // factor]` or + `[N, H // factor, W // factor, C]`, and same datatype as `x`. + """ + + assert isinstance(factor, int) and factor >= 1 + _outC, _inC, convH, convW = w.shape + assert convW == convH + if k is None: + k = [1] * factor + k = _setup_kernel(k) * gain + p = (k.shape[0] - factor) + (convW - 1) + s = [factor, factor] + x = upfirdn2d(x, torch.tensor(k, device=x.device), + pad=((p + 1) // 2, p // 2)) + return F.conv2d(x, w, stride=s, padding=0) + + +def _setup_kernel(k): + k = np.asarray(k, dtype=np.float32) + if k.ndim == 1: + k = np.outer(k, k) + k /= np.sum(k) + assert k.ndim == 2 + assert k.shape[0] == k.shape[1] + return k + + +def _shape(x, dim): + return x.shape[dim] + + +def upsample_2d(x, k=None, factor=2, gain=1): + r"""Upsample a batch of 2D images with the given filter. + + Accepts a batch of 2D images of the shape `[N, C, H, W]` or `[N, H, W, C]` + and upsamples each image with the given filter. The filter is normalized so + that + if the input pixels are constant, they will be scaled by the specified + `gain`. + Pixels outside the image are assumed to be zero, and the filter is padded + with + zeros so that its shape is a multiple of the upsampling factor. + Args: + x: Input tensor of the shape `[N, C, H, W]` or `[N, H, W, + C]`. + k: FIR filter of the shape `[firH, firW]` or `[firN]` + (separable). The default is `[1] * factor`, which corresponds to + nearest-neighbor upsampling. + factor: Integer upsampling factor (default: 2). + gain: Scaling factor for signal magnitude (default: 1.0). + + Returns: + Tensor of the shape `[N, C, H * factor, W * factor]` + """ + assert isinstance(factor, int) and factor >= 1 + if k is None: + k = [1] * factor + k = _setup_kernel(k) * (gain * (factor ** 2)) + p = k.shape[0] - factor + return upfirdn2d(x, torch.tensor(k, device=x.device), + up=factor, pad=((p + 1) // 2 + factor - 1, p // 2)) + + +def downsample_2d(x, k=None, factor=2, gain=1): + r"""Downsample a batch of 2D images with the given filter. + + Accepts a batch of 2D images of the shape `[N, C, H, W]` or `[N, H, W, C]` + and downsamples each image with the given filter. The filter is normalized + so that + if the input pixels are constant, they will be scaled by the specified + `gain`. + Pixels outside the image are assumed to be zero, and the filter is padded + with + zeros so that its shape is a multiple of the downsampling factor. + Args: + x: Input tensor of the shape `[N, C, H, W]` or `[N, H, W, + C]`. + k: FIR filter of the shape `[firH, firW]` or `[firN]` + (separable). The default is `[1] * factor`, which corresponds to + average pooling. + factor: Integer downsampling factor (default: 2). + gain: Scaling factor for signal magnitude (default: 1.0). + + Returns: + Tensor of the shape `[N, C, H // factor, W // factor]` + """ + + assert isinstance(factor, int) and factor >= 1 + if k is None: + k = [1] * factor + k = _setup_kernel(k) * gain + p = k.shape[0] - factor + return upfirdn2d(x, torch.tensor(k, device=x.device), + down=factor, pad=((p + 1) // 2, p // 2)) diff --git a/case_studies/diffpure/score_sde/models/utils.py b/case_studies/diffpure/score_sde/models/utils.py new file mode 100644 index 0000000..b6ee60a --- /dev/null +++ b/case_studies/diffpure/score_sde/models/utils.py @@ -0,0 +1,187 @@ +# coding=utf-8 +# Copyright 2020 The Google Research Authors. +# +# 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. + +"""All functions and modules related to model definition. +""" + +import torch +from score_sde import sde_lib +import numpy as np + +_MODELS = {} + + +def register_model(cls=None, *, name=None): + """A decorator for registering model classes.""" + + def _register(cls): + if name is None: + local_name = cls.__name__ + else: + local_name = name + if local_name in _MODELS: + raise ValueError(f'Already registered model with name: {local_name}') + _MODELS[local_name] = cls + return cls + + if cls is None: + return _register + else: + return _register(cls) + + +def get_model(name): + return _MODELS[name] + + +def get_sigmas(config): + """Get sigmas --- the set of noise levels for SMLD from config files. + Args: + config: A ConfigDict object parsed from the config file + Returns: + sigmas: a jax numpy arrary of noise levels + """ + sigmas = np.exp( + np.linspace(np.log(config.model.sigma_max), np.log(config.model.sigma_min), config.model.num_scales)) + + return sigmas + + +def get_ddpm_params(config): + """Get betas and alphas --- parameters used in the original DDPM paper.""" + num_diffusion_timesteps = 1000 + # parameters need to be adapted if number of time steps differs from 1000 + beta_start = config.model.beta_min / config.model.num_scales + beta_end = config.model.beta_max / config.model.num_scales + betas = np.linspace(beta_start, beta_end, num_diffusion_timesteps, dtype=np.float64) + + alphas = 1. - betas + alphas_cumprod = np.cumprod(alphas, axis=0) + sqrt_alphas_cumprod = np.sqrt(alphas_cumprod) + sqrt_1m_alphas_cumprod = np.sqrt(1. - alphas_cumprod) + + return { + 'betas': betas, + 'alphas': alphas, + 'alphas_cumprod': alphas_cumprod, + 'sqrt_alphas_cumprod': sqrt_alphas_cumprod, + 'sqrt_1m_alphas_cumprod': sqrt_1m_alphas_cumprod, + 'beta_min': beta_start * (num_diffusion_timesteps - 1), + 'beta_max': beta_end * (num_diffusion_timesteps - 1), + 'num_diffusion_timesteps': num_diffusion_timesteps + } + + +def create_model(config): + """Create the score model.""" + model_name = config.model.name + score_model = get_model(model_name)(config) + # score_model = score_model.to(config.device) + # score_model = torch.nn.DataParallel(score_model) + return score_model + + +def get_model_fn(model, train=False): + """Create a function to give the output of the score-based model. + + Args: + model: The score model. + train: `True` for training and `False` for evaluation. + + Returns: + A model function. + """ + + def model_fn(x, labels): + """Compute the output of the score-based model. + + Args: + x: A mini-batch of input data. + labels: A mini-batch of conditioning variables for time steps. Should be interpreted differently + for different models. + + Returns: + A tuple of (model output, new mutable states) + """ + if not train: + model.eval() + return model(x, labels) + else: + model.train() + return model(x, labels) + + return model_fn + + +def get_score_fn(sde, model, train=False, continuous=False): + """Wraps `score_fn` so that the model output corresponds to a real time-dependent score function. + + Args: + sde: An `sde_lib.SDE` object that represents the forward SDE. + model: A score model. + train: `True` for training and `False` for evaluation. + continuous: If `True`, the score-based model is expected to directly take continuous time steps. + + Returns: + A score function. + """ + model_fn = get_model_fn(model, train=train) + + if isinstance(sde, sde_lib.VPSDE) or isinstance(sde, sde_lib.subVPSDE): + def score_fn(x, t): + # Scale neural network output by standard deviation and flip sign + if continuous or isinstance(sde, sde_lib.subVPSDE): + # For VP-trained models, t=0 corresponds to the lowest noise level + # The maximum value of time embedding is assumed to 999 for + # continuously-trained models. + labels = t * 999 + score = model_fn(x, labels) + std = sde.marginal_prob(torch.zeros_like(x), t)[1] + else: + # For VP-trained models, t=0 corresponds to the lowest noise level + labels = t * (sde.N - 1) + score = model_fn(x, labels) + std = sde.sqrt_1m_alphas_cumprod.to(labels.device)[labels.long()] + + score = -score / std[:, None, None, None] + return score + + elif isinstance(sde, sde_lib.VESDE): + def score_fn(x, t): + if continuous: + labels = sde.marginal_prob(torch.zeros_like(x), t)[1] + else: + # For VE-trained models, t=0 corresponds to the highest noise level + labels = sde.T - t + labels *= sde.N - 1 + labels = torch.round(labels).long() + + score = model_fn(x, labels) + return score + + else: + raise NotImplementedError(f"SDE class {sde.__class__.__name__} not yet supported.") + + return score_fn + + +def to_flattened_numpy(x): + """Flatten a torch tensor `x` and convert it to numpy.""" + return x.detach().cpu().numpy().reshape((-1,)) + + +def from_flattened_numpy(x, shape): + """Form a torch tensor with the given `shape` from a flattened numpy array `x`.""" + return torch.from_numpy(x.reshape(shape)) diff --git a/case_studies/diffpure/score_sde/op/__init__.py b/case_studies/diffpure/score_sde/op/__init__.py new file mode 100644 index 0000000..aa3a30e --- /dev/null +++ b/case_studies/diffpure/score_sde/op/__init__.py @@ -0,0 +1,10 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/yang-song/score_sde_pytorch/blob/main/op/__init__.py +# +# The license for the original version of this file can be +# found in the `score_sde` directory (LICENSE_SCORE_SDE). +# --------------------------------------------------------------- + +from .fused_act import FusedLeakyReLU, fused_leaky_relu +from .upfirdn2d import upfirdn2d diff --git a/case_studies/diffpure/score_sde/op/fused_act.py b/case_studies/diffpure/score_sde/op/fused_act.py new file mode 100644 index 0000000..10c90fc --- /dev/null +++ b/case_studies/diffpure/score_sde/op/fused_act.py @@ -0,0 +1,105 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/yang-song/score_sde_pytorch/blob/main/op/fused_act.py +# +# The license for the original version of this file can be +# found in the `score_sde` directory (LICENSE_SCORE_SDE). +# --------------------------------------------------------------- + +import os + +import torch +from torch import nn +from torch.nn import functional as F +from torch.autograd import Function +from torch.utils.cpp_extension import load + + +module_path = os.path.dirname(__file__) +fused = load( + "fused", + sources=[ + os.path.join(module_path, "fused_bias_act.cpp"), + os.path.join(module_path, "fused_bias_act_kernel.cu"), + ], +) + + +class FusedLeakyReLUFunctionBackward(Function): + @staticmethod + def forward(ctx, grad_output, out, negative_slope, scale): + ctx.save_for_backward(out) + ctx.negative_slope = negative_slope + ctx.scale = scale + + empty = grad_output.new_empty(0) + + grad_input = fused.fused_bias_act( + grad_output, empty, out, 3, 1, negative_slope, scale + ) + + dim = [0] + + if grad_input.ndim > 2: + dim += list(range(2, grad_input.ndim)) + + grad_bias = grad_input.sum(dim).detach() + + return grad_input, grad_bias + + @staticmethod + def backward(ctx, gradgrad_input, gradgrad_bias): + out, = ctx.saved_tensors + gradgrad_out = fused.fused_bias_act( + gradgrad_input, gradgrad_bias, out, 3, 1, ctx.negative_slope, ctx.scale + ) + + return gradgrad_out, None, None, None + + +class FusedLeakyReLUFunction(Function): + @staticmethod + def forward(ctx, input, bias, negative_slope, scale): + empty = input.new_empty(0) + out = fused.fused_bias_act(input, bias, empty, 3, 0, negative_slope, scale) + ctx.save_for_backward(out) + ctx.negative_slope = negative_slope + ctx.scale = scale + + return out + + @staticmethod + def backward(ctx, grad_output): + out, = ctx.saved_tensors + + grad_input, grad_bias = FusedLeakyReLUFunctionBackward.apply( + grad_output, out, ctx.negative_slope, ctx.scale + ) + + return grad_input, grad_bias, None, None + + +class FusedLeakyReLU(nn.Module): + def __init__(self, channel, negative_slope=0.2, scale=2 ** 0.5): + super().__init__() + + self.bias = nn.Parameter(torch.zeros(channel)) + self.negative_slope = negative_slope + self.scale = scale + + def forward(self, input): + return fused_leaky_relu(input, self.bias, self.negative_slope, self.scale) + + +def fused_leaky_relu(input, bias, negative_slope=0.2, scale=2 ** 0.5): + if input.device.type == "cpu": + rest_dim = [1] * (input.ndim - bias.ndim - 1) + return ( + F.leaky_relu( + input + bias.view(1, bias.shape[0], *rest_dim), negative_slope=0.2 + ) + * scale + ) + + else: + return FusedLeakyReLUFunction.apply(input, bias, negative_slope, scale) diff --git a/case_studies/diffpure/score_sde/op/fused_bias_act.cpp b/case_studies/diffpure/score_sde/op/fused_bias_act.cpp new file mode 100644 index 0000000..d7f951e --- /dev/null +++ b/case_studies/diffpure/score_sde/op/fused_bias_act.cpp @@ -0,0 +1,29 @@ +// --------------------------------------------------------------- +// Taken from the following link as is from: +// https://github.com/yang-song/score_sde_pytorch/blob/main/op/fused_bias_act.cpp +// +// The license for the original version of this file can be +// found in the `score_sde` directory (LICENSE_SCORE_SDE). +// --------------------------------------------------------------- + +#include + + +torch::Tensor fused_bias_act_op(const torch::Tensor& input, const torch::Tensor& bias, const torch::Tensor& refer, + int act, int grad, float alpha, float scale); + +#define CHECK_CUDA(x) TORCH_CHECK(x.type().is_cuda(), #x " must be a CUDA tensor") +#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x " must be contiguous") +#define CHECK_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) + +torch::Tensor fused_bias_act(const torch::Tensor& input, const torch::Tensor& bias, const torch::Tensor& refer, + int act, int grad, float alpha, float scale) { + CHECK_CUDA(input); + CHECK_CUDA(bias); + + return fused_bias_act_op(input, bias, refer, act, grad, alpha, scale); +} + +PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { + m.def("fused_bias_act", &fused_bias_act, "fused bias act (CUDA)"); +} \ No newline at end of file diff --git a/case_studies/diffpure/score_sde/op/fused_bias_act_kernel.cu b/case_studies/diffpure/score_sde/op/fused_bias_act_kernel.cu new file mode 100644 index 0000000..c9fa56f --- /dev/null +++ b/case_studies/diffpure/score_sde/op/fused_bias_act_kernel.cu @@ -0,0 +1,99 @@ +// Copyright (c) 2019, NVIDIA Corporation. All rights reserved. +// +// This work is made available under the Nvidia Source Code License-NC. +// To view a copy of this license, visit +// https://nvlabs.github.io/stylegan2/license.html + +#include + +#include +#include +#include +#include + +#include +#include + + +template +static __global__ void fused_bias_act_kernel(scalar_t* out, const scalar_t* p_x, const scalar_t* p_b, const scalar_t* p_ref, + int act, int grad, scalar_t alpha, scalar_t scale, int loop_x, int size_x, int step_b, int size_b, int use_bias, int use_ref) { + int xi = blockIdx.x * loop_x * blockDim.x + threadIdx.x; + + scalar_t zero = 0.0; + + for (int loop_idx = 0; loop_idx < loop_x && xi < size_x; loop_idx++, xi += blockDim.x) { + scalar_t x = p_x[xi]; + + if (use_bias) { + x += p_b[(xi / step_b) % size_b]; + } + + scalar_t ref = use_ref ? p_ref[xi] : zero; + + scalar_t y; + + switch (act * 10 + grad) { + default: + case 10: y = x; break; + case 11: y = x; break; + case 12: y = 0.0; break; + + case 30: y = (x > 0.0) ? x : x * alpha; break; + case 31: y = (ref > 0.0) ? x : x * alpha; break; + case 32: y = 0.0; break; + } + + out[xi] = y * scale; + } +} + + +torch::Tensor fused_bias_act_op(const torch::Tensor& input, const torch::Tensor& bias, const torch::Tensor& refer, + int act, int grad, float alpha, float scale) { + int curDevice = -1; + cudaGetDevice(&curDevice); + cudaStream_t stream = at::cuda::getCurrentCUDAStream(curDevice); + + auto x = input.contiguous(); + auto b = bias.contiguous(); + auto ref = refer.contiguous(); + + int use_bias = b.numel() ? 1 : 0; + int use_ref = ref.numel() ? 1 : 0; + + int size_x = x.numel(); + int size_b = b.numel(); + int step_b = 1; + + for (int i = 1 + 1; i < x.dim(); i++) { + step_b *= x.size(i); + } + + int loop_x = 4; + int block_size = 4 * 32; + int grid_size = (size_x - 1) / (loop_x * block_size) + 1; + + auto y = torch::empty_like(x); + + AT_DISPATCH_FLOATING_TYPES_AND_HALF(x.scalar_type(), "fused_bias_act_kernel", [&] { + fused_bias_act_kernel<<>>( + y.data_ptr(), + x.data_ptr(), + b.data_ptr(), + ref.data_ptr(), + act, + grad, + alpha, + scale, + loop_x, + size_x, + step_b, + size_b, + use_bias, + use_ref + ); + }); + + return y; +} \ No newline at end of file diff --git a/case_studies/diffpure/score_sde/op/upfirdn2d.cpp b/case_studies/diffpure/score_sde/op/upfirdn2d.cpp new file mode 100644 index 0000000..294cda5 --- /dev/null +++ b/case_studies/diffpure/score_sde/op/upfirdn2d.cpp @@ -0,0 +1,31 @@ +// --------------------------------------------------------------- +// Taken from the following link as is from: +// https://github.com/yang-song/score_sde_pytorch/blob/main/op/upfirdn2d.cpp +// +// The license for the original version of this file can be +// found in the `score_sde` directory (LICENSE_SCORE_SDE). +// --------------------------------------------------------------- + +#include + + +torch::Tensor upfirdn2d_op(const torch::Tensor& input, const torch::Tensor& kernel, + int up_x, int up_y, int down_x, int down_y, + int pad_x0, int pad_x1, int pad_y0, int pad_y1); + +#define CHECK_CUDA(x) TORCH_CHECK(x.type().is_cuda(), #x " must be a CUDA tensor") +#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x " must be contiguous") +#define CHECK_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) + +torch::Tensor upfirdn2d(const torch::Tensor& input, const torch::Tensor& kernel, + int up_x, int up_y, int down_x, int down_y, + int pad_x0, int pad_x1, int pad_y0, int pad_y1) { + CHECK_CUDA(input); + CHECK_CUDA(kernel); + + return upfirdn2d_op(input, kernel, up_x, up_y, down_x, down_y, pad_x0, pad_x1, pad_y0, pad_y1); +} + +PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { + m.def("upfirdn2d", &upfirdn2d, "upfirdn2d (CUDA)"); +} \ No newline at end of file diff --git a/case_studies/diffpure/score_sde/op/upfirdn2d.py b/case_studies/diffpure/score_sde/op/upfirdn2d.py new file mode 100644 index 0000000..bc53c65 --- /dev/null +++ b/case_studies/diffpure/score_sde/op/upfirdn2d.py @@ -0,0 +1,208 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/yang-song/score_sde_pytorch/blob/main/op/upfirdn2d.py +# +# The license for the original version of this file can be +# found in the `score_sde` directory (LICENSE_SCORE_SDE). +# --------------------------------------------------------------- + +import os + +import torch +from torch.nn import functional as F +from torch.autograd import Function +from torch.utils.cpp_extension import load + + +module_path = os.path.dirname(__file__) +upfirdn2d_op = load( + "upfirdn2d", + sources=[ + os.path.join(module_path, "upfirdn2d.cpp"), + os.path.join(module_path, "upfirdn2d_kernel.cu"), + ], +) + + +class UpFirDn2dBackward(Function): + @staticmethod + def forward( + ctx, grad_output, kernel, grad_kernel, up, down, pad, g_pad, in_size, out_size + ): + + up_x, up_y = up + down_x, down_y = down + g_pad_x0, g_pad_x1, g_pad_y0, g_pad_y1 = g_pad + + grad_output = grad_output.reshape(-1, out_size[0], out_size[1], 1) + + grad_input = upfirdn2d_op.upfirdn2d( + grad_output, + grad_kernel, + down_x, + down_y, + up_x, + up_y, + g_pad_x0, + g_pad_x1, + g_pad_y0, + g_pad_y1, + ) + grad_input = grad_input.view(in_size[0], in_size[1], in_size[2], in_size[3]) + + ctx.save_for_backward(kernel) + + pad_x0, pad_x1, pad_y0, pad_y1 = pad + + ctx.up_x = up_x + ctx.up_y = up_y + ctx.down_x = down_x + ctx.down_y = down_y + ctx.pad_x0 = pad_x0 + ctx.pad_x1 = pad_x1 + ctx.pad_y0 = pad_y0 + ctx.pad_y1 = pad_y1 + ctx.in_size = in_size + ctx.out_size = out_size + + return grad_input + + @staticmethod + def backward(ctx, gradgrad_input): + kernel, = ctx.saved_tensors + + gradgrad_input = gradgrad_input.reshape(-1, ctx.in_size[2], ctx.in_size[3], 1) + + gradgrad_out = upfirdn2d_op.upfirdn2d( + gradgrad_input, + kernel, + ctx.up_x, + ctx.up_y, + ctx.down_x, + ctx.down_y, + ctx.pad_x0, + ctx.pad_x1, + ctx.pad_y0, + ctx.pad_y1, + ) + # gradgrad_out = gradgrad_out.view(ctx.in_size[0], ctx.out_size[0], ctx.out_size[1], ctx.in_size[3]) + gradgrad_out = gradgrad_out.view( + ctx.in_size[0], ctx.in_size[1], ctx.out_size[0], ctx.out_size[1] + ) + + return gradgrad_out, None, None, None, None, None, None, None, None + + +class UpFirDn2d(Function): + @staticmethod + def forward(ctx, input, kernel, up, down, pad): + up_x, up_y = up + down_x, down_y = down + pad_x0, pad_x1, pad_y0, pad_y1 = pad + + kernel_h, kernel_w = kernel.shape + batch, channel, in_h, in_w = input.shape + ctx.in_size = input.shape + + input = input.reshape(-1, in_h, in_w, 1) + + ctx.save_for_backward(kernel, torch.flip(kernel, [0, 1])) + + out_h = (in_h * up_y + pad_y0 + pad_y1 - kernel_h) // down_y + 1 + out_w = (in_w * up_x + pad_x0 + pad_x1 - kernel_w) // down_x + 1 + ctx.out_size = (out_h, out_w) + + ctx.up = (up_x, up_y) + ctx.down = (down_x, down_y) + ctx.pad = (pad_x0, pad_x1, pad_y0, pad_y1) + + g_pad_x0 = kernel_w - pad_x0 - 1 + g_pad_y0 = kernel_h - pad_y0 - 1 + g_pad_x1 = in_w * up_x - out_w * down_x + pad_x0 - up_x + 1 + g_pad_y1 = in_h * up_y - out_h * down_y + pad_y0 - up_y + 1 + + ctx.g_pad = (g_pad_x0, g_pad_x1, g_pad_y0, g_pad_y1) + + out = upfirdn2d_op.upfirdn2d( + input, kernel, up_x, up_y, down_x, down_y, pad_x0, pad_x1, pad_y0, pad_y1 + ) + # out = out.view(major, out_h, out_w, minor) + out = out.view(-1, channel, out_h, out_w) + + return out + + @staticmethod + def backward(ctx, grad_output): + kernel, grad_kernel = ctx.saved_tensors + + grad_input = UpFirDn2dBackward.apply( + grad_output, + kernel, + grad_kernel, + ctx.up, + ctx.down, + ctx.pad, + ctx.g_pad, + ctx.in_size, + ctx.out_size, + ) + + return grad_input, None, None, None, None + + +def upfirdn2d(input, kernel, up=1, down=1, pad=(0, 0)): + if input.device.type == "cpu": + out = upfirdn2d_native( + input, kernel, up, up, down, down, pad[0], pad[1], pad[0], pad[1] + ) + + else: + out = UpFirDn2d.apply( + input, kernel, (up, up), (down, down), (pad[0], pad[1], pad[0], pad[1]) + ) + + return out + + +def upfirdn2d_native( + input, kernel, up_x, up_y, down_x, down_y, pad_x0, pad_x1, pad_y0, pad_y1 +): + _, channel, in_h, in_w = input.shape + input = input.reshape(-1, in_h, in_w, 1) + + _, in_h, in_w, minor = input.shape + kernel_h, kernel_w = kernel.shape + + out = input.view(-1, in_h, 1, in_w, 1, minor) + out = F.pad(out, [0, 0, 0, up_x - 1, 0, 0, 0, up_y - 1]) + out = out.view(-1, in_h * up_y, in_w * up_x, minor) + + out = F.pad( + out, [0, 0, max(pad_x0, 0), max(pad_x1, 0), max(pad_y0, 0), max(pad_y1, 0)] + ) + out = out[ + :, + max(-pad_y0, 0) : out.shape[1] - max(-pad_y1, 0), + max(-pad_x0, 0) : out.shape[2] - max(-pad_x1, 0), + :, + ] + + out = out.permute(0, 3, 1, 2) + out = out.reshape( + [-1, 1, in_h * up_y + pad_y0 + pad_y1, in_w * up_x + pad_x0 + pad_x1] + ) + w = torch.flip(kernel, [0, 1]).view(1, 1, kernel_h, kernel_w) + out = F.conv2d(out, w) + out = out.reshape( + -1, + minor, + in_h * up_y + pad_y0 + pad_y1 - kernel_h + 1, + in_w * up_x + pad_x0 + pad_x1 - kernel_w + 1, + ) + out = out.permute(0, 2, 3, 1) + out = out[:, ::down_y, ::down_x, :] + + out_h = (in_h * up_y + pad_y0 + pad_y1 - kernel_h) // down_y + 1 + out_w = (in_w * up_x + pad_x0 + pad_x1 - kernel_w) // down_x + 1 + + return out.view(-1, channel, out_h, out_w) diff --git a/case_studies/diffpure/score_sde/op/upfirdn2d_kernel.cu b/case_studies/diffpure/score_sde/op/upfirdn2d_kernel.cu new file mode 100644 index 0000000..a88bc77 --- /dev/null +++ b/case_studies/diffpure/score_sde/op/upfirdn2d_kernel.cu @@ -0,0 +1,369 @@ +// Copyright (c) 2019, NVIDIA Corporation. All rights reserved. +// +// This work is made available under the Nvidia Source Code License-NC. +// To view a copy of this license, visit +// https://nvlabs.github.io/stylegan2/license.html + +#include + +#include +#include +#include +#include + +#include +#include + +static __host__ __device__ __forceinline__ int floor_div(int a, int b) { + int c = a / b; + + if (c * b > a) { + c--; + } + + return c; +} + +struct UpFirDn2DKernelParams { + int up_x; + int up_y; + int down_x; + int down_y; + int pad_x0; + int pad_x1; + int pad_y0; + int pad_y1; + + int major_dim; + int in_h; + int in_w; + int minor_dim; + int kernel_h; + int kernel_w; + int out_h; + int out_w; + int loop_major; + int loop_x; +}; + +template +__global__ void upfirdn2d_kernel_large(scalar_t *out, const scalar_t *input, + const scalar_t *kernel, + const UpFirDn2DKernelParams p) { + int minor_idx = blockIdx.x * blockDim.x + threadIdx.x; + int out_y = minor_idx / p.minor_dim; + minor_idx -= out_y * p.minor_dim; + int out_x_base = blockIdx.y * p.loop_x * blockDim.y + threadIdx.y; + int major_idx_base = blockIdx.z * p.loop_major; + + if (out_x_base >= p.out_w || out_y >= p.out_h || + major_idx_base >= p.major_dim) { + return; + } + + int mid_y = out_y * p.down_y + p.up_y - 1 - p.pad_y0; + int in_y = min(max(floor_div(mid_y, p.up_y), 0), p.in_h); + int h = min(max(floor_div(mid_y + p.kernel_h, p.up_y), 0), p.in_h) - in_y; + int kernel_y = mid_y + p.kernel_h - (in_y + 1) * p.up_y; + + for (int loop_major = 0, major_idx = major_idx_base; + loop_major < p.loop_major && major_idx < p.major_dim; + loop_major++, major_idx++) { + for (int loop_x = 0, out_x = out_x_base; + loop_x < p.loop_x && out_x < p.out_w; loop_x++, out_x += blockDim.y) { + int mid_x = out_x * p.down_x + p.up_x - 1 - p.pad_x0; + int in_x = min(max(floor_div(mid_x, p.up_x), 0), p.in_w); + int w = min(max(floor_div(mid_x + p.kernel_w, p.up_x), 0), p.in_w) - in_x; + int kernel_x = mid_x + p.kernel_w - (in_x + 1) * p.up_x; + + const scalar_t *x_p = + &input[((major_idx * p.in_h + in_y) * p.in_w + in_x) * p.minor_dim + + minor_idx]; + const scalar_t *k_p = &kernel[kernel_y * p.kernel_w + kernel_x]; + int x_px = p.minor_dim; + int k_px = -p.up_x; + int x_py = p.in_w * p.minor_dim; + int k_py = -p.up_y * p.kernel_w; + + scalar_t v = 0.0f; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + v += static_cast(*x_p) * static_cast(*k_p); + x_p += x_px; + k_p += k_px; + } + + x_p += x_py - w * x_px; + k_p += k_py - w * k_px; + } + + out[((major_idx * p.out_h + out_y) * p.out_w + out_x) * p.minor_dim + + minor_idx] = v; + } + } +} + +template +__global__ void upfirdn2d_kernel(scalar_t *out, const scalar_t *input, + const scalar_t *kernel, + const UpFirDn2DKernelParams p) { + const int tile_in_h = ((tile_out_h - 1) * down_y + kernel_h - 1) / up_y + 1; + const int tile_in_w = ((tile_out_w - 1) * down_x + kernel_w - 1) / up_x + 1; + + __shared__ volatile float sk[kernel_h][kernel_w]; + __shared__ volatile float sx[tile_in_h][tile_in_w]; + + int minor_idx = blockIdx.x; + int tile_out_y = minor_idx / p.minor_dim; + minor_idx -= tile_out_y * p.minor_dim; + tile_out_y *= tile_out_h; + int tile_out_x_base = blockIdx.y * p.loop_x * tile_out_w; + int major_idx_base = blockIdx.z * p.loop_major; + + if (tile_out_x_base >= p.out_w | tile_out_y >= p.out_h | + major_idx_base >= p.major_dim) { + return; + } + + for (int tap_idx = threadIdx.x; tap_idx < kernel_h * kernel_w; + tap_idx += blockDim.x) { + int ky = tap_idx / kernel_w; + int kx = tap_idx - ky * kernel_w; + scalar_t v = 0.0; + + if (kx < p.kernel_w & ky < p.kernel_h) { + v = kernel[(p.kernel_h - 1 - ky) * p.kernel_w + (p.kernel_w - 1 - kx)]; + } + + sk[ky][kx] = v; + } + + for (int loop_major = 0, major_idx = major_idx_base; + loop_major < p.loop_major & major_idx < p.major_dim; + loop_major++, major_idx++) { + for (int loop_x = 0, tile_out_x = tile_out_x_base; + loop_x < p.loop_x & tile_out_x < p.out_w; + loop_x++, tile_out_x += tile_out_w) { + int tile_mid_x = tile_out_x * down_x + up_x - 1 - p.pad_x0; + int tile_mid_y = tile_out_y * down_y + up_y - 1 - p.pad_y0; + int tile_in_x = floor_div(tile_mid_x, up_x); + int tile_in_y = floor_div(tile_mid_y, up_y); + + __syncthreads(); + + for (int in_idx = threadIdx.x; in_idx < tile_in_h * tile_in_w; + in_idx += blockDim.x) { + int rel_in_y = in_idx / tile_in_w; + int rel_in_x = in_idx - rel_in_y * tile_in_w; + int in_x = rel_in_x + tile_in_x; + int in_y = rel_in_y + tile_in_y; + + scalar_t v = 0.0; + + if (in_x >= 0 & in_y >= 0 & in_x < p.in_w & in_y < p.in_h) { + v = input[((major_idx * p.in_h + in_y) * p.in_w + in_x) * + p.minor_dim + + minor_idx]; + } + + sx[rel_in_y][rel_in_x] = v; + } + + __syncthreads(); + for (int out_idx = threadIdx.x; out_idx < tile_out_h * tile_out_w; + out_idx += blockDim.x) { + int rel_out_y = out_idx / tile_out_w; + int rel_out_x = out_idx - rel_out_y * tile_out_w; + int out_x = rel_out_x + tile_out_x; + int out_y = rel_out_y + tile_out_y; + + int mid_x = tile_mid_x + rel_out_x * down_x; + int mid_y = tile_mid_y + rel_out_y * down_y; + int in_x = floor_div(mid_x, up_x); + int in_y = floor_div(mid_y, up_y); + int rel_in_x = in_x - tile_in_x; + int rel_in_y = in_y - tile_in_y; + int kernel_x = (in_x + 1) * up_x - mid_x - 1; + int kernel_y = (in_y + 1) * up_y - mid_y - 1; + + scalar_t v = 0.0; + +#pragma unroll + for (int y = 0; y < kernel_h / up_y; y++) +#pragma unroll + for (int x = 0; x < kernel_w / up_x; x++) + v += sx[rel_in_y + y][rel_in_x + x] * + sk[kernel_y + y * up_y][kernel_x + x * up_x]; + + if (out_x < p.out_w & out_y < p.out_h) { + out[((major_idx * p.out_h + out_y) * p.out_w + out_x) * p.minor_dim + + minor_idx] = v; + } + } + } + } +} + +torch::Tensor upfirdn2d_op(const torch::Tensor &input, + const torch::Tensor &kernel, int up_x, int up_y, + int down_x, int down_y, int pad_x0, int pad_x1, + int pad_y0, int pad_y1) { + int curDevice = -1; + cudaGetDevice(&curDevice); + cudaStream_t stream = at::cuda::getCurrentCUDAStream(curDevice); + + UpFirDn2DKernelParams p; + + auto x = input.contiguous(); + auto k = kernel.contiguous(); + + p.major_dim = x.size(0); + p.in_h = x.size(1); + p.in_w = x.size(2); + p.minor_dim = x.size(3); + p.kernel_h = k.size(0); + p.kernel_w = k.size(1); + p.up_x = up_x; + p.up_y = up_y; + p.down_x = down_x; + p.down_y = down_y; + p.pad_x0 = pad_x0; + p.pad_x1 = pad_x1; + p.pad_y0 = pad_y0; + p.pad_y1 = pad_y1; + + p.out_h = (p.in_h * p.up_y + p.pad_y0 + p.pad_y1 - p.kernel_h + p.down_y) / + p.down_y; + p.out_w = (p.in_w * p.up_x + p.pad_x0 + p.pad_x1 - p.kernel_w + p.down_x) / + p.down_x; + + auto out = + at::empty({p.major_dim, p.out_h, p.out_w, p.minor_dim}, x.options()); + + int mode = -1; + + int tile_out_h = -1; + int tile_out_w = -1; + + if (p.up_x == 1 && p.up_y == 1 && p.down_x == 1 && p.down_y == 1 && + p.kernel_h <= 4 && p.kernel_w <= 4) { + mode = 1; + tile_out_h = 16; + tile_out_w = 64; + } + + if (p.up_x == 1 && p.up_y == 1 && p.down_x == 1 && p.down_y == 1 && + p.kernel_h <= 3 && p.kernel_w <= 3) { + mode = 2; + tile_out_h = 16; + tile_out_w = 64; + } + + if (p.up_x == 2 && p.up_y == 2 && p.down_x == 1 && p.down_y == 1 && + p.kernel_h <= 4 && p.kernel_w <= 4) { + mode = 3; + tile_out_h = 16; + tile_out_w = 64; + } + + if (p.up_x == 2 && p.up_y == 2 && p.down_x == 1 && p.down_y == 1 && + p.kernel_h <= 2 && p.kernel_w <= 2) { + mode = 4; + tile_out_h = 16; + tile_out_w = 64; + } + + if (p.up_x == 1 && p.up_y == 1 && p.down_x == 2 && p.down_y == 2 && + p.kernel_h <= 4 && p.kernel_w <= 4) { + mode = 5; + tile_out_h = 8; + tile_out_w = 32; + } + + if (p.up_x == 1 && p.up_y == 1 && p.down_x == 2 && p.down_y == 2 && + p.kernel_h <= 2 && p.kernel_w <= 2) { + mode = 6; + tile_out_h = 8; + tile_out_w = 32; + } + + dim3 block_size; + dim3 grid_size; + + if (tile_out_h > 0 && tile_out_w > 0) { + p.loop_major = (p.major_dim - 1) / 16384 + 1; + p.loop_x = 1; + block_size = dim3(32 * 8, 1, 1); + grid_size = dim3(((p.out_h - 1) / tile_out_h + 1) * p.minor_dim, + (p.out_w - 1) / (p.loop_x * tile_out_w) + 1, + (p.major_dim - 1) / p.loop_major + 1); + } else { + p.loop_major = (p.major_dim - 1) / 16384 + 1; + p.loop_x = 4; + block_size = dim3(4, 32, 1); + grid_size = dim3((p.out_h * p.minor_dim - 1) / block_size.x + 1, + (p.out_w - 1) / (p.loop_x * block_size.y) + 1, + (p.major_dim - 1) / p.loop_major + 1); + } + + AT_DISPATCH_FLOATING_TYPES_AND_HALF(x.scalar_type(), "upfirdn2d_cuda", [&] { + switch (mode) { + case 1: + upfirdn2d_kernel + <<>>(out.data_ptr(), + x.data_ptr(), + k.data_ptr(), p); + + break; + + case 2: + upfirdn2d_kernel + <<>>(out.data_ptr(), + x.data_ptr(), + k.data_ptr(), p); + + break; + + case 3: + upfirdn2d_kernel + <<>>(out.data_ptr(), + x.data_ptr(), + k.data_ptr(), p); + + break; + + case 4: + upfirdn2d_kernel + <<>>(out.data_ptr(), + x.data_ptr(), + k.data_ptr(), p); + + break; + + case 5: + upfirdn2d_kernel + <<>>(out.data_ptr(), + x.data_ptr(), + k.data_ptr(), p); + + break; + + case 6: + upfirdn2d_kernel + <<>>(out.data_ptr(), + x.data_ptr(), + k.data_ptr(), p); + + break; + + default: + upfirdn2d_kernel_large<<>>( + out.data_ptr(), x.data_ptr(), + k.data_ptr(), p); + } + }); + + return out; +} \ No newline at end of file diff --git a/case_studies/diffpure/score_sde/sampling.py b/case_studies/diffpure/score_sde/sampling.py new file mode 100644 index 0000000..8454dc7 --- /dev/null +++ b/case_studies/diffpure/score_sde/sampling.py @@ -0,0 +1,485 @@ +# coding=utf-8 +# Copyright 2020 The Google Research Authors. +# +# 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. + +# pylint: skip-file +# pytype: skip-file +"""Various sampling methods.""" +import functools + +import torch +import numpy as np +import abc + +from .models.utils import from_flattened_numpy, to_flattened_numpy, get_score_fn +from scipy import integrate +from . import sde_lib +from .models import utils as mutils + +_CORRECTORS = {} +_PREDICTORS = {} + + +def register_predictor(cls=None, *, name=None): + """A decorator for registering predictor classes.""" + + def _register(cls): + if name is None: + local_name = cls.__name__ + else: + local_name = name + if local_name in _PREDICTORS: + raise ValueError(f'Already registered model with name: {local_name}') + _PREDICTORS[local_name] = cls + return cls + + if cls is None: + return _register + else: + return _register(cls) + + +def register_corrector(cls=None, *, name=None): + """A decorator for registering corrector classes.""" + + def _register(cls): + if name is None: + local_name = cls.__name__ + else: + local_name = name + if local_name in _CORRECTORS: + raise ValueError(f'Already registered model with name: {local_name}') + _CORRECTORS[local_name] = cls + return cls + + if cls is None: + return _register + else: + return _register(cls) + + +def get_predictor(name): + return _PREDICTORS[name] + + +def get_corrector(name): + return _CORRECTORS[name] + + +def get_sampling_fn(config, sde, shape, inverse_scaler, eps): + """Create a sampling function. + + Args: + config: A `ml_collections.ConfigDict` object that contains all configuration information. + sde: A `sde_lib.SDE` object that represents the forward SDE. + shape: A sequence of integers representing the expected shape of a single sample. + inverse_scaler: The inverse data normalizer function. + eps: A `float` number. The reverse-time SDE is only integrated to `eps` for numerical stability. + + Returns: + A function that takes random states and a replicated training state and outputs samples with the + trailing dimensions matching `shape`. + """ + + sampler_name = config.sampling.method + # Probability flow ODE sampling with black-box ODE solvers + if sampler_name.lower() == 'ode': + sampling_fn = get_ode_sampler(sde=sde, + shape=shape, + inverse_scaler=inverse_scaler, + denoise=config.sampling.noise_removal, + eps=eps, + device=config.device) + # Predictor-Corrector sampling. Predictor-only and Corrector-only samplers are special cases. + elif sampler_name.lower() == 'pc': + predictor = get_predictor(config.sampling.predictor.lower()) + corrector = get_corrector(config.sampling.corrector.lower()) + sampling_fn = get_pc_sampler(sde=sde, + shape=shape, + predictor=predictor, + corrector=corrector, + inverse_scaler=inverse_scaler, + snr=config.sampling.snr, + n_steps=config.sampling.n_steps_each, + probability_flow=config.sampling.probability_flow, + continuous=config.training.continuous, + denoise=config.sampling.noise_removal, + eps=eps, + device=config.device) + else: + raise ValueError(f"Sampler name {sampler_name} unknown.") + + return sampling_fn + + +class Predictor(abc.ABC): + """The abstract class for a predictor algorithm.""" + + def __init__(self, sde, score_fn, probability_flow=False): + super().__init__() + self.sde = sde + # Compute the reverse SDE/ODE + self.rsde = sde.reverse(score_fn, probability_flow) + self.score_fn = score_fn + + @abc.abstractmethod + def update_fn(self, x, t): + """One update of the predictor. + + Args: + x: A PyTorch tensor representing the current state + t: A Pytorch tensor representing the current time step. + + Returns: + x: A PyTorch tensor of the next state. + x_mean: A PyTorch tensor. The next state without random noise. Useful for denoising. + """ + pass + + +class Corrector(abc.ABC): + """The abstract class for a corrector algorithm.""" + + def __init__(self, sde, score_fn, snr, n_steps): + super().__init__() + self.sde = sde + self.score_fn = score_fn + self.snr = snr + self.n_steps = n_steps + + @abc.abstractmethod + def update_fn(self, x, t): + """One update of the corrector. + + Args: + x: A PyTorch tensor representing the current state + t: A PyTorch tensor representing the current time step. + + Returns: + x: A PyTorch tensor of the next state. + x_mean: A PyTorch tensor. The next state without random noise. Useful for denoising. + """ + pass + + +@register_predictor(name='euler_maruyama') +class EulerMaruyamaPredictor(Predictor): + def __init__(self, sde, score_fn, probability_flow=False): + super().__init__(sde, score_fn, probability_flow) + + def update_fn(self, x, t): + dt = -1. / self.rsde.N + z = torch.randn_like(x) + drift, diffusion = self.rsde.sde(x, t) + x_mean = x + drift * dt + x = x_mean + diffusion[:, None, None, None] * np.sqrt(-dt) * z + return x, x_mean + + +@register_predictor(name='reverse_diffusion') +class ReverseDiffusionPredictor(Predictor): + def __init__(self, sde, score_fn, probability_flow=False): + super().__init__(sde, score_fn, probability_flow) + + def update_fn(self, x, t): + f, G = self.rsde.discretize(x, t) + z = torch.randn_like(x) + x_mean = x - f + x = x_mean + G[:, None, None, None] * z + return x, x_mean + + +@register_predictor(name='ancestral_sampling') +class AncestralSamplingPredictor(Predictor): + """The ancestral sampling predictor. Currently only supports VE/VP SDEs.""" + + def __init__(self, sde, score_fn, probability_flow=False): + super().__init__(sde, score_fn, probability_flow) + if not isinstance(sde, sde_lib.VPSDE) and not isinstance(sde, sde_lib.VESDE): + raise NotImplementedError(f"SDE class {sde.__class__.__name__} not yet supported.") + assert not probability_flow, "Probability flow not supported by ancestral sampling" + + def vesde_update_fn(self, x, t): + sde = self.sde + timestep = (t * (sde.N - 1) / sde.T).long() + sigma = sde.discrete_sigmas[timestep] + adjacent_sigma = torch.where(timestep == 0, torch.zeros_like(t), sde.discrete_sigmas.to(t.device)[timestep - 1]) + score = self.score_fn(x, t) + x_mean = x + score * (sigma ** 2 - adjacent_sigma ** 2)[:, None, None, None] + std = torch.sqrt((adjacent_sigma ** 2 * (sigma ** 2 - adjacent_sigma ** 2)) / (sigma ** 2)) + noise = torch.randn_like(x) + x = x_mean + std[:, None, None, None] * noise + return x, x_mean + + def vpsde_update_fn(self, x, t): + sde = self.sde + timestep = (t * (sde.N - 1) / sde.T).long() + beta = sde.discrete_betas.to(t.device)[timestep] + score = self.score_fn(x, t) + x_mean = (x + beta[:, None, None, None] * score) / torch.sqrt(1. - beta)[:, None, None, None] + noise = torch.randn_like(x) + x = x_mean + torch.sqrt(beta)[:, None, None, None] * noise + return x, x_mean + + def update_fn(self, x, t): + if isinstance(self.sde, sde_lib.VESDE): + return self.vesde_update_fn(x, t) + elif isinstance(self.sde, sde_lib.VPSDE): + return self.vpsde_update_fn(x, t) + + +@register_predictor(name='none') +class NonePredictor(Predictor): + """An empty predictor that does nothing.""" + + def __init__(self, sde, score_fn, probability_flow=False): + pass + + def update_fn(self, x, t): + return x, x + + +@register_corrector(name='langevin') +class LangevinCorrector(Corrector): + def __init__(self, sde, score_fn, snr, n_steps): + super().__init__(sde, score_fn, snr, n_steps) + if not isinstance(sde, sde_lib.VPSDE) \ + and not isinstance(sde, sde_lib.VESDE) \ + and not isinstance(sde, sde_lib.subVPSDE): + raise NotImplementedError(f"SDE class {sde.__class__.__name__} not yet supported.") + + def update_fn(self, x, t): + sde = self.sde + score_fn = self.score_fn + n_steps = self.n_steps + target_snr = self.snr + if isinstance(sde, sde_lib.VPSDE) or isinstance(sde, sde_lib.subVPSDE): + timestep = (t * (sde.N - 1) / sde.T).long() + alpha = sde.alphas.to(t.device)[timestep] + else: + alpha = torch.ones_like(t) + + for i in range(n_steps): + grad = score_fn(x, t) + noise = torch.randn_like(x) + grad_norm = torch.norm(grad.reshape(grad.shape[0], -1), dim=-1).mean() + noise_norm = torch.norm(noise.reshape(noise.shape[0], -1), dim=-1).mean() + step_size = (target_snr * noise_norm / grad_norm) ** 2 * 2 * alpha + x_mean = x + step_size[:, None, None, None] * grad + x = x_mean + torch.sqrt(step_size * 2)[:, None, None, None] * noise + + return x, x_mean + + +@register_corrector(name='ald') +class AnnealedLangevinDynamics(Corrector): + """The original annealed Langevin dynamics predictor in NCSN/NCSNv2. + + We include this corrector only for completeness. It was not directly used in our paper. + """ + + def __init__(self, sde, score_fn, snr, n_steps): + super().__init__(sde, score_fn, snr, n_steps) + if not isinstance(sde, sde_lib.VPSDE) \ + and not isinstance(sde, sde_lib.VESDE) \ + and not isinstance(sde, sde_lib.subVPSDE): + raise NotImplementedError(f"SDE class {sde.__class__.__name__} not yet supported.") + + def update_fn(self, x, t): + sde = self.sde + score_fn = self.score_fn + n_steps = self.n_steps + target_snr = self.snr + if isinstance(sde, sde_lib.VPSDE) or isinstance(sde, sde_lib.subVPSDE): + timestep = (t * (sde.N - 1) / sde.T).long() + alpha = sde.alphas.to(t.device)[timestep] + else: + alpha = torch.ones_like(t) + + std = self.sde.marginal_prob(x, t)[1] + + for i in range(n_steps): + grad = score_fn(x, t) + noise = torch.randn_like(x) + step_size = (target_snr * std) ** 2 * 2 * alpha + x_mean = x + step_size[:, None, None, None] * grad + x = x_mean + noise * torch.sqrt(step_size * 2)[:, None, None, None] + + return x, x_mean + + +@register_corrector(name='none') +class NoneCorrector(Corrector): + """An empty corrector that does nothing.""" + + def __init__(self, sde, score_fn, snr, n_steps): + pass + + def update_fn(self, x, t): + return x, x + + +def shared_predictor_update_fn(x, t, sde, model, predictor, probability_flow, continuous): + """A wrapper that configures and returns the update function of predictors.""" + score_fn = mutils.get_score_fn(sde, model, train=False, continuous=continuous) + if predictor is None: + # Corrector-only sampler + predictor_obj = NonePredictor(sde, score_fn, probability_flow) + else: + predictor_obj = predictor(sde, score_fn, probability_flow) + return predictor_obj.update_fn(x, t) + + +def shared_corrector_update_fn(x, t, sde, model, corrector, continuous, snr, n_steps): + """A wrapper tha configures and returns the update function of correctors.""" + score_fn = mutils.get_score_fn(sde, model, train=False, continuous=continuous) + if corrector is None: + # Predictor-only sampler + corrector_obj = NoneCorrector(sde, score_fn, snr, n_steps) + else: + corrector_obj = corrector(sde, score_fn, snr, n_steps) + return corrector_obj.update_fn(x, t) + + +def get_pc_sampler(sde, shape, predictor, corrector, inverse_scaler, snr, + n_steps=1, probability_flow=False, continuous=False, + denoise=True, eps=1e-3, device='cuda'): + """Create a Predictor-Corrector (PC) sampler. + + Args: + sde: An `sde_lib.SDE` object representing the forward SDE. + shape: A sequence of integers. The expected shape of a single sample. + predictor: A subclass of `sampling.Predictor` representing the predictor algorithm. + corrector: A subclass of `sampling.Corrector` representing the corrector algorithm. + inverse_scaler: The inverse data normalizer. + snr: A `float` number. The signal-to-noise ratio for configuring correctors. + n_steps: An integer. The number of corrector steps per predictor update. + probability_flow: If `True`, solve the reverse-time probability flow ODE when running the predictor. + continuous: `True` indicates that the score model was continuously trained. + denoise: If `True`, add one-step denoising to the final samples. + eps: A `float` number. The reverse-time SDE and ODE are integrated to `epsilon` to avoid numerical issues. + device: PyTorch device. + + Returns: + A sampling function that returns samples and the number of function evaluations during sampling. + """ + # Create predictor & corrector update functions + predictor_update_fn = functools.partial(shared_predictor_update_fn, + sde=sde, + predictor=predictor, + probability_flow=probability_flow, + continuous=continuous) + corrector_update_fn = functools.partial(shared_corrector_update_fn, + sde=sde, + corrector=corrector, + continuous=continuous, + snr=snr, + n_steps=n_steps) + + def pc_sampler(model): + """ The PC sampler funciton. + + Args: + model: A score model. + Returns: + Samples, number of function evaluations. + """ + with torch.no_grad(): + # Initial sample + x = sde.prior_sampling(shape).to(device) + timesteps = torch.linspace(sde.T, eps, sde.N, device=device) + + for i in range(sde.N): + t = timesteps[i] + vec_t = torch.ones(shape[0], device=t.device) * t + x, x_mean = corrector_update_fn(x, vec_t, model=model) + x, x_mean = predictor_update_fn(x, vec_t, model=model) + + return inverse_scaler(x_mean if denoise else x), sde.N * (n_steps + 1) + + return pc_sampler + + +def get_ode_sampler(sde, shape, inverse_scaler, + denoise=False, rtol=1e-5, atol=1e-5, + method='RK45', eps=1e-3, device='cuda'): + """Probability flow ODE sampler with the black-box ODE solver. + + Args: + sde: An `sde_lib.SDE` object that represents the forward SDE. + shape: A sequence of integers. The expected shape of a single sample. + inverse_scaler: The inverse data normalizer. + denoise: If `True`, add one-step denoising to final samples. + rtol: A `float` number. The relative tolerance level of the ODE solver. + atol: A `float` number. The absolute tolerance level of the ODE solver. + method: A `str`. The algorithm used for the black-box ODE solver. + See the documentation of `scipy.integrate.solve_ivp`. + eps: A `float` number. The reverse-time SDE/ODE will be integrated to `eps` for numerical stability. + device: PyTorch device. + + Returns: + A sampling function that returns samples and the number of function evaluations during sampling. + """ + + def denoise_update_fn(model, x): + score_fn = get_score_fn(sde, model, train=False, continuous=True) + # Reverse diffusion predictor for denoising + predictor_obj = ReverseDiffusionPredictor(sde, score_fn, probability_flow=False) + vec_eps = torch.ones(x.shape[0], device=x.device) * eps + _, x = predictor_obj.update_fn(x, vec_eps) + return x + + def drift_fn(model, x, t): + """Get the drift function of the reverse-time SDE.""" + score_fn = get_score_fn(sde, model, train=False, continuous=True) + rsde = sde.reverse(score_fn, probability_flow=True) + return rsde.sde(x, t)[0] + + def ode_sampler(model, z=None): + """The probability flow ODE sampler with black-box ODE solver. + + Args: + model: A score model. + z: If present, generate samples from latent code `z`. + Returns: + samples, number of function evaluations. + """ + with torch.no_grad(): + # Initial sample + if z is None: + # If not represent, sample the latent code from the prior distibution of the SDE. + x = sde.prior_sampling(shape).to(device) + else: + x = z + + def ode_func(t, x): + x = from_flattened_numpy(x, shape).to(device).type(torch.float32) + vec_t = torch.ones(shape[0], device=x.device) * t + drift = drift_fn(model, x, vec_t) + return to_flattened_numpy(drift) + + # Black-box ODE solver for the probability flow ODE + solution = integrate.solve_ivp(ode_func, (sde.T, eps), to_flattened_numpy(x), + rtol=rtol, atol=atol, method=method) + nfe = solution.nfev + x = torch.tensor(solution.y[:, -1]).reshape(shape).to(device).type(torch.float32) + + # Denoising is equivalent to running one predictor step without adding noise + if denoise: + x = denoise_update_fn(model, x) + + x = inverse_scaler(x) + return x, nfe + + return ode_sampler diff --git a/case_studies/diffpure/score_sde/sde_lib.py b/case_studies/diffpure/score_sde/sde_lib.py new file mode 100644 index 0000000..1062602 --- /dev/null +++ b/case_studies/diffpure/score_sde/sde_lib.py @@ -0,0 +1,262 @@ +# --------------------------------------------------------------- +# Taken from the following link as is from: +# https://github.com/yang-song/score_sde_pytorch/blob/main/sde_lib.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_SCORE_SDE). +# --------------------------------------------------------------- + +"""Abstract SDE classes, Reverse SDE, and VE/VP SDEs.""" +import abc +import torch +import numpy as np + + +class SDE(abc.ABC): + """SDE abstract class. Functions are designed for a mini-batch of inputs.""" + + def __init__(self, N): + """Construct an SDE. + + Args: + N: number of discretization time steps. + """ + super().__init__() + self.N = N + + @property + @abc.abstractmethod + def T(self): + """End time of the SDE.""" + pass + + @abc.abstractmethod + def sde(self, x, t): + pass + + @abc.abstractmethod + def marginal_prob(self, x, t): + """Parameters to determine the marginal distribution of the SDE, $p_t(x)$.""" + pass + + @abc.abstractmethod + def prior_sampling(self, shape): + """Generate one sample from the prior distribution, $p_T(x)$.""" + pass + + @abc.abstractmethod + def prior_logp(self, z): + """Compute log-density of the prior distribution. + + Useful for computing the log-likelihood via probability flow ODE. + + Args: + z: latent code + Returns: + log probability density + """ + pass + + def discretize(self, x, t): + """Discretize the SDE in the form: x_{i+1} = x_i + f_i(x_i) + G_i z_i. + + Useful for reverse diffusion sampling and probabiliy flow sampling. + Defaults to Euler-Maruyama discretization. + + Args: + x: a torch tensor + t: a torch float representing the time step (from 0 to `self.T`) + + Returns: + f, G + """ + dt = 1 / self.N + drift, diffusion = self.sde(x, t) + f = drift * dt + G = diffusion * torch.sqrt(torch.tensor(dt, device=t.device)) + return f, G + + def reverse(self, score_fn, probability_flow=False): + """Create the reverse-time SDE/ODE. + + Args: + score_fn: A time-dependent score-based model that takes x and t and returns the score. + probability_flow: If `True`, create the reverse-time ODE used for probability flow sampling. + """ + N = self.N + T = self.T + sde_fn = self.sde + discretize_fn = self.discretize + + # Build the class for reverse-time SDE. + class RSDE(self.__class__): + def __init__(self): + self.N = N + self.probability_flow = probability_flow + + @property + def T(self): + return T + + def sde(self, x, t): + """Create the drift and diffusion functions for the reverse SDE/ODE.""" + drift, diffusion = sde_fn(x, t) + score = score_fn(x, t) + drift = drift - diffusion[:, None, None, None] ** 2 * score * (0.5 if self.probability_flow else 1.) + # Set the diffusion function to zero for ODEs. + diffusion = 0. if self.probability_flow else diffusion + return drift, diffusion + + def discretize(self, x, t): + """Create discretized iteration rules for the reverse diffusion sampler.""" + f, G = discretize_fn(x, t) + rev_f = f - G[:, None, None, None] ** 2 * score_fn(x, t) * (0.5 if self.probability_flow else 1.) + rev_G = torch.zeros_like(G) if self.probability_flow else G + return rev_f, rev_G + + return RSDE() + + +class VPSDE(SDE): + def __init__(self, beta_min=0.1, beta_max=20, N=1000): + """Construct a Variance Preserving SDE. + + Args: + beta_min: value of beta(0) + beta_max: value of beta(1) + N: number of discretization steps + """ + super().__init__(N) + self.beta_0 = beta_min + self.beta_1 = beta_max + self.N = N + self.discrete_betas = torch.linspace(beta_min / N, beta_max / N, N) + self.alphas = 1. - self.discrete_betas + self.alphas_cumprod = torch.cumprod(self.alphas, dim=0) + self.sqrt_alphas_cumprod = torch.sqrt(self.alphas_cumprod) + self.sqrt_1m_alphas_cumprod = torch.sqrt(1. - self.alphas_cumprod) + + @property + def T(self): + return 1 + + def sde(self, x, t): + beta_t = self.beta_0 + t * (self.beta_1 - self.beta_0) + drift = -0.5 * beta_t[:, None, None, None] * x + diffusion = torch.sqrt(beta_t) + return drift, diffusion + + def marginal_prob(self, x, t): + log_mean_coeff = -0.25 * t ** 2 * (self.beta_1 - self.beta_0) - 0.5 * t * self.beta_0 + mean = torch.exp(log_mean_coeff[:, None, None, None]) * x + std = torch.sqrt(1. - torch.exp(2. * log_mean_coeff)) + return mean, std + + def prior_sampling(self, shape): + return torch.randn(*shape) + + def prior_logp(self, z): + shape = z.shape + N = np.prod(shape[1:]) + logps = -N / 2. * np.log(2 * np.pi) - torch.sum(z ** 2, dim=(1, 2, 3)) / 2. + return logps + + def discretize(self, x, t): + """DDPM discretization.""" + timestep = (t * (self.N - 1) / self.T).long() + beta = self.discrete_betas.to(x.device)[timestep] + alpha = self.alphas.to(x.device)[timestep] + sqrt_beta = torch.sqrt(beta) + f = torch.sqrt(alpha)[:, None, None, None] * x - x + G = sqrt_beta + return f, G + + +class subVPSDE(SDE): + def __init__(self, beta_min=0.1, beta_max=20, N=1000): + """Construct the sub-VP SDE that excels at likelihoods. + + Args: + beta_min: value of beta(0) + beta_max: value of beta(1) + N: number of discretization steps + """ + super().__init__(N) + self.beta_0 = beta_min + self.beta_1 = beta_max + self.N = N + + @property + def T(self): + return 1 + + def sde(self, x, t): + beta_t = self.beta_0 + t * (self.beta_1 - self.beta_0) + drift = -0.5 * beta_t[:, None, None, None] * x + discount = 1. - torch.exp(-2 * self.beta_0 * t - (self.beta_1 - self.beta_0) * t ** 2) + diffusion = torch.sqrt(beta_t * discount) + return drift, diffusion + + def marginal_prob(self, x, t): + log_mean_coeff = -0.25 * t ** 2 * (self.beta_1 - self.beta_0) - 0.5 * t * self.beta_0 + mean = torch.exp(log_mean_coeff)[:, None, None, None] * x + std = 1 - torch.exp(2. * log_mean_coeff) + return mean, std + + def prior_sampling(self, shape): + return torch.randn(*shape) + + def prior_logp(self, z): + shape = z.shape + N = np.prod(shape[1:]) + return -N / 2. * np.log(2 * np.pi) - torch.sum(z ** 2, dim=(1, 2, 3)) / 2. + + +class VESDE(SDE): + def __init__(self, sigma_min=0.01, sigma_max=50, N=1000): + """Construct a Variance Exploding SDE. + + Args: + sigma_min: smallest sigma. + sigma_max: largest sigma. + N: number of discretization steps + """ + super().__init__(N) + self.sigma_min = sigma_min + self.sigma_max = sigma_max + self.discrete_sigmas = torch.exp(torch.linspace(np.log(self.sigma_min), np.log(self.sigma_max), N)) + self.N = N + + @property + def T(self): + return 1 + + def sde(self, x, t): + sigma = self.sigma_min * (self.sigma_max / self.sigma_min) ** t + drift = torch.zeros_like(x) + diffusion = sigma * torch.sqrt(torch.tensor(2 * (np.log(self.sigma_max) - np.log(self.sigma_min)), + device=t.device)) + return drift, diffusion + + def marginal_prob(self, x, t): + std = self.sigma_min * (self.sigma_max / self.sigma_min) ** t + mean = x + return mean, std + + def prior_sampling(self, shape): + return torch.randn(*shape) * self.sigma_max + + def prior_logp(self, z): + shape = z.shape + N = np.prod(shape[1:]) + return -N / 2. * np.log(2 * np.pi * self.sigma_max ** 2) - torch.sum(z ** 2, dim=(1, 2, 3)) / (2 * self.sigma_max ** 2) + + def discretize(self, x, t): + """SMLD(NCSN) discretization.""" + timestep = (t * (self.N - 1) / self.T).long() + sigma = self.discrete_sigmas.to(t.device)[timestep] + adjacent_sigma = torch.where(timestep == 0, torch.zeros_like(t), + self.discrete_sigmas[timestep - 1].to(t.device)) + f = torch.zeros_like(x) + G = torch.sqrt(sigma ** 2 - adjacent_sigma ** 2) + return f, G \ No newline at end of file diff --git a/case_studies/diffpure/slurm/analyze_logs.py b/case_studies/diffpure/slurm/analyze_logs.py new file mode 100644 index 0000000..757e543 --- /dev/null +++ b/case_studies/diffpure/slurm/analyze_logs.py @@ -0,0 +1,74 @@ +import numpy as np +import glob +import argparse +import os + + +def parse_log(path): + with open(path, "r") as f: + lines = f.readlines() + + lines = [l.strip() for l in lines] + + if len(lines) < 4: + return None + + if lines[-4].startswith("interior-vs-boundary discimination"): + asr = float(lines[-4].split(":")[1].strip()) + logit_diff = float(lines[-3].split(":")[1].split("+-")[0].strip()) + validation_acc = eval(lines[-2].split(":")[-1].replace("nan", "np.nan")) + if type(validation_acc) is float: + validation_acc = (np.nan, np.nan, np.nan, np.nan, np.nan, np.nan) + validation_acc = np.array(validation_acc) + n_failed = int(lines[-1].split("for ")[1].split("/")[0].strip()) + + return asr, logit_diff, validation_acc, n_failed + else: + return None + + +def main(input_folder): + logs = glob.glob(os.path.join(input_folder, "*.log")) + + results = [(p, parse_log(p)) for p in logs] + + incomplete_logs = [it[0] for it in results if it[1] is None] + if len(incomplete_logs) > 0: + print("Found incomplete logs for experiments:") + for it in incomplete_logs: + print(f"\t{it}") + + results = [it[1] for it in results if it[1] is not None] + + if len(results) == 0: + print("No results found.") + return + + results = results[:512] + + properties = [np.array([it[i] for it in results]) for i in range(len(results[0]))] + + n_samples = len(results) + n_failed_samples = np.sum(properties[3]) + + # filter failed samples + failed_samples = [idx for idx in range(len(properties[3])) if properties[3][idx] == 1] + properties = [[prop[idx] for idx in range(len(prop)) if idx not in failed_samples] for prop in properties] + + import pdb; pdb.set_trace() + + means = [np.mean(prop, 0) for prop in properties] + stds = [np.std(prop, 0) for prop in properties] + + print(f"ASR: {means[0]}") + print(f"Normalized Logit-Difference-Improvement: {means[1]} +- {stds[1]}") + print(f"Validation Accuracy (I, B, BS, BC, R. ASR S, R. ASR C): {tuple(means[2])}") + print(f"Setup failed for {n_failed_samples}/{n_samples} samples") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--input", "-i", required=True) + args = parser.parse_args() + main(args.input) + diff --git a/case_studies/diffpure/slurm/binarization_test.sh b/case_studies/diffpure/slurm/binarization_test.sh new file mode 100644 index 0000000..d632695 --- /dev/null +++ b/case_studies/diffpure/slurm/binarization_test.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +SLURMDIR="/home/bethge/rzimmermann/diffpure-slurm-logs/" +function execute_job { + local arguments=$1 + + echo "Using arguments: $arguments" + #read -r -p "Are you sure? [enter N to cancel] " response + #if [ "$response" == "N" ]; then + # exit 1 + #fi + + sbatch case_studies/diffpure/slurm/binarization_test_single.sh "${arguments}" || echo "error in $SLURMDIR/slog--$SLURM_JOB_ID.err on $SLURM_JOB_NODELIST" > $SLURMDIR/slog-common.err +} + +mkdir -p "$SLURMDIR" + + +for startidx in {1..500}; do + endidx=$(expr $startidx + 1) + execute_job "1 1 $startidx $endidx" +done \ No newline at end of file diff --git a/case_studies/diffpure/slurm/binarization_test_single.sh b/case_studies/diffpure/slurm/binarization_test_single.sh new file mode 100644 index 0000000..f8a5ddd --- /dev/null +++ b/case_studies/diffpure/slurm/binarization_test_single.sh @@ -0,0 +1,45 @@ +#!/bin/bash +#SBATCH --ntasks=1 # Number of tasks (see below) +#SBATCH --nodes=1 # Ensure that all cores are on one machine +#SBATCH --partition=gpu-2080ti # Partition to submit to +#SBATCH --mem=20G # Memory pool for all cores (see also --mem-per-cpu) +#SBATCH --time=3-00:00 # Runtime in D-HH:MM +#SBATCH --output=/home/bethge/rzimmermann/diffpure-slurm-logs/slog-%j.out # File to which STDOUT will be written +#SBATCH --error=/home/bethge/rzimmermann/diffpure-slurm-logs/slog-%j.err # File to which STDERR will be written +#SBATCH --gres=gpu:1 # Request right GPUs +#SBATCH --cpus-per-task=8 +#SBATCH --job-name=diffpure_binarization_test + + +function _termmsg() +{ + SLURMDIR="/home/bethge/rzimmermann/diffpure-slurm-logs/" + echo "terminaged $SLURM_JOB_ID on $SLURM_JOB_NODELIST. Check slog-$SLURM_JOB_ID.err" > $SLURMDIR/slog-common.err +} + +trap _termmsg SIGTERM + +arguments=$1 + +# include information about the job in the output +scontrol show job=$SLURM_JOB_ID + +echo "GPU information:" +nvidia-smi --query-gpu=memory.used --format=csv + +SCRATCH_DIRECTORY="/scratch_local/$SLURM_JOB_USER-$SLURM_JOBID" + +echo "Copying SIF..." +qcopy /mnt/qb/home/bethge/rzimmermann/sifs/diffpure.sif $SCRATCH_DIRECTORY +echo "SIF copied!" + +echo "arguments: $1" + +log_folder="/home/bethge/rzimmermann/diffpure-logs/" +mkdir -p ${log_folder} + +log_path="${log_folder}/${arguments// /_}" + +echo "Slurm Job ID: $SLURM_JOB_ID" >> $log_path.out +srun singularity exec --nv --bind /mnt/qb/ --bind $SCRATCH_DIRECTORY "$SCRATCH_DIRECTORY/diffpure.sif" \ + /bin/bash -c "cd /mnt/qb/bethge/rzimmermann/code/active-adversarial-tests-internal && ./case_studies/diffpure/run_scripts/cifar10/run_cifar_rand_inf_binarization_test.sh $arguments 2> ${log_path}.err | tee ${log_path}.log" diff --git a/case_studies/diffpure/stadv_eot/attacks.py b/case_studies/diffpure/stadv_eot/attacks.py new file mode 100644 index 0000000..f3aea13 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/attacks.py @@ -0,0 +1,136 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This work is licensed under the NVIDIA Source Code License +# for DiffPure. To view a copy of this license, see the LICENSE file. +# --------------------------------------------------------------- + +import functools +import torch +from torch import nn +from torch import optim + +# mister_ed +from .recoloradv.mister_ed import loss_functions as lf +from .recoloradv.mister_ed import adversarial_training as advtrain +from .recoloradv.mister_ed import adversarial_perturbations as ap +from .recoloradv.mister_ed import adversarial_attacks as aa +from .recoloradv.mister_ed import spatial_transformers as st + + +PGD_ITERS = 20 + + +def run_attack_with_random_targets(attack, model, inputs, labels, num_classes): + """ + Runs an attack with targets randomly selected from all classes besides the + correct one. The attack should be a function from (inputs, labels) to + adversarial examples. + """ + + rand_targets = torch.randint( + 0, num_classes - 1, labels.size(), + dtype=labels.dtype, device=labels.device, + ) + targets = torch.remainder(labels + rand_targets + 1, num_classes) + + adv_inputs = attack(inputs, targets) + adv_labels = model(adv_inputs).argmax(1) + unsuccessful = adv_labels != targets + adv_inputs[unsuccessful] = inputs[unsuccessful] + + return adv_inputs + + +class MisterEdAttack(nn.Module): + """ + Base class for attacks using the mister_ed library. + """ + + def __init__(self, model, threat_model, randomize=False, + perturbation_norm_loss=False, lr=0.001, random_targets=False, + num_classes=None, **kwargs): + super().__init__() + + self.model = model + self.normalizer = nn.Identity() + + self.threat_model = threat_model + self.randomize = randomize + self.perturbation_norm_loss = perturbation_norm_loss + self.attack_kwargs = kwargs + self.lr = lr + self.random_targets = random_targets + self.num_classes = num_classes + + self.attack = None + + def _setup_attack(self): + cw_loss = lf.CWLossF6(self.model, self.normalizer, kappa=float('inf')) + if self.random_targets: + cw_loss.forward = functools.partial(cw_loss.forward, targeted=True) + perturbation_loss = lf.PerturbationNormLoss(lp=2) + pert_factor = 0.0 + if self.perturbation_norm_loss is True: + pert_factor = 0.05 + elif type(self.perturbation_norm_loss) is float: + pert_factor = self.perturbation_norm_loss + adv_loss = lf.RegularizedLoss({ + 'cw': cw_loss, + 'pert': perturbation_loss, + }, { + 'cw': 1.0, + 'pert': pert_factor, + }, negate=True) + + self.pgd_attack = aa.PGD(self.model, self.normalizer, + self.threat_model(), adv_loss) + + attack_params = { + 'optimizer': optim.Adam, + 'optimizer_kwargs': {'lr': self.lr}, + 'signed': False, + 'verbose': False, + 'num_iterations': 0 if self.randomize else PGD_ITERS, + 'random_init': self.randomize, + } + attack_params.update(self.attack_kwargs) + + self.attack = advtrain.AdversarialAttackParameters( + self.pgd_attack, + 1.0, + attack_specific_params={'attack_kwargs': attack_params}, + ) + self.attack.set_gpu(False) + + def forward(self, inputs, labels): + if self.attack is None: + self._setup_attack() + assert self.attack is not None + + if self.random_targets: + return run_attack_with_random_targets( + lambda inputs, labels: self.attack.attack(inputs, labels)[0], + self.model, + inputs, + labels, + num_classes=self.num_classes, + ) + else: + return self.attack.attack(inputs, labels)[0] + + +class StAdvAttack(MisterEdAttack): + def __init__(self, model, bound=0.05, **kwargs): + kwargs.setdefault('lr', 0.01) + super().__init__( + model, + threat_model=lambda: ap.ThreatModel(ap.ParameterizedXformAdv, { + 'lp_style': 'inf', + 'lp_bound': bound, + 'xform_class': st.FullSpatial, + 'use_stadv': True, + }), + perturbation_norm_loss=0.0025 / bound, + **kwargs, + ) diff --git a/case_studies/diffpure/stadv_eot/recoloradv/LICENSE_RECOLORADV b/case_studies/diffpure/stadv_eot/recoloradv/LICENSE_RECOLORADV new file mode 100644 index 0000000..3754756 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/LICENSE_RECOLORADV @@ -0,0 +1,17 @@ +MIT License +Copyright (c) 2018 YOUR NAME +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/case_studies/diffpure/stadv_eot/recoloradv/__init__.py b/case_studies/diffpure/stadv_eot/recoloradv/__init__.py new file mode 100644 index 0000000..ad92927 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/__init__.py @@ -0,0 +1,12 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/__init__.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- diff --git a/case_studies/diffpure/stadv_eot/recoloradv/color_spaces.py b/case_studies/diffpure/stadv_eot/recoloradv/color_spaces.py new file mode 100644 index 0000000..cc0e1e8 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/color_spaces.py @@ -0,0 +1,272 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/color_spaces.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" +Contains classes that convert from RGB to various other color spaces and back. +""" + +import torch +import numpy as np +import math + + +class ColorSpace(object): + """ + Base class for color spaces. + """ + + def from_rgb(self, imgs): + """ + Converts an Nx3xWxH tensor in RGB color space to a Nx3xWxH tensor in + this color space. All outputs should be in the 0-1 range. + """ + raise NotImplementedError() + + def to_rgb(self, imgs): + """ + Converts an Nx3xWxH tensor in this color space to a Nx3xWxH tensor in + RGB color space. + """ + raise NotImplementedError() + + +class RGBColorSpace(ColorSpace): + """ + RGB color space. Just applies identity transformation. + """ + + def from_rgb(self, imgs): + return imgs + + def to_rgb(self, imgs): + return imgs + + +class YPbPrColorSpace(ColorSpace): + """ + YPbPr color space. Uses ITU-R BT.601 standard by default. + """ + + def __init__(self, kr=0.299, kg=0.587, kb=0.114, luma_factor=1, + chroma_factor=1): + self.kr, self.kg, self.kb = kr, kg, kb + self.luma_factor = luma_factor + self.chroma_factor = chroma_factor + + def from_rgb(self, imgs): + r, g, b = imgs.permute(1, 0, 2, 3) + + y = r * self.kr + g * self.kg + b * self.kb + pb = (b - y) / (2 * (1 - self.kb)) + pr = (r - y) / (2 * (1 - self.kr)) + + return torch.stack([y * self.luma_factor, + pb * self.chroma_factor + 0.5, + pr * self.chroma_factor + 0.5], 1) + + def to_rgb(self, imgs): + y_prime, pb_prime, pr_prime = imgs.permute(1, 0, 2, 3) + y = y_prime / self.luma_factor + pb = (pb_prime - 0.5) / self.chroma_factor + pr = (pr_prime - 0.5) / self.chroma_factor + + b = pb * 2 * (1 - self.kb) + y + r = pr * 2 * (1 - self.kr) + y + g = (y - r * self.kr - b * self.kb) / self.kg + + return torch.stack([r, g, b], 1).clamp(0, 1) + + +class ApproxHSVColorSpace(ColorSpace): + """ + Converts from RGB to approximately the HSV cone using a much smoother + transformation. + """ + + def from_rgb(self, imgs): + r, g, b = imgs.permute(1, 0, 2, 3) + + x = r * np.sqrt(2) / 3 - g / (np.sqrt(2) * 3) - b / (np.sqrt(2) * 3) + y = g / np.sqrt(6) - b / np.sqrt(6) + z, _ = imgs.max(1) + + return torch.stack([z, x + 0.5, y + 0.5], 1) + + def to_rgb(self, imgs): + z, xp, yp = imgs.permute(1, 0, 2, 3) + x, y = xp - 0.5, yp - 0.5 + + rp = float(np.sqrt(2)) * x + gp = -x / np.sqrt(2) + y * np.sqrt(3 / 2) + bp = -x / np.sqrt(2) - y * np.sqrt(3 / 2) + + delta = z - torch.max(torch.stack([rp, gp, bp], 1), 1)[0] + r, g, b = rp + delta, gp + delta, bp + delta + + return torch.stack([r, g, b], 1).clamp(0, 1) + + +class HSVConeColorSpace(ColorSpace): + """ + Converts from RGB to the HSV "cone", where (x, y, z) = + (s * v cos h, s * v sin h, v). Note that this cone is then squashed to fit + in [0, 1]^3 by letting (x', y', z') = ((x + 1) / 2, (y + 1) / 2, z). + + WARNING: has a very complex derivative, not very useful in practice + """ + + def from_rgb(self, imgs): + r, g, b = imgs.permute(1, 0, 2, 3) + + mx, argmx = imgs.max(1) + mn, _ = imgs.min(1) + chroma = mx - mn + eps = 1e-10 + h_max_r = math.pi / 3 * (g - b) / (chroma + eps) + h_max_g = math.pi / 3 * (b - r) / (chroma + eps) + math.pi * 2 / 3 + h_max_b = math.pi / 3 * (r - g) / (chroma + eps) + math.pi * 4 / 3 + + h = (((argmx == 0) & (chroma != 0)).float() * h_max_r + + ((argmx == 1) & (chroma != 0)).float() * h_max_g + + ((argmx == 2) & (chroma != 0)).float() * h_max_b) + + x = torch.cos(h) * chroma + y = torch.sin(h) * chroma + z = mx + + return torch.stack([(x + 1) / 2, (y + 1) / 2, z], 1) + + def _to_rgb_part(self, h, chroma, v, n): + """ + Implements the function f(n) defined here: + https://en.wikipedia.org/wiki/HSL_and_HSV#Alternative_HSV_to_RGB + """ + + k = (n + h * math.pi / 3) % 6 + return v - chroma * torch.min(k, 4 - k).clamp(0, 1) + + def to_rgb(self, imgs): + xp, yp, z = imgs.permute(1, 0, 2, 3) + x, y = xp * 2 - 1, yp * 2 - 1 + + # prevent NaN gradients when calculating atan2 + x_nonzero = (1 - 2 * (torch.sign(x) == -1).float()) * (torch.abs(x) + 1e-10) + h = torch.atan2(y, x_nonzero) + v = z.clamp(0, 1) + chroma = torch.min(torch.sqrt(x ** 2 + y ** 2 + 1e-10), v) + + r = self._to_rgb_part(h, chroma, v, 5) + g = self._to_rgb_part(h, chroma, v, 3) + b = self._to_rgb_part(h, chroma, v, 1) + + return torch.stack([r, g, b], 1).clamp(0, 1) + + +class CIEXYZColorSpace(ColorSpace): + """ + The 1931 CIE XYZ color space (assuming input is in sRGB). + + Warning: may have values outside [0, 1] range. Should only be used in + the process of converting to/from other color spaces. + """ + + def from_rgb(self, imgs): + # apply gamma correction + small_values_mask = (imgs < 0.04045).float() + imgs_corrected = ( + (imgs / 12.92) * small_values_mask + + ((imgs + 0.055) / 1.055) ** 2.4 * (1 - small_values_mask) + ) + + # linear transformation to XYZ + r, g, b = imgs_corrected.permute(1, 0, 2, 3) + x = 0.4124 * r + 0.3576 * g + 0.1805 * b + y = 0.2126 * r + 0.7152 * g + 0.0722 * b + z = 0.0193 * r + 0.1192 * g + 0.9504 * b + + return torch.stack([x, y, z], 1) + + def to_rgb(self, imgs): + # linear transformation + x, y, z = imgs.permute(1, 0, 2, 3) + r = 3.2406 * x - 1.5372 * y - 0.4986 * z + g = -0.9689 * x + 1.8758 * y + 0.0415 * z + b = 0.0557 * x - 0.2040 * y + 1.0570 * z + + imgs = torch.stack([r, g, b], 1) + + # apply gamma correction + small_values_mask = (imgs < 0.0031308).float() + imgs_clamped = imgs.clamp(min=1e-10) # prevent NaN gradients + imgs_corrected = ( + (12.92 * imgs) * small_values_mask + + (1.055 * imgs_clamped ** (1 / 2.4) - 0.055) * + (1 - small_values_mask) + ) + + return imgs_corrected + + +class CIELUVColorSpace(ColorSpace): + """ + Converts to the 1976 CIE L*u*v* color space. + """ + + def __init__(self, up_white=0.1978, vp_white=0.4683, y_white=1, + eps=1e-10): + self.xyz_cspace = CIEXYZColorSpace() + self.up_white = up_white + self.vp_white = vp_white + self.y_white = y_white + self.eps = eps + + def from_rgb(self, imgs): + x, y, z = self.xyz_cspace.from_rgb(imgs).permute(1, 0, 2, 3) + + # calculate u' and v' + denom = x + 15 * y + 3 * z + self.eps + up = 4 * x / denom + vp = 9 * y / denom + + # calculate L*, u*, and v* + small_values_mask = (y / self.y_white < (6 / 29) ** 3).float() + y_clamped = y.clamp(min=self.eps) # prevent NaN gradients + L = ( + ((29 / 3) ** 3 * y / self.y_white) * small_values_mask + + (116 * (y_clamped / self.y_white) ** (1 / 3) - 16) * + (1 - small_values_mask) + ) + u = 13 * L * (up - self.up_white) + v = 13 * L * (vp - self.vp_white) + + return torch.stack([L / 100, (u + 100) / 200, (v + 100) / 200], 1) + + def to_rgb(self, imgs): + L = imgs[:, 0, :, :] * 100 + u = imgs[:, 1, :, :] * 200 - 100 + v = imgs[:, 2, :, :] * 200 - 100 + + up = u / (13 * L + self.eps) + self.up_white + vp = v / (13 * L + self.eps) + self.vp_white + + small_values_mask = (L <= 8).float() + y = ( + (self.y_white * L * (3 / 29) ** 3) * small_values_mask + + (self.y_white * ((L + 16) / 116) ** 3) * (1 - small_values_mask) + ) + denom = 4 * vp + self.eps + x = y * 9 * up / denom + z = y * (12 - 3 * up - 20 * vp) / denom + + return self.xyz_cspace.to_rgb( + torch.stack([x, y, z], 1).clamp(0, 1.1)).clamp(0, 1) diff --git a/case_studies/diffpure/stadv_eot/recoloradv/color_transformers.py b/case_studies/diffpure/stadv_eot/recoloradv/color_transformers.py new file mode 100644 index 0000000..e5df968 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/color_transformers.py @@ -0,0 +1,379 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/color_transformers.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" +Contains various parameterizations for spatial transformation in 3D color space. +""" + +import torch +import torch.nn as nn +from .mister_ed.utils import pytorch_utils as utils +from torch.autograd import Variable +from . import norms +from functools import lru_cache + + +############################################################################## +# # +# SKELETON CLASS # +# # +############################################################################## + +class ParameterizedTransformation(nn.Module): + """ General class of transformations. + All subclasses need the following methods: + - norm: no args -> scalar variable + - identity_params: shape -> TENSOR : takes an input shape and outputs + the subclass-specific parameter for the identity + transformation + - forward : Variable -> Variable - is the transformation + """ + + def __init__(self, **kwargs): + super(ParameterizedTransformation, self).__init__() + + if kwargs.get('manual_gpu', None) is not None: + self.use_gpu = kwargs['manual_gpu'] + else: + self.use_gpu = utils.use_gpu() + + def clone(self, shape=None, example_index=None): + raise NotImplementedError() + + def norm(self, lp='inf'): + raise NotImplementedError("Need to call subclass's norm!") + + @classmethod + def identity_params(self, shape): + raise NotImplementedError("Need to call subclass's identity_params!") + + def merge_xform(self, other, self_mask): + """ Takes in an other instance of this same class with the same + shape of parameters (NxSHAPE) and a self_mask bytetensor of length + N and outputs the merge between self's parameters for the indices + of 1s in the self_mask and other's parameters for the indices of 0's + ARGS: + other: instance of same class as self with params of shape NxSHAPE - + the thing we merge with this one + self_mask : ByteTensor (length N) - which indices of parameters we + keep from self, and which we keep from other + RETURNS: + New instance of this class that's merged between the self and other + (same shaped params) + """ + + # JUST DO ASSERTS IN THE SKELETON CLASS + assert self.__class__ == other.__class__ + + self_params = self.xform_params.data + other_params = other.xform_params.data + assert self_params.shape == other_params.shape + assert self_params.shape[0] == self_mask.shape[0] + assert other_params.shape[0] == self_mask.shape[0] + + new_xform = self.__class__(shape=self.img_shape) + + new_params = utils.fold_mask(self.xform_params.data, + other.xform_params.data, self_mask) + new_xform.xform_params = nn.Parameter(new_params) + new_xform.use_gpu = self.use_gpu + return new_xform + + def forward(self, examples): + raise NotImplementedError("Need to call subclass's forward!") + + +class AffineTransform(ParameterizedTransformation): + def __init__(self, *args, **kwargs): + super(AffineTransform, self).__init__(**kwargs) + img_shape = kwargs['shape'] + self.img_shape = img_shape + self.xform_params = nn.Parameter(self.identity_params(img_shape)) + + def clone(self, shape=None, example_index=None): + xform = AffineTransform(shape=shape or self.img_shape) + if example_index is None: + my_params = self.xform_params + else: + my_params = self.xform_params[example_index][None] + xform.xform_params = nn.Parameter( + my_params.clone() + .expand(shape[0], -1, -1) + ) + return xform + + def norm(self, lp='inf'): + identity_params = Variable(self.identity_params(self.img_shape)) + return utils.batchwise_norm(self.xform_params - identity_params, lp, + dim=0) + + def identity_params(self, shape): + num_examples = shape[0] + identity_affine_transform = torch.zeros(num_examples, 3, 4) + if self.use_gpu: + identity_affine_transform = identity_affine_transform.cuda() + + identity_affine_transform[:, 0, 0] = 1 + identity_affine_transform[:, 1, 1] = 1 + identity_affine_transform[:, 2, 2] = 1 + + return identity_affine_transform + + def project_params(self, lp, lp_bound): + assert isinstance(lp, int) or lp == 'inf' + diff = self.xform_params.data - self.identity_params(self.img_shape) + new_diff = utils.batchwise_lp_project(diff, lp, lp_bound) + self.xform_params.data.add_(new_diff - diff) + + def forward(self, x): + N, _, W, H = self.img_shape + x_padded = torch.cat([x, torch.ones(N, 1, W, H)], 1).permute( + 0, 2, 3, 1) + transform_padded = self.xform_params[:, None, None, :, :] \ + .expand(-1, W, H, -1, -1) + x_transformed = transform_padded.matmul(x_padded[..., None]) \ + .squeeze(4) \ + .permute(0, 3, 1, 2) + return x_transformed + + +class FullSpatial(ParameterizedTransformation): + def __init__(self, *args, resolution_x=8, + resolution_y=8, resolution_z=8, **kwargs): + super(FullSpatial, self).__init__(**kwargs) + + self.resolution_x = resolution_x + self.resolution_y = resolution_y + self.resolution_z = resolution_z + + img_shape = kwargs['shape'] + self.img_shape = img_shape + + self.cspace = kwargs.get('cspace') + + batch_size = self.img_shape[0] + self.identity_params = FullSpatial.construct_identity_params( + batch_size, + self.resolution_x, + self.resolution_y, + self.resolution_z, + torch.cuda.current_device() if self.use_gpu else None, + ) + self.xform_params = nn.Parameter( + torch.empty_like(self.identity_params) + .copy_(self.identity_params) + ) + + def clone(self, shape=None, example_index=None): + xform = FullSpatial( + shape=shape or self.img_shape, + resolution_x=self.resolution_x, + resolution_y=self.resolution_y, + resolution_z=self.resolution_z, + cspace=self.cspace, + ) + if example_index is None: + my_params = self.xform_params + else: + my_params = self.xform_params[example_index][None] + xform.xform_params = nn.Parameter( + my_params.clone() + .expand(shape[0], -1, -1, -1, -1) + ) + return xform + + def smoothness_norm(self): + return norms.smoothness(self.xform_params - + self.identity_params) + + def norm(self, lp='inf'): + if isinstance(lp, int) or lp == 'inf': + return utils.batchwise_norm( + self.xform_params - self.identity_params, + lp, dim=0, + ) + else: + assert lp == 'smooth' + return self.smoothness_norm() + + def clip_params(self): + """ + Clips the parameters to be between 0 and 1 and also within the color + space's gamut. + """ + + clamp_params = torch.clamp(self.xform_params, 0, 1).data + + params_shape = self.xform_params.size() + flattened_params = ( + clamp_params + .permute(0, 4, 1, 2, 3) + .reshape(params_shape[0], 3, -1, 1) + ) + gamut_params = self.cspace.from_rgb(self.cspace.to_rgb( + flattened_params)) + clamp_params = ( + gamut_params + .permute(0, 2, 3, 1) + .reshape(*params_shape) + ) + + change_in_params = clamp_params - self.xform_params.data + self.xform_params.data.add_(change_in_params) + + def merge_xform(self, other, self_mask): + """ + Takes in an other instance of this same class with the same + shape of parameters (NxSHAPE) and a self_mask bytetensor of length + N and outputs the merge between self's parameters for the indices + of 1s in the self_mask and other's parameters for the indices of 0's + """ + + super().merge_xform(other, self_mask) + new_xform = FullSpatial(shape=self.img_shape, + manual_gpu=self.use_gpu, + resolution_x=self.resolution_x, + resolution_y=self.resolution_y, + resolution_z=self.resolution_z, + cspace=self.cspace) + new_params = utils.fold_mask(self.xform_params.data, + other.xform_params.data, self_mask) + new_xform.xform_params = nn.Parameter(new_params) + + return new_xform + + def project_params(self, lp, lp_bound): + """ + Projects the params to be within lp_bound (according to an lp) + of the identity map. First thing we do is clip the params to be + valid, too. + ARGS: + lp : int or 'inf' - which LP norm we use. Must be an int or the + string 'inf'. + lp_bound : float - how far we're allowed to go in LP land. Can be + a list to indicate that we can go more in some channels + than others. + RETURNS: + None, but modifies self.xform_params + """ + + assert isinstance(lp, int) or lp == 'inf' + + # clip first + self.clip_params() + + # then project back + if lp == 'inf': + try: + # first, assume lp_bound is a vector, and then revert to scalar + # if it's not + clamped_channels = [] + for channel_index, bound in enumerate(lp_bound): + clamped_channels.append(utils.clamp_ref( + self.xform_params[..., channel_index], + self.identity_params[..., channel_index], + bound, + )) + clamp_params = torch.stack(clamped_channels, 4) + except TypeError: + clamp_params = utils.clamp_ref(self.xform_params.data, + self.identity_params, lp_bound) + change_in_params = clamp_params - self.xform_params.data + else: + flattened_params = ( + self.xform_params.data - + self.identity_params + ).reshape((-1, 3)) + projected_params = flattened_params.renorm(lp, 0, lp_bound) + flattened_change = projected_params - flattened_params + change_in_params = flattened_change.reshape( + self.xform_params.size()) + self.xform_params.data.add_(change_in_params) + + def forward(self, imgs): + device = torch.device('cuda') if self.use_gpu else None + N, C, W, H = self.img_shape + imgs = imgs.permute(0, 2, 3, 1) # N x W x H x C + imgs = imgs * torch.tensor( + [ + self.resolution_x - 1, + self.resolution_y - 1, + self.resolution_z - 1, + ], + dtype=torch.float, + device=device, + )[None, None, None, :].expand(N, W, H, C) + integer_part, float_part = torch.floor(imgs).long(), imgs % 1 + params_list = self.xform_params.view(N, -1, 3) + + # do trilinear interpolation from the params grid + endpoint_values = [] + for delta_x in [0, 1]: + corner_values = [] + for delta_y in [0, 1]: + vertex_values = [] + for delta_z in [0, 1]: + params_index = Variable(torch.zeros( + N, W, H, + dtype=torch.long, + device=device, + )) + for color_index, resolution in [ + (integer_part[..., 0] + delta_x, self.resolution_x), + (integer_part[..., 1] + delta_y, self.resolution_y), + (integer_part[..., 2] + delta_z, self.resolution_z), + ]: + color_index = color_index.clamp( + 0, resolution - 1) + params_index = (params_index * resolution + + color_index) + params_index = params_index.view(N, -1)[:, :, None] \ + .expand(-1, -1, 3) + vertex_values.append( + params_list.gather(1, params_index) + .view(N, W, H, C) + ) + corner_values.append( + vertex_values[0] * (1 - float_part[..., 2, None]) + + vertex_values[1] * float_part[..., 2, None] + ) + endpoint_values.append( + corner_values[0] * (1 - float_part[..., 1, None]) + + corner_values[1] * float_part[..., 1, None] + ) + result = ( + endpoint_values[0] * (1 - float_part[..., 0, None]) + + endpoint_values[1] * float_part[..., 0, None] + ) + return result.permute(0, 3, 1, 2) + + @staticmethod + @lru_cache(maxsize=10) + def construct_identity_params(batch_size, resolution_x, resolution_y, + resolution_z, device): + identity_params = torch.empty( + batch_size, resolution_x, resolution_y, + resolution_z, 3, + dtype=torch.float, + device=device, + ) + for x in range(resolution_x): + for y in range(resolution_y): + for z in range(resolution_z): + identity_params[:, x, y, z, 0] = \ + x / (resolution_x - 1) + identity_params[:, x, y, z, 1] = \ + y / (resolution_y - 1) + identity_params[:, x, y, z, 2] = \ + z / (resolution_z - 1) + return identity_params diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/README.md b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/README.md new file mode 100644 index 0000000..69e668c --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/README.md @@ -0,0 +1 @@ +Code in this directory is adapted from the [`mister_ed`](https://github.com/revbucket/mister_ed) library. \ No newline at end of file diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/__init__.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/__init__.py new file mode 100644 index 0000000..4f3e26b --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/__init__.py @@ -0,0 +1,12 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/__init__.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_attacks.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_attacks.py new file mode 100644 index 0000000..cd8bfda --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_attacks.py @@ -0,0 +1,710 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/adversarial_attacks.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" Holds the various attacks we can do """ + +from __future__ import print_function +from six import string_types +import torch +from torch.autograd import Variable +from torch import optim + +from .utils import pytorch_utils as utils +from . import loss_functions as lf + +MAXFLOAT = 1e20 + + +############################################################################### +# # +# PARENT CLASS FOR ADVERSARIAL ATTACKS # +# # +############################################################################### + +class AdversarialAttack(object): + """ Wrapper for adversarial attacks. Is helpful for when subsidiary methods + are needed. + """ + + def __init__(self, classifier_net, normalizer, threat_model, + manual_gpu=None): + """ Initializes things to hold to perform a single batch of + adversarial attacks + ARGS: + classifier_net : nn.Module subclass - neural net that is the + classifier we're attacking + normalizer : DifferentiableNormalize object - object to convert + input data to mean-zero, unit-var examples + threat_model : ThreatModel object - object that allows us to create + per-minibatch adversarial examples + manual_gpu : None or boolean - if not None, we override the + environment variable 'MISTER_ED_GPU' for how we use + the GPU in this object + + """ + self.classifier_net = classifier_net + self.normalizer = normalizer or utils.IdentityNormalize() + if manual_gpu is not None: + self.use_gpu = manual_gpu + else: + self.use_gpu = utils.use_gpu() + self.validator = lambda *args: None + self.threat_model = threat_model + + @property + def _dtype(self): + return torch.cuda.FloatTensor if self.use_gpu else torch.FloatTensor + + def setup(self): + self.classifier_net.eval() + self.normalizer.differentiable_call() + + def eval(self, ground_examples, adversarials, labels, topk=1): + """ Evaluates how good the adversarial examples are + ARGS: + ground_truths: Variable (NxCxHxW) - examples before we did + adversarial perturbation. Vals in [0, 1] range + adversarials: Variable (NxCxHxW) - examples after we did + adversarial perturbation. Should be same shape and + in same order as ground_truth + labels: Variable (longTensor N) - correct labels of classification + output + RETURNS: + tuple of (% of correctly classified original examples, + % of correctly classified adversarial examples) + """ + normed_ground = self.normalizer.forward(ground_examples) + ground_output = self.classifier_net.forward(normed_ground) + + normed_advs = self.normalizer.forward(adversarials) + adv_output = self.classifier_net.forward(normed_advs) + + start_prec = utils.accuracy(ground_output.data, labels.data, + topk=(topk,)) + adv_prec = utils.accuracy(adv_output.data, labels.data, + topk=(topk,)) + + return float(start_prec[0]), float(adv_prec[0]) + + def eval_attack_only(self, adversarials, labels, topk=1): + """ Outputs the accuracy of the adv_inputs only + ARGS: + adv_inputs: Variable NxCxHxW - examples after we did adversarial + perturbation + labels: Variable (longtensor N) - correct labels of classification + output + topk: int - criterion for 'correct' classification + RETURNS: + (int) number of correctly classified examples + """ + + normed_advs = self.normalizer.forward(adversarials) + + adv_output = self.classifier_net.forward(normed_advs) + return utils.accuracy_int(adv_output, labels, topk=topk) + + def print_eval_str(self, ground_examples, adversarials, labels, topk=1): + """ Prints how good this adversarial attack is + (explicitly prints out %CorrectlyClassified(ground_examples) + vs %CorrectlyClassified(adversarials) + + ARGS: + ground_truths: Variable (NxCxHxW) - examples before we did + adversarial perturbation. Vals in [0, 1] range + adversarials: Variable (NxCxHxW) - examples after we did + adversarial perturbation. Should be same shape and + in same order as ground_truth + labels: Variable (longTensor N) - correct labels of classification + output + RETURNS: + None, prints some stuff though + """ + + og, adv = self.eval(ground_examples, adversarials, labels, topk=topk) + print("Went from %s correct to %s correct" % (og, adv)) + + def validation_loop(self, examples, labels, iter_no=None): + """ Prints out validation values interim for use in iterative techniques + ARGS: + new_examples: Variable (NxCxHxW) - [0.0, 1.0] images to be + classified and compared against labels + labels: Variable (longTensor + N) - correct labels for indices of + examples + iter_no: String - an extra thing for prettier prints + RETURNS: + None + """ + normed_input = self.normalizer.forward(examples) + new_output = self.classifier_net.forward(normed_input) + new_prec = utils.accuracy(new_output.data, labels.data, topk=(1,)) + print_str = "" + if isinstance(iter_no, int): + print_str += "(iteration %02d): " % iter_no + elif isinstance(iter_no, string_types): + print_str += "(%s): " % iter_no + else: + pass + + print_str += " %s correct" % float(new_prec[0]) + + print(print_str) + + +############################################################################## +# # +# Fast Gradient Sign Method (FGSM) # +# # +############################################################################## + +class FGSM(AdversarialAttack): + def __init__(self, classifier_net, normalizer, threat_model, loss_fxn, + manual_gpu=None): + super(FGSM, self).__init__(classifier_net, normalizer, threat_model, + manual_gpu=manual_gpu) + self.loss_fxn = loss_fxn + + def attack(self, examples, labels, step_size=0.05, verbose=True): + """ Builds FGSM examples for the given examples with l_inf bound + ARGS: + classifier: Pytorch NN + examples: Nxcxwxh tensor for N examples. NOT NORMALIZED (i.e. all + vals are between 0.0 and 1.0 ) + labels: single-dimension tensor with labels of examples (in same + order) + step_size: float - how much we nudge each parameter along the + signs of its gradient + normalizer: DifferentiableNormalize object to prep objects into + classifier + evaluate: boolean, if True will validation results + loss_fxn: RegularizedLoss object - partially applied loss fxn that + takes [0.0, 1.0] image Variables and labels and outputs + a scalar loss variable. Also has a zero_grad method + RETURNS: + AdversarialPerturbation object with correct parameters. + Calling perturbation() gets Variable of output and + calling perturbation().data gets tensor of output + """ + self.classifier_net.eval() # ALWAYS EVAL FOR BUILDING ADV EXAMPLES + + perturbation = self.threat_model(examples) + + var_examples = Variable(examples, requires_grad=True) + var_labels = Variable(labels, requires_grad=False) + + ###################################################################### + # Build adversarial examples # + ###################################################################### + + # Fix the 'reference' images for the loss function + self.loss_fxn.setup_attack_batch(var_examples) + + # take gradients + loss = self.loss_fxn.forward(perturbation(var_examples), var_labels, + perturbation=perturbation) + torch.autograd.backward(loss) + + # add adversarial noise to each parameter + update_fxn = lambda grad_data: step_size * torch.sign(grad_data) + perturbation.update_params(update_fxn) + + if verbose: + self.validation_loop(perturbation(var_examples), var_labels, + iter_no='Post FGSM') + + # output tensor with the data + self.loss_fxn.cleanup_attack_batch() + perturbation.attach_originals(examples) + return perturbation + + +############################################################################## +# # +# PGD/FGSM^k/BIM # +# # +############################################################################## +# This goes by a lot of different names in the literature +# The key idea here is that we take many small steps of FGSM +# I'll call it PGD though + +class PGD(AdversarialAttack): + + def __init__(self, classifier_net, normalizer, threat_model, loss_fxn, + manual_gpu=None): + super(PGD, self).__init__(classifier_net, normalizer, threat_model, + manual_gpu=manual_gpu) + self.loss_fxn = loss_fxn # WE MAXIMIZE THIS!!! + + def attack(self, examples, labels, step_size=1.0 / 255.0, + num_iterations=20, random_init=False, signed=True, + optimizer=None, optimizer_kwargs=None, + loss_convergence=0.999, verbose=True, + keep_best=True, eot_iter=1): + """ Builds PGD examples for the given examples with l_inf bound and + given step size. Is almost identical to the BIM attack, except + we take steps that are proportional to gradient value instead of + just their sign. + + ARGS: + examples: NxCxHxW tensor - for N examples, is NOT NORMALIZED + (i.e., all values are in between 0.0 and 1.0) + labels: N longTensor - single dimension tensor with labels of + examples (in same order as examples) + l_inf_bound : float - how much we're allowed to perturb each pixel + (relative to the 0.0, 1.0 range) + step_size : float - how much of a step we take each iteration + num_iterations: int or pair of ints - how many iterations we take. + If pair of ints, is of form (lo, hi), where we run + at least 'lo' iterations, at most 'hi' iterations + and we quit early if loss has stabilized. + random_init : bool - if True, we randomly pick a point in the + l-inf epsilon ball around each example + signed : bool - if True, each step is + adversarial = adversarial + sign(grad) + [this is the form that madry et al use] + if False, each step is + adversarial = adversarial + grad + keep_best : bool - if True, we keep track of the best adversarial + perturbations per example (in terms of maximal + loss) in the minibatch. The output is the best of + each of these then + RETURNS: + AdversarialPerturbation object with correct parameters. + Calling perturbation() gets Variable of output and + calling perturbation().data gets tensor of output + """ + + ###################################################################### + # Setups and assertions # + ###################################################################### + + self.classifier_net.eval() + + if not verbose: + self.validator = lambda ex, label, iter_no: None + else: + self.validator = self.validation_loop + + perturbation = self.threat_model(examples) + + num_examples = examples.shape[0] + var_examples = Variable(examples, requires_grad=True) + var_labels = Variable(labels, requires_grad=False) + + if isinstance(num_iterations, int): + min_iterations = num_iterations + max_iterations = num_iterations + elif isinstance(num_iterations, tuple): + min_iterations, max_iterations = num_iterations + + best_perturbation = None + if keep_best: + best_loss_per_example = {i: None for i in range(num_examples)} + + prev_loss = None + + ###################################################################### + # Loop through iterations # + ###################################################################### + + self.loss_fxn.setup_attack_batch(var_examples) + self.validator(var_examples, var_labels, iter_no="START") + + # random initialization if necessary + if random_init: + perturbation.random_init() + self.validator(perturbation(var_examples), var_labels, + iter_no="RANDOM") + + # Build optimizer techniques for both signed and unsigned methods + optimizer = optimizer or optim.Adam + if optimizer_kwargs is None: + optimizer_kwargs = {'lr': 0.0001} + optimizer = optimizer(perturbation.parameters(), **optimizer_kwargs) + + update_fxn = lambda grad_data: -1 * step_size * torch.sign(grad_data) + + param_list = list(perturbation.parameters()) + assert len(param_list) == 1, len(param_list) + param = param_list[0] + print(f'inside PGD attack, eot_iter: {eot_iter}, max_iterations: {max_iterations}') + for iter_no in range(max_iterations): + print("pgd iter", iter_no) + perturbation.zero_grad() + + grad = torch.zeros_like(param) + loss_per_example_ave = 0 + for i in range(eot_iter): + loss_per_example = self.loss_fxn.forward(perturbation(var_examples), var_labels, + perturbation=perturbation, + output_per_example=keep_best) + + loss_per_example_ave += loss_per_example.detach().clone() + loss = -1 * loss_per_example.sum() + + loss.backward() + grad += param.grad.data.detach() + param.grad.data.zero_() + + grad /= float(eot_iter) + loss_per_example_ave /= float(eot_iter) + + assert len(param_list) == 1, len(param_list) + param.grad.data = grad.clone() + + if signed: + perturbation.update_params(update_fxn) + else: + optimizer.step() + + if keep_best: + mask_val = torch.zeros(num_examples, dtype=torch.uint8) + for i, el in enumerate(loss_per_example_ave): + this_best_loss = best_loss_per_example[i] + if this_best_loss is None or this_best_loss[1] < float(el): + mask_val[i] = 1 + best_loss_per_example[i] = (iter_no, float(el)) + + if best_perturbation is None: + best_perturbation = self.threat_model(examples) + + best_perturbation = perturbation.merge_perturbation( + best_perturbation, + mask_val) + + self.validator((best_perturbation or perturbation)(var_examples), + var_labels, iter_no=iter_no) + + # Stop early if loss didn't go down too much + if (iter_no >= min_iterations and + float(loss) >= loss_convergence * prev_loss): + if verbose: + print("Stopping early at %03d iterations" % iter_no) + break + prev_loss = float(loss) + + perturbation.zero_grad() + self.loss_fxn.cleanup_attack_batch() + perturbation.attach_originals(examples) + return perturbation + + +############################################################################## +# # +# CARLINI WAGNER # +# # +############################################################################## +""" +General class of CW attacks: these aim to solve optim problems of the form + +Adv(x) = argmin_{x'} D(x, x') + s.t. f(x) != f(x') + x' is a valid attack (e.g., meets LP bounds) + +Which is typically relaxed to solving +Adv(x) = argmin_{x'} D(x, x') + lambda * L_adv(x') +where L_adv(x') is only nonpositive when f(x) != f(x'). + +Binary search is performed on a per-example basis to find the appropriate +lambda. + +The distance function is backpropagated through in each bin search step, so it +needs to be differentiable. It does not need to be a true distance metric tho +""" + + +class CarliniWagner(AdversarialAttack): + + def __init__(self, classifier_net, normalizer, threat_model, + distance_fxn, carlini_loss, manual_gpu=None): + """ This is a different init than the other style attacks because the + loss function is separated into two arguments here + ARGS: + classifier_net: standard attack arg + normalizer: standard attack arg + threat_model: standard attack arg + distance_fxn: lf.ReferenceRegularizer subclass (CLASS NOT INSTANCE) + - is a loss function + that stores originals so it can be used to create a + RegularizedLoss object with the carlini loss object + carlini_loss: lf.PartialLoss subclass (CLASS NOT INSTANCE) - is the + loss term that is + a function on images and labels that only + returns zero when the images are adversarial + """ + super(CarliniWagner, self).__init__(classifier_net, normalizer, + threat_model, manual_gpu=manual_gpu) + + assert issubclass(distance_fxn, lf.ReferenceRegularizer) + assert issubclass(carlini_loss, lf.CWLossF6) + + self.loss_classes = {'distance_fxn': distance_fxn, + 'carlini_loss': carlini_loss} + + def _construct_loss_fxn(self, initial_lambda, confidence): + """ Uses the distance_fxn and carlini_loss to create a loss function to + be optimized + ARGS: + initial_lambda : float - which lambda to use initially + in the regularization of the carlini loss + confidence : float - how great the difference in the logits must be + for the carlini_loss to be zero. Overwrites the + self.carlini_loss.kappa value + RETURNS: + RegularizedLoss OBJECT to be used as the loss for this optimization + """ + losses = {'distance_fxn': self.loss_classes['distance_fxn'](None, + use_gpu=self.use_gpu), + 'carlini_loss': self.loss_classes['carlini_loss']( + self.classifier_net, + self.normalizer, + kappa=confidence)} + scalars = {'distance_fxn': 1.0, + 'carlini_loss': initial_lambda} + return lf.RegularizedLoss(losses, scalars) + + def _optimize_step(self, optimizer, perturbation, var_examples, + var_targets, var_scale, loss_fxn, targeted=False): + """ Does one step of optimization """ + assert not targeted + optimizer.zero_grad() + + loss = loss_fxn.forward(perturbation(var_examples), var_targets) + if torch.numel(loss) > 1: + loss = loss.sum() + loss.backward() + + optimizer.step() + # return a loss 'average' to determine if we need to stop early + return loss.item() + + def _batch_compare(self, example_logits, targets, confidence=0.0, + targeted=False): + """ Returns a list of indices of valid adversarial examples + ARGS: + example_logits: Variable/Tensor (Nx#Classes) - output logits for a + batch of images + targets: Variable/Tensor (N) - each element is a class index for the + target class for the i^th example. + confidence: float - how much the logits must differ by for an + attack to be considered valid + targeted: bool - if True, the 'targets' arg should be the targets + we want to hit. If False, 'targets' arg should be + the targets we do NOT want to hit + RETURNS: + Variable ByteTensor of length (N) on the same device as + example_logits/targets with 1's for successful adversaral examples, + 0's for unsuccessful + """ + # check if the max val is the targets + target_vals = example_logits.gather(1, targets.view(-1, 1)) + max_vals, max_idxs = torch.max(example_logits, 1) + max_eq_targets = torch.eq(targets, max_idxs) + + # check margins between max and target_vals + if targeted: + max_2_vals, _ = example_logits.kthvalue(2, dim=1) + good_confidence = torch.gt(max_vals - confidence, max_2_vals) + one_hot_indices = max_eq_targets * good_confidence + else: + good_confidence = torch.gt(max_vals.view(-1, 1), + target_vals + confidence) + one_hot_indices = ((1 - max_eq_targets.data).view(-1, 1) * + good_confidence.data) + + return one_hot_indices.squeeze() + # return [idx for idx, el in enumerate(one_hot_indices) if el[0] == 1] + + @classmethod + def tweak_lambdas(cls, var_scale_lo, var_scale_hi, var_scale, + successful_mask): + """ Modifies the constant scaling that we keep to weight f_adv vs D(.) + in our loss function. + + IF the attack was successful + THEN hi -> lambda + lambda -> (lambda + lo) /2 + ELSE + lo -> lambda + lambda -> (lambda + hi) / 2 + + + ARGS: + var_scale_lo : Variable (N) - variable that holds the running lower + bounds in our binary search + var_scale_hi: Variable (N) - variable that holds the running upper + bounds in our binary search + var_scale : Variable (N) - variable that holds the lambdas we + actually use + successful_mask : Variable (ByteTensor N) - mask that holds the + indices of the successful attacks + RETURNS: + (var_scale_lo, var_scale_hi, var_scale) but modified according to + the rule describe in the spec of this method + """ + prev_his = var_scale_hi.data + downweights = (var_scale_lo.data + var_scale.data) / 2.0 + upweights = (var_scale_hi.data + var_scale.data) / 2.0 + + scale_hi = utils.fold_mask(var_scale.data, var_scale_hi.data, + successful_mask.data) + scale_lo = utils.fold_mask(var_scale_lo.data, var_scale.data, + successful_mask.data) + scale = utils.fold_mask(downweights, upweights, + successful_mask.data) + return (Variable(scale_lo), Variable(scale_hi), Variable(scale)) + + def attack(self, examples, labels, targets=None, initial_lambda=1.0, + num_bin_search_steps=10, num_optim_steps=1000, + confidence=0.0, verbose=True): + """ Performs Carlini Wagner attack on provided examples to make them + not get classified as the labels. + ARGS: + examples : Tensor (NxCxHxW) - input images to be made adversarial + labels : Tensor (N) - correct labels of the examples + initial_lambda : float - which lambda to use initially + in the regularization of the carlini loss + num_bin_search_steps : int - how many binary search steps we perform + to optimize the lambda + num_optim_steps : int - how many optimizer steps we perform during + each binary search step (we may stop early) + confidence : float - how great the difference in the logits must be + for the carlini_loss to be zero. Overwrites the + self.carlini_loss.kappa value + RETURNS: + AdversarialPerturbation object with correct parameters. + Calling perturbation() gets Variable of output and + calling perturbation().data gets tensor of output + calling perturbation(distances=True) returns a dict like + {} + """ + + ###################################################################### + # First perform some setups # + ###################################################################### + + if targets is not None: + raise NotImplementedError("Targeted attacks aren't built yet") + + if self.use_gpu: + examples = examples.cuda() + labels = labels.cuda() + + self.classifier_net.eval() # ALWAYS EVAL FOR BUILDING ADV EXAMPLES + + var_examples = Variable(examples, requires_grad=False) + var_labels = Variable(labels, requires_grad=False) + + loss_fxn = self._construct_loss_fxn(initial_lambda, confidence) + loss_fxn.setup_attack_batch(var_examples) + distance_fxn = loss_fxn.losses['distance_fxn'] + + num_examples = examples.shape[0] + + best_results = {'best_dist': torch.ones(num_examples) \ + .type(examples.type()) \ + * MAXFLOAT, + 'best_perturbation': self.threat_model(examples)} + + ###################################################################### + # Now start the binary search # + ###################################################################### + var_scale_lo = Variable(torch.zeros(num_examples) \ + .type(self._dtype).squeeze()) + + var_scale = Variable(torch.ones(num_examples, 1).type(self._dtype) * + initial_lambda).squeeze() + var_scale_hi = Variable(torch.ones(num_examples).type(self._dtype) + * 128).squeeze() # HARDCODED UPPER LIMIT + + for bin_search_step in range(num_bin_search_steps): + perturbation = self.threat_model(examples) + ################################################################## + # Optimize with a given scale constant # + ################################################################## + if verbose: + print("Starting binary_search_step %02d..." % bin_search_step) + + prev_loss = MAXFLOAT + optimizer = optim.Adam(perturbation.parameters(), lr=0.001) + + for optim_step in range(num_optim_steps): + + if verbose and optim_step > 0 and optim_step % 25 == 0: + print("Optim search: %s, Loss: %s" % + (optim_step, prev_loss)) + + loss_sum = self._optimize_step(optimizer, perturbation, + var_examples, var_labels, + var_scale, loss_fxn) + + if loss_sum + 1e-10 > prev_loss * 0.99999 and optim_step >= 100: + if verbose: + print(("...stopping early on binary_search_step %02d " + " after %03d iterations") % (bin_search_step, + optim_step)) + break + prev_loss = loss_sum + # End inner optimize loop + + ################################################################ + # Update with results from optimization # + ################################################################ + + # We only keep this round's perturbations if two things occur: + # 1) the perturbation fools the classifier + # 2) the perturbation is closer to original than the best-so-far + + bin_search_perts = perturbation(var_examples) + bin_search_out = self.classifier_net.forward(bin_search_perts) + successful_attack_idxs = self._batch_compare(bin_search_out, + var_labels) + + batch_dists = distance_fxn.forward(bin_search_perts).data + + successful_dist_idxs = batch_dists < best_results['best_dist'] + successful_dist_idxs = successful_dist_idxs + + successful_mask = successful_attack_idxs * successful_dist_idxs + + # And then generate a new 'best distance' and 'best perturbation' + + best_results['best_dist'] = utils.fold_mask(batch_dists, + best_results['best_dist'], + successful_mask) + + best_results['best_perturbation'] = \ + perturbation.merge_perturbation( + best_results['best_perturbation'], + successful_mask) + + # And then adjust the scale variables (lambdas) + new_scales = self.tweak_lambdas(var_scale_lo, var_scale_hi, + var_scale, + Variable(successful_mask)) + + var_scale_lo, var_scale_hi, var_scale = new_scales + + # End binary search loop + if verbose: + num_successful = len([_ for _ in best_results['best_dist'] + if _ < MAXFLOAT]) + print("\n Ending attack") + print("Successful attacks for %03d/%03d examples in CONTINUOUS" % \ + (num_successful, num_examples)) + + loss_fxn.cleanup_attack_batch() + perturbation.attach_originals(examples) + perturbation.attach_attr('distances', best_results['best_dist']) + + return perturbation diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_perturbations.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_perturbations.py new file mode 100644 index 0000000..9c98081 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_perturbations.py @@ -0,0 +1,813 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/adversarial_perturbations.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" File that holds adversarial perturbations as torch.nn.Modules. + An adversarial perturbation is an example-specific +""" + +import torch +import torch.nn as nn +from . import spatial_transformers as st +from .utils import image_utils as img_utils +from .utils import pytorch_utils as utils +from torch.autograd import Variable +import functools + + +# assert initialized decorator +def initialized(func): + @functools.wraps(func) + def wrapper(self, *args, **kwargs): + assert self.initialized, ("Parameters not initialized yet. " + "Call .forward(...) first") + return func(self, *args, **kwargs) + return wrapper + +############################################################################## +# # +# SKELETON CLASS # +# # +############################################################################## + +class AdversarialPerturbation(nn.Module): + """ Skeleton class to hold adversarial perturbations FOR A SINGLE MINIBATCH. + For general input-agnostic adversarial perturbations, see the + ThreatModel class + + All subclasses need the following: + - perturbation_norm() : no args -> scalar Variable + - self.parameters() needs to iterate over params we want to optimize + - constrain_params() : no args -> no return, + modifies the parameters such that this is still a valid image + - forward : no args -> Variable - applies the adversarial perturbation + the originals and outputs a Variable of how we got there + - adversarial_tensors() : applies the adversarial transform to the + originals and outputs TENSORS that are the + adversarial images + """ + + def __init__(self, threat_model, perturbation_params): + + super(AdversarialPerturbation, self).__init__() + self.threat_model = threat_model + self.initialized = False + self.perturbation_params = perturbation_params + + if isinstance(perturbation_params, tuple): + self.use_gpu = perturbation_params[1].use_gpu or utils.use_gpu() + else: + self.use_gpu = perturbation_params.use_gpu or utils.use_gpu() + # Stores parameters of the adversarial perturbation and hyperparams + # to compute total perturbation norm here + + + def __call__(self, x): + return self.forward(x) + + def __repr__(self): + if isinstance(self.perturbation_params, tuple): + output_str = "[Perturbation] %s: %s" % (self.__class__.__name__, + self.perturbation_params[1]) + output_str += '\n[' + for el in self.perturbation_params[0]: + output_str += '\n\t%s,' % el + output_str += '\n]' + return output_str + else: + return "[Perturbation] %s: %s" % (self.__class__.__name__, + self.perturbation_params) + + def _merge_setup(self, *args): + """ Internal method to be used when initializing a new perturbation + from merging only. Should not be called outside this file!! + """ + pass + + def setup(self, x): + """ This is the standard setup technique and should be used to + initialize a perturbation (i.e. sets up parameters and unlocks + all other methods) + ARGS: + x : Variable or Tensor (NxCxHxW) - the images this perturbation is + intended for + """ + self.num_examples = x.shape[0] + + + @initialized + def perturbation_norm(self, x=None): + """ This returns the 'norm' of this perturbation. Optionally, for + certain norms, having access to the images for which the + perturbation is intended can have an effect on the output. + ARGS: + x : Variable or Tensor (NxCxHxW) - optionally can be the images + that the perturbation was intended for + RETURNS: + Scalar Variable + """ + raise NotImplementedError("Need to call subclass method here") + + @initialized + def constrain_params(self): + """ This modifies the parameters such that the perturbation falls within + the threat model it belongs to. E.g. for l-infinity threat models, + this clips the params to match the right l-infinity bound. + + TODO: for non-lp norms, projecting to the nearest point in the level + set + """ + raise NotImplementedError("Need to call subclass method here") + + @initialized + def make_valid_image(self, x): + """ This takes in the minibatch self's parameters were tuned for and + clips the parameters such that this is still a valid image. + ARGS: + x : Variable or Tensor (NxCxHxW) - the images this this perturbation + was intended for + RETURNS: + None + """ + pass # Only implement in classes that can create invalid images + + @initialized + def forward(self, x): + """ This takes in the minibatch self's parameters were tuned for and + outputs a variable of the perturbation applied to the images + ARGS: + x : Variable (NxCxHxW) - the images this this perturbation + was intended for + RETURNS: + Variable (NxCxHxW) - the perturbation applied to the input images + """ + raise NotImplementedError("Need to call subclass method here") + + @initialized + def add_to_params(self, grad_data): + """ This takes in a Tensor the same shape as self's parameters and + adds to them. Note that this usually won't preserve gradient + information + (also this might have different signatures in subclasses) + ARGS: + x : Tensor (params-shape) - Tensor to be added to the + parameters of self + RETURNS: + None, but modifies self's parameters + """ + raise NotImplementedError("Need to call subclass method here") + + @initialized + def update_params(self, step_fxn): + """ This takes in a function step_fxn: Tensor -> Tensor that generates + the change to the parameters that we step along. This loops through + all parameters and updates signs accordingly. + For sequential perturbations, this also multiplies by a scalar if + provided + ARGS: + step_fxn : Tensor -> Tensor - function that maps tensors to tensors. + e.g. for FGSM, we want a function that multiplies signs + by step_size + RETURNS: + None, but updates the parameters + """ + raise NotImplementedError("Need to call subclass method here") + + + @initialized + def adversarial_tensors(self, x=None): + """ Little helper method to get the tensors of the adversarial images + directly + """ + assert x is not None or self.originals is not None + if x is None: + x = self.originals + + return self.forward(x).data + + @initialized + def attach_attr(self, attr_name, attr): + """ Special method to set an attribute if it doesn't exist in this + object yet. throws error if this attr already exists + ARGS: + attr_name : string - name of attribute we're attaching + attr: object - attribute we're attaching + RETURNS: + None + """ + if hasattr(self, attr_name): + raise Exception("%s already has attribute %s" % (self, attr_name)) + else: + setattr(self, attr_name, attr) + + + @initialized + def attach_originals(self, originals): + """ Little helper method to tack on the original images to self to + pass around the (images, perturbation) in a single object + """ + self.attach_attr('originals', originals) + + + @initialized + def random_init(self): + """ Modifies the parameters such that they're randomly initialized + uniformly across the threat model (this is harder for nonLp threat + models...). Takes no args and returns nothing, but modifies the + parameters + """ + raise NotImplementedError("Need to call subclass method here") + + @initialized + def merge_perturbation(self, other, self_mask): + """ Special technique to merge this perturbation with another + perturbation of the same threat model. + This will return a new perturbation object that, for each parameter + will return the parameters of self for self_mask, and the + perturbation of other for NOT(self_mask) + + ARGS: + other: AdversarialPerturbation Object - instance of other + adversarial perturbation that is instantiated with the + same threat model as self + self_indices: ByteTensor [N] : bytetensor indicating which + parameters to include from self and which to include + from other + """ + + # this parent class just does the shared asserts such that this is a + # valid thing + assert self.__class__ == other.__class__ + assert self.threat_model == other.threat_model + assert self.num_examples == other.num_examples + assert self.perturbation_params == other.perturbation_params + assert other.initialized + + @initialized + def collect_successful(self, classifier_net, normalizer): + """ Returns a list of [adversarials, originals] of the SUCCESSFUL + attacks only, according to the given classifier_net, normalizer + SUCCESSFUL here means that the adversarial is different + ARGS: + TODO: fill in when I'm not in crunchtime + """ + + assert self.originals is not None + adversarials = Variable(self.adversarial_tensors()) + originals = Variable(self.originals) + + adv_out = torch.max(classifier_net(normalizer(adversarials)), 1)[1] + out = torch.max(classifier_net(normalizer(originals)), 1)[1] + adv_idx_bytes = adv_out != out + idxs = [] + for idx, el in enumerate(adv_idx_bytes): + if float(el) > 0: + idxs.append(idx) + + idxs = torch.LongTensor(idxs) + if self.originals.is_cuda: + idxs = idxs.cuda() + + return [torch.index_select(self.adversarial_tensors(), 0, idxs), + torch.index_select(self.originals, 0, idxs)] + + @initialized + def collect_adversarially_successful(self, classifier_net, normalizer, + labels): + """ Returns an object containing the SUCCESSFUL attacked examples, + their corresponding originals, and the number of misclassified + examples + ARGS: + classifier_net : nn.Module subclass - neural net that is the + relevant classifier + normalizer : DifferentiableNormalize object - object to convert + input data to mean-zero, unit-var examples + labels : Variable (longTensor N) - correct labels for classification + of self.originals + RETURNS: + dict with structure: + {'adversarials': Variable(N'xCxHxW) - adversarial perturbation + applied + 'originals': Variable(N'xCxHxW) - unperturbed examples that + were correctly classified AND + successfully attacked + 'num_correctly_classified': int - number of correctly classified + unperturbed examples + } + """ + assert self.originals is not None + adversarials = Variable(self.adversarial_tensors()) + originals = Variable(self.originals) + + adv_out = torch.max(classifier_net(normalizer(adversarials)), 1)[1] + out = torch.max(classifier_net(normalizer(originals)), 1)[1] + + # First take a subset of correctly classified originals + correct_idxs = (out == labels) # correctly classified idxs + adv_idx_bytes = (adv_out != out) # attacked examples + + num_correctly_classified = int(sum(correct_idxs)) + + adv_idxs = adv_idx_bytes * correct_idxs + + + idxs = [] + for idx, el in enumerate(adv_idxs): + if float(el) > 0: + idxs.append(idx) + + idxs = torch.LongTensor(idxs) + if self.originals.is_cuda: + idxs = idxs.cuda() + + + return {'adversarial': torch.index_select(self.adversarial_tensors(), + 0, idxs), + 'originals': torch.index_select(self.originals, 0, idxs), + 'num_correctly_classified': num_correctly_classified} + + + + @initialized + def display(self, scale=5, successful_only=False, classifier_net=None, + normalizer=None): + """ Displays this adversarial perturbation in a 3-row format: + top row is adversarial images, second row is original images, + bottom row is difference magnified by scale (default 5) + ARGS: + scale: int - how much to magnify differences by + successful_only: bool - if True we only display successful (in that + advs output different classifier outputs) + If this is not None, classifie_net and normalizer + cannot be None + RETURNS: + None, but displays images + """ + if successful_only: + assert classifier_net is not None + assert normalizer is not None + advs, origs = self.collect_successful(classifier_net, normalizer) + else: + advs = self.adversarial_tensors() + origs = self.originals + + diffs = torch.clamp((advs - origs) * scale + 0.5, 0, 1) + img_utils.show_images([advs, origs, diffs]) + + +class PerturbationParameters(dict): + """ Object that stores parameters like a dictionary. + This allows perturbation classes to be only partially instantiated and + then fed various 'originals' later. + Implementation taken from : https://stackoverflow.com/a/14620633/3837607 + (and then modified with the getattribute trick to return none instead of + error for missing attributes) + """ + def __init__(self, *args, **kwargs): + super(PerturbationParameters, self).__init__(*args, **kwargs) + if kwargs.get('manual_gpu') is not None: + self.use_gpu = kwargs['manual_gpu'] + else: + self.use_gpu = utils.use_gpu() + self.__dict__ = self + + def __getattribute__(self, name): + try: + return object.__getattribute__(self, name) + except AttributeError: + return None + + +class ThreatModel(object): + def __init__(self, perturbation_class, param_kwargs, *other_args): + """ Factory class to generate per_minibatch instances of Adversarial + perturbations. + ARGS: + perturbation_class : class - subclass of Adversarial Perturbations + param_kwargs : dict - dict containing named kwargs to instantiate + the class in perturbation class + """ + assert issubclass(perturbation_class, AdversarialPerturbation) + self.perturbation_class = perturbation_class + if isinstance(param_kwargs, dict): + param_kwargs = PerturbationParameters(**param_kwargs) + self.param_kwargs = param_kwargs + self.other_args = other_args + + def __repr__(self): + return "[Threat] %s: %s" % (str(self.perturbation_class.__name__), + self.param_kwargs) + + def __call__(self, *args): + if args == (): + return self.perturbation_obj() + else: + perturbation_obj = self.perturbation_obj() + perturbation_obj.setup(*args) + return perturbation_obj + + + + def perturbation_obj(self): + return self.perturbation_class(self, self.param_kwargs, *self.other_args) + + + +############################################################################## +# # +# ADDITION PARAMETERS # +# # +############################################################################## + +class DeltaAddition(AdversarialPerturbation): + + def __init__(self, threat_model, perturbation_params, *other_args): + """ Maintains a delta that gets addded to the originals to generate + adversarial images. This is the type of adversarial perturbation + that the literature extensivey studies + ARGS: + threat_model : ThreatModel object that is used to initialize self + perturbation_params: PerturbationParameters object. + { lp_style : None, int or 'inf' - if not None is the type of + Lp_bound that we apply to this adversarial example + lp_bound : None or float - cannot be None if lp_style is + not None, but if not None should be the lp bound + we allow for adversarial perturbations + custom_norm : None or fxn:(NxCxHxW) -> Scalar Variable. This is + not implemented for now + } + """ + + super(DeltaAddition, self).__init__(threat_model, perturbation_params) + self.lp_style = perturbation_params.lp_style + self.lp_bound = perturbation_params.lp_bound + if perturbation_params.custom_norm is not None: + raise NotImplementedError("Only LP norms allowed for now") + self.scalar_step = perturbation_params.scalar_step or 1.0 + + + def _merge_setup(self, num_examples, delta_data): + """ DANGEROUS TO BE CALLED OUTSIDE OF THIS FILE!!!""" + self.num_examples = num_examples + self.delta = nn.Parameter(delta_data) + self.initialized = True + + + def setup(self, x): + super(DeltaAddition, self).setup(x) + self.delta = nn.Parameter(torch.zeros_like(x)) + self.initialized = True + + @initialized + def perturbation_norm(self, x=None, lp_style=None): + lp_style = lp_style or self.lp_style + assert isinstance(lp_style, int) or lp_style == 'inf' + return utils.batchwise_norm(self.delta, lp=lp_style) + + + @initialized + def constrain_params(self): + new_delta = utils.batchwise_lp_project(self.delta.data, self.lp_style, + self.lp_bound) + delta_diff = new_delta - self.delta.data + self.delta.data.add_(delta_diff) + + @initialized + def make_valid_image(self, x): + new_delta = self.delta.data + change_in_delta = utils.clamp_0_1_delta(new_delta, x) + self.delta.data.add_(change_in_delta) + + @initialized + def update_params(self, step_fxn): + assert self.delta.grad.data is not None + self.add_to_params(step_fxn(self.delta.grad.data) * self.scalar_step) + + @initialized + def add_to_params(self, grad_data): + """ sets params to be self.params + grad_data """ + self.delta.data.add_(grad_data) + + + @initialized + def random_init(self): + self.delta = nn.Parameter(utils.random_from_lp_ball(self.delta.data, + self.lp_style, + self.lp_bound)) + + @initialized + def merge_perturbation(self, other, self_mask): + super(DeltaAddition, self).merge_perturbation(other, self_mask) + + # initialize a new perturbation + new_perturbation = DeltaAddition(self.threat_model, + self.perturbation_params) + + # make the new parameters + new_delta = utils.fold_mask(self.delta.data, other.delta.data, + self_mask) + + # do the merge setup and return the object + new_perturbation._merge_setup(self.num_examples, + new_delta) + return new_perturbation + + + def forward(self, x): + if not self.initialized: + self.setup(x) + self.make_valid_image(x) # not sure which one to do first... + self.constrain_params() + return x + self.delta + + + + +############################################################################## +# # +# SPATIAL PARAMETERS # +# # +############################################################################## + +class ParameterizedXformAdv(AdversarialPerturbation): + + def __init__(self, threat_model, perturbation_params, *other_args): + super(ParameterizedXformAdv, self).__init__(threat_model, + perturbation_params) + assert issubclass(perturbation_params.xform_class, + st.ParameterizedTransformation) + + self.lp_style = perturbation_params.lp_style + self.lp_bound = perturbation_params.lp_bound + self.use_stadv = perturbation_params.use_stadv + self.scalar_step = perturbation_params.scalar_step or 1.0 + + + def _merge_setup(self, num_examples, new_xform): + """ DANGEROUS TO BE CALLED OUTSIDE OF THIS FILE!!!""" + self.num_examples = num_examples + self.xform = new_xform + self.initialized = True + + def setup(self, originals): + super(ParameterizedXformAdv, self).setup(originals) + self.xform = self.perturbation_params.xform_class(shape=originals.shape, + manual_gpu=self.use_gpu) + self.initialized = True + + @initialized + def perturbation_norm(self, x=None, lp_style=None): + lp_style = lp_style or self.lp_style + if self.use_stadv is not None: + assert isinstance(self.xform, st.FullSpatial) + return self.xform.stAdv_norm() + else: + return self.xform.norm(lp=lp_style) + + @initialized + def constrain_params(self, x=None): + # Do lp projections + if isinstance(self.lp_style, int) or self.lp_style == 'inf': + self.xform.project_params(self.lp_style, self.lp_bound) + + + + @initialized + def update_params(self, step_fxn): + param_list = list(self.xform.parameters()) + assert len(param_list) == 1 + params = param_list[0] + assert params.grad.data is not None + self.add_to_params(step_fxn(params.grad.data) * self.scalar_step) + + + @initialized + def add_to_params(self, grad_data): + """ Assumes only one parameters object in the Spatial Transform """ + param_list = list(self.xform.parameters()) + assert len(param_list) == 1 + params = param_list[0] + params.data.add_(grad_data) + + @initialized + def random_init(self): + param_list = list(self.xform.parameters()) + assert len(param_list) == 1 + param = param_list[0] + random_perturb = utils.random_from_lp_ball(param.data, + self.lp_style, + self.lp_bound) + + param.data.add_(self.xform.identity_params(self.xform.img_shape) + + random_perturb - self.xform.xform_params.data) + + + @initialized + def merge_perturbation(self, other, self_mask): + super(ParameterizedXformAdv, self).merge_perturbation(other, self_mask) + new_perturbation = ParameterizedXformAdv(self.threat_model, + self.perturbation_params) + + new_xform = self.xform.merge_xform(other.xform, self_mask) + new_perturbation._merge_setup(self.num_examples, new_xform) + + return new_perturbation + + + def forward(self, x): + if not self.initialized: + self.setup(x) + self.constrain_params() + return self.xform.forward(x) + + + + +############################################################################## +# # +# SPATIAL + ADDITION PARAMETERS # +# # +############################################################################## + +class SequentialPerturbation(AdversarialPerturbation): + """ Takes a list of perturbations and composes them. A norm needs to + be specified here to describe the perturbations. + """ + + def __init__(self, threat_model, perturbation_sequence, + global_parameters=PerturbationParameters(pad=10), + preinit_pipeline=None): + """ Initializes a sequence of adversarial perturbation layers + ARGS: + originals : NxCxHxW tensor - original images we create adversarial + perturbations for + perturbation_sequence : ThreatModel[] - + list of ThreatModel objects + global_parameters : PerturbationParameters - global parameters to + use. These contain things like how to norm this + sequence, how to constrain this sequence, etc + preinit_pipelines: list[] + if not None i + """ + super(SequentialPerturbation, self).__init__(threat_model, + (perturbation_sequence, + global_parameters)) + + if preinit_pipeline is not None: + layers = preinit_pipeline + else: + layers = [] + for threat_model in perturbation_sequence: + assert isinstance(threat_model, ThreatModel) + layers.append(threat_model()) + + self.pipeline = [] + for layer_no, layer in enumerate(layers): + self.pipeline.append(layer) + self.add_module('layer_%02d' % layer_no, layer) + + + # norm: pipeline -> Scalar Variable + self.norm = global_parameters.norm + self.norm_weights = global_parameters.norm_weights + + # padding with black is useful to not throw information away during + # sequential steps + self.pad = nn.ConstantPad2d(global_parameters.pad or 0, 0) + self.unpad = nn.ConstantPad2d(-1 * (global_parameters.pad or 0), 0) + + + + + def _merge_setup(self, num_examples): + self.num_examples = num_examples + self.initialized = True + + + def setup(self, x): + super(SequentialPerturbation, self).setup(x) + x = self.pad(x) + for layer in self.pipeline: + layer.setup(x) + self.initialized = True + + + @initialized + def perturbation_norm(self, x=None, lp_style=None): + # Need to define a nice way to describe the norm here. This can be + # an empirical norm between input/output + # For now, let's just say it's the sum of the norms of each constituent + if self.norm is not None: + return self.norm(self.pipeline, x=x, lp_style=lp_style) + else: + norm_weights = self.norm_weights or\ + [1.0 for _ in range(len(self.pipeline))] + out = None + for i, layer in enumerate(self.pipeline): + weight = norm_weights[i] + layer_norm = layer.perturbation_norm(x=x, lp_style=lp_style) + if out is None: + out = layer_norm * weight + else: + out = out + layer_norm * weight + return out + + @initialized + def make_valid_image(self, x): + x = self.pad(x) + for layer in self.pipeline: + layer.make_valid_image(x) + x = layer(x) + + + @initialized + def constrain_params(self): + # Need to do some sort of crazy projection operator for general things + # For now, let's just constrain each thing in sequence + + for layer in self.pipeline: + layer.constrain_params() + + @initialized + def update_params(self, step_fxn): + for layer in self.pipeline: + layer.update_params(step_fxn) + + + @initialized + def merge_perturbation(self, other, self_mask): + super(SequentialPerturbation, self).merge_perturbation(other, self_mask) + + + new_pipeline = [] + for self_layer, other_layer in zip(self.pipeline, other.pipeline): + new_pipeline.append(self_layer.merge_perturbation(other_layer, + self_mask)) + + + layer_params, global_params = self.perturbation_params + + new_perturbation = SequentialPerturbation(self.threat_model, + layer_params, + global_parameters=global_params, + preinit_pipeline=new_pipeline) + new_perturbation._merge_setup(self.num_examples) + + return new_perturbation + + + + def forward(self, x, layer_slice=None): + """ Layer slice here is either an int or a tuple + If int, we run forward only the first layer_slice layers + If tuple, we start at the + + """ + + # Blocks to handle only particular layer slices (debugging) + if layer_slice is None: + pipeline_iter = iter(self.pipeline) + elif isinstance(layer_slice, int): + pipeline_iter = iter(self.pipeline[:layer_slice]) + elif isinstance(layer_slice, tuple): + pipeline_iter = iter(self.pipeline[layer_slice[0]: layer_slice[1]]) + # End block to handle particular layer slices + + # Handle padding + original_hw = x.shape[-2:] + if not self.initialized: + self.setup(x) + + self.constrain_params() + self.make_valid_image(x) + + x = self.pad(x) + for layer in pipeline_iter: + x = layer(x) + return self.unpad(x) + + + @initialized + def random_init(self): + for layer in self.pipeline: + layer.random_init() + + @initialized + def attach_originals(self, originals): + self.originals = originals + for layer in self.pipeline: + layer.attach_originals(originals) + + + + + diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_training.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_training.py new file mode 100644 index 0000000..0e7f46c --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/adversarial_training.py @@ -0,0 +1,550 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/adversarial_training.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" Contains training code for adversarial training """ + +from __future__ import print_function +import torch +import torch.cuda as cuda +import torch.optim as optim +import torch.nn as nn + +from torch.autograd import Variable + +import random + +from .utils import pytorch_utils as utils, checkpoints + + +############################################################################## +# # +# ATTACK PARAMETERS OBJECT # +# # +############################################################################## + +class AdversarialAttackParameters(object): + """ Wrapper to store an adversarial attack object as well as some extra + parameters for how to use it in training + """ + + def __init__(self, adv_attack_obj, proportion_attacked=1.0, + attack_specific_params=None): + """ Stores params for how to use adversarial attacks in training + ARGS: + adv_attack_obj : AdversarialAttack subclass - + thing that actually does the attack + proportion_attacked: float between [0.0, 1.0] - what proportion of + the minibatch we build adv examples for + attack_specific_params: possibly None dict, but possibly dict with + specific parameters for attacks + + """ + self.adv_attack_obj = adv_attack_obj + self.proportion_attacked = proportion_attacked + + attack_specific_params = attack_specific_params or {} + self.attack_specific_params = attack_specific_params + self.attack_kwargs = attack_specific_params.get('attack_kwargs', {}) + + def set_gpu(self, use_gpu): + """ Propagates changes of the 'use_gpu' parameter down to the attack + ARGS: + use_gpu : bool - if True, the attack uses the GPU, ow it doesn't + RETURNS: + None + """ + self.adv_attack_obj.use_gpu = use_gpu + + def attack(self, inputs, labels): + """ Builds some adversarial examples given real inputs and labels + ARGS: + inputs : torch.Tensor (NxCxHxW) - tensor with examples needed + labels : torch.Tensor (N) - tensor with the examples needed + RETURNS: + some sample of (self.proportion_attacked * N ) examples that are + adversarial, and the corresponding NONADVERSARIAL LABELS + + output is a tuple with three tensors: + (adv_examples, pre_adv_labels, selected_idxs, coupled ) + adv_examples: Tensor with shape (N'xCxHxW) [the perturbed outputs] + pre_adv_labels: Tensor with shape (N') [original labels] + selected_idxs : Tensor with shape (N') [idxs selected] + adv_inputs : Tensor with shape (N') [examples used to make advs] + perturbation: Adversarial Perturbation Object + """ + num_elements = inputs.shape[0] + + selected_idxs = sorted(random.sample(list(range(num_elements)), + int(self.proportion_attacked * num_elements))) + + selected_idxs = inputs.new(selected_idxs).long() + if selected_idxs.numel() == 0: + return (None, None, None) + + adv_inputs = Variable(inputs.index_select(0, selected_idxs)) + pre_adv_labels = labels.index_select(0, selected_idxs) + + perturbation = self.adv_attack_obj.attack(adv_inputs.data, + pre_adv_labels, + **self.attack_kwargs) + adv_examples = perturbation(adv_inputs) + + return (adv_examples, pre_adv_labels, selected_idxs, adv_inputs, + perturbation) + + def eval(self, ground_inputs, adv_inputs, labels, idxs, topk=1): + """ Outputs the accuracy of the adversarial examples + + NOTE: notice the difference between N and N' in the argument + ARGS: + ground_inputs: Variable (NxCxHxW) - examples before we did + adversarial perturbation. Vals in [0, 1] range + adversarials: Variable (N'xCxHxW) - examples after we did + adversarial perturbation. Should be same shape and + in same order as ground_truth + labels: Variable (longTensor N) - correct labels of classification + output + idxs: Variable (longtensor N') - indices of ground_inputs/labels + used for adversarials. + RETURNS: + tuple of (% of correctly classified original examples, + % of correctly classified adversarial examples) + + """ + + selected_grounds = ground_inputs.index_select(0, idxs) + selected_labels = labels.index_select(0, idxs) + return self.adv_attack_obj.eval(selected_grounds, adv_inputs, + selected_labels, topk=topk) + + def eval_attack_only(self, adv_inputs, labels, topk=1): + """ Outputs the accuracy of the adv_inputs only + ARGS: + adv_inputs: Variable NxCxHxW - examples after we did adversarial + perturbation + labels: Variable (longtensor N) - correct labels of classification + output + topk: int - criterion for 'correct' classification + RETURNS: + (int) number of correctly classified examples + """ + + return self.adv_attack_obj.eval_attack_only(adv_inputs, labels, + topk=topk) + + +############################################################################## +# # +# TRAINING OBJECT # +# # +############################################################################## + + +class AdversarialTraining(object): + """ Wrapper for training of a NN with adversarial examples cooked in + """ + + def __init__(self, classifier_net, normalizer, + experiment_name, architecture_name, + manual_gpu=None): + + """ + ARGS: + classifier_net : nn.Module subclass - instance of neural net to classify + images. Can have already be trained, or not + normalizer : DifferentiableNormalize - object to convert to zero-mean + unit-variance domain + experiment_name : String - human-readable name of the 'trained_model' + (this is helpful for identifying checkpoints later) + manual_gpu : None or bool - if not None is a manual override of whether + or not to use the GPU. If left None, we use the GPU if we + can + + ON NOMENCLATURE: + Depending on verbosity levels, training checkpoints are saved after + some training epochs. These are saved as + '//.path.tar' + + Best practice is to keep architecture_name consistent across + adversarially trained models built off the same architecture and having + a descriptive experiment_name for each training instance + """ + self.classifier_net = classifier_net + self.normalizer = normalizer + self.experiment_name = experiment_name + self.architecture_name = architecture_name + + if manual_gpu is not None: + self.use_gpu = manual_gpu + else: + self.use_gpu = utils.use_gpu() + + self.verbosity_level = None + self.verbosity_minibatch = None + self.verbosity_adv = None + self.verbosity_epoch = None + + self.logger = utils.TrainingLogger() + self.log_level = None + self.log_minibatch = None + self.log_adv = None + self.log_epoch = None + + def reset_logger(self): + """ Clears the self.logger instance - useful occasionally """ + self.logger = utils.TrainingLogger() + + def set_verbosity_loglevel(self, level, + verbosity_or_loglevel='verbosity'): + """ Sets the verbosity or loglevel for training. + Is called in .train method so this method doesn't need to be + explicitly called. + + Verbosity is mapped from a string to a comparable int 'level'. + _level : int - comparable value of verbosity + _minibatch: int - we do a printout every this many + minibatches + _adv: int - we evaluate the efficacy of our attack every + this many minibatches + _epoch: int - we printout/log and checkpoint every this many + epochs + ARGS: + level : string ['low', 'medium', 'high', 'snoop'], + varying levels of verbosity/logging in increasing order + + RETURNS: None + """ + assert level in ['low', 'medium', 'high', 'snoop'] + assert verbosity_or_loglevel in ['verbosity', 'loglevel'] + setattr(self, verbosity_or_loglevel, level) + + _level = {'low': 0, + 'medium': 1, + 'high': 2, + 'snoop': 420}[level] + setattr(self, verbosity_or_loglevel + '_level', _level) + + _minibatch = {'medium': 2000, + 'high': 100, + 'snoop': 1}.get(level) + setattr(self, verbosity_or_loglevel + '_minibatch', _minibatch) + + _adv = {'medium': 2000, + 'high': 100, + 'snoop': 1}.get(level) + setattr(self, verbosity_or_loglevel + '_adv', _minibatch) + + _epoch = {'low': 100, + 'medium': 10, + 'high': 1, + 'snoop': 1}.get(level) + setattr(self, verbosity_or_loglevel + '_epoch', _epoch) + + def _attack_subroutine(self, attack_parameters, inputs, labels, + epoch_num, minibatch_num, adv_saver, + logger): + """ Subroutine to run the specified attack on a minibatch and append + the results to inputs/labels. + + NOTE: THIS DOES NOT MUTATE inputs/labels !!!! + + ARGS: + attack_parameters: {k: AdversarialAttackParameters} (or None) - + if not None, contains info on how to do adv + attacks. If None, we don't train adversarially + inputs : Tensor (NxCxHxW) - minibatch of data we build adversarial + examples for + labels : Tensor (longtensor N) - minibatch of labels + epoch_num : int - number of which epoch we're working on. + Is helpful for printing + minibatch_num : int - number of which minibatch we're working on. + Is helpful for printing + adv_saver : None or checkpoints.CustomDataSaver - + if not None, we save the adversarial images for later + use, else we don't save them. + logger : utils.TrainingLogger instance - logger instance to keep + track of logging data if we need data for this instance + RETURNS: + (inputs, labels, adv_inputs, coupled_inputs) + where inputs = ++ adv_inputs + labels is original labels + adv_inputs is the (Variable) adversarial examples generated, + coupled_inputs is the (Variable) inputs used to generate the + adversarial examples (useful for when we don't + augment 1:1). + """ + if attack_parameters is None: + return inputs, labels, None, None + + assert isinstance(attack_parameters, dict) + + adv_inputs_total, adv_labels_total, coupled_inputs = [], [], [] + for (key, param) in attack_parameters.items(): + adv_data = param.attack(inputs, labels) + adv_inputs, adv_labels, adv_idxs, og_adv_inputs, _ = adv_data + + needs_print = (self.verbosity_level >= 1 and + minibatch_num % self.verbosity_adv == self.verbosity_adv - 1) + needs_log = (self.loglevel_level >= 1 and + minibatch_num % self.loglevel_adv == self.loglevel_adv - 1) + + if needs_print or needs_log: + accuracy = param.eval(inputs, adv_inputs, labels, adv_idxs) + + if needs_print: + print('[%d, %5d] accuracy: (%.3f, %.3f)' % + (epoch_num, minibatch_num + 1, accuracy[1], accuracy[0])) + + if needs_log: + logger.log(key, epoch_num, minibatch_num + 1, + (accuracy[1], accuracy[0])) + + if adv_saver is not None: # Save the adversarial examples + adv_saver.save_minibatch(adv_inputs, adv_labels) + + adv_inputs_total.append(adv_inputs) + adv_labels_total.append(adv_labels) + coupled_inputs.append(og_adv_inputs) + + inputs = torch.cat([inputs] + [_.data for _ in adv_inputs_total], dim=0) + labels = torch.cat([labels] + adv_labels_total, dim=0) + coupled = torch.cat(coupled_inputs, dim=0) + return inputs, labels, torch.cat(adv_inputs_total, dim=0), coupled + + def train(self, data_loader, num_epochs, train_loss, + optimizer=None, attack_parameters=None, + verbosity='medium', loglevel='medium', logger=None, + starting_epoch=0, adversarial_save_dir=None, + regularize_adv_scale=None): + """ Modifies the NN weights of self.classifier_net by training with + the specified parameters s + ARGS: + data_loader: torch.utils.data.DataLoader OR + checkpoints.CustomDataLoader - object that loads the + data + num_epoch: int - number of epochs to train on + train_loss: ???? - TBD + optimizer: torch.Optimizer subclass - defaults to Adam with some + decent default params. Pass this in as an actual argument + to do anything different + attack_parameters: AdversarialAttackParameters obj | None | + {key: AdversarialAttackParameters} - + if not None, is either an object or dict of + objects containing names and info on how to do + adv attacks. If None, we don't train + adversarially + verbosity : string - must be 'low', 'medium', 'high', which + describes how much to print + loglevel : string - must be 'low', 'medium', 'high', which + describes how much to log + logger : if not None, is a utils.TrainingLogger instance. Otherwise + we use this instance's self.logger object to log + starting_epoch : int - which epoch number we start on. Is useful + for correct labeling of checkpoints and figuring + out how many epochs we actually need to run for + (i.e., num_epochs - starting_epoch) + adversarial_save_dir: string or None - if not None is the name of + the directory we save adversarial images to. + If None, we don't save adversarial images + regularize_adv_scale : float > 0 or None - if not None we do L1 loss + between the logits of the adv examples and + the inputs used to generate them. This is the + scale constant of that loss + stdout_prints: bool - if True we print out using stdout so we don't + spam logs like crazy + + RETURNS: + None, but modifies the classifier_net's weights + """ + + ###################################################################### + # Setup/ input validations # + ###################################################################### + self.classifier_net.train() # in training mode + assert isinstance(num_epochs, int) + + if attack_parameters is not None: + if not isinstance(attack_parameters, dict): + attack_parameters = {'attack': attack_parameters} + + # assert that the adv attacker uses the NN that's being trained + for param in attack_parameters.values(): + assert (param.adv_attack_obj.classifier_net == + self.classifier_net) + + assert not (self.use_gpu and not cuda.is_available()) + if self.use_gpu: + self.classifier_net.cuda() + if attack_parameters is not None: + for param in attack_parameters.values(): + param.set_gpu(self.use_gpu) + + # Verbosity parameters + assert verbosity in ['low', 'medium', 'high', 'snoop', None] + self.set_verbosity_loglevel(verbosity, + verbosity_or_loglevel='verbosity') + verbosity_level = self.verbosity_level + verbosity_minibatch = self.verbosity_minibatch + verbosity_epoch = self.verbosity_epoch + + # Loglevel parameters and logger initialization + assert loglevel in ['low', 'medium', 'high', 'snoop', None] + if logger is None: + logger = self.logger + if logger.data_count() > 0: + print("WARNING: LOGGER IS NOT EMPTY! BE CAREFUL!") + logger.add_series('training_loss') + for key in (attack_parameters or {}).keys(): + logger.add_series(key) + + self.set_verbosity_loglevel(loglevel, verbosity_or_loglevel='loglevel') + loglevel_level = self.loglevel_level + loglevel_minibatch = self.loglevel_minibatch + loglevel_epoch = self.loglevel_epoch + + # Adversarial image saver: + adv_saver = None + if adversarial_save_dir is not None and attack_parameters is not None: + adv_saver = checkpoints.CustomDataSaver(adversarial_save_dir) + + # setup loss fxn, optimizer + optimizer = optimizer or optim.Adam(self.classifier_net.parameters(), + lr=0.001) + + # setup regularize adv object + if regularize_adv_scale is not None: + regularize_adv_criterion = nn.L1Loss() + + ###################################################################### + # Training loop # + ###################################################################### + + for epoch in range(starting_epoch + 1, num_epochs + 1): + running_loss_print, running_loss_print_mb = 0.0, 0 + running_loss_log, running_loss_log_mb = 0.0, 0 + for i, data in enumerate(data_loader, 0): + inputs, labels = data + if self.use_gpu: + inputs = inputs.cuda() + labels = labels.cuda() + + # Build adversarial examples + attack_out = self._attack_subroutine(attack_parameters, + inputs, labels, + epoch, i, adv_saver, + logger) + inputs, labels, adv_examples, adv_inputs = attack_out + # Now proceed with standard training + self.normalizer.differentiable_call() + self.classifier_net.train() + inputs, labels = Variable(inputs), Variable(labels) + optimizer.zero_grad() + + # forward step + outputs = self.classifier_net.forward(self.normalizer(inputs)) + loss = train_loss.forward(outputs, labels) + + if regularize_adv_scale is not None: + # BE SURE TO 'DETACH' THE ADV_INPUTS!!! + reg_adv_loss = regularize_adv_criterion(adv_examples, + Variable(adv_inputs.data)) + print(float(loss), regularize_adv_scale * float(reg_adv_loss)) + loss = loss + regularize_adv_scale * reg_adv_loss + + # backward step + loss.backward() + optimizer.step() + + # print things + + running_loss_print += float(loss.data) + running_loss_print_mb += 1 + if (verbosity_level >= 1 and + i % verbosity_minibatch == verbosity_minibatch - 1): + print('[%d, %5d] loss: %.6f' % + (epoch, i + 1, running_loss_print / + float(running_loss_print_mb))) + running_loss_print = 0.0 + running_loss_print_mb = 0 + + # log things + running_loss_log += float(loss.data) + running_loss_log_mb += 1 + if (loglevel_level >= 1 and + i % loglevel_minibatch == loglevel_minibatch - 1): + logger.log('training_loss', epoch, i + 1, + running_loss_log / float(running_loss_log_mb)) + running_loss_log = 0.0 + running_loss_log_mb = 0 + + # end_of_epoch + if epoch % verbosity_epoch == 0: + print("COMPLETED EPOCH %04d... checkpointing here" % epoch) + checkpoints.save_state_dict(self.experiment_name, + self.architecture_name, + epoch, self.classifier_net, + k_highest=3) + + if verbosity_level >= 1: + print('Finished Training') + + return logger + + def train_from_checkpoint(self, data_loader, num_epochs, loss_fxn, + optimizer=None, attack_parameters=None, + verbosity='medium', + starting_epoch='max', + adversarial_save_dir=None): + """ Resumes training from a saved checkpoint with the same architecture. + i.e. loads weights from specified checkpoint, figures out which + epoch we checkpointed on and then continues training until + we reach num_epochs epochs + ARGS: + same as in train + starting_epoch: 'max' or int - which epoch we start training from. + 'max' means the highest epoch we can find, + an int means a specified int epoch exactly. + RETURNS: + None + """ + + ###################################################################### + # Checkpoint handling block # + ###################################################################### + # which epoch to load + valid_epochs = checkpoints.list_saved_epochs(self.experiment_name, + self.architecture_name) + assert valid_epochs != [] + if starting_epoch == 'max': + epoch = max(valid_epochs) + else: + assert starting_epoch in valid_epochs + epoch = starting_epoch + + # modify the classifer to use these weights + + self.classifier_net = checkpoints.load_state_dict(self.experiment_name, + self.architecture_name, + epoch, + self.classifier_net) + + ###################################################################### + # Training block # + ###################################################################### + + self.train(data_loader, num_epochs, loss_fxn, + optimizer=optimizer, + attack_parameters=attack_parameters, + verbosity=verbosity, + starting_epoch=epoch, + adversarial_save_dir=adversarial_save_dir) diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/config.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/config.py new file mode 100644 index 0000000..21c1ec3 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/config.py @@ -0,0 +1,40 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/config.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +import os + +config_dir = os.path.abspath(os.path.dirname(__file__)) + + +def path_resolver(path): + if path.startswith('~/'): + return os.path.expanduser(path) + + if path.startswith('./'): + return os.path.join(*[config_dir] + path.split('/')[1:]) + + +DEFAULT_DATASETS_DIR = path_resolver('~/datasets') +MODEL_PATH = path_resolver('./pretrained_models/') +OUTPUT_IMAGE_PATH = path_resolver('./output_images/') + +DEFAULT_BATCH_SIZE = 128 +DEFAULT_WORKERS = 4 +CIFAR10_MEANS = [0.485, 0.456, 0.406] +CIFAR10_STDS = [0.229, 0.224, 0.225] + +WIDE_CIFAR10_MEANS = [0.4914, 0.4822, 0.4465] +WIDE_CIFAR10_STDS = [0.2023, 0.1994, 0.2010] + +IMAGENET_MEANS = [0.485, 0.456, 0.406] +IMAGENET_STDS = [0.229, 0.224, 0.225] diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/loss_functions.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/loss_functions.py new file mode 100644 index 0000000..fe2a80c --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/loss_functions.py @@ -0,0 +1,562 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/loss_functions.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +import torch.nn as nn +import torch +from numbers import Number +from .utils import pytorch_utils as utils +from .utils import image_utils as img_utils +from . import spatial_transformers as st +from torch.autograd import Variable +from functools import partial +from . import adversarial_perturbations as ap + +""" Loss function building blocks """ + + +############################################################################## +# # +# LOSS FUNCTION WRAPPER # +# # +############################################################################## + +class RegularizedLoss(object): + """ Wrapper for multiple PartialLoss objects where we combine with + regularization constants """ + + def __init__(self, losses, scalars, negate=False): + """ + ARGS: + losses : dict - dictionary of partialLoss objects, each is keyed + with a nice identifying name + scalars : dict - dictionary of scalars, each is keyed with the + same identifying name as is in self.losses + negate : bool - if True, we negate the whole thing at the end + """ + + assert sorted(losses.keys()) == sorted(scalars.keys()) + + self.losses = losses + self.scalars = scalars + self.negate = negate + + def forward(self, examples, labels, *args, **kwargs): + + output = None + output_per_example = kwargs.get('output_per_example', False) + for k in self.losses: + loss = self.losses[k] + scalar = self.scalars[k] + + loss_val = loss.forward(examples, labels, *args, **kwargs) + # assert scalar is either a... + assert (isinstance(scalar, float) or # number + scalar.numel() == 1 or # tf wrapping of a number + scalar.shape == loss_val.shape) # same as the loss_val + + addendum = loss_val * scalar + if addendum.numel() > 1: + if not output_per_example: + addendum = torch.sum(addendum) + + if output is None: + output = addendum + else: + output = output + addendum + if self.negate: + return output * -1 + else: + return output + + def setup_attack_batch(self, fix_im): + """ Setup before calling loss on a new minibatch. Ensures the correct + fix_im for reference regularizers and that all grads are zeroed + ARGS: + fix_im: Variable (NxCxHxW) - Ground images for this minibatch + SHOULD BE IN [0.0, 1.0] RANGE + """ + for loss in self.losses.values(): + if isinstance(loss, ReferenceRegularizer): + loss.setup_attack_batch(fix_im) + else: + loss.zero_grad() + + def cleanup_attack_batch(self): + """ Does some cleanup stuff after we finish on a minibatch: + - clears the fixed images for ReferenceRegularizers + - zeros grads + - clears example-based scalars (i.e. scalars that depend on which + example we're using) + """ + for loss in self.losses.values(): + if isinstance(loss, ReferenceRegularizer): + loss.cleanup_attack_batch() + else: + loss.zero_grad() + + for key, scalar in self.scalars.items(): + if not isinstance(scalar, Number): + self.scalars[key] = None + + def zero_grad(self): + for loss in self.losses.values(): + loss.zero_grad() # probably zeros the same net more than once... + + +class PartialLoss(object): + """ Partially applied loss object. Has forward and zero_grad methods """ + + def __init__(self): + self.nets = [] + + def zero_grad(self): + for net in self.nets: + net.zero_grad() + + +############################################################################## +# # +# LOSS FUNCTIONS # +# # +############################################################################## + +############################################################################ +# NAIVE CORRECT INDICATOR LOSS # +############################################################################ + +class IncorrectIndicator(PartialLoss): + def __init__(self, classifier, normalizer=None): + super(IncorrectIndicator, self).__init__() + self.classifier = classifier + self.normalizer = normalizer + + def forward(self, examples, labels, *args, **kwargs): + """ Returns either (the number | a boolean vector) of examples that + don't match the labels when run through the + classifier(normalizer(.)) composition. + ARGS: + examples: Variable (NxCxHxW) - should be same shape as + ctx.fix_im, is the examples we define loss for. + SHOULD BE IN [0.0, 1.0] RANGE + labels: Variable (longTensor of length N) - true classification + output for fix_im/examples + KWARGS: + return_type: String - either 'int' or 'vector'. If 'int', we return + the number of correctly classified examples, + if 'vector' we return a boolean length-N longtensor + with the indices of + RETURNS: + scalar loss variable or boolean vector, depending on kwargs + """ + return_type = kwargs.get('return_type', 'int') + assert return_type in ['int', 'vector'] + + class_out = self.classifier.forward(self.normalizer.forward(examples)) + + _, outputs = torch.max(class_out, 1) + incorrect_indicator = outputs != labels + + if return_type == 'int': + return torch.sum(incorrect_indicator) + else: + return incorrect_indicator + + +############################################################################## +# Standard XEntropy Loss # +############################################################################## + +class PartialXentropy(PartialLoss): + def __init__(self, classifier, normalizer=None): + super(PartialXentropy, self).__init__() + self.classifier = classifier + self.normalizer = normalizer + self.nets.append(self.classifier) + + def forward(self, examples, labels, *args, **kwargs): + """ Returns XEntropy loss + ARGS: + examples: Variable (NxCxHxW) - should be same shape as + ctx.fix_im, is the examples we define loss for. + SHOULD BE IN [0.0, 1.0] RANGE + labels: Variable (longTensor of length N) - true classification + output for fix_im/examples + RETURNS: + scalar loss variable + """ + + if self.normalizer is not None: + normed_examples = self.normalizer.forward(examples) + else: + normed_examples = examples + + xentropy_init_kwargs = {} + if kwargs.get('output_per_example') == True: + xentropy_init_kwargs['reduction'] = 'none' + criterion = nn.CrossEntropyLoss(**xentropy_init_kwargs) + return criterion(self.classifier.forward(normed_examples), labels) + + +############################################################################## +# Carlini Wagner loss functions # +############################################################################## + +class CWLossF6(PartialLoss): + def __init__(self, classifier, normalizer=None, kappa=0.0): + super(CWLossF6, self).__init__() + self.classifier = classifier + self.normalizer = normalizer + self.nets.append(self.classifier) + self.kappa = kappa + + def forward(self, examples, labels, *args, **kwargs): + classifier_in = self.normalizer.forward(examples) + classifier_out = self.classifier.forward(classifier_in) + + # get target logits + target_logits = torch.gather(classifier_out, 1, labels.view(-1, 1)) + + # get largest non-target logits + max_2_logits, argmax_2_logits = torch.topk(classifier_out, 2, dim=1) + top_max, second_max = max_2_logits.chunk(2, dim=1) + top_argmax, _ = argmax_2_logits.chunk(2, dim=1) + targets_eq_max = top_argmax.squeeze().eq(labels).float().view(-1, 1) + targets_ne_max = top_argmax.squeeze().ne(labels).float().view(-1, 1) + max_other = targets_eq_max * second_max + targets_ne_max * top_max + + if kwargs.get('targeted', False): + # in targeted case, want to make target most likely + f6 = torch.clamp(max_other - target_logits, min=-1 * self.kappa) + else: + # in NONtargeted case, want to make NONtarget most likely + f6 = torch.clamp(target_logits - max_other, min=-1 * self.kappa) + + return f6.squeeze() + + +############################################################################## +# # +# REFERENCE REGULARIZERS # +# # +############################################################################## +""" Regularization terms that refer back to a set of 'fixed images', or the + original images. + example: L2 regularization which computes L2dist between a perturbed image + and the FIXED ORIGINAL IMAGE + + NOTE: it's important that these return Variables that are scalars + (output.numel() == 1), otherwise there's a memory leak w/ CUDA. + See my discussion on this here: + https://discuss.pytorch.org/t/cuda-memory-not-being-freed/15965 +""" + + +class ReferenceRegularizer(PartialLoss): + def __init__(self, fix_im): + super(ReferenceRegularizer, self).__init__() + self.fix_im = fix_im + + def setup_attack_batch(self, fix_im): + """ Setup function to ensure fixed images are set + has been made; also zeros grads + ARGS: + fix_im: Variable (NxCxHxW) - Ground images for this minibatch + SHOULD BE IN [0.0, 1.0] RANGE + """ + self.fix_im = fix_im + self.zero_grad() + + def cleanup_attack_batch(self): + """ Cleanup function to clear the fixed images after an attack batch + has been made; also zeros grads + """ + old_fix_im = self.fix_im + self.fix_im = None + del old_fix_im + self.zero_grad() + + +############################################################################# +# SOFT L_INF REGULARIZATION # +############################################################################# + +class SoftLInfRegularization(ReferenceRegularizer): + ''' + see page 10 of this paper (https://arxiv.org/pdf/1608.04644.pdf) + for discussion on why we want SOFT l inf + ''' + + def __init__(self, fix_im, **kwargs): + super(SoftLInfRegularization, self).__init__(fix_im) + + def forward(self, examples, *args, **kwargs): + # ARGS should have one element, which serves as the tau value + + tau = 8.0 / 255.0 # starts at 1 each time? + scale_factor = 0.9 + l_inf_dist = float(torch.max(torch.abs(examples - self.fix_im))) + ''' + while scale_factor * tau > l_inf_dist: + tau *= scale_factor + + assert tau > l_inf_dist + ''' + delta_minus_taus = torch.clamp(torch.abs(examples - self.fix_im) - tau, + min=0.0) + batchwise = utils.batchwise_norm(delta_minus_taus, 'inf', dim=0) + return batchwise.squeeze() + + +############################################################################# +# L2 REGULARIZATION # +############################################################################# + +class L2Regularization(ReferenceRegularizer): + + def __init__(self, fix_im, **kwargs): + super(L2Regularization, self).__init__(fix_im) + + def forward(self, examples, *args, **kwargs): + l2_dist = img_utils.nchw_l2(examples, self.fix_im, + squared=True).view(-1, 1) + return l2_dist.squeeze() + + +############################################################################# +# LPIPS PERCEPTUAL REGULARIZATION # +############################################################################# + +class LpipsRegularization(ReferenceRegularizer): + + def __init__(self, fix_im, **kwargs): + super(LpipsRegularization, self).__init__(fix_im) + + manual_gpu = kwargs.get('manual_gpu', None) + if manual_gpu is not None: + self.use_gpu = manual_gpu + else: + self.use_gpu = utils.use_gpu() + + self.dist_model = dm.DistModel(net='alex', manual_gpu=self.use_gpu) + + def forward(self, examples, *args, **kwargs): + xform = lambda im: im * 2.0 - 1.0 + perceptual_loss = self.dist_model.forward_var(examples, + self.fix_im) + + return perceptual_loss.squeeze() + + +############################################################################# +# SSIM PERCEPTUAL REGULARIZATION # +############################################################################# + +class SSIMRegularization(ReferenceRegularizer): + + def __init__(self, fix_im, **kwargs): + super(SSIMRegularization, self).__init__(fix_im) + + if 'window_size' in kwargs: + self.ssim_instance = ssim.SSIM(window_size=kwargs['window_size']) + else: + self.ssim_instance = ssim.SSIM() + + manual_gpu = kwargs.get('manual_gpu', None) + if manual_gpu is not None: + self.use_gpu = manual_gpu + else: + self.use_gpu = utils.use_gpu() + + def forward(self, examples, *args, **kwargs): + output = [] + for ex, fix_ex in zip(examples, self.fix_im): + output.append(1.0 - self.ssim_instance(ex.unsqueeze(0), + fix_ex.unsqueeze(0))) + return torch.stack(output) + + +############################################################################## +# # +# SPATIAL LOSS FUNCTIONS # +# # +############################################################################## + +class FullSpatialLpLoss(PartialLoss): + """ Spatial loss using lp norms on the spatial transformation parameters + This is defined as the Lp difference between the identity map and the + provided spatial transformation parameters + """ + + def __init__(self, **kwargs): + super(FullSpatialLpLoss, self).__init__() + + lp = kwargs.get('lp', 2) + assert lp in [1, 2, 'inf'] + self.lp = lp + + def forward(self, examples, *args, **kwargs): + """ Computes lp loss between identity map and spatial transformation. + There better be a kwarg with key 'spatial' which is as FullSpatial + object describing how the examples were generated from the originals + """ + st_obj = kwargs['spatial'] + assert isinstance(st_obj, st.FullSpatial) + + # First create the identity map and make same type as examples + identity_map = Variable(st_obj.identity_params(examples.shape)) + if examples.is_cuda: + identity_map.cuda() + + # Then take diffs and take lp norms + diffs = st_obj.grid_params - identity_map + lp_norm = utils.batchwise_norm(diffs, self.lp, dim=0) + return lp_norm # return Nx1 variable, will sum in parent class + + +class PerturbationNormLoss(PartialLoss): + + def __init__(self, **kwargs): + super(PerturbationNormLoss, self).__init__() + + lp = kwargs.get('lp', 2) + assert lp in [1, 2, 'inf'] + self.lp = lp + + def forward(self, examples, *args, **kwargs): + """ Computes perturbation norm and multiplies by scale + There better be a kwarg with key 'perturbation' which is a perturbation + object with a 'perturbation_norm' method that takes 'lp_style' as a + kwarg + """ + + perturbation = kwargs['perturbation'] + assert isinstance(perturbation, ap.AdversarialPerturbation) + + return perturbation.perturbation_norm(lp_style=self.lp) + + +############################################################################## +# # +# Combined Transformer Loss # +# # +############################################################################## + +class CombinedTransformerLoss(ReferenceRegularizer): + """ General class for distance functions and loss functions of the form + min_T ||X - T(Y)|| + c * || T || + where X is the original image, and Y is the 'adversarial' input image. + """ + + def __init__(self, fix_im, transform_class=None, + regularization_constant=1.0, + transformation_loss=partial(utils.summed_lp_norm, lp=2), + transform_norm_kwargs=None): + """ Takes in a reference fix im and a class of transformations we need + to search over to compute forward. + """ + super(CombinedTransformerLoss, self).__init__(fix_im) + self.transform_class = transform_class + self.regularization_constant = regularization_constant + self.transformation_loss = transformation_loss + self.transform_norm_kwargs = transform_norm_kwargs or {} + self.transformer = None + + def cleanup_attack_batch(self): + super(CombinedTransformerLoss, self).cleanup_attack_batch() + self.transformer = None + + def _inner_loss(self, examples): + """ Computes the combined loss for a particular transformation """ + + trans_examples = self.transformer.forward(examples) + trans_loss = self.transformation_loss(self.fix_im - trans_examples) + + trans_norm = self.transformer.norm(**self.transform_norm_kwargs) + return trans_loss + trans_norm * self.regularization_constant + + def forward(self, examples, *args, **kwargs): + """ Computes the distance between examples and args + ARGS: + examples : NxCxHxW Variable - 'adversarially' perturbed image from + the self.fix_im + KWARGS: + optimization stuff here + """ + + ###################################################################### + # Setup transformer + optimizer # + ###################################################################### + self.transformer = self.transform_class(shape=examples.shape) + + optim_kwargs = kwargs.get('xform_loss_optim_kwargs', {}) + optim_type = kwargs.get('xform_loss_optim_type', torch.optim.Adam) + num_iter = kwargs.get('xform_loss_num_iter', 20) + + optimizer = optim_type(self.transformer.parameters(), **optim_kwargs) + + ##################################################################### + # Iterate and optimize the transformer # + ##################################################################### + for iter_no in range(num_iter): + optimizer.zero_grad() + loss = self._inner_loss(examples) + loss.backward() + optimizer.step() + + return self._inner_loss(examples) + + +class RelaxedTransformerLoss(ReferenceRegularizer): + """ Relaxed version of transformer loss: assumes that the adversarial + examples are of the form Y=S(X) + delta for some S in the + transformation class and some small delta perturbation outside the + perturbation. + + In this case, we just compute ||delta|| + c||S|| + + This saves us from having to do the inner minmization step + """ + + def __init__(self, fix_im, + regularization_constant=1.0, + transformation_loss=partial(utils.summed_lp_norm, lp=2), + transform_norm_kwargs=None): + """ Takes in a reference fix im and a class of transformations we need + to search over to compute forward. + """ + super(RelaxedTransformerLoss, self).__init__(fix_im) + self.regularization_constant = regularization_constant + self.transformation_loss = transformation_loss + self.transform_norm_kwargs = transform_norm_kwargs or {} + + def forward(self, examples, *args, **kwargs): + """ Computes the distance between examples and args + ARGS: + examples : NxCxHxW Variable - 'adversarially' perturbed image from + the self.fix_im + KWARGS: + optimization stuff here + """ + + # Collect transformer norm + transformer = kwargs['transformer'] + assert isinstance(transformer, st.ParameterizedTransformation) + + transformer_norm = self.regularization_constant * \ + transformer.norm(**self.transform_norm_kwargs) + + # Collect transformation loss + delta = self.transformer.forward(self.fix_im) - examples + transformation_loss = self.transformation_loss(delta) + + return transformation_loss + transformer_norm diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/spatial_transformers.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/spatial_transformers.py new file mode 100644 index 0000000..a05b861 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/spatial_transformers.py @@ -0,0 +1,528 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/spatial_transformers.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" File that contains various parameterizations for spatial transformation + styles. At its simplest, spatial transforms can be affine grids, + parameterized by 6 values. At their most complex, for a CxHxW type image + grids can be parameterized by CxHxWx2 parameters. + + This file will define subclasses of nn.Module that will have parameters + corresponding to the transformation parameters and will take in an image + and output a transformed image. + + Further we'll also want a method to initialize each set to be the identity + initially +""" + +import torch +import torch.nn as nn +import torch.nn.functional as F +from .utils import pytorch_utils as utils +from torch.autograd import Variable + + +############################################################################## +# # +# SKELETON CLASS # +# # +############################################################################## + +class ParameterizedTransformation(nn.Module): + """ General class of transformations. + All subclasses need the following methods: + - norm: no args -> scalar variable + - identity_params: shape -> TENSOR : takes an input shape and outputs + the subclass-specific parameter for the identity + transformation + - forward : Variable -> Variable - is the transformation + """ + + def __init__(self, **kwargs): + super(ParameterizedTransformation, self).__init__() + + if kwargs.get('manual_gpu', None) is not None: + self.use_gpu = kwargs['manual_gpu'] + else: + self.use_gpu = utils.use_gpu() + + def norm(self, lp='inf'): + raise NotImplementedError("Need to call subclass's norm!") + + @classmethod + def identity_params(self, shape): + raise NotImplementedError("Need to call subclass's identity_params!") + + def merge_xform(self, other, self_mask): + """ Takes in an other instance of this same class with the same + shape of parameters (NxSHAPE) and a self_mask bytetensor of length + N and outputs the merge between self's parameters for the indices + of 1s in the self_mask and other's parameters for the indices of 0's + ARGS: + other: instance of same class as self with params of shape NxSHAPE - + the thing we merge with this one + self_mask : ByteTensor (length N) - which indices of parameters we + keep from self, and which we keep from other + RETURNS: + New instance of this class that's merged between the self and other + (same shaped params) + """ + + # JUST DO ASSERTS IN THE SKELETON CLASS + assert self.__class__ == other.__class__ + + self_params = self.xform_params.data + other_params = other.xform_params.data + assert self_params.shape == other_params.shape + assert self_params.shape[0] == self_mask.shape[0] + assert other_params.shape[0] == self_mask.shape[0] + + new_xform = self.__class__(shape=self.img_shape) + + new_params = utils.fold_mask(self.xform_params.data, + other.xform_params.data, self_mask) + new_xform.xform_params = nn.Parameter(new_params) + new_xform.use_gpu = self.use_gpu + return new_xform + + + def forward(self, examples): + raise NotImplementedError("Need to call subclass's forward!") + + + + + +############################################################################### +# # +# FULLY PARAMETERIZED SPATIAL TRANSFORMATION NETWORK # +# # +############################################################################### + +class FullSpatial(ParameterizedTransformation): + def __init__(self, *args, **kwargs): + """ FullSpatial just has parameters that are the grid themselves. + Forward then will just call grid sample using these params directly + """ + + super(FullSpatial, self).__init__(**kwargs) + img_shape = kwargs['shape'] + self.img_shape = img_shape + self.xform_params = nn.Parameter(self.identity_params(img_shape)) + + + + def identity_params(self, shape): + """ Returns some grid parameters such that the minibatch of images isn't + changed when forward is called on it + ARGS: + shape: torch.Size - shape of the minibatch of images we'll be + transforming. First index should be num examples + RETURNS: + torch TENSOR (not variable!!!) + if shape arg has shape NxCxHxW, this has shape NxCxHxWx2 + """ + + # Work smarter not harder -- use idenity affine transforms here + num_examples = shape[0] + identity_affine_transform = torch.zeros(num_examples, 2, 3) + if self.use_gpu: + identity_affine_transform = identity_affine_transform.cuda() + + identity_affine_transform[:,0,0] = 1 + identity_affine_transform[:,1,1] = 1 + + return F.affine_grid(identity_affine_transform, shape).data + + + def stAdv_norm(self): + """ Computes the norm used in + "Spatially Transformed Adversarial Examples" + """ + + # ONLY WORKS FOR SQUARE MATRICES + dtype = self.xform_params.data.type() + num_examples, height, width = tuple(self.xform_params.shape[0:3]) + assert height == width + ###################################################################### + # Build permutation matrices # + ###################################################################### + + def id_builder(): + x = torch.zeros(height, width).type(dtype) + for i in range(height): + x[i,i] = 1 + return x + + col_permuts = [] + row_permuts = [] + # torch.matmul(foo, col_permut) + for col in ['left', 'right']: + col_val = {'left': -1, 'right': 1}[col] + idx = ((torch.arange(width) - col_val) % width) + idx = idx.type(dtype).type(torch.LongTensor) + if self.xform_params.is_cuda: + idx = idx.cuda() + + col_permut = torch.zeros(height, width).index_copy_(1, idx.cpu(), + id_builder().cpu()) + col_permut = col_permut.type(dtype) + + if col == 'left': + col_permut[-1][0] = 0 + col_permut[0][0] = 1 + else: + col_permut[0][-1] = 0 + col_permut[-1][-1] = 1 + col_permut = Variable(col_permut) + col_permuts.append(col_permut) + row_permuts.append(col_permut.transpose(0, 1)) + + ###################################################################### + # Build delta_u, delta_v grids # + ###################################################################### + id_params = Variable(self.identity_params(self.img_shape)) + delta_grids = self.xform_params - id_params + delta_grids = delta_grids.permute(0, 3, 1, 2) + + ###################################################################### + # Compute the norm # + ###################################################################### + output = Variable(torch.zeros(num_examples).type(dtype)) + + for row_or_col, permutes in zip(['row', 'col'], + [row_permuts, col_permuts]): + for permute in permutes: + if row_or_col == 'row': + temp = delta_grids - torch.matmul(permute, delta_grids) + else: + temp = delta_grids - torch.matmul(delta_grids, permute) + temp = temp.pow(2) + temp = temp.sum(1) + temp = (temp + 1e-10).pow(0.5) + output.add_(temp.sum((1, 2))) + return output + + + def norm(self, lp='inf'): + """ Returns the 'norm' of this transformation in terms of an LP norm on + the parameters, summed across each transformation per minibatch + ARGS: + lp : int or 'inf' - which lp type norm we use + """ + + if isinstance(lp, int) or lp == 'inf': + identity_params = Variable(self.identity_params(self.img_shape)) + return utils.batchwise_norm(self.xform_params - identity_params, lp, + dim=0) + else: + assert lp == 'stAdv' + return self._stAdv_norm() + + + def clip_params(self): + """ Clips the parameters to be between -1 and 1 as required for + grid_sample + """ + clamp_params = torch.clamp(self.xform_params, -1, 1).data + change_in_params = clamp_params - self.xform_params.data + self.xform_params.data.add_(change_in_params) + + + def merge_xform(self, other, self_mask): + """ Takes in an other instance of this same class with the same + shape of parameters (NxSHAPE) and a self_mask bytetensor of length + N and outputs the merge between self's parameters for the indices + of 1s in the self_mask and other's parameters for the indices of 0's + """ + super(FullSpatial, self).merge_xform(other, self_mask) + + new_xform = FullSpatial(shape=self.img_shape, + manual_gpu=self.use_gpu) + + new_params = utils.fold_mask(self.xform_params.data, + other.xform_params.data, self_mask) + new_xform.xform_params = nn.Parameter(new_params) + + return new_xform + + + + def project_params(self, lp, lp_bound): + """ Projects the params to be within lp_bound (according to an lp) + of the identity map. First thing we do is clip the params to be + valid, too + ARGS: + lp : int or 'inf' - which LP norm we use. Must be an int or the + string 'inf' + lp_bound : float - how far we're allowed to go in LP land + RETURNS: + None, but modifies self.xform_params + """ + + assert isinstance(lp, int) or lp == 'inf' + + # clip first + self.clip_params() + + # then project back + + if lp == 'inf': + identity_params = self.identity_params(self.img_shape) + clamp_params = utils.clamp_ref(self.xform_params.data, + identity_params, lp_bound) + change_in_params = clamp_params - self.xform_params.data + self.xform_params.data.add_(change_in_params) + else: + raise NotImplementedError("Only L-infinity bounds working for now ") + + + def forward(self, x): + # usual forward technique + return F.grid_sample(x, self.xform_params) + + + + +############################################################################### +# # +# AFFINE TRANSFORMATION NETWORK # +# # +############################################################################### + +class AffineTransform(ParameterizedTransformation): + """ Affine transformation -- just has 6 parameters per example: 4 for 2d + rotation, and 1 for translation in each direction + """ + + def __init__(self, *args, **kwargs): + super(AffineTransform, self).__init__(**kwargs) + img_shape = kwargs['shape'] + self.img_shape = img_shape + self.xform_params = nn.Parameter(self.identity_params(img_shape)) + + + def norm(self, lp='inf'): + identity_params = Variable(self.identity_params(self.img_shape)) + return utils.batchwise_norm(self.xform_params - identity_params, lp, + dim=0) + + def identity_params(self, shape): + """ Returns parameters for identity affine transformation + ARGS: + shape: torch.Size - shape of the minibatch of images we'll be + transforming. First index should be num examples + RETURNS: + torch TENSOR (not variable!!!) + if shape arg has shape NxCxHxW, this has shape Nx2x3 + """ + + # Work smarter not harder -- use idenity affine transforms here + num_examples = shape[0] + identity_affine_transform = torch.zeros(num_examples, 2, 3) + if self.use_gpu: + identity_affine_transform = identity_affine_transform.cuda() + + identity_affine_transform[:,0,0] = 1 + identity_affine_transform[:,1,1] = 1 + + return identity_affine_transform + + + def project_params(self, lp, lp_bound): + """ Projects the params to be within lp_bound (according to an lp) + of the identity map. First thing we do is clip the params to be + valid, too + ARGS: + lp : int or 'inf' - which LP norm we use. Must be an int or the + string 'inf' + lp_bound : float - how far we're allowed to go in LP land + RETURNS: + None, but modifies self.xform_params + """ + + assert isinstance(lp, int) or lp == 'inf' + + diff = self.xform_params.data - self.identity_params(self.img_shape) + new_diff = utils.batchwise_lp_project(diff, lp, lp_bound) + self.xform_params.data.add_(new_diff - diff) + + + def forward(self, x): + # usual forward technique with affine grid + grid = F.affine_grid(self.xform_params, x.shape) + return F.grid_sample(x, grid) + + + +class RotationTransform(AffineTransform): + """ Rotations only -- only has one parameter, the angle by which we rotate + """ + + def __init__(self, *args, **kwargs): + super(RotationTransform, self).__init__(**kwargs) + ''' + img_shape = kwargs['shape'] + self.img_shape = img_shape + self.xform_params = nn.Parameter(self.identity_params(img_shape)) + ''' + + + def identity_params(self, shape): + num_examples = shape[0] + params = torch.zeros(num_examples) + if self.use_gpu: + params = params.cuda() + return params + + + def make_grid(self, x): + assert isinstance(x, Variable) + cos_xform = self.xform_params.cos() + sin_xform = self.xform_params.sin() + zeros = torch.zeros_like(self.xform_params) + + affine_xform = torch.stack([cos_xform, -sin_xform, zeros, + sin_xform, cos_xform, zeros]) + affine_xform = affine_xform.transpose(0, 1).contiguous().view(-1, 2, 3) + + return F.affine_grid(affine_xform, x.shape) + + def forward(self, x): + return F.grid_sample(x, self.make_grid(x)) + + + +class TranslationTransform(AffineTransform): + """ Rotations only -- only has one parameter, the angle by which we rotate + """ + + def __init__(self, *args, **kwargs): + super(TranslationTransform, self).__init__(**kwargs) + + + + def identity_params(self, shape): + num_examples = shape[0] + params = torch.zeros(num_examples, 2) # x and y translation only + if self.use_gpu: + params = params.cuda() + return params + + def make_grid(self, x): + assert isinstance(x, Variable) + ones = Variable(torch.ones(self.xform_params.shape[0])) + zeros = Variable(torch.zeros(self.xform_params.shape[0])) + if self.xform_params.cuda: + ones = ones.cuda() + zeros = zeros.cuda() + + affine_xform = torch.stack([ones, zeros, self.xform_params[:,0], + zeros, ones, self.xform_params[:,1]]) + + affine_xform = affine_xform.transpose(0, 1).contiguous().view(-1, 2, 3) + + return F.affine_grid(affine_xform, x.shape) + + def forward(self, x): + return F.grid_sample(x, self.make_grid(x)) + + + +############################################################################## +# # +# BARREL + PINCUSHION TRANSFORMATIONS # +# # +############################################################################## + +class PointScaleTransform(ParameterizedTransformation): + """ Point Scale transformations are pincushion/barrel distortions. + We pick a point to anchor the image and optimize a distortion size to + either dilate or contract + """ + + def __init__(self, *args, **kwargs): + super(PointScaleTransform, self).__init__(**kwargs) + img_shape = kwargs['shape'] + self.img_shape = img_shape + self.xform_params = nn.Parameter(self.identity_params(img_shape)) + + + + def norm(self, lp='inf'): + return utils.batchwise_norm(self.xform_params, lp, dim=0) + + + def project_params(self, lp, lp_bound): + """ Projects the params to be within lp_bound (according to an lp) + of the identity map. First thing we do is clip the params to be + valid, too + ARGS: + lp : int or 'inf' - which LP norm we use. Must be an int or the + string 'inf' + lp_bound : float - how far we're allowed to go in LP land + RETURNS: + None, but modifies self.xform_params + """ + + assert isinstance(lp, int) or lp == 'inf' + + diff = self.xform_params.data + new_diff = utils.batchwise_lp_project(diff, lp, lp_bound) + self.xform_params.data.add_(new_diff - diff) + + def identity_params(self, shape): + num_examples = shape[0] + identity_param = torch.zeros(num_examples) + if self.use_gpu: + identity_param = identity_param.cuda() + + return identity_param + + + def make_grid(self): + + ###################################################################### + # Compute identity flow grid first # + ###################################################################### + + num_examples = self.img_shape[0] + identity_affine_transform = torch.zeros(num_examples, 2, 3) + if self.use_gpu: + identity_affine_transform = identity_affine_transform.cuda() + + identity_affine_transform[:,0,0] = 1 + identity_affine_transform[:,1,1] = 1 + + basic_grid = F.affine_grid(identity_affine_transform, self.img_shape) + + ###################################################################### + # Compute scaling based on parameters # + ###################################################################### + + radii_squared = basic_grid.pow(2).sum(-1) + + new_radii = (radii_squared + 1e-20).pow(0.5) *\ + (1 + self.xform_params.view(-1, 1, 1) * radii_squared) + thetas = torch.atan2(basic_grid[:,:,:,1], (basic_grid[:,:,:, 0])) + cosines = torch.cos(thetas) * new_radii + sines = torch.sin(thetas) * new_radii + + return torch.stack([cosines, sines], -1) + + + + def forward(self, x): + return F.grid_sample(x, self.make_grid()) + + + diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/__init__.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/__init__.py new file mode 100644 index 0000000..352b770 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/__init__.py @@ -0,0 +1,12 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/utils/__init__.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/checkpoints.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/checkpoints.py new file mode 100644 index 0000000..2237668 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/checkpoints.py @@ -0,0 +1,311 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/utils/checkpoints.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" Code for saving/loading pytorch models and batches of adversarial images + +CHECKPOINT NAMING CONVENTIONS: + ..<6 digits of epoch number>path.tar +e.g. + fgsm_def.resnet32.20180301.120000.path.tar + +All checkpoints are stored in CHECKPOINT_DIR + +Checkpoints are state dicts only!!! + +""" + +import torch +import os +import re +import glob +from .. import config +import numpy as np +import random + +CHECKPOINT_DIR = config.MODEL_PATH +OUTPUT_IMAGE_DIR = config.OUTPUT_IMAGE_PATH + + +############################################################################## +# # +# CHECKPOINTING MODELS # +# # +############################################################################## + + +def clear_experiment(experiment_name, architecture): + """ Deletes all saved state dicts for an experiment/architecture pair """ + + for filename in params_to_filename(experiment_name, architecture): + full_path = os.path.join(*[CHECKPOINT_DIR, filename]) + os.remove(full_path) if os.path.exists(full_path) else None + + +def list_saved_epochs(experiment_name, architecture): + """ Returns a list of int epochs we've checkpointed for this + experiment name and architecture + """ + + extract_epoch = lambda f: int(f.split('.')[-3]) + filename_list = params_to_filename(experiment_name, architecture) + return [extract_epoch(f) for f in filename_list] + + +def params_to_filename(experiment_name, architecture, epoch_val=None): + """ Outputs string name of file. + ARGS: + experiment_name : string - name of experiment we're saving + architecture : string - abbreviation for model architecture + epoch_val : int/(intLo, intHi)/None - + - if int we return this int exactly + - if (intLo, intHi) we return all existing filenames with + highest epoch in range (intLo, intHi), in sorted order + - if None, we return all existing filenames with params + in ascending epoch-sorted order + + RETURNS: + filenames: string or (possibly empty) string[] of just the base name + of saved models + """ + + if isinstance(epoch_val, int): + return '.'.join([experiment_name, architecture, '%06d' % epoch_val, + 'path', 'tar']) + + glob_prefix = os.path.join(*[CHECKPOINT_DIR, + '%s.%s.*' % (experiment_name, architecture)]) + re_prefix = '%s\.%s\.' % (experiment_name, architecture) + re_suffix = r'\.path\.tar' + + valid_name = lambda f: bool(re.match(re_prefix + r'\d{6}' + re_suffix, f)) + select_epoch = lambda f: int(re.sub(re_prefix, '', + re.sub(re_suffix, '', f))) + valid_epoch = lambda e: (e >= (epoch_val or (0, 0))[0] and + e <= (epoch_val or (0, float('inf')))[1]) + + filename_epoch_pairs = [] + for full_path in glob.glob(glob_prefix): + filename = os.path.basename(full_path) + if not valid_name(filename): + continue + + epoch = select_epoch(filename) + if valid_epoch(epoch): + filename_epoch_pairs.append((filename, epoch)) + + return [_[0] for _ in sorted(filename_epoch_pairs, key=lambda el: el[1])] + + +def save_state_dict(experiment_name, architecture, epoch_val, model, + k_highest=10): + """ Saves the state dict of a model with the given parameters. + ARGS: + experiment_name : string - name of experiment we're saving + architecture : string - abbreviation for model architecture + epoch_val : int - which epoch we're saving + model : model - object we're saving the state dict of + k_higest : int - if not None, we make sure to not include more than + k state_dicts for (experiment_name, architecture) pair, + keeping the k-most recent if we overflow + RETURNS: + The model we saved + """ + + # First resolve THIS filename + this_filename = params_to_filename(experiment_name, architecture, epoch_val) + + # Next clear up memory if too many state dicts + current_filenames = params_to_filename(experiment_name, architecture) + delete_els = [] + if k_highest is not None: + num_to_delete = len(current_filenames) - k_highest + 1 + if num_to_delete > 0: + delete_els = sorted(current_filenames)[:num_to_delete] + + for delete_el in delete_els: + full_path = os.path.join(*[CHECKPOINT_DIR, delete_el]) + os.remove(full_path) if os.path.exists(full_path) else None + + # Finally save the state dict + torch.save(model.state_dict(), os.path.join(*[CHECKPOINT_DIR, + this_filename])) + + return model + + +def load_state_dict_from_filename(filename, model): + """ Skips the whole parameter argument thing and just loads the whole + state dict from a filename. + ARGS: + filename : string - filename without directories + model : nn.Module - has 'load_state_dict' method + RETURNS: + the model loaded with the weights contained in the file + """ + assert len(glob.glob(os.path.join(*[CHECKPOINT_DIR, filename]))) == 1 + + # LOAD FILENAME + + # If state_dict in keys, use that as the loader + right_dict = lambda d: d.get('state_dict', d) + + model.load_state_dict(right_dict(torch.load( + os.path.join(*[CHECKPOINT_DIR, filename])))) + return model + + +def load_state_dict(experiment_name, architecture, epoch, model): + """ Loads a checkpoint that was previously saved + experiment_name : string - name of experiment we're saving + architecture : string - abbreviation for model architecture + epoch_val : int - which epoch we're loading + """ + + filename = params_to_filename(experiment_name, architecture, epoch) + return load_state_dict_from_filename(filename, model) + + +############################################################################### +# # +# CHECKPOINTING DATA # +# # +############################################################################### +""" + This is a hacky fix to save batches of adversarial images along with their + labels. +""" + + +class CustomDataSaver(object): + # TODO: make this more pytorch compliant + def __init__(self, image_subdirectory): + self.image_subdirectory = image_subdirectory + # make this folder if it doesn't exist yet + + def save_minibatch(self, examples, labels): + """ Assigns a random name to this minibatch and saves the examples and + labels in two separate files: + .examples.npy and .labels.npy + ARGS: + examples: Variable or Tensor (NxCxHxW) - examples to be saved + labels : Variable or Tensor (N) - labels matching the examples + """ + # First make both examples and labels into numpy arrays + examples = examples.cpu().numpy() + labels = labels.cpu().numpy() + + # Make a name for the files + random_string = str(random.random())[2:] # DO THIS BETTER WHEN I HAVE INTERNET + + # Save both files + example_file = '%s.examples.npy' % random_string + example_path = os.path.join(OUTPUT_IMAGE_DIR, self.image_subdirectory, + example_file) + np.save(example_path, examples) + + label_file = '%s.labels.npy' % random_string + label_path = os.path.join(OUTPUT_IMAGE_DIR, self.image_subdirectory, + label_file) + np.save(label_path, labels) + + +class CustomDataLoader(object): + # TODO: make this more pytorch compliant + def __init__(self, image_subdirectory, batch_size=128, to_tensor=True, + use_gpu=False): + super(CustomDataLoader, self).__init__() + self.image_subdirectory = image_subdirectory + self.batch_size = batch_size + + assert to_tensor >= use_gpu + self.to_tensor = to_tensor + self.use_gpu = use_gpu + + def _prepare_data(self, examples, labels): + """ Takes in numpy examples and labels and tensor-ifies and cuda's them + if necessary + """ + + if self.to_tensor: + examples = torch.Tensor(examples) + labels = torch.Tensor(labels) + + if self.use_gpu: + examples = examples.cuda() + labels = labels.cuda() + + return (examples, labels) + + def _base_loader(self, prefix, which): + assert which in ['examples', 'labels'] + filename = '%s.%s.npy' % (prefix, which) + full_path = os.path.join(OUTPUT_IMAGE_DIR, self.image_subdirectory, + filename) + return np.load(full_path) + + def _example_loader(self, prefix): + """ Loads the numpy array of examples given the random 'prefix' """ + return self._base_loader(prefix, 'examples') + + def _label_loader(self, prefix): + """ Loads the numpy array of labels given the random 'prefix' """ + return self._base_loader(prefix, 'labels') + + def __iter__(self): + + # First collect all the filenames: + glob_prefix = os.path.join(OUTPUT_IMAGE_DIR, self.image_subdirectory, + '*') + files = glob.glob(glob_prefix) + valid_random_names = set(os.path.basename(_).split('.')[0] + for _ in files) + + # Now loop through filenames and yield out minibatches of correct size + running_examples, running_labels = [], [] + running_size = 0 + for random_name in valid_random_names: + # Load data from files and append to 'running' lists + loaded_examples = self._example_loader(random_name) + loaded_labels = self._label_loader(random_name) + running_examples.append(loaded_examples) + running_labels.append(loaded_labels) + running_size += loaded_examples.shape[0] + + if running_size < self.batch_size: + # Load enough data to populate one minibatch, which might + # take multiple files + continue + + # Concatenate all images together + merged_examples = np.concatenate(running_examples, axis=0) + merged_labels = np.concatenate(running_labels, axis=0) + + # Make minibatches out of concatenated things, + for batch_no in range(running_size // self.batch_size): + index_lo = batch_no * self.batch_size + index_hi = index_lo + self.batch_size + example_batch = merged_examples[index_lo:index_hi] + label_batch = merged_labels[index_lo:index_hi] + yield self._prepare_data(example_batch, label_batch) + + # Handle any remainder for remaining files + remainder_idx = (running_size // self.batch_size) * self.batch_size + running_examples = [merged_examples[remainder_idx:]] + running_labels = [merged_labels[remainder_idx:]] + running_size = running_size - remainder_idx + + # If we're out of files, yield this last sub-minibatch of data + if running_size > 0: + merged_examples = np.concatenate(running_examples, axis=0) + merged_labels = np.concatenate(running_labels, axis=0) + yield self._prepare_data(merged_examples, merged_labels) diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/discretization.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/discretization.py new file mode 100644 index 0000000..f4f4488 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/discretization.py @@ -0,0 +1,224 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/utils/discretization.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" File that holds techniques for discretizing images -- + In general, images of the form NxCxHxW will with values in the [0.,1.] range + need to be converted to the [0, 255 (int)] range to be displayed as images. + + Sometimes the naive rounding scheme can mess up the classification, so this + file holds techniques to discretize these images into tensors with values + of the form i/255.0 for some integers i. +""" + +import torch +from torch.autograd import Variable +from . import pytorch_utils as utils + + +############################################################################## +# # +# HELPER METHODS # +# # +############################################################################## + + +def discretize_image(img_tensor, zero_one=False): + """ Discretizes an image tensor into a tensor filled with ints ranging + between 0 and 255 + ARGS: + img_tensor : floatTensor (NxCxHxW) - tensor to be discretized + pixel_max : int - discretization bucket size + zero_one : bool - if True divides output by 255 before returning it + """ + + assert float(torch.min(img_tensor)) >= 0. + assert float(torch.max(img_tensor)) <= 1.0 + + original_shape = img_tensor.shape + if img_tensor.dim() != 4: + img_tensor = img_tensor.unsqueeze(0) + + int_tensors = [] # actually floatTensor, but full of ints + img_shape = original_shape[1:] + for example in img_tensor: + pixel_channel_tuples = zip(*list(smp.toimage(example).getdata())) + int_tensors.append(img_tensor.new(pixel_channel_tuples).view(img_shape)) + + stacked_tensors = torch.stack(int_tensors) + if zero_one: + return stacked_tensors / 255.0 + return stacked_tensors + + +############################################################################## +# # +# MAIN DISCRETIZATION TECHNIQUES # +# # +############################################################################## + +def discretized_adversarial(img_tensor, classifier_net, normalizer, + flavor='greedy'): + """ Takes in an image_tensor and classifier/normalizer pair and outputs a + 'discretized' image_tensor [each val is i/255.0 for some integer i] + with the same classification + ARGS: + img_tensor : tensor (NxCxHxW) - tensor of images with values between + 0.0 and 1.0. + classifier_net : NN - neural net with .forward method to classify + normalized images + normalizer : differentiableNormalizer object - normalizes 0,1 images + into classifier_domain + flavor : string - either 'random' or 'greedy', determining which + 'next_pixel_to_flip' function we use + RETURNS: + img_tensor of the same shape, but no with values of the form i/255.0 + for integers i. + """ + + img_tensor = utils.safe_tensor(img_tensor) + + nptf_map = {'random': flip_random_pixel, + 'greedy': flip_greedy_pixel} + next_pixel_to_flip = nptf_map[flavor](classifier_net, normalizer) + + ########################################################################## + # First figure out 'correct' labels and the 'discretized' labels # + ########################################################################## + var_img = utils.safe_var(img_tensor) + norm_var = normalizer.forward(var_img) + norm_output = classifier_net.forward(norm_var) + correct_targets = norm_output.max(1)[1] + + og_discretized = utils.safe_var(discretize_image(img_tensor, zero_one=True)) + norm_discretized = normalizer.forward(og_discretized) + discretized_output = classifier_net.forward(norm_discretized) + discretized_targets = discretized_output.max(1)[1] + + ########################################################################## + # Collect idxs for examples affected by discretization # + ########################################################################## + incorrect_idxs = set() + + for i, el in enumerate(correct_targets.ne(discretized_targets)): + if float(el) != 0: + incorrect_idxs.add(i) + + ########################################################################## + # Fix all bad images # + ########################################################################## + + corrected_imgs = [] + for idx in incorrect_idxs: + desired_target = correct_targets[idx] + example = og_discretized[idx].data.clone() # tensor + signs = torch.sign(var_img - og_discretized) + bad_discretization = True + pixels_changed_so_far = set() # populated with tuples of idxs + + while bad_discretization: + pixel_idx, grad_sign = next_pixel_to_flip(example, + pixels_changed_so_far, + desired_target) + pixels_changed_so_far.add(pixel_idx) + + if grad_sign == 0: + grad_sign = utils.tuple_getter(signs[idx], pixel_idx) + + new_val = (grad_sign / 255. + utils.tuple_getter(example, pixel_idx)) + utils.tuple_setter(example, pixel_idx, float(new_val)) + + new_out = classifier_net.forward(normalizer.forward( \ + Variable(example.unsqueeze(0)))) + bad_discretization = (int(desired_target) != int(new_out.max(1)[1])) + corrected_imgs.append(example) + + # Stack up results + output = [] + + for idx in range(len(img_tensor)): + if idx in incorrect_idxs: + output.append(corrected_imgs.pop(0)) + else: + output.append(og_discretized[idx].data) + + return torch.stack(output) # Variable + + +############################################################################# +# # +# FLIP TECHNIQUES # +# # +############################################################################# +''' Flip techniques in general have the following specs: + ARGS: + classifier_net : NN - neural net with .forward method to classify + normalized images + normalizer : differentiableNormalizer object - normalizes 0,1 images + into classifier_domain + RETURNS: flip_function +''' + +''' + Flip function is a function that takes the following args: + ARGS: + img_tensor : Tensor (CxHxW) - image tensor in range 0.0 to 1.0 and is + already discretized + pixels_changed_so_far: set - set of index_tuples that have already been + modified (we don't want to modify a pixel by + more than 1/255 in any channel) + correct_target : torch.LongTensor (1) - single element in a tensor that + is the target class + (e.g. int between 0 and 9 for CIFAR ) + RETURNS: (idx_tuple, sign) + index_tuple is a triple of indices indicating which pixel-channel needs + to be modified, and sign is in {-1, 0, 1}. If +-1, we will modify the + pixel-channel in that direction, otherwise we'll modify in the opposite + of the direction that discretization rounded to. +''' + + +def flip_random_pixel(classifier_net, normalizer): + def flip_fxn(img_tensor, pixels_changed_so_far, correct_target): + numel = img_tensor.numel() + if len(pixels_changed_so_far) > numel * .9: + raise Exception("WHAT IS GOING ON???") + + while True: + pixel_idx, _ = utils.random_element_index(img_tensor) + if pixel_idx not in pixels_changed_so_far: + return pixel_idx, 0 + + return flip_fxn + + +def flip_greedy_pixel(classifier_net, normalizer): + def flip_fxn(img_tensor, pixels_changed_so_far, correct_target, + classifier_net=classifier_net, normalizer=normalizer): + # Computes gradient and figures out which px most affects class_out + classifier_net.zero_grad() + img_var = Variable(img_tensor.unsqueeze(0), requires_grad=True) + class_out = classifier_net.forward(normalizer.forward(img_var)) + + criterion = torch.nn.CrossEntropyLoss() + loss = criterion(class_out, correct_target) # RESHAPE HERE + loss.backward() + # Really inefficient algorithm here, can probably do better + new_grad_data = img_var.grad.data.clone().squeeze() + signs = new_grad_data.sign() + for idx_tuple in pixels_changed_so_far: + utils.tuple_setter(new_grad_data, idx_tuple, 0) + + argmax = utils.torch_argmax(new_grad_data.abs()) + return argmax, -1 * utils.tuple_getter(signs, argmax) + + return flip_fxn diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/image_utils.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/image_utils.py new file mode 100644 index 0000000..c6e09d7 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/image_utils.py @@ -0,0 +1,193 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/utils/image_utils.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" Specific utilities for image classification + (i.e. RGB images i.e. tensors of the form NxCxHxW ) +""" + +from __future__ import print_function +import torch +import numpy as np +import matplotlib.pyplot as plt +import random + + +def nhwc255_xform(img_np_array): + """ Takes in a numpy array and transposes it so that the channel is the last + axis. Also multiplies all values by 255.0 + ARGS: + img_np_array : np.ndarray - array of shape (NxHxWxC) or (NxCxHxW) + [assumes that we're in NCHW by default, + but if not ambiguous will handle NHWC too ] + RETURNS: + array of form NHWC + """ + assert isinstance(img_np_array, np.ndarray) + shape = img_np_array.shape + assert len(shape) == 4 + + # determine which configuration we're in + ambiguous = (shape[1] == shape[3] == 3) + nhwc = (shape[1] == 3) + + # transpose unless we're unambiguously in nhwc case + if nhwc and not ambiguous: + return img_np_array * 255.0 + else: + return np.transpose(img_np_array, (0, 2, 3, 1)) * 255.0 + + +def show_images(images, normalize=None, ipython=True, + margin_height=2, margin_color='red', + figsize=(18, 16)): + """ Shows pytorch tensors/variables as images """ + + # first format the first arg to be hz-stacked numpy arrays + if not isinstance(images, list): + images = [images] + images = [np.dstack(image.cpu().numpy()) for image in images] + image_shape = images[0].shape + assert all(image.shape == image_shape for image in images) + assert all(image.ndim == 3 for image in images) # CxHxW + + # now build the list of final rows + rows = [] + if margin_height > 0: + assert margin_color in ['red', 'black'] + margin_shape = list(image_shape) + margin_shape[1] = margin_height + margin = np.zeros(margin_shape) + if margin_color == 'red': + margin[0] = 1 + else: + margin = None + + for image_row in images: + rows.append(margin) + rows.append(image_row) + + rows = [_ for _ in rows[1:] if _ is not None] + plt.figure(figsize=figsize, dpi=80, facecolor='w', edgecolor='k') + + cat_rows = np.concatenate(rows, 1).transpose(1, 2, 0) + imshow_kwargs = {} + if cat_rows.shape[-1] == 1: # 1 channel: greyscale + cat_rows = cat_rows.squeeze() + imshow_kwargs['cmap'] = 'gray' + + plt.imshow(cat_rows, **imshow_kwargs) + + plt.show() + + +def display_adversarial_2row(classifier_net, normalizer, original_images, + adversarial_images, num_to_show=4, which='incorrect', + ipython=False, margin_width=2): + """ Displays adversarial images side-by-side with their unperturbed + counterparts. Opens a window displaying two rows: top row is original + images, bottom row is perturbed + ARGS: + classifier_net : nn - with a .forward method that takes normalized + variables and outputs logits + normalizer : object w/ .forward method - should probably be an instance + of utils.DifferentiableNormalize or utils.IdentityNormalize + original_images: Variable or Tensor (NxCxHxW) - original images to + display. Images in [0., 1.] range + adversarial_images: Variable or Tensor (NxCxHxW) - perturbed images to + display. Should be same shape as original_images + num_to_show : int - number of images to show + which : string in ['incorrect', 'random', 'correct'] - which images to + show. + -- 'incorrect' means successfully attacked images, + -- 'random' means some random selection of images + -- 'correct' means unsuccessfully attacked images + ipython: bool - if True, we use in an ipython notebook so slightly + different way to show Images + margin_width - int : height in pixels of the red margin separating top + and bottom rows. Set to 0 for no margin + RETURNS: + None, but displays images + """ + assert which in ['incorrect', 'random', 'correct'] + + # If not 'random' selection, prune to only the valid things + to_sample_idxs = [] + if which != 'random': + classifier_net.eval() # can never be too safe =) + + # classify the originals with top1 + original_norm_var = normalizer.forward(original_images) + original_out_logits = classifier_net.forward(original_norm_var) + _, original_out_classes = original_out_logits.max(1) + + # classify the adversarials with top1 + adv_norm_var = normalizer.forward(adversarial_images) + adv_out_logits = classifier_net.forward(adv_norm_var) + _, adv_out_classes = adv_out_logits.max(1) + + # collect indices of matching + selector = lambda var: (which == 'correct') == bool(float(var)) + for idx, var_el in enumerate(original_out_classes == adv_out_classes): + if selector(var_el): + to_sample_idxs.append(idx) + else: + to_sample_idxs = list(range(original_images.shape[0])) + + # Now select some indices to show + if to_sample_idxs == []: + print("Couldn't show anything. Try changing the 'which' argument here") + return + + to_show_idxs = random.sample(to_sample_idxs, min([num_to_show, + len(to_sample_idxs)])) + + # Now start building up the images : first horizontally, then vertically + top_row = torch.cat([original_images[idx] for idx in to_show_idxs], dim=2) + bottom_row = torch.cat([adversarial_images[idx] for idx in to_show_idxs], + dim=2) + + if margin_width > 0: + margin = torch.zeros(3, margin_width, top_row.shape[-1]) + margin[0] = 1.0 # make it red + margin = margin.type(type(top_row)) + stack = [top_row, margin, bottom_row] + else: + stack = [top_row, bottom_row] + + plt.imshow(torch.cat(stack, dim=1).cpu().numpy().transpose(1, 2, 0)) + plt.show() + + +def display_adversarial_notebook(): + pass + + +def nchw_l2(x, y, squared=True): + """ Computes l2 norm between two NxCxHxW images + ARGS: + x, y: Tensor/Variable (NxCxHxW) - x, y must be same type & shape. + squared : bool - if True we return squared loss, otherwise we return + square root of l2 + RETURNS: + ||x - y ||_2 ^2 (no exponent if squared == False), + shape is (Nx1x1x1) + """ + temp = torch.pow(x - y, 2) # square diff + + for i in range(1, temp.dim()): # reduce on all but first dimension + temp = torch.sum(temp, i, keepdim=True) + + if not squared: + temp = torch.pow(temp, 0.5) + + return temp.squeeze() diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/pytorch_ssim.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/pytorch_ssim.py new file mode 100644 index 0000000..c50d92b --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/pytorch_ssim.py @@ -0,0 +1,89 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/utils/pytorch_ssim.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" Implementation directly lifted from Po-Hsun-Su for pytorch ssim +See github repo here: https://github.com/Po-Hsun-Su/pytorch-ssim +""" + +import torch +import torch.nn.functional as F +from torch.autograd import Variable +from math import exp + +def gaussian(window_size, sigma): + gauss = torch.Tensor([exp(-(x - window_size//2)**2/float(2*sigma**2)) for x in range(window_size)]) + return gauss/gauss.sum() + +def create_window(window_size, channel): + _1D_window = gaussian(window_size, 1.5).unsqueeze(1) + _2D_window = _1D_window.mm(_1D_window.t()).float().unsqueeze(0).unsqueeze(0) + window = Variable(_2D_window.expand(channel, 1, window_size, window_size).contiguous()) + return window + +def _ssim(img1, img2, window, window_size, channel, size_average = True): + mu1 = F.conv2d(img1, window, padding = window_size//2, groups = channel) + mu2 = F.conv2d(img2, window, padding = window_size//2, groups = channel) + + mu1_sq = mu1.pow(2) + mu2_sq = mu2.pow(2) + mu1_mu2 = mu1*mu2 + + sigma1_sq = F.conv2d(img1*img1, window, padding = window_size//2, groups = channel) - mu1_sq + sigma2_sq = F.conv2d(img2*img2, window, padding = window_size//2, groups = channel) - mu2_sq + sigma12 = F.conv2d(img1*img2, window, padding = window_size//2, groups = channel) - mu1_mu2 + + C1 = 0.01**2 + C2 = 0.03**2 + + ssim_map = ((2*mu1_mu2 + C1)*(2*sigma12 + C2))/((mu1_sq + mu2_sq + C1)*(sigma1_sq + sigma2_sq + C2)) + + if size_average: + return ssim_map.mean() + else: + return ssim_map.mean(1).mean(1).mean(1) + +class SSIM(torch.nn.Module): + def __init__(self, window_size = 11, size_average = True): + super(SSIM, self).__init__() + self.window_size = window_size + self.size_average = size_average + self.channel = 1 + self.window = create_window(window_size, self.channel) + + def forward(self, img1, img2): + (_, channel, _, _) = img1.size() + + if channel == self.channel and self.window.data.type() == img1.data.type(): + window = self.window + else: + window = create_window(self.window_size, channel) + + if img1.is_cuda: + window = window.cuda(img1.get_device()) + window = window.type_as(img1) + + self.window = window + self.channel = channel + + + return _ssim(img1, img2, window, self.window_size, channel, self.size_average) + +def ssim(img1, img2, window_size = 11, size_average = True): + (_, channel, _, _) = img1.size() + window = create_window(window_size, channel) + + if img1.is_cuda: + window = window.cuda(img1.get_device()) + window = window.type_as(img1) + + return _ssim(img1, img2, window, window_size, channel, size_average) \ No newline at end of file diff --git a/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/pytorch_utils.py b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/pytorch_utils.py new file mode 100644 index 0000000..0235137 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/mister_ed/utils/pytorch_utils.py @@ -0,0 +1,637 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/mister_ed/utils/pytorch_utils.py +# +# The license for the original version of this file can be +# found in the `recoloradv` directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +""" Utilities for general pytorch helpfulness """ + +from __future__ import print_function +import torch +import numpy as np +import torchvision.transforms as transforms +import torch.cuda as cuda +import gc +import os +import warnings +from torch.autograd import Variable, Function +import subprocess +from functools import reduce + + +############################################################################### +# # +# SAFETY DANCE # +# # +############################################################################### +# aka things for safer pytorch usage + + +def use_gpu(): + """ The shortcut to retrieve the environment variable 'MISTER_ED_GPU'""" + try: + str_val = os.environ['MISTER_ED_GPU'] + except: + set_global_gpu() + str_val = os.environ['MISTER_ED_GPU'] + assert str_val in ['True', 'False'] + return str_val == 'True' + + +def set_global_gpu(manual=None): + """ Sets the environment variable 'MISTER_ED_GPU'. Defaults to using gpu + if cuda is available + ARGS: + manual : bool - we set the 'MISTER_ED_GPU' environment var to the string + of whatever this is + RETURNS + None + """ + if manual is None: + val = cuda.is_available() + else: + val = manual + os.environ['MISTER_ED_GPU'] = str(val) + + +def unset_global_gpu(): + """ Removes the environment variable 'MISTER_ED_GPU' + # NOTE: this relies on unsetenv, which works on 'most flavors of Unix' + according to the docs + """ + try: + os.unsetenv('MISTER_ED_GPU') + except: + raise Warning("os.unsetenv(.) isn't working properly") + + +def cuda_assert(use_cuda): + assert not (use_cuda and not cuda.is_available()) + + +def safe_var(entity, **kwargs): + """ Returns a variable of an entity, which may or may not already be a + variable + """ + warnings.warn("As of >=pytorch0.4.0 this is no longer necessary", + DeprecationWarning) + if isinstance(entity, Variable): + return entity + elif isinstance(entity, torch._C._TensorBase): + return Variable(entity, **kwargs) + else: + raise Exception("Can't cast %s to a Variable" % + entity.__class__.__name__) + + +def safe_tensor(entity): + """ Returns a tensor of an entity, which may or may not already be a + tensor + """ + warnings.warn("As of >=pytorch0.4.0 this is no longer necessary", + DeprecationWarning) + if isinstance(entity, Variable): + return entity.data + elif isinstance(entity, torch.tensor._TensorBase): + return entity + elif isinstance(entity, np.ndarray): + return torch.Tensor(entity) # UNSAFE CUDA CASTING + else: + raise Exception("Can't cast %s to a Variable" % + entity.__class__.__name__) + + +############################################################################## +# # +# CONVENIENCE STORE # +# # +############################################################################## +# aka convenient things that are not builtin to pytorch + +class AverageMeter(object): + """Computes and stores the average and current value""" + + def __init__(self): + self.reset() + + def reset(self): + self.val = 0 + self.avg = 0 + self.sum = 0 + self.count = 0 + + def update(self, val, n=1): + self.val = val + self.sum += val * n + self.count += n + self.avg = self.sum / self.count + + def __str__(self): + return str(self.avg) + + +def tuple_getter(tensor, idx_tuple): + """ access a tensor by a tuple """ + tensor_ = tensor + for el in idx_tuple: + tensor_ = tensor_[el] + return tensor_ + + +def tuple_setter(tensor, idx_tuple, val): + """ Sets a tensor element while indexing by a tuple""" + + tensor_ = tensor + for el in idx_tuple[:-1]: + tensor_ = tensor_[el] + + tensor_[idx_tuple[-1]] = val + return tensor + + +def torch_argmax(tensor): + """ Returns the idx tuple that corresponds to the max value in the tensor""" + + flat_tensor = tensor.view(tensor.numel()) + _, argmax = flat_tensor.max(0) + return np.unravel_index(int(argmax), tensor.shape) + + +def torch_argmin(tensor): + """ Returns the idx tuple that corresponds to the min value in the tensor""" + flat_tensor = tensor.view(tensor.numel()) + _, argmin = flat_tensor.min(0) + return np.unravel_index(int(argmin), tensor.shape) + + +def clamp_ref(x, y, l_inf): + """ Clamps each element of x to be within l_inf of each element of y """ + return torch.clamp(x - y, -l_inf, l_inf) + y + + +def torch_arctanh(x, eps=1e-6): + x *= (1. - eps) + return (torch.log((1 + x) / (1 - x))) * 0.5 + + +def tanh_rescale(x, x_min=-1., x_max=1.): + return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min + + +def checkpoint_incremental_array(output_file, numpy_list, + return_concat=True): + """ Takes in a string of a filename and a list of numpy arrays and + concatenates them along first axis, saves them to a file, and then + outputs a list containing only that single concatenated array + ARGS: + output_file : string ending in .npy - full path location of the + place we're saving this numpy array + numpy_list : list of numpy arrays (all same shape except for the first + axis) - list of arrays we concat and save to file + return_concat : boolean - if True, we return these concatenated arrays + in a list, else we return nothing + RETURNS: + maybe nothing, maybe the a singleton list containing the concatenated + arrays + """ + concat = np.concatenate(numpy_list, axis=0) + np.save(output_file, concat) + if return_concat: + return [concat] + + +def sizeof_fmt(num, suffix='B'): + """ https://stackoverflow.com/a/1094933 + answer by Sridhar Ratnakumar """ + for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']: + if abs(num) < 1024.0: + return "%3.1f%s%s" % (num, unit, suffix) + num /= 1024.0 + return "%.1f%s%s" % (num, 'Yi', suffix) + + +def clip_0_1(tensorlike): + # Clips tensorlike object into [0., 1.0] range + return torch.clamp(tensorlike, 0.0, 1.0) + + +def clamp_0_1_delta(x, y): + """ Returns the delta that'd have to be added to (x + y) such that + (x + y) + delta is in the range [0.0, 1.0] + """ + return torch.clamp(x + y, 0.0, 1.0) - (x + y) + + +def random_linf_pertubation(examples_like, l_inf): + """ Returns an object of the same type/shape as examples_like that holds + a uniformly random pertubation in the l_infinity box of l_inf. + NOTE THAT THIS DOES NOT ADD TO examples_like! + """ + + is_var = isinstance(examples_like, Variable) + + random_tensor = (torch.rand(*examples_like.shape) * l_inf * 2 - + torch.ones(*examples_like.shape) * l_inf) + + random_tensor.type(type(examples_like)) + + if is_var: + return Variable(random_tensor) + else: + return random_tensor + + +def batchwise_norm(examples, lp, dim=0): + """ Returns the per-example norm of the examples, keeping along the + specified dimension. + e.g. if examples is NxCxHxW, applying this fxn with dim=0 will return a + N-length tensor with the lp norm of each example + ARGS: + examples : tensor or Variable - needs more than one dimension + lp : string or int - either 'inf' or an int for which lp norm we use + dim : int - which dimension to keep + RETURNS: + 1D object of same type as examples, but with shape examples.shape[dim] + """ + + assert isinstance(lp, int) or lp == 'inf' + examples = torch.abs(examples) + example_dim = examples.dim() + if dim != 0: + examples = examples.transpose(dim, 0) + + if lp == 'inf': + for reduction in range(1, example_dim): + examples, _ = examples.max(1) + return examples + + else: + examples = torch.pow(examples + 1e-10, lp) + for reduction in range(1, example_dim): + examples = examples.sum(1) + return torch.pow(examples, 1.0 / lp) + + +def batchwise_lp_project(x, lp, lp_bound, dim=0): + """ Projects x (a N-by-(...) TENSOR) to be a N-by-(...) TENSOR into the + provided lp ball + ARGS: + x : Tensor (N-by-(...)) - arbitrary style + lp : 'inf' or int - which style of lp we use + lp_bound : float - size of lp ball we project into + dim : int - if not 0 is the dimension we keep and project onto + RETURNS: + None + """ + assert isinstance(lp, int) or lp == 'inf' + + if lp == 'inf': + return torch.clamp(x, -lp_bound, lp_bound) + + needs_squeeze = False + if len(x.shape) == 1: + x = x.unsqueeze(1) + needs_squeeze = True + + output = torch.renorm(x, lp, dim, lp_bound) + + if needs_squeeze: + return output.squeeze() + return output + + +def summed_lp_norm(examples, lp): + """ Returns the sum of the lp norm of each example in examples + ARGS: + examples : tensor or Variable, with first dimension having size N + lp : string or int - either 'inf' or an int for which lp norm we use + RETURNS: + sum of each of the lp norm of each of the N elements in examples + """ + return torch.sum(batchwise_norm(examples, lp, dim=0)) + + +def random_from_lp_ball(tensorlike, lp, lp_bound, dim=0): + """ Returns a new object of the same type/shape as tensorlike that is + randomly samples from the unit ball. + + NOTE THIS IS NOT A UNIFORM SAMPLING METHOD! + (that's hard to implement, https://mathoverflow.net/a/9192/123034) + + ARGS: + tensorlike : Tensor - reference object for which we generate + a new object of same shape/memory_location + lp : int or 'inf' - which style of lp we use + lp_bound : float - size of the L + dim : int - which dimension is the 'keep dimension' + RETURNS: + new tensorlike where each slice across dim is uniform across the + lp ball of size lp_bound + """ + assert isinstance(lp, int) or lp == 'inf' + + rand_direction = torch.rand(tensorlike.shape).type(tensorlike.type()) + + if lp == 'inf': + return rand_direction * (2 * lp_bound) - lp_bound + else: + rand_direction = rand_direction - 0.5 # allow for sign swapping + # first magnify such that each element is above the ball + min_norm = torch.min(batchwise_norm(rand_direction.abs(), lp, dim=dim)) + rand_direction = rand_direction / (min_norm + 1e-6) + rand_magnitudes = torch.rand(tensorlike.shape[dim]).type( + tensorlike.type()) + rand_magnitudes = rand_magnitudes.unsqueeze(1) + rand_magnitudes = rand_magnitudes.expand(*rand_direction.shape) + + return torch.renorm(rand_direction, lp, dim, lp_bound) * rand_magnitudes + + +def tanh_transform(tensorlike, forward=True): + """ Takes in Tensor or Variable and converts it between [0, 1] range and + (-inf, +inf) range by performing an invertible tanh transformation. + ARGS: + tensorlike : Tensor or Variable (arbitrary shape) - object to be + modified into or out of tanh space + forward : bool - if True we convert from [0, 1] space to (-inf, +inf) + space + if False we convert from (-inf, +inf) space to [0, 1] + space + RETURNS: + object of the same shape/type as tensorlike, but with the appropriate + transformation + """ + if forward: + assert torch.min(tensorlike) >= 0.0 + assert torch.max(tensorlike) <= 1.0 + # first convert to [-1, +1] space + temp = (tensorlike * 2 - 1) * (1 - 1e-6) + return torch.log((1 + temp) / (1 - temp)) / 2.0 + + else: + return (torch.tanh(tensorlike) + 1) / 2.0 + + +def fold_mask(x, y, mask): + """ Creates a new tensor that's the result of masking between x and y + ARGS: + x : Tensor or Variable (NxSHAPE) - tensor that we're selecting where the + masked values are 1 + y : Tensor or Variable (NxSHAPE) - tensor that we're selecting where the + masked values are 0 + mask: ByteTensor (N) - masked values. Is only one dimensional: we expand + it in the creation of this + RETURNS: + new object of the same shape/type as x and y + """ + assert x.shape == y.shape + assert mask.shape == (x.shape[0],) + assert type(x) == type(y) + is_var = isinstance(x, Variable) + if is_var: + assert isinstance(mask, Variable) + + per_example_shape = x.shape[1:] + make_broadcastable = lambda m: m.view(-1, *tuple([1] * (x.dim() - 1))) + + broadcast_mask = make_broadcastable(mask) + broadcast_not_mask = make_broadcastable(1 - safe_tensor(mask)) + if is_var: + broadcast_not_mask = Variable(broadcast_not_mask) + + output = torch.zeros_like(x) + output.add_(x * (broadcast_mask.type(x.type()))) + output.add_(y * (broadcast_not_mask.type(y.type()))) + + return output + + +############################################################################### +# # +# CUDA RELATED THINGS # +# # +############################################################################### + +# fxn taken from https://discuss.pytorch.org/t/memory-leaks-in-trans-conv/12492 +def get_gpu_memory_map(): + try: + result = subprocess.check_output( + [ + 'nvidia-smi', '--query-gpu=memory.used', + '--format=csv,nounits,noheader' + ]) + except: + result = "" + try: + return float(result) + except: + return result + + +def rough_gpu_estimate(): + """ Roughly estimates the size of the cuda tensors stored on GPUs. + If multiple gpus, returns a dict of {GPU_id: total num elements } + otherwise just returns the total number of elements + """ + cuda_count = {} + listprod = lambda l: reduce(lambda x, y: x * y, l) + for el in gc.get_objects(): + if isinstance(el, (torch.tensor._TensorBase, Variable)) and el.is_cuda: + device = el.get_device() + cuda_count[device] = (cuda_count.get(device, 0) + + listprod(el.size())) + + if len(cuda_count.keys()) == 0: + return 0 + elif len(cuda_count.keys()) == 1: + return sizeof_fmt(cuda_count.values()[0]) + else: + return {k: sizeof_fmt(v) for k, v in cuda_count.items()} + + +############################################################################## +# # +# CLASSIFICATION HELPERS # +# # +############################################################################## +# aka little utils that are useful for classification + +def accuracy_int(output, target, topk=1): + """ Computes the number of correct examples in the output. + RETURNS an int! + """ + _, pred = output.topk(topk, 1, True, True) + pred = pred.t() + correct = pred.eq(target.view(1, -1).expand_as(pred)) + return int(correct.data.sum()) + + +def accuracy(output, target, topk=(1,)): + """Computes the precision@k for the specified values of k""" + maxk = max(topk) + batch_size = target.size(0) + + _, pred = output.topk(maxk, 1, True, True) + pred = pred.t() + correct = pred.eq(target.view(1, -1).expand_as(pred)) + + res = [] + for k in topk: + correct_k = correct[:k].view(-1).float().sum(0) + res.append(correct_k.mul_(100.0 / batch_size)) + return res + + +############################################################################### +# # +# NORMALIZERS # +# # +############################################################################### + + +class IdentityNormalize(Function): + def __init__(self): + pass + + def forward(self, var): + return var + + def differentiable_call(self): + pass + + +class DifferentiableNormalize(Function): + + def __init__(self, mean, std): + super(DifferentiableNormalize, self).__init__() + self.mean = mean + self.std = std + self.differentiable = True + self.nondiff_normer = transforms.Normalize(mean, std) + + def __call__(self, var): + if self.differentiable: + return self.forward(var) + else: + return self.nondiff_normer(var) + + def _setter(self, c, mean, std): + """ Modifies params going forward """ + if mean is not None: + self.mean = mean + assert len(self.mean) == c + + if std is not None: + self.std = std + assert len(self.std) == c + + if mean is not None or std is not None: + self.nondiff_normer = transforms.Normalize(self.mean, self.std) + + def differentiable_call(self): + """ Sets the __call__ method to be the differentiable version """ + self.differentiable = True + + def nondifferentiable_call(self): + """ Sets the __call__ method to be the torchvision.transforms version""" + self.differentiable = False + + def forward(self, var, mean=None, std=None): + """ Normalizes var by subtracting the mean of each channel and then + dividing each channel by standard dev + ARGS: + self - stores mean and std for later + var - Variable of shape NxCxHxW + mean - if not None is a list of length C for channel-means + std - if not None is a list of length C for channel-stds + RETURNS: + variable of normalized var + """ + c = var.shape[1] + self._setter(c, mean, std) + + mean_var = Variable(var.data.new(self.mean).view(1, c, 1, 1)) + std_var = Variable(var.data.new(self.std).view(1, c, 1, 1)) + return (var - mean_var) / std_var + + +############################################################################## +# # +# TRAINING LOGGER # +# # +############################################################################## + + +class TrainingLogger(object): + + def __init__(self): + """ Unified object to keep track of training data at a specified logging + level. Namely this tracks ground accuracy, loss and attack accuracy + for each attack incorporated into adversarial training. + Will ultimately contain plotting techniques too (TODO!) + """ + self.series = {} + + def data_count(self): + """ Returns the number of data points in this logger instance """ + return sum(len(_) for _ in self.series.values()) + + def add_series(self, name): + """ Adds the name of a 'data series' where each data series is a list + of data-entries, where each data-entry is of the form + ((epoch, minibatch), data-value ) [and data-value is a float] + """ + if name not in self.series: + self.series[name] = [] + + def sort_series(self, name, return_keys=False): + """ Simply returns the series of specified name sorted by epoch and then + minibatch. + ARGS: + name: string - name of exsiting series in self.series + return_keys: bool - if True, the output list is like + [((epoch, minibatch), val), ...] + and if False, it's just like [val, ... val...] + RETURNS: + sorted list of outputs, the exact form of which is determined by + the value of return_keys + """ + data_series = self.series[name] + + sorted_series = sorted(data_series, key=lambda p: p[0]) + + if return_keys is False: + return [_[1] for _ in sorted_series] + else: + return sorted_series + + def get_series(self, name): + """ simple getter method for the given named data series """ + return self.series[name] + + def log_datapoint(self, name, data_tuple): + """ Logs the full data point + ARGS: + name: string - name of existing series in self.series + data_tuple : tuple of form ((epoch, minibatch), value) + RETURNS: + None + """ + self.series[name].append(data_tuple) + + def log(self, name, epoch, minibatch, value): + """ Logs the data point by specifying each of epoch, minibatch, value + ARGS: + name : string - name of existing series in self.series + epoch: int - which epoch of training we're logging + minibatch : int - which minibatch of training we're logging + value : - value we're logging + """ + self.log_datapoint(name, ((epoch, minibatch), value)) diff --git a/case_studies/diffpure/stadv_eot/recoloradv/norms.py b/case_studies/diffpure/stadv_eot/recoloradv/norms.py new file mode 100644 index 0000000..57f65cd --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/norms.py @@ -0,0 +1,51 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/norms.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +import torch +from torch.autograd import Variable + + +def smoothness(grid): + """ + Given a variable of dimensions (N, X, Y, [Z], C), computes the sum of + the differences between adjacent points in the grid formed by the + dimensions X, Y, and (optionally) Z. Returns a tensor of dimension N. + """ + + num_dims = len(grid.size()) - 2 + batch_size = grid.size()[0] + norm = Variable(torch.zeros(batch_size, dtype=grid.data.dtype, + device=grid.data.device)) + + for dim in range(num_dims): + slice_before = (slice(None),) * (dim + 1) + slice_after = (slice(None),) * (num_dims - dim) + shifted_grids = [ + # left + torch.cat([ + grid[slice_before + (slice(1, None),) + slice_after], + grid[slice_before + (slice(-1, None),) + slice_after], + ], dim + 1), + # right + torch.cat([ + grid[slice_before + (slice(None, 1),) + slice_after], + grid[slice_before + (slice(None, -1),) + slice_after], + ], dim + 1) + ] + for shifted_grid in shifted_grids: + delta = shifted_grid - grid + norm_components = (delta.pow(2).sum(-1) + 1e-10).pow(0.5) + norm.add_(norm_components.sum( + tuple(range(1, len(norm_components.size()))))) + + return norm diff --git a/case_studies/diffpure/stadv_eot/recoloradv/perturbations.py b/case_studies/diffpure/stadv_eot/recoloradv/perturbations.py new file mode 100644 index 0000000..bf07af7 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/perturbations.py @@ -0,0 +1,129 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/perturbations.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +from .mister_ed import adversarial_perturbations as ap +from .mister_ed.adversarial_perturbations import initialized +from .mister_ed.utils import pytorch_utils as utils + +from . import color_transformers as ct +from . import color_spaces as cs + + +class ReColorAdv(ap.AdversarialPerturbation): + """ + Puts the color at each pixel in the image through the same transformation. + + Parameters: + - lp_style: number or 'inf' + - lp_bound: maximum norm of color transformation. Can be a tensor of size + (num_channels,), in which case each channel will be bounded by the + cooresponding bound in the tensor. For instance, passing + [0.1, 0.15, 0.05] would allow a norm of 0.1 for R, 0.15 for G, and 0.05 + for B. Not supported by all transformations. + - use_smooth_loss: whether to optimize using the loss function + for FullSpatial that rewards smooth vector fields + - xform_class: a subclass of + color_transformers.ParameterizedTransformation + - xform_params: dict of parameters to pass to the xform_class. + - cspace_class: a subclass of color_spaces.ColorSpace that indicates + in which color space the transformation should be performed + (RGB by default) + """ + + def __init__(self, threat_model, perturbation_params, *other_args): + super().__init__(threat_model, perturbation_params) + assert issubclass(perturbation_params.xform_class, + ct.ParameterizedTransformation) + + self.lp_style = perturbation_params.lp_style + self.lp_bound = perturbation_params.lp_bound + self.use_smooth_loss = perturbation_params.use_smooth_loss + self.scalar_step = perturbation_params.scalar_step or 1.0 + self.cspace = perturbation_params.cspace or cs.RGBColorSpace() + + def _merge_setup(self, num_examples, new_xform): + """ DANGEROUS TO BE CALLED OUTSIDE OF THIS FILE!!!""" + self.num_examples = num_examples + self.xform = new_xform + self.initialized = True + + def setup(self, originals): + super().setup(originals) + self.xform = self.perturbation_params.xform_class( + shape=originals.shape, manual_gpu=self.use_gpu, + cspace=self.cspace, + **(self.perturbation_params.xform_params or {}), + ) + self.initialized = True + + @initialized + def perturbation_norm(self, x=None, lp_style=None): + lp_style = lp_style or self.lp_style + if self.use_smooth_loss: + assert isinstance(self.xform, ct.FullSpatial) + return self.xform.smoothness_norm() + else: + return self.xform.norm(lp=lp_style) + + @initialized + def constrain_params(self, x=None): + # Do lp projections + if isinstance(self.lp_style, int) or self.lp_style == 'inf': + self.xform.project_params(self.lp_style, self.lp_bound) + + @initialized + def update_params(self, step_fxn): + param_list = list(self.xform.parameters()) + assert len(param_list) == 1 + params = param_list[0] + assert params.grad.data is not None + self.add_to_params(step_fxn(params.grad.data) * self.scalar_step) + + @initialized + def add_to_params(self, grad_data): + """ Assumes only one parameters object in the Spatial Transform """ + param_list = list(self.xform.parameters()) + assert len(param_list) == 1 + params = param_list[0] + params.data.add_(grad_data) + + @initialized + def random_init(self): + param_list = list(self.xform.parameters()) + assert len(param_list) == 1 + param = param_list[0] + random_perturb = utils.random_from_lp_ball(param.data, + self.lp_style, + self.lp_bound) + + param.data.add_(self.xform.identity_params + + random_perturb - self.xform.xform_params.data) + + @initialized + def merge_perturbation(self, other, self_mask): + super().merge_perturbation(other, self_mask) + new_perturbation = ReColorAdv(self.threat_model, + self.perturbation_params) + + new_xform = self.xform.merge_xform(other.xform, self_mask) + new_perturbation._merge_setup(self.num_examples, new_xform) + + return new_perturbation + + def forward(self, x): + if not self.initialized: + self.setup(x) + self.constrain_params() + + return self.cspace.to_rgb( + self.xform.forward(self.cspace.from_rgb(x))) diff --git a/case_studies/diffpure/stadv_eot/recoloradv/utils.py b/case_studies/diffpure/stadv_eot/recoloradv/utils.py new file mode 100644 index 0000000..bd10178 --- /dev/null +++ b/case_studies/diffpure/stadv_eot/recoloradv/utils.py @@ -0,0 +1,108 @@ +# --------------------------------------------------------------- +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# This file has been modified from recoloradv. +# +# Source: +# https://github.com/cassidylaidlaw/ReColorAdv/blob/master/recoloradv/utils.py +# +# The license for the original version of this file can be +# found in this directory (LICENSE_RECOLORADV). +# The modifications to this file are subject to the same license. +# --------------------------------------------------------------- + +from torch import nn +from torch import optim + +from .mister_ed.utils.pytorch_utils import DifferentiableNormalize +from .mister_ed import adversarial_perturbations as ap +from .mister_ed import adversarial_attacks as aa +from .mister_ed import spatial_transformers as st +from .mister_ed import loss_functions as lf +from .mister_ed import adversarial_training as advtrain + +from . import perturbations as pt +from . import color_transformers as ct +from . import color_spaces as cs + + +def get_attack_from_name( + name: str, + classifier: nn.Module, + normalizer: DifferentiableNormalize, + verbose: bool = False, +) -> advtrain.AdversarialAttackParameters: + """ + Builds an attack from a name like "recoloradv" or "stadv+delta" or + "recoloradv+stadv+delta". + """ + + threats = [] + norm_weights = [] + + for attack_part in name.split('+'): + if attack_part == 'delta': + threats.append(ap.ThreatModel( + ap.DeltaAddition, + ap.PerturbationParameters( + lp_style='inf', + lp_bound=8.0 / 255, + ), + )) + norm_weights.append(0.0) + elif attack_part == 'stadv': + threats.append(ap.ThreatModel( + ap.ParameterizedXformAdv, + ap.PerturbationParameters( + lp_style='inf', + lp_bound=0.05, + xform_class=st.FullSpatial, + use_stadv=True, + ), + )) + norm_weights.append(1.0) + elif attack_part == 'recoloradv': + threats.append(ap.ThreatModel( + pt.ReColorAdv, + ap.PerturbationParameters( + lp_style='inf', + lp_bound=[0.06, 0.06, 0.06], + xform_params={ + 'resolution_x': 16, + 'resolution_y': 32, + 'resolution_z': 32, + }, + xform_class=ct.FullSpatial, + use_smooth_loss=True, + cspace=cs.CIELUVColorSpace(), + ), + )) + norm_weights.append(1.0) + else: + raise ValueError(f'Invalid attack "{attack_part}"') + + sequence_threat = ap.ThreatModel( + ap.SequentialPerturbation, + threats, + ap.PerturbationParameters(norm_weights=norm_weights), + ) + + # use PGD attack + adv_loss = lf.CWLossF6(classifier, normalizer, kappa=float('inf')) + st_loss = lf.PerturbationNormLoss(lp=2) + loss_fxn = lf.RegularizedLoss({'adv': adv_loss, 'pert': st_loss}, + {'adv': 1.0, 'pert': 0.05}, + negate=True) + + pgd_attack = aa.PGD(classifier, normalizer, sequence_threat, loss_fxn) + return advtrain.AdversarialAttackParameters( + pgd_attack, + 1.0, + attack_specific_params={'attack_kwargs': { + 'num_iterations': 100, + 'optimizer': optim.Adam, + 'optimizer_kwargs': {'lr': 0.001}, + 'signed': False, + 'verbose': verbose, + }}, + ) diff --git a/case_studies/dla/adversarial_evaluation.py b/case_studies/dla/adversarial_evaluation.py new file mode 100644 index 0000000..5200fcd --- /dev/null +++ b/case_studies/dla/adversarial_evaluation.py @@ -0,0 +1,133 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import logging +logging.getLogger('tensorflow').setLevel(logging.FATAL) +import warnings +warnings.filterwarnings("ignore") + +import argparse + +import torch +import numpy as np + +import defense_v3 +import defense_v2 +import defense +from cifar import CIFAR10 +import pgd_attack + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--batch-size", type=int, default=512) + parser.add_argument("--n-samples", type=int, default=512) + parser.add_argument("--adversarial-attack", + choices=(None, "pgd", "selective-pgd", "joined-pgd"), + default=None) + parser.add_argument("--epsilon", type=float, default=0.31) + parser.add_argument("--n-steps", type=int, default=100) + parser.add_argument("--step-size", type=float, default=0.001) + parser.add_argument("--threshold", type=float, default=None) + parser.add_argument("--fpr-threshold", type=float, default=0.05) + + args = parser.parse_args() + assert args.n_samples < 5000 + if args.epsilon > 0 or args.n_steps > 0 or args.step_size > 0: + assert args.adversarial_attack is not None + + device = "cuda" if torch.cuda.is_available() else "cpu" + + dataset = CIFAR10(tf_mode=True) + classifier_and_detector, classifier, detector = defense_v2.load_model( + device=device) + + n_batches = int(np.ceil(args.n_samples / args.batch_size)) + + is_adv = [] + adv_detector_scores = [] + detector_scores = [] + for batch_idx in range(n_batches): + x_batch = dataset.test_data[batch_idx*args.batch_size : + (batch_idx+1)*args.batch_size] + y_batch = dataset.test_labels[batch_idx*args.batch_size : + (batch_idx+1)*args.batch_size] + x_batch = x_batch.transpose((0, 3, 1, 2)) + x_batch = torch.tensor(x_batch, dtype=torch.float32).to(device) + y_batch = torch.tensor(y_batch, dtype=torch.long).to(device) + + if args.adversarial_attack is not None: + x_adv_batch = pgd_attack.attack( + x_batch, y_batch, classifier, classifier_and_detector, + args.adversarial_attack, args.n_steps, args.step_size, args.epsilon) + + with torch.no_grad(): + logits, adv_detector_scores_batch = classifier_and_detector(x_adv_batch) + adv_detector_scores_batch = adv_detector_scores_batch.cpu().numpy() + adv_predictions_batch = logits.argmax(1) + detector_scores_batch = detector(x_batch).cpu().numpy() + + is_adv_batch = adv_predictions_batch != y_batch + is_adv_batch = is_adv_batch.cpu().numpy() + + is_adv.append(is_adv_batch) + detector_scores.append(detector_scores_batch) + adv_detector_scores.append(adv_detector_scores_batch) + + is_adv = np.concatenate(is_adv, 0) + is_adv = is_adv[:args.n_samples] + + detector_scores = np.concatenate(detector_scores, 0) + detector_scores = detector_scores[:args.n_samples] + + adv_detector_scores = np.concatenate(adv_detector_scores, 0) + adv_detector_scores = adv_detector_scores[:args.n_samples] + + if args.threshold is None: + detector_threshold = np.sort(detector_scores)[ + -int(len(detector_scores) * args.fpr_threshold)] + print("Threshold for FPR", args.fpr_threshold, "=", detector_threshold) + else: + detector_threshold = args.threshold + adv_is_detected = adv_detector_scores > detector_threshold + is_detected = detector_scores > detector_threshold + + # true positive: detected + adversarial example + # true negative: not detected + normal example + # false positive: detected + normal example + # false negative: not detected + adversarial example + tpr = np.mean(adv_is_detected) + fnr = np.mean(~adv_is_detected) + tnr = np.mean(~is_detected) + fpr = np.mean(is_detected) + + tp = np.sum(adv_is_detected) + fn = np.sum(~adv_is_detected) + fp = np.sum(is_detected) + + f1 = tp / (tp + 0.5 * (fp + fn)) + + print("TPR", tpr) + print("FPR", fpr) + print("TNR", tnr) + print("FNR", fnr) + print("F1 ", f1) + + is_adv_and_not_detected = np.logical_and(is_adv, ~adv_is_detected) + + print("Attack Success Rate (w/o detector):", np.mean(is_adv)) + print("Attack Success Rate (w/ detector):", np.mean(is_adv_and_not_detected)) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/case_studies/dla/adversarial_evaluation.sh b/case_studies/dla/adversarial_evaluation.sh new file mode 100644 index 0000000..641aae6 --- /dev/null +++ b/case_studies/dla/adversarial_evaluation.sh @@ -0,0 +1,27 @@ +n_samples=512 + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "epsilon = 0.01, FGSM" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) \ + python case_studies/dla/adversarial_evaluation.py \ + --adversarial-attack=pgd \ + --epsilon=0.01 \ + --step-size=0.01 \ + --n-steps=1 \ + --n-samples=$n_samples \ + --batch-size=256 + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "epsilon = 0.01, PGD" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) \ + python case_studies/dla/adversarial_evaluation.py \ + --adversarial-attack=pgd \ + --epsilon=0.01 \ + --step-size=0.001 \ + --n-steps=200 \ + --n-samples=$n_samples \ + --batch-size=256 \ No newline at end of file diff --git a/case_studies/dla/binarization_test.py b/case_studies/dla/binarization_test.py new file mode 100644 index 0000000..3d18190 --- /dev/null +++ b/case_studies/dla/binarization_test.py @@ -0,0 +1,241 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import logging +import math +import warnings + +from active_tests.decision_boundary_binarization import format_result +from active_tests.decision_boundary_binarization import \ + interior_boundary_discrimination_attack +from argparse_utils import DecisionBoundaryBinarizationSettings + +logging.getLogger('tensorflow').setLevel(logging.FATAL) +# import warnings +# warnings.filterwarnings("ignore") + +import argparse + +import torch +import numpy as np +import utils as ut + +import defense_v2 +from cifar import CIFAR10 +import pgd_attack + + +class TorchWithDetectAndOtherReadout(torch.nn.Module): + def __init__(self, model, alarm, other_readout): + super().__init__() + self.model = model + self.alarm = alarm + self.other_readout = other_readout + + def forward(self, x): + _, hidden, features = self.model(x, return_features=True) + is_ok = self.alarm(hidden) + out = self.other_readout(features) + return out, is_ok + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--batch-size", type=int, default=512) + parser.add_argument("--n-samples", type=int, default=512) + parser.add_argument("--adversarial-attack", + choices=("pgd", "selective-pgd", "joined-pgd"), + required=True) + parser.add_argument("--epsilon", type=float, default=0) + parser.add_argument("--n-steps", type=int, default=0) + parser.add_argument("--step-size", type=float, default=0) + + parser.add_argument("--n-boundary-points", default=49, type=int) + parser.add_argument("--n-inner-points", default=10, type=int) + # parser.add_argument("--dont-verify-training-data", action="store_true") + # parser.add_argument("--use-boundary-adverarials", action="store_true") + parser.add_argument("--inverted-test", action="store_true") + + args = parser.parse_args() + assert args.n_samples < 5000 + if args.epsilon > 0 or args.n_steps > 0 or args.step_size > 0: + assert args.adversarial_attack is not None + + if args.inverted_test: + print("Running inverted test") + else: + print("Running normal/non-inverted test") + + device = "cuda" if torch.cuda.is_available() else "cpu" + + dataset = CIFAR10(tf_mode=True) + classifier_and_detector, classifier, detector = defense_v2.load_model( + device=device) + + def verify_valid_input_data(x_set: torch.Tensor) -> np.ndarray: + """Returns True if something is not detected as an adversarial example.""" + n_batches = math.ceil(x_set.shape[0] / args.batch_size) + with torch.no_grad(): + return np.concatenate( + [(detector( + x_set[b * args.batch_size:(b + 1) * args.batch_size] + ) < 0).cpu().numpy() for b in range(n_batches)]) + + def get_boundary_adversarials(x, y, n_samples, epsilon): + """Generate adversarial examples for the base classifier.""" + assert len(x.shape) == 3 + x = x.unsqueeze(0) + x = torch.repeat_interleave(x, n_samples, dim=0) + + y = y.unsqueeze(0) + y = torch.repeat_interleave(y, n_samples, dim=0) + + for _ in range(25): + x_adv = pgd_attack.attack( + x, y, classifier, classifier_and_detector, + "pgd", args.n_steps, args.step_size, epsilon) + + # project adversarials to the max norm boundary + x_adv = ut.clipping_aware_rescaling(x, x_adv - x, args.epsilon, + norm="linf") + is_valid = verify_valid_input_data(x_adv) + is_invalid = ~is_valid + + if np.all(is_invalid): + # generative until we finally found an adversarial example that gets + # detected + break + else: + raise RuntimeError("Could not generate adversarial example that gets " + "detected after 25 trials.") + return x_adv + + def run_attack(m, l, attack_kwargs): + modified_classifier_and_detector = TorchWithDetectAndOtherReadout( + classifier_and_detector.model, + (lambda *args, **kwargs: -classifier_and_detector.alarm( + *args, + **kwargs)) if args.inverted_test else classifier_and_detector.alarm, + list(m.children())[-1]) + for x, y in l: + x, y = x.to(device), y.to(device) + x_adv = pgd_attack.attack( + x, y, m, modified_classifier_and_detector, + args.adversarial_attack, args.n_steps, args.step_size, args.epsilon) + with torch.no_grad(): + logits = m(x_adv) + is_adv = (logits.argmax(1) != y).cpu().numpy() + + if args.inverted_test: + undetected = (detector(x_adv) > 0).cpu().numpy() + else: + undetected = (detector(x_adv) < 0).cpu().numpy() + is_adv = np.logical_and(is_adv, undetected) + + return is_adv, (x_adv, logits) + + class FeatureExtractor(torch.nn.Module): + def __init__(self, classifier_and_detector): + super().__init__() + self.classifier = classifier_and_detector.model + + def forward(self, x, features_only=True): + if features_only: + _, _, f = self.classifier(x, return_features=True) + return f + else: + return self.classifier(x) + + feature_extractor = FeatureExtractor(classifier_and_detector) + + # select clean data samples which don't get rejected by the detector + test_data_x = [] + test_data_y = [] + batch_idx = 0 + n_samples = 0 + with torch.no_grad(): + while n_samples < args.n_samples: + x_batch = dataset.test_data[batch_idx * args.batch_size: + (batch_idx + 1) * args.batch_size] + y_batch = dataset.test_labels[batch_idx * args.batch_size: + (batch_idx + 1) * args.batch_size] + x_batch = x_batch.transpose((0, 3, 1, 2)) + x_batch = torch.tensor(x_batch, dtype=torch.float32) + y_batch = torch.tensor(y_batch, dtype=torch.long) + mask = verify_valid_input_data(x_batch.to(device)) + x_batch = x_batch[mask].numpy() + y_batch = y_batch[mask].numpy() + test_data_x.append(x_batch) + test_data_y.append(y_batch) + n_samples += len(x_batch) + test_data_x = np.concatenate(test_data_x, 0) + test_data_y = np.concatenate(test_data_y, 0) + test_data_x = test_data_x[:args.n_samples] + test_data_y = test_data_y[:args.n_samples] + del batch_idx, n_samples + + test_loader = ut.build_dataloader_from_arrays( + test_data_x, test_data_y) + + if args.inverted_test: + additional_settings = dict( + n_boundary_points=args.n_boundary_points, + n_boundary_adversarial_points=1, + n_far_off_boundary_points=1, + n_far_off_adversarial_points=1, + ) + else: + additional_settings = dict( + n_boundary_points=args.n_boundary_points, + n_boundary_adversarial_points=args.n_boundary_points - 1, + n_far_off_boundary_points=1, + n_far_off_adversarial_points=0, + ) + + far_off_distance = 1.75 + + scores_logit_differences_and_validation_accuracies = \ + interior_boundary_discrimination_attack( + feature_extractor, + test_loader, + attack_fn=lambda m, l, attack_kwargs: run_attack(m, l, attack_kwargs), + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=args.epsilon, + norm="linf", + lr=10000, + adversarial_attack_settings=None, + optimizer="sklearn", + n_inner_points=args.n_inner_points, + **additional_settings + ), + n_samples=args.n_samples, + device=device, + batch_size=args.batch_size, + n_samples_evaluation=200, + n_samples_asr_evaluation=200, + + verify_valid_boundary_training_data_fn=verify_valid_input_data, + get_boundary_adversarials_fn=get_boundary_adversarials, + verify_valid_inner_training_data_fn=None, + verify_valid_input_validation_data_fn=None, + fill_batches_for_verification=False, + far_off_distance=far_off_distance + ) + + print(format_result(scores_logit_differences_and_validation_accuracies, + args.n_samples)) + + +if __name__ == "__main__": + main() diff --git a/case_studies/dla/binarization_test.sh b/case_studies/dla/binarization_test.sh new file mode 100644 index 0000000..f81c9a9 --- /dev/null +++ b/case_studies/dla/binarization_test.sh @@ -0,0 +1,94 @@ +n_samples=512 + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Normal test (1 boundary, 999 inner points), normal PGD" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) \ + python case_studies/dla/binarization_test.py \ + --adversarial-attack=pgd \ + --epsilon=0.01 \ + --step-size=0.001 \ + --n-steps=200 \ + --n-inner-points=999 \ + --n-boundary-points=1 \ + --n-samples=$n_samples \ + --batch-size=2048 + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Inverted test (1 boundary, 999 inner points), normal PGD" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) \ + python case_studies/dla/binarization_test.py \ + --adversarial-attack=pgd \ + --epsilon=0.01 \ + --step-size=0.001 \ + --n-steps=200 \ + --n-inner-points=999 \ + --n-boundary-points=1 \ + --n-samples=$n_samples \ + --batch-size=2048 \ + --inverted-test + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Normal test (1 boundary, 999 inner points), joined PGD" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) \ + python case_studies/dla/binarization_test.py \ + --adversarial-attack=joined-pgd \ + --epsilon=0.01 \ + --step-size=0.001 \ + --n-steps=200 \ + --n-inner-points=999 \ + --n-boundary-points=1 \ + --n-samples=$n_samples \ + --batch-size=2048 + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Inverted test (1 boundary, 999 inner points), joined PGD" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) \ + python case_studies/dla/binarization_test.py \ + --adversarial-attack=joined-pgd \ + --epsilon=0.01 \ + --step-size=0.001 \ + --n-steps=200 \ + --n-inner-points=999 \ + --n-boundary-points=1 \ + --n-samples=$n_samples \ + --batch-size=2048 \ + --inverted-test + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Normal test (1 boundary, 999 inner points), selective PGD" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) \ + python case_studies/dla/binarization_test.py \ + --adversarial-attack=selective-pgd \ + --epsilon=0.01 \ + --step-size=0.001 \ + --n-steps=200 \ + --n-inner-points=999 \ + --n-boundary-points=1 \ + --n-samples=$n_samples \ + --batch-size=2048 + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Inverted test (1 boundary, 999 inner points), selective PGD" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) \ + python case_studies/dla/binarization_test.py \ + --adversarial-attack=selective-pgd \ + --epsilon=0.01 \ + --step-size=0.001 \ + --n-steps=200 \ + --n-inner-points=999 \ + --n-boundary-points=1 \ + --n-samples=$n_samples \ + --batch-size=2048 \ + --inverted-test \ No newline at end of file diff --git a/case_studies/dla/cifar.py b/case_studies/dla/cifar.py new file mode 100644 index 0000000..294d151 --- /dev/null +++ b/case_studies/dla/cifar.py @@ -0,0 +1,51 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import numpy as np + + +class CIFAR10: + def __init__(self, seed = 43, tf_mode=False): + if tf_mode: + import tensorflow.compat.v1 as tf + tf.disable_v2_behavior() + tf.compat.v1.disable_eager_execution() + (train_data, train_labels),(self.test_data, self.test_labels) = tf.keras.datasets.cifar10.load_data() + else: + import torchvision + train_dataset = torchvision.datasets.CIFAR10("data", train=True) + test_dataset = torchvision.datasets.CIFAR10("data", train=False) + train_data, train_labels = train_dataset.data, np.array(train_dataset.targets, dtype=int) + self.test_data, self.test_labels = test_dataset.data, np.array(test_dataset.targets, dtype=int) + + train_data = train_data/255. + self.test_data = self.test_data/255. + + VALIDATION_SIZE = 5000 + + np.random.seed(seed) + shuffled_indices = np.arange(len(train_data)) + np.random.shuffle(shuffled_indices) + train_data = train_data[shuffled_indices] + train_labels = train_labels[shuffled_indices] + + shuffled_indices = np.arange(len(self.test_data)) + np.random.shuffle(shuffled_indices) + self.test_data = self.test_data[shuffled_indices] + self.test_labels = self.test_labels[shuffled_indices].flatten() + + self.validation_data = train_data[:VALIDATION_SIZE, :, :, :] + self.validation_labels = train_labels[:VALIDATION_SIZE] + self.train_data = train_data[VALIDATION_SIZE:, :, :, :] + self.train_labels = train_labels[VALIDATION_SIZE:] \ No newline at end of file diff --git a/case_studies/dla/defense.py b/case_studies/dla/defense.py new file mode 100644 index 0000000..1add5e9 --- /dev/null +++ b/case_studies/dla/defense.py @@ -0,0 +1,187 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import torch +import numpy as np + + +class TorchAlarm(torch.nn.Module): + def __init__(self): + super().__init__() + + self.layers = torch.nn.ModuleList([ + torch.nn.Linear(28682, 112), + torch.nn.ReLU(), + torch.nn.Linear(112, 100), + torch.nn.ReLU(), + torch.nn.Linear(100, 300), + torch.nn.ReLU(), + torch.nn.Linear(300, 200), + torch.nn.ReLU(), + torch.nn.Linear(200, 77), + torch.nn.ReLU(), + torch.nn.Linear(77, 1), + ]) + + def __call__(self, x, training=False): + if not isinstance(x, torch.Tensor): + x = torch.tensor(x, dtype=torch.float32) + for layer in self.layers: + x = layer(x) + return x + + +class resnet_layer_torch(torch.nn.Module): + def __init__(self, + prior_filters=16, + num_filters=16, + kernel_size=3, + strides=1): + super().__init__() + self.a = torch.nn.Conv2d(prior_filters, num_filters, kernel_size=kernel_size, padding=1) + self.b = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.c = torch.nn.Conv2d(num_filters, num_filters, kernel_size=kernel_size, padding=1) + self.d = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.layers = [self.a, self.b, self.c, self.d] + def forward(self, inputs): + x1 = self.a(inputs) + x2 = self.b(x1) + x3 = torch.nn.ReLU()(x2) + x4 = self.c(x3) + x5 = self.d(x4) + x6 = x5 + inputs + return x6, x2, x5 + + +class resnet_layer2_torch(torch.nn.Module): + def __init__(self, + prior_filters=16, + num_filters=16, + kernel_size=3, + strides=1): + super().__init__() + self.a = torch.nn.Conv2d(prior_filters, num_filters, kernel_size=kernel_size, padding=0, stride=(2,2)) + self.b = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.c = torch.nn.Conv2d(num_filters, num_filters, kernel_size=kernel_size, padding=1) + self.c2 = torch.nn.Conv2d(prior_filters, num_filters, kernel_size=1, padding=0, stride=(2,2)) + self.d = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.layers = [self.a, self.b, self.c, self.c2, self.d] + + def forward(self, x): + xp = torch.nn.functional.pad(x, (0, 1, 0, 1), "constant", 0) + y = self.a(xp) + y = self.b(y) + y = torch.nn.ReLU()(y) + y = self.c(y) + z = self.c2(x) + y = self.d(y) + x = z+y + return x + + +class TorchModel(torch.nn.Module): + def __init__(self): + super().__init__() + + class Transpose(torch.nn.Module): + def forward(self, x): + return x.permute((0, 2, 3, 1)) + + self.layers = torch.nn.ModuleList([ + torch.nn.Conv2d(3, 16, kernel_size=3, padding=1), + torch.nn.BatchNorm2d(16, eps=.000), + torch.nn.ReLU(), + # AAA + + resnet_layer_torch(16, 16), + torch.nn.ReLU(), + resnet_layer_torch(16, 16), + torch.nn.ReLU(), + resnet_layer_torch(16, 16), + torch.nn.ReLU(), + + + resnet_layer2_torch(16, 32), + torch.nn.ReLU(), + + resnet_layer_torch(32, 32), + torch.nn.ReLU(), + resnet_layer_torch(32, 32), + torch.nn.ReLU(), + + resnet_layer2_torch(32, 64), + torch.nn.ReLU(), + + resnet_layer_torch(64, 64), + torch.nn.ReLU(), + resnet_layer_torch(64, 64), + torch.nn.ReLU(), + + torch.nn.AvgPool2d(8), + # + Transpose(), + torch.nn.Flatten(), + torch.nn.Linear(64, 10), + + + ]) + + def __call__(self, x, training=False): + if not isinstance(x, torch.Tensor): + x = torch.tensor(x, dtype=torch.float32) + extra = [] + for i,layer in enumerate(self.layers): + if isinstance(layer, resnet_layer_torch): + x,y,z = layer(x) + if i == 11: + extra.append(y) + if i == 19: + extra.append(z) + else: + x = layer(x) + if i == 1: + extra.append(x) + + extra = torch.cat([x.permute((0, 2, 3, 1)).reshape((x.shape[0], -1)) for x in extra] + [x], axis=1) + return x, extra + + +class TorchWithDetect: + def __init__(self, model, alarm): + self.model = model + self.alarm = alarm + + def __call__(self, x): + out, hidden = self.model(x) + is_ok = self.alarm(hidden) + return out, is_ok + + +#def load_model(path_model_weights='checkpoints/dla/dla_cifar_classifier.h5', +# path_detector_weights='checkpoints/dla/dla_cifar_detector.h5', device=None): +def load_model(path_model_weights='/home/AUTHOR/dla/dla/cifar_model.h5', + path_detector_weights='/home/AUTHOR/dla/dla/cifar_alarm.h5', device=None): + torch_model = TorchModel() + torch_model.load_state_dict( + torch.load(path_model_weights)) + torch_model.eval().to(device) + + torch_alarm = TorchAlarm() + torch_alarm.load_state_dict( + torch.load(path_detector_weights)) + torch_alarm.eval().to(device) + + return TorchWithDetect(torch_model, torch_alarm), \ + lambda x: torch_model(x)[0], \ + lambda x, how=None: torch_alarm(torch_model(x)[1]).flatten() diff --git a/case_studies/dla/defense_v2.py b/case_studies/dla/defense_v2.py new file mode 100644 index 0000000..fbb10d8 --- /dev/null +++ b/case_studies/dla/defense_v2.py @@ -0,0 +1,257 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import torch + + +class TorchAlarm(torch.nn.Module): + def __init__(self): + super().__init__() + + self.layers = torch.nn.ModuleList([ + torch.nn.Linear(28682, 112), + torch.nn.ReLU(), + torch.nn.Linear(112, 100), + torch.nn.ReLU(), + torch.nn.Linear(100, 300), + torch.nn.ReLU(), + torch.nn.Linear(300, 200), + torch.nn.ReLU(), + torch.nn.Linear(200, 77), + torch.nn.ReLU(), + torch.nn.Linear(77, 1), + ]) + + def __call__(self, x, training=False): + if not isinstance(x, torch.Tensor): + x = torch.tensor(x, dtype=torch.float32) + for layer in self.layers: + x = layer(x) + return x + +class resnet_layer_torch(torch.nn.Module): + def __init__(self, + prior_filters=16, + num_filters=16, + kernel_size=3, + strides=1): + super().__init__() + self.a = torch.nn.Conv2d(prior_filters, num_filters, kernel_size=kernel_size, padding=1) + self.b = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.c = torch.nn.Conv2d(num_filters, num_filters, kernel_size=kernel_size, padding=1) + self.d = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.layers = [self.a, self.b, self.c, self.d] + def forward(self, inputs): + x1 = self.a(inputs) + x2 = self.b(x1) + x3 = torch.nn.ReLU()(x2) + x4 = self.c(x3) + x5 = self.d(x4) + x6 = x5 + inputs + return x6, x2, x5 + + +class resnet_layer2_torch(torch.nn.Module): + def __init__(self, + prior_filters=16, + num_filters=16, + kernel_size=3, + strides=1): + super().__init__() + self.a = torch.nn.Conv2d(prior_filters, num_filters, kernel_size=kernel_size, padding=0, stride=(2,2)) + self.b = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.c = torch.nn.Conv2d(num_filters, num_filters, kernel_size=kernel_size, padding=1) + self.c2 = torch.nn.Conv2d(prior_filters, num_filters, kernel_size=1, padding=0, stride=(2,2)) + self.d = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.layers = [self.a, self.b, self.c, self.c2, self.d] + + def forward(self, x): + xp = torch.nn.functional.pad(x, (0, 1, 0, 1), "constant", 0) + y = self.a(xp) + y = self.b(y) + y = torch.nn.ReLU()(y) + y = self.c(y) + z = self.c2(x) + y = self.d(y) + x = z+y + return x + +class TorchModel(torch.nn.Module): + def __init__(self): + super().__init__() + + class Transpose(torch.nn.Module): + def forward(self, x): + return x.permute((0, 2, 3, 1)) + + self.layers = torch.nn.ModuleList([ + torch.nn.Conv2d(3, 16, kernel_size=3, padding=1), + torch.nn.BatchNorm2d(16, eps=.000), + torch.nn.ReLU(), + # AAA + + resnet_layer_torch(16, 16), + torch.nn.ReLU(), + resnet_layer_torch(16, 16), + torch.nn.ReLU(), + resnet_layer_torch(16, 16), + torch.nn.ReLU(), + + + resnet_layer2_torch(16, 32), + torch.nn.ReLU(), + + resnet_layer_torch(32, 32), + torch.nn.ReLU(), + resnet_layer_torch(32, 32), + torch.nn.ReLU(), + + resnet_layer2_torch(32, 64), + torch.nn.ReLU(), + + resnet_layer_torch(64, 64), + torch.nn.ReLU(), + resnet_layer_torch(64, 64), + torch.nn.ReLU(), + + torch.nn.AvgPool2d(8), + # + Transpose(), + torch.nn.Flatten(), + torch.nn.Linear(64, 10), + + + ]) + + def __call__(self, x, training=False, return_features=False): + if not isinstance(x, torch.Tensor): + x = torch.tensor(x, dtype=torch.float32) + extra = [] + for i,layer in enumerate(self.layers): + if isinstance(layer, resnet_layer_torch): + x,y,z = layer(x) + if i == 11: + extra.append(y) + if i == 19: + extra.append(z) + else: + x = layer(x) + if i == 1: + extra.append(x) + + if isinstance(layer, torch.nn.Flatten): + features = x + + extra = torch.cat([x.permute((0, 2, 3, 1)).reshape((x.shape[0], -1)) for x in extra] + [x], axis=1) + + if return_features: + return x, extra, features + else: + return x, extra + +class TorchModel(torch.nn.Module): + def __init__(self): + super().__init__() + + class Transpose(torch.nn.Module): + def forward(self, x): + return x.permute((0, 2, 3, 1)) + + self.layers = torch.nn.ModuleList([ + torch.nn.Conv2d(3, 32, kernel_size=3, padding=1), + torch.nn.ReLU(), + torch.nn.Conv2d(32, 32, kernel_size=3), + torch.nn.ReLU(), + torch.nn.MaxPool2d(2, 2), + torch.nn.Conv2d(32, 64, kernel_size=3, padding=1), + torch.nn.ReLU(), + torch.nn.Conv2d(64, 64, kernel_size=3), + torch.nn.ReLU(), + torch.nn.MaxPool2d(2, 2), + Transpose(), + torch.nn.Flatten(), + torch.nn.Linear(2304, 512), + torch.nn.ReLU(), + torch.nn.Linear(512, 10)]) + + + def __call__(self, x, training=False, return_features=False): + if not isinstance(x, torch.Tensor): + x = torch.tensor(x, dtype=torch.float32) + + for i,layer in enumerate(self.layers): + #print('l',layer) + #print('x',x.shape) + x = layer(x) + if i == 13: + #print("Have", x) + sav = x + + if isinstance(layer, torch.nn.Flatten): + features = x + #print('aaa', sav) + if return_features: + return x, torch.cat([sav, x], axis=1), features + else: + return x, torch.cat([sav, x], axis=1) + + +class TorchAlarm(torch.nn.Module): + def __init__(self): + super().__init__() + + self.layers = torch.nn.ModuleList([ + torch.nn.Linear(522, 100), + torch.nn.SELU(), + torch.nn.Linear(100, 50), + torch.nn.SELU(), + torch.nn.Linear(50, 10), + torch.nn.SELU(), + torch.nn.Linear(10, 1) + ]) + + def __call__(self, x, training=False): + if not isinstance(x, torch.Tensor): + x = torch.tensor(x, dtype=torch.float32) + for layer in self.layers: + x = layer(x) + return x + + +class TorchWithDetect: + def __init__(self, model, alarm): + self.model = model + self.alarm = alarm + + def __call__(self, x): + out, hidden = self.model(x) + is_ok = self.alarm(hidden) + return out, is_ok + + +def load_model(path_model_weights='checkpoints/dla/dla_cifar_classifier_v2.h5', + path_detector_weights='checkpoints/dla/dla_cifar_detector_v2.h5', device=None): + torch_model = TorchModel() + torch_model.load_state_dict( + torch.load(path_model_weights)) + torch_model.eval().to(device) + + torch_alarm = TorchAlarm() + torch_alarm.load_state_dict( + torch.load(path_detector_weights)) + torch_alarm.eval().to(device) + + return TorchWithDetect(torch_model, torch_alarm), \ + lambda x: torch_model(x)[0], \ + lambda x, how=None: torch_alarm(torch_model(x)[1]).flatten() \ No newline at end of file diff --git a/case_studies/dla/defense_v3.py b/case_studies/dla/defense_v3.py new file mode 100644 index 0000000..e68f0e1 --- /dev/null +++ b/case_studies/dla/defense_v3.py @@ -0,0 +1,263 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import torch + + +class TorchResnetAlarm(torch.nn.Module): + def __init__(self): + super().__init__() + + self.layers = torch.nn.ModuleList([ + torch.nn.Linear(28682, 112), + torch.nn.ReLU(), + torch.nn.Linear(112, 100), + torch.nn.ReLU(), + torch.nn.Linear(100, 300), + torch.nn.ReLU(), + torch.nn.Linear(300, 200), + torch.nn.ReLU(), + torch.nn.Linear(200, 77), + torch.nn.ReLU(), + torch.nn.Linear(77, 1), + ]) + + def __call__(self, x, training=False): + if not isinstance(x, torch.Tensor): + x = torch.tensor(x, dtype=torch.float32) + for layer in self.layers: + x = layer(x) + return x + +class resnet_layer_torch(torch.nn.Module): + def __init__(self, + prior_filters=16, + num_filters=16, + kernel_size=3, + strides=1): + super().__init__() + self.a = torch.nn.Conv2d(prior_filters, num_filters, kernel_size=kernel_size, padding=1) + self.b = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.c = torch.nn.Conv2d(num_filters, num_filters, kernel_size=kernel_size, padding=1) + self.d = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.layers = [self.a, self.b, self.c, self.d] + def forward(self, inputs): + x1 = self.a(inputs) + x2 = self.b(x1) + x3 = torch.nn.ReLU()(x2) + x4 = self.c(x3) + x5 = self.d(x4) + x6 = x5 + inputs + return x6, x2, x5 + + +class resnet_layer2_torch(torch.nn.Module): + def __init__(self, + prior_filters=16, + num_filters=16, + kernel_size=3, + strides=1): + super().__init__() + self.a = torch.nn.Conv2d(prior_filters, num_filters, kernel_size=kernel_size, padding=0, stride=(2,2)) + self.b = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.c = torch.nn.Conv2d(num_filters, num_filters, kernel_size=kernel_size, padding=1) + self.c2 = torch.nn.Conv2d(prior_filters, num_filters, kernel_size=1, padding=0, stride=(2,2)) + self.d = torch.nn.BatchNorm2d(num_filters, eps=.000) + self.layers = [self.a, self.b, self.c, self.c2, self.d] + + def forward(self, x): + xp = torch.nn.functional.pad(x, (0, 1, 0, 1), "constant", 0) + y = self.a(xp) + y = self.b(y) + y = torch.nn.ReLU()(y) + y = self.c(y) + z = self.c2(x) + y = self.d(y) + x = z+y + return x + +class TorchResnetModel(torch.nn.Module): + def __init__(self): + super().__init__() + + class Transpose(torch.nn.Module): + def forward(self, x): + return x.permute((0, 2, 3, 1)) + + self.layers = torch.nn.ModuleList([ + torch.nn.Conv2d(3, 16, kernel_size=3, padding=1), + torch.nn.BatchNorm2d(16, eps=.000), + torch.nn.ReLU(), + # AAA + + resnet_layer_torch(16, 16), + torch.nn.ReLU(), + resnet_layer_torch(16, 16), + torch.nn.ReLU(), + resnet_layer_torch(16, 16), + torch.nn.ReLU(), + + + resnet_layer2_torch(16, 32), + torch.nn.ReLU(), + + resnet_layer_torch(32, 32), + torch.nn.ReLU(), + resnet_layer_torch(32, 32), + torch.nn.ReLU(), + + resnet_layer2_torch(32, 64), + torch.nn.ReLU(), + + resnet_layer_torch(64, 64), + torch.nn.ReLU(), + resnet_layer_torch(64, 64), + torch.nn.ReLU(), + + torch.nn.AvgPool2d(8), + # + Transpose(), + torch.nn.Flatten(), + torch.nn.Linear(64, 10), + + + ]) + + def __call__(self, x, training=False, return_features=False): + if not isinstance(x, torch.Tensor): + x = torch.tensor(x, dtype=torch.float32) + extra = [] + for i,layer in enumerate(self.layers): + if isinstance(layer, resnet_layer_torch): + x,y,z = layer(x) + if i == 11: + extra.append(y) + if i == 19: + extra.append(z) + else: + x = layer(x) + if i == 1: + extra.append(x) + + if isinstance(layer, torch.nn.Flatten): + features = x + + extra = torch.cat([x.permute((0, 2, 3, 1)).reshape((x.shape[0], -1)) for x in extra] + [x], axis=1) + + if return_features: + return x, extra, features + else: + return x, extra + +class TorchModel(torch.nn.Module): + def __init__(self): + super().__init__() + + class Transpose(torch.nn.Module): + def forward(self, x): + return x.permute((0, 2, 3, 1)) + + self.layers = torch.nn.ModuleList([ + torch.nn.Conv2d(3, 32, kernel_size=3, padding=1), + torch.nn.ReLU(), + torch.nn.Conv2d(32, 32, kernel_size=3), + torch.nn.ReLU(), + torch.nn.MaxPool2d(2, 2), + torch.nn.Conv2d(32, 64, kernel_size=3, padding=1), + torch.nn.ReLU(), + torch.nn.Conv2d(64, 64, kernel_size=3), + torch.nn.ReLU(), + torch.nn.MaxPool2d(2, 2), + Transpose(), + torch.nn.Flatten(), + torch.nn.Linear(2304, 512), + torch.nn.ReLU(), + torch.nn.Linear(512, 10)]) + + + def __call__(self, x, training=False, return_features=False): + if not isinstance(x, torch.Tensor): + x = torch.tensor(x, dtype=torch.float32) + + for i,layer in enumerate(self.layers): + #print('l',layer) + #print('x',x.shape) + x = layer(x) + if i == 13: + #print("Have", x) + sav = x + + if isinstance(layer, torch.nn.Flatten): + features = x + #print('aaa', sav) + if return_features: + return x, torch.cat([sav, x], axis=1), features + else: + return x, torch.cat([sav, x], axis=1) + + +class TorchAlarm(torch.nn.Module): + def __init__(self): + super().__init__() + + self.layers = torch.nn.ModuleList([ + torch.nn.Linear(522, 100), + # modification by AUTHOR + #torch.nn.SELU(), + torch.nn.Linear(100, 50), + # modification by AUTHOR + #torch.nn.SELU(), + torch.nn.Linear(50, 10), + # modification by AUTHOR + #torch.nn.SELU(), + torch.nn.Linear(10, 1) + ]) + + def __call__(self, x, training=False): + if not isinstance(x, torch.Tensor): + x = torch.tensor(x, dtype=torch.float32) + for i, layer in enumerate(self.layers): + x = layer(x) + # modification by AUTHOR + if i != len(self.layers) - 1: + x = torch.relu(x) + return x + + +class TorchWithDetect: + def __init__(self, model, alarm): + self.model = model + self.alarm = alarm + + def __call__(self, x): + out, hidden = self.model(x) + is_ok = self.alarm(hidden) + return out, is_ok + + +def load_model(path_model_weights='/home/AUTHOR/dla/more_dla/CIFAR10_keras_cnn.torchmodel', + path_detector_weights='/home/AUTHOR/dla/more_dla/CIFAR10_keras_cnn_LinfPGD_alarm_DLA.torchmodel', device=None): + torch_model = TorchModel() + torch_model.load_state_dict( + torch.load(path_model_weights)) + torch_model.eval().to(device) + + torch_alarm = TorchAlarm() + torch_alarm.load_state_dict( + torch.load(path_detector_weights)) + torch_alarm.eval().to(device) + + return TorchWithDetect(torch_model, torch_alarm), \ + lambda x: torch_model(x)[0], \ + lambda x, how=None: torch_alarm(torch_model(x)[1]).flatten() \ No newline at end of file diff --git a/case_studies/dla/dla.py b/case_studies/dla/dla.py new file mode 100644 index 0000000..5ae8036 --- /dev/null +++ b/case_studies/dla/dla.py @@ -0,0 +1,39 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import torch +import defense + + +if __name__ == '__main__': + device = "cuda" + classifier_and_detector, classifier, detector = defense.load_model(device=device) + data = defense.CIFAR10(seed=43) + + # ### PGD + num_images = 2000 + + images = torch.tensor(data.test_data[:num_images].transpose((0, 3, 1, 2)), dtype=torch.float32, requires_grad=False) + targets = torch.tensor(data.test_labels[:num_images], dtype=torch.int64) + + outs, is_ok = classifier_and_detector(images.to(device)) + outs = outs.cpu() + is_ok = is_ok.cpu() + import pdb; pdb.set_trace() + + correct = data.test_labels[:num_images] == outs.argmax(1).detach().numpy() + is_ok = is_ok.detach().numpy() + print('acc', correct.mean()) + print('fraction bad', (is_ok > 0).mean()) + print("successful attacks", ((~correct) & (is_ok < 0)).mean()) diff --git a/case_studies/dla/pgd_attack.py b/case_studies/dla/pgd_attack.py new file mode 100644 index 0000000..1945b95 --- /dev/null +++ b/case_studies/dla/pgd_attack.py @@ -0,0 +1,69 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import torch +import torch.nn.functional as F +import attacks.pgd + + +def attack(x_batch, y_batch, classifier, classifier_and_detector, + adversarial_attack, n_steps, step_size, epsilon): + if adversarial_attack == "pgd": + loss_fn = lambda x, y: -F.cross_entropy(classifier(x), y) + def is_adversarial_fn(x, y): + with torch.no_grad(): + return classifier(x).argmax(-1) != y + + elif adversarial_attack == "joined-pgd": + def loss_fn(x, y): + l, k = classifier_and_detector(x) + return -F.cross_entropy(l, y) - F.binary_cross_entropy_with_logits( + k, torch.ones_like(k)) + + def is_adversarial_fn(x, y): + with torch.no_grad(): + l, k = classifier_and_detector(x) + yc = l.argmax(1) != y + yd = k < 0 + return torch.logical_and(yc, yd) + + elif adversarial_attack == "selective-pgd": + def loss_fn(x, y): + l, k = classifier_and_detector(x) + mc = (l.argmax(1) == y).float().detach() + md = (k > 0).float().detach() + + return -torch.mean( + mc * F.cross_entropy(l, y, reduction="none") + + md * F.binary_cross_entropy_with_logits( + k, torch.ones_like(k), reduction="none") + ) + + def is_adversarial_fn(x, y): + with torch.no_grad(): + l, k = classifier_and_detector(x) + yc = l.argmax(1) != y + yd = k < 0 + return torch.logical_and(yc, yd) + + elif adversarial_attack == "orthogonal-pgd": + raise ValueError("not implemented") + + x_batch = attacks.pgd.general_pgd(loss_fn, is_adversarial_fn, + x_batch, y_batch, n_steps, + step_size, epsilon, "linf", + early_stopping=True, + random_start=False + )[0] + return x_batch diff --git a/case_studies/empir/README.md b/case_studies/empir/README.md new file mode 100644 index 0000000..bf82ea7 --- /dev/null +++ b/case_studies/empir/README.md @@ -0,0 +1,145 @@ +# EMPIR: Ensembles of Mixed Precision Deep Networks for Increased Robustness against Adversarial Attacks +[![Build Status](https://travis-ci.org/tensorflow/cleverhans.svg?branch=master)](https://travis-ci.org/tensorflow/cleverhans) + +This repository contains the source code for the paper EMPIR: Ensembles of Mixed Precision Deep Networks for Increased Robustness against Adversarial Attacks ([Accepted at ICLR 2020](https://openreview.net/forum?id=HJem3yHKwH)) + +It is based on [CleverHans](https://github.com/tensorflow/cleverhans) 1.0.0, a Python library to +benchmark machine learning systems' vulnerability to +[adversarial examples](http://karpathy.github.io/2015/03/30/breaking-convnets/). +You can learn more about such vulnerabilities on the accompanying [blog](http://cleverhans.io). + +## Setting up ++ Install [TensorFlow](https://www.tensorflow.org/) ++ Install [Keras](https://keras.io/) ++ Git clone this repository ++ For ImageNet results, download ImageNet dataset and convert the data into `TFRecords` using [this](https://github.com/tensorflow/tpu/blob/master/tools/datasets/imagenet_to_gcs.py) script. + +We tested this setup using tensorflow-gpu 1.10, keras 2.2.4, python 3.5, CUDA 9.2 and Ubuntu 18.04 on a single RTX 2080 Ti GPU. Tensorflow was installed using [anaconda](https://www.anaconda.com/). + +## Example commands ++ `python examples/mnist_attack.py --wbits=$model1_weight_prec --abits=$model1_activation_prec --wbits2=$model2_weight_prec --abits2=$model2_activation_prec --ensembleThree --model_path1=/path/to/model1/ckpt --model_path2=/path/to/model2/ckpt --model_path3=/path/to/model3/ckpt` - White-Box CW attack on MNISTconv EMPIR model ++ `python examples/mnist_attack.py --model_path=/path/to/baseline/model/ckpt` - White-Box CW attack on MNISTconv baseline model ++ `python examples/cifar10_attack.py --abits=$model1_activation_prec --wbits=$model1_weight_prec --abits2=$model2_activation_prec --wbits2=$model2_weight_prec --model_path1=/path/to/model1/ckpt --model_path2=/path/to/model2/ckpt --model_path3=/path/to/model3/ckpt --ensembleThree` - White-Box CW attack on CIFARconv EMPIR model ++ `python examples/cifar10_attack.py --model_path=/path/to/baseline/model/ckpt` - White-Box CW attack on CIFARconv baseline model ++ `python examples/alexnet_attack.py --batch_size=100 --imagenet_path=/path/to/imagenet/tf_records --ensembleThree --abits=$model1_activation_prec --wbits=$model1_weight_prec --abits2=$model2_activation_prec --wbits2=$model2_weight_prec --model_path1=/path/to/model1/ckpt --model_path2=/path/to/model2/ckpt --model_path3=/path/to/model3/ckpt` - White-Box CW attack on AlexNet EMPIR model ++ `python examples/alexnet_attack.py --batch_size=100 --imagenet_path=/path/to/imagenet/tf_records --model_path=/path/to/baseline/model/ckpt` - White-Box CW attack on AlexNet baseline model + +## Results ++ EMPIR models + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DatasetPrecisionsUnperturbed Accuracy (%)Adversarial Accuracy (%)
Model 1Model 2Model 3CWFGSMBIMPGDAverage
MNIST abits=4, wbits=2 Download abits=4, wbits=2 Download Full-precision (32 bits) Download 98.89 86.73 67.06 18.61 17.51 47.48
CIFAR-10 abits=2, wbits=4 Download abits=2, wbits=2 Download Full-precision (32 bits) Download 72.56 48.51 20.45 24.59 13.55 26.78
ImageNet abits=2, wbits=2 Download abits=4, wbits=4 Download Full-precision (32 bits) Download 55.09 29.36 21.65 20.67 11.76 20.86
+ ++ Baseline models + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DatasetModelsUnperturbed Accuracy (%)Adversarial Accuracy (%)
CWFGSMBIMPGDAverage
MNIST MNISTconv Download 98.87 3.69 14.32 0.9 0.77 4.92
CIFAR-10 CIFARconv Download 74.54 13.38 10.28 11.97 10.69 11.58
ImageNet AlexNet Download 53.23 9.94 10.29 10.81 10.30 10.34
+ +## Citing this work + +``` +@inproceedings{ +sen2020empir, +title={{\{}EMPIR{\}}: Ensembles of Mixed Precision Deep Networks for Increased Robustness Against Adversarial Attacks}, +author={Sanchari Sen and Balaraman Ravindran and Anand Raghunathan}, +booktitle={International Conference on Learning Representations}, +year={2020}, +url={https://openreview.net/forum?id=HJem3yHKwH} +} +``` +## Copyright + +Copyright 2017 - Google Inc., OpenAI and Pennsylvania State University. diff --git a/case_studies/empir/cleverhans_tutorials/__init__.py b/case_studies/empir/cleverhans_tutorials/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/case_studies/empir/cleverhans_tutorials/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/case_studies/empir/cleverhans_tutorials/tutorial_models.py b/case_studies/empir/cleverhans_tutorials/tutorial_models.py new file mode 100644 index 0000000..26283ad --- /dev/null +++ b/case_studies/empir/cleverhans_tutorials/tutorial_models.py @@ -0,0 +1,1984 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +A pure TensorFlow implementation of a neural network. This can be +used as a drop-in replacement for a Keras model. +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import numpy as np +import tensorflow as tf +from modified_cleverhans.model import Model + +BN_EPSILON = 1e-5 + +## For alexnet's local response normalization +RADIUS = 2; ALPHA = 2E-05; BETA = 0.75; BIAS = 1.0 # values copied from myalexnet_forward_newtf.py + +@tf.RegisterGradient("QuantizeGrad") +def quantize_grad(op, grad): + return tf.clip_by_value(tf.identity(grad), -1, 1) + + +def hard_sigmoid(x): + return tf.cast(tf.clip_by_value((x + 1.) / 2., 0., 1.), tf.float32) + + +class MLP(Model): + """ + An example of a bare bones multilayer perceptron (MLP) class. + """ + + def __init__(self, layers, input_shape): + super(MLP, self).__init__() + + self.layer_names = [] + self.layers = layers + self.input_shape = input_shape + if isinstance(layers[-1], Softmax): + layers[-1].name = 'probs' + layers[-2].name = 'logits' + else: + layers[-1].name = 'logits' + for i, layer in enumerate(self.layers): + if hasattr(layer, 'name'): + name = layer.name + else: + name = layer.__class__.__name__ + str(i) + self.layer_names.append(name) + + layer.set_input_shape(input_shape, False) + input_shape = layer.get_output_shape() + print(self.layer_names) + + def fprop(self, x, reuse, set_ref=False): + states = [] + for layer in self.layers: + if set_ref: + layer.ref = x + x = layer.fprop(x, reuse) + assert x is not None + states.append(x) + states = dict(zip(self.get_layer_names(), states)) + return states + +# special distilled model class consisting of a teacher and a student model +class distilledModel(Model): + """ + An example of a bare bones multilayer perceptron (MLP) class. + """ + + def __init__(self, teacher_layers, student_layers, input_shape): + super(distilledModel, self).__init__() + + self.layer_names = [] + self.teacher_layers = teacher_layers + self.student_layers = student_layers + self.input_shape = input_shape + original_input_shape = input_shape + if isinstance(teacher_layers[-1], Softmax): + teacher_layers[-1].name = 'teacher_probs' + teacher_layers[-2].name = 'teacher_logits' + else: + layers[-1].name = 'teacher_logits' + for i, layer in enumerate(self.teacher_layers): + if hasattr(layer, 'name'): + name = layer.name + else: + name = layer.__class__.__name__ + str(i) + self.layer_names.append(name) + + layer.set_input_shape(input_shape, False) + input_shape = layer.get_output_shape() + + input_shape = original_input_shape + if isinstance(student_layers[-1], Softmax): + student_layers[-1].name = 'probs' + student_layers[-2].name = 'logits' + else: + student_layers[-1].name = 'logits' + for i, layer in enumerate(self.student_layers): + if hasattr(layer, 'name'): + name = layer.name + else: + name = layer.__class__.__name__ + str(i) + self.layer_names.append(name) + + layer.set_input_shape(input_shape, False) + input_shape = layer.get_output_shape() + + print(self.layer_names) + + def fprop(self, x, reuse, set_ref=False): + states = [] + original_x = x + for layer in self.teacher_layers: + if set_ref: + layer.ref = x + x = layer.fprop(x, reuse) + assert x is not None + states.append(x) + x = original_x + num_student_layers = len(self.student_layers) + layer_count = 0 + for layer in self.student_layers: + if set_ref: + layer.ref = x + x = layer.fprop(x, reuse) + assert x is not None + states.append(x) + layer_count = layer_count + 1 + states = dict(zip(self.get_layer_names(), states)) + return states + +# ensembleThreeModel class build on Model class that forms ensemble of three models +class ensembleThreeModel(Model): + """ + An example ensemble model. + """ + + def __init__(self, layers1, layers2, layers3, input_shape, num_classes): #layers1: layers of model1, layers2: layers of model2 + super(ensembleThreeModel, self).__init__() + + self.layer_names = [] + self.layers1 = layers1 + self.layers2 = layers2 + self.layers3 = layers3 + self.input_shape = input_shape + self.num_classes = num_classes + original_input_shape = input_shape + if isinstance(layers1[-1], Softmax): + layers1[-1].name = 'probs' + layers1[-2].name = 'logits' + else: + layers1[-1].name = 'logits' + # First model + for i, layer in enumerate(self.layers1): + if hasattr(layer, 'name'): + if layer.name == 'probs' or layer.name == 'logits': + name = layer.name + else: + name = 'Model1_' + layer.name + else: + name = 'Model1_' + layer.__class__.__name__ + str(i) + self.layer_names.append(name) + + layer.set_input_shape(input_shape, False) + input_shape = layer.get_output_shape() + + input_shape = original_input_shape + # Second model + if isinstance(layers2[-1], Softmax): + layers2[-1].name = 'probs' + layers2[-2].name = 'logits' + else: + layers2[-1].name = 'logits' + for i, layer in enumerate(self.layers2): + if hasattr(layer, 'name'): + if layer.name == 'probs' or layer.name == 'logits': + name = layer.name + else: + name = 'Model2_' + layer.name + else: + name = 'Model2_' + layer.__class__.__name__ + str(i) + self.layer_names.append(name) + + layer.set_input_shape(input_shape, False) + input_shape = layer.get_output_shape() + input_shape = original_input_shape + # Third model + if isinstance(layers3[-1], Softmax): + layers3[-1].name = 'probs' + layers3[-2].name = 'logits' + else: + layers3[-1].name = 'logits' + for i, layer in enumerate(self.layers3): + if hasattr(layer, 'name'): + if layer.name == 'probs' or layer.name == 'logits': + name = layer.name + else: + name = 'Model3_' + layer.name + else: + name = 'Model3_' + layer.__class__.__name__ + str(i) + self.layer_names.append(name) + + layer.set_input_shape(input_shape, False) + input_shape = layer.get_output_shape() + self.layer_names.append('combined_features') + self.layer_names.append('combined_logits') + + combined_layer_name = 'combined' ## Gives the final class prediction based on max voting + self.layer_names.append(combined_layer_name) + combinedCorrectProb_layer_name = 'combinedAvgCorrectProb' ## Gives average probability values of the models that decided the final prediction + self.layer_names.append(combinedCorrectProb_layer_name) + combinedProb_layer_name = 'combinedAvgProb' ## Gives average probability values of all the models + self.layer_names.append(combinedProb_layer_name) + + print(self.layer_names) + + def fprop(self, x, reuse, set_ref=False): + states = [] + original_x = x + for layer in self.layers1: + if set_ref: + layer.ref = x + x = layer.fprop(x, reuse) + assert x is not None + states.append(x) + + output1 = states[-1] + features1 = states[-3] + x = original_x + for layer in self.layers2: + if set_ref: + layer.ref = x + x = layer.fprop(x, reuse) + assert x is not None + states.append(x) + + features2 = states[-3] + output2 = states[-1] + x = original_x + for layer in self.layers3: + if set_ref: + layer.ref = x + x = layer.fprop(x, reuse) + assert x is not None + states.append(x) + output3 = states[-1] + features3 = states[-3] + + states.append(tf.stack((features1, features2, features3), 1)) + states.append(tf.stack((output1, output2, output3), 1)) + + # Find class predictions with each model + pred1 = tf.argmax(output1, axis=-1) + pred2 = tf.argmax(output2, axis=-1) + pred3 = tf.argmax(output3, axis=-1) + comb_pred = tf.stack([pred1, pred2, pred3], axis=1) + comb_pred = tf.cast(comb_pred, dtype=tf.int32) # converting to int32 as bincount requires int32 + + # Find how many times each of the classes are predicted among the three models and identify the max class + initial_imidx = 1 + + binarray = tf.bincount(comb_pred[0], minlength=self.num_classes)# initial bincount, counts number of occurences of each integer from 0 to 10 for the 1d array, returns a 1d array + max_class = tf.argmax(binarray, axis=-1) + count_max = tf.gather(binarray, max_class) # max vote count for a class + rand_idx = np.random.random_integers(3) + value = tf.cond(tf.less(count_max, 2), lambda: pred3[0], lambda: max_class) + in_class_array = tf.fill([1], value) + + ## Added below to allow better gradient calculation for max voted model + in_avgCorrectprob = tf.cond(tf.equal(value, pred3[0]), lambda: output3[0], lambda: tf.zeros_like(output3[0])) # add pred3 if it affected the final decision + in_avgCorrectprob = tf.cond(tf.equal(value, pred2[0]), lambda: tf.add(output2[0], in_avgCorrectprob), lambda: in_avgCorrectprob) # add pred2 if it affected the final decision + in_avgCorrectprob = tf.cond(tf.equal(value, pred1[0]), lambda: tf.add(output1[0], in_avgCorrectprob), lambda: in_avgCorrectprob) # add pred2 if it affected the final decision + in_avgCorrectprob_array = tf.expand_dims(tf.div(in_avgCorrectprob, tf.cast(count_max, dtype=tf.float32)), 0) + + #condition check: when true the loop body executes + def idx_loop_condition(class_array, avgCorrectprob_array, im_idx): + return tf.less(im_idx, tf.shape(pred1)[0]) + + #loop body to calculate the max voted class for each image + def idx_loop_body(class_array, avgCorrectprob_array, im_idx): + binarray_new = tf.bincount(comb_pred[im_idx], minlength=self.num_classes) # counts number of occurences of each integer from 0 to 10 for the 1d array, returns a 1d array + max_class = tf.argmax(binarray_new, axis=-1) + count_max = tf.gather(binarray_new, max_class) # max vote count for a class + rand_idx = np.random.random_integers(3) + value = tf.cond(tf.less(count_max, 2), lambda: pred3[im_idx], lambda: max_class)# If the max vote is less than 2, take the prediction of the full precision model + new_array = tf.fill([1], value) + class_array = tf.concat([class_array, new_array], 0) + + ## Added below to allow better gradient calculation for max voted model + avgCorrectprob = tf.cond(tf.equal(value, pred3[im_idx]), lambda: output3[im_idx], lambda: tf.zeros_like(output3[im_idx])) # add pred3 if it affected the final decision + avgCorrectprob = tf.cond(tf.equal(value, pred2[im_idx]), lambda: tf.add(output2[im_idx], avgCorrectprob), lambda: avgCorrectprob) # add pred2 if it affected the final decision + avgCorrectprob = tf.cond(tf.equal(value, pred1[im_idx]), lambda: tf.add(output1[im_idx], avgCorrectprob), lambda: avgCorrectprob) # add pred2 if it affected the final decision + avgCorrectprob = tf.expand_dims(tf.div(avgCorrectprob, tf.cast(count_max, dtype=tf.float32)), 0) + avgCorrectprob_array = tf.concat([avgCorrectprob_array, avgCorrectprob], 0) + + return (class_array, avgCorrectprob_array, im_idx+1) + + res = tf.while_loop( + cond=idx_loop_condition, + body=idx_loop_body, + loop_vars=[in_class_array, in_avgCorrectprob_array, initial_imidx], + shape_invariants=[tf.TensorShape([None]), tf.TensorShape([None, self.num_classes]), tf.TensorShape([])], #add shape invariant saying that the first dimension of in_class_array changes and is thus None + ) + pred_output = tf.cast(res[0], dtype=tf.int64) # no. of times each class is predicted for all images + + states.append(pred_output) + + avgCorrectprob_output = res[1] # no. of times each class is predicted for all images + + states.append(avgCorrectprob_output) + + avgprob = tf.div(tf.add_n([output2, output1, output3]), tf.cast(3, dtype=tf.float32)) # Average probability across all models + + states.append(avgprob) + + states = dict(zip(self.get_layer_names(), states)) + + return states + +class Layer(object): + + def get_output_shape(self): + return self.output_shape + + +class SimpleLinear(Layer): + + def __init__(self, num_hid): + self.num_hid = num_hid + + def set_input_shape(self, input_shape, reuse): + batch_size, dim = input_shape + self.input_shape = [batch_size, dim] + self.output_shape = [batch_size, self.num_hid] + init = tf.random_normal([dim, self.num_hid], dtype=tf.float32) + init = init / tf.sqrt(1e-7 + tf.reduce_sum(tf.square(init), axis=0, + keep_dims=True)) + self.W = tf.Variable(init) + self.b = tf.Variable(np.zeros((self.num_hid,)).astype('float32')) + + def fprop(self, x, reuse): + return tf.matmul(x, self.W) + self.b + + +class Linear(Layer): + + def __init__(self, num_hid, detail, useBias=False): + self.__dict__.update(locals()) + # self.num_hid = num_hid + + def set_input_shape(self, input_shape, reuse): + + # with tf.variable_scope(self.scope_name+ 'init', reuse): # this works + # with black box, but now can't load checkpoints from wb + # this works with white-box + with tf.variable_scope(self.detail + self.name + '_init', reuse): + + batch_size, dim = input_shape + self.input_shape = [batch_size, dim] + self.output_shape = [batch_size, self.num_hid] + if self.useBias: + self.bias_shape = self.num_hid + init = tf.random_normal([dim, self.num_hid], dtype=tf.float32) + init = init / tf.sqrt(1e-7 + tf.reduce_sum(tf.square(init), axis=0, + keep_dims=True)) + self.W = tf.get_variable( + "W", initializer=init) + W_summ = tf.summary.histogram('W', values=self.W) + if self.useBias: + bias_init = tf.zeros(self.bias_shape) + self.bias =tf.get_variable("b", initializer= bias_init) + + def fprop(self, x, reuse): + + # with tf.variable_scope(self.scope_name + '_fprop', reuse): + # this works with white-box + with tf.variable_scope(self.detail + self.name + '_fprop', reuse): + + x = tf.matmul(x, self.W) # + self.b + if self.useBias: + x = tf.nn.bias_add(tf.contrib.layers.flatten(x), tf.reshape(self.bias, [-1])) + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + +class HiddenLinear(Layer): + + def __init__(self, num_hid, scope_name, useBias=False): + self.__dict__.update(locals()) + + def set_input_shape(self, input_shape, reuse): + + with tf.variable_scope(self.scope_name+ 'init', reuse): + + batch_size, dim = input_shape + self.input_shape = [batch_size, dim] + self.output_shape = [batch_size, self.num_hid] + + if self.useBias: + self.bias_shape = self.num_hid + + init = tf.random_normal([dim, self.num_hid], dtype=tf.float32) + init = init / tf.sqrt(1e-7 + tf.reduce_sum(tf.square(init), axis=0, + keep_dims=True)) + self.W = tf.get_variable( + "W", initializer=init) + + if self.useBias: + bias_init = tf.zeros(self.bias_shape) + self.bias =tf.get_variable("b", initializer= bias_init) + + W_summ = tf.summary.histogram('W', values=self.W) + + def fprop(self, x, reuse): + + with tf.variable_scope(self.scope_name + '_fprop', reuse): + + x = tf.matmul(x, self.W) + if self.useBias: + x = tf.nn.bias_add(tf.contrib.layers.flatten(x), tf.reshape(self.bias, [-1])) + + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + +class HiddenLinear_lowprecision(Layer): + + # def __init__(self, num_hid, scope_name): + def __init__(self, wbits, abits, num_hid, scope_name, useBias=False): + self.__dict__.update(locals()) + + def quantize(self, x, k): ## k= No. of quantized bits + n = float(2**k-1) ## Max value representable with k bits + + @tf.custom_gradient ## Can be used to define a custom gradient function + def _quantize(x): + return tf.round(x*n)/n, lambda dy: dy # Second part is the function evaluated during gradient, identity function + + return _quantize(x) + + def quantizeWt(self, x): + x = tf.tanh(x) ## Normalizing weights to [-1, 1] + x = x/tf.reduce_max(abs(x))*0.5 + 0.5 ## Normalizing weights to [0, 1] + return 2*self.quantize(x, self.wbits) - 1 ## Normalizing back to [0, 1] after quantizing + + def quantizeAct(self, x): + x = tf.clip_by_value(x, 0, 1.0) ## Normalizing activations to [0, 1] --> performed in nonlin(x) function of alexnet-dorefa.py + return self.quantize(x, self.abits) + + def set_input_shape(self, input_shape, reuse): + + with tf.variable_scope(self.scope_name+ 'init', reuse): # this works + # with black box, but now can't load checkpoints from wb + # this works with white-box + # with tf.variable_scope(self.detail + self.name + '_init', reuse): + + batch_size, dim = input_shape + self.input_shape = [batch_size, dim] + self.output_shape = [batch_size, self.num_hid] + + if self.useBias: + self.bias_shape = self.num_hid + init = tf.random_normal([dim, self.num_hid], dtype=tf.float32) + init = init / tf.sqrt(1e-7 + tf.reduce_sum(tf.square(init), axis=0, + keep_dims=True)) + self.W = tf.get_variable( + "W", initializer=init) + + if (self.wbits < 32): + self.W = self.quantizeWt(self.W) + + if self.useBias: + bias_init = tf.zeros(self.bias_shape) + self.bias =tf.get_variable("b", initializer= bias_init) + + W_summ = tf.summary.histogram('W', values=self.W) + + def fprop(self, x, reuse): + + with tf.variable_scope(self.scope_name + '_fprop', reuse): + # this works with white-box + # with tf.variable_scope(self.detail + self.name + '_fprop', reuse): + if self.abits < 32: + x = self.quantizeAct(x) + + x = tf.matmul(x, self.W) # + self.b + if self.useBias: + x = tf.nn.bias_add(tf.contrib.layers.flatten(x), tf.reshape(self.bias, [-1])) + + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + +class Conv2DRand(Layer): + + def __init__(self, output_channels, kernel_shape, strides, padding, phase, scope_name): + self.__dict__.update(locals()) + self.G = tf.get_default_graph() + del self.self + + def quantize_rand(self, x, dist): + with self.G.gradient_override_map({"Sign": "QuantizeGrad"}): + return 2 * dist(probs=hard_sigmoid(x)).sample() - 1 + + def quantize(self, x): + with self.G.gradient_override_map({"Sign": "QuantizeGrad"}): + return tf.sign(x) + + def set_input_shape(self, input_shape, reuse): + + batch_size, rows, cols, input_channels = input_shape + kernel_shape = tuple(self.kernel_shape) + (input_channels, + self.output_channels) + assert len(kernel_shape) == 4 + assert all(isinstance(e, int) for e in kernel_shape), kernel_shape + + with tf.variable_scope(self.scope_name + '_init', reuse): + + init = tf.truncated_normal( + kernel_shape, stddev=0.2, dtype=tf.float32) + self.kernels = tf.get_variable("k", initializer=init) + k_summ = tf.summary.histogram( + name="k", values=self.kernels) + + from tensorflow.contrib.distributions import MultivariateNormalDiag + with self.G.gradient_override_map({"MultivariateNormalDiag": "QuantizeGrad"}): + self.kernels = MultivariateNormalDiag( + loc=self.kernels).sample() + + k_rand_summ = tf.summary.histogram( + name="k_rand", values=self.kernels) + + orig_input_batch_size = input_shape[0] + input_shape = list(input_shape) + input_shape[0] = 1 + dummy_batch = tf.zeros(input_shape) + dummy_output = self.fprop(dummy_batch, False) + output_shape = [int(e) for e in dummy_output.get_shape()] + output_shape[0] = 1 + self.output_shape = tuple(output_shape) + + def fprop(self, x, reuse): + + # need variable_scope here because the batch_norm layer creates + # variables internally + with tf.variable_scope(self.scope_name + '_fprop', reuse=reuse) as scope: + + x = tf.nn.conv2d(x, self.kernels, (1,) + + tuple(self.strides) + (1,), self.padding) + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + + +class Conv2D(Layer): + + def __init__(self, output_channels, kernel_shape, strides, padding, phase, scope_name, useBias=False): + self.__dict__.update(locals()) + self.G = tf.get_default_graph() + del self.self + + def quantize(self, x): + with self.G.gradient_override_map({"Sign": "QuantizeGrad"}): + return tf.sign(x) + + def set_input_shape(self, input_shape, reuse): + + batch_size, rows, cols, input_channels = input_shape + kernel_shape = tuple(self.kernel_shape) + (input_channels, + self.output_channels) + assert len(kernel_shape) == 4 + assert all(isinstance(e, int) for e in kernel_shape), kernel_shape + + with tf.variable_scope(self.scope_name + '_init', reuse): + + init = tf.truncated_normal( + kernel_shape, stddev=0.1, dtype=tf.float32) + init = init / tf.sqrt(1e-7 + tf.reduce_sum(tf.square(init), + axis=(0, 1, 2))) + self.kernels = tf.get_variable("k", initializer=init) + k_summ = tf.summary.histogram( + name="k", values=self.kernels) + + orig_input_batch_size = input_shape[0] + input_shape = list(input_shape) + input_shape[0] = 1 + dummy_batch = tf.zeros(input_shape) + # Set output shape using fprop without bias if useBias set + if self.useBias: + dummy_output = self.fprop_withoutbias(dummy_batch, False) + else: #--default below + dummy_output = self.fprop(dummy_batch, False) + + output_shape = [int(e) for e in dummy_output.get_shape()] + output_shape[0] = 1 + self.output_shape = tuple(output_shape) + + if self.useBias: + self.bias_shape = self.output_shape + bias_init = tf.zeros(self.bias_shape) + self.bias =tf.get_variable("b", initializer= bias_init) + + def fprop(self, x, reuse): + + # need variable_scope here because the batch_norm layer creates + # variables internally + with tf.variable_scope(self.scope_name + '_fprop', reuse=reuse) as scope: + + x = tf.nn.conv2d(x, self.kernels, (1,) + + tuple(self.strides) + (1,), self.padding) + + if self.useBias: + output_shape = tf.shape(x) # Checking output shape before bias + x = tf.nn.bias_add(tf.contrib.layers.flatten(x), tf.reshape(self.bias, [-1])) + x = tf.reshape(x, output_shape) + + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + + # special function without bias to get output shape + def fprop_withoutbias(self, x, reuse): + + # need variable_scope here because the batch_norm layer creates + # variables internally + with tf.variable_scope(self.scope_name + '_fprop', reuse=reuse) as scope: + + x = tf.nn.conv2d(x, self.kernels, (1,) + + tuple(self.strides) + (1,), self.padding) + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + +class Conv2D_lowprecision(Layer): + + def __init__(self, wbits, abits, output_channels, kernel_shape, strides, padding, phase, scope_name, seed=1, useBatchNorm=False, stocRound=False, useBias=False): + self.__dict__.update(locals()) + self.G = tf.get_default_graph() + del self.self + + def quantize(self, x, k): ## k= No. of quantized bits + n = float(2**k-1) ## Max value representable with k bits + + @tf.custom_gradient ## Can be used to define a custom gradient function + def _quantize(x): + if self.stocRound: # If stochastic rounding is set + xn_int = tf.floor(x*n) # Get integer part + xn_frac = tf.subtract(x*n, xn_int) # Get fractional part + xn_frac_rand = tf.distributions.Bernoulli(probs=xn_frac, dtype=tf.float32).sample() # Get random number from bernoulli distribution with prob=fractional part value + x_q = (xn_int + xn_frac_rand)/n + + return x_q, lambda dy: dy # Second part is the function evaluated during gradient, identity function + else: + return tf.round(x*n)/n, lambda dy: dy # Second part is the function evaluated during gradient, identity function + + return _quantize(x) + + def quantizeWt(self, x): + x = tf.tanh(x) ## Normalizing weights to [-1, 1] + x = x/tf.reduce_max(abs(x))*0.5 + 0.5 ## Normalizing weights to [0, 1] + return 2*self.quantize(x, self.wbits) - 1 ## Normalizing back to [0, 1] after quantizing + + def quantizeAct(self, x): + x = tf.clip_by_value(x, 0, 1.0) ## Normalizing activations to [0, 1] --> performed in nonlin(x) function of alexnet-dorefa.py + return self.quantize(x, self.abits) + + def set_input_shape(self, input_shape, reuse): + + batch_size, rows, cols, input_channels = input_shape + kernel_shape = tuple(self.kernel_shape) + (input_channels, + self.output_channels) + assert len(kernel_shape) == 4 + assert all(isinstance(e, int) for e in kernel_shape), kernel_shape + + with tf.variable_scope(self.scope_name + '_init', reuse): + + if self.wbits < 32: + init = tf.truncated_normal( + kernel_shape, stddev=0.2, dtype=tf.float32) + init = init / tf.sqrt(1e-7 + tf.reduce_sum(tf.square(init), + axis=(0, 1, 2))) + self.kernels = tf.get_variable("k", initializer=init) + else: + init = tf.truncated_normal( + kernel_shape, stddev=0.1, dtype=tf.float32) + init = init / tf.sqrt(1e-7 + tf.reduce_sum(tf.square(init), + axis=(0, 1, 2))) + self.kernels = tf.get_variable("k", initializer=init) + + if (self.wbits < 32): ## Quantize if no. of bits less than 32 + self.kernels = self.quantizeWt(self.kernels) + k_bin_summ = tf.summary.histogram( + name="k_bin", values=self.kernels) + + k_summ = tf.summary.histogram( + name="k", values=self.kernels) + + orig_input_batch_size = input_shape[0] + input_shape = list(input_shape) + input_shape[0] = 1 + dummy_batch = tf.zeros(input_shape) + + # Set output shape using fprop without bias if useBias set + if self.useBias: + dummy_output = self.fprop_withoutbias(dummy_batch, False) + else: #--default below + dummy_output = self.fprop(dummy_batch, False) + + output_shape = [int(e) for e in dummy_output.get_shape()] + output_shape[0] = 1 + self.output_shape = tuple(output_shape) + + # setting bias shape + if self.useBias: + self.bias_shape = self.output_shape + bias_init = tf.zeros(self.bias_shape) + self.bias =tf.get_variable("b", initializer= bias_init) + if self.wbits < 32: ## Quantize if no. of bits less than 32 + self.bias =self.quantizeWt(self.bias) + + def fprop(self, x, reuse): + + # need variable_scope here because the batch_norm layer creates + # variables internally + with tf.variable_scope(self.scope_name + '_fprop', reuse=reuse) as scope: + + if self.abits < 32: + if self.useBatchNorm: ## Specifies whether we want to use Batch Normalization or not + x = tf.contrib.layers.batch_norm( + x, epsilon=BN_EPSILON, is_training=self.phase, + reuse=reuse, scope=scope) + x = self.quantizeAct(x) + x = tf.nn.conv2d(x, self.kernels, (1,) + + tuple(self.strides) + (1,), self.padding) + + if self.useBias: + output_shape = tf.shape(x) # Checking output shape before bias + x = tf.nn.bias_add(tf.contrib.layers.flatten(x), tf.reshape(self.bias, [-1])) + x = tf.reshape(x, output_shape) + + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + + # special function without bias to get output shape + def fprop_withoutbias(self, x, reuse): + + # need variable_scope here because the batch_norm layer creates + # variables internally + with tf.variable_scope(self.scope_name + '_fprop', reuse=reuse) as scope: + + x = tf.nn.conv2d(x, self.kernels, (1,) + + tuple(self.strides) + (1,), self.padding) + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + +class Conv2DGroup(Layer): + + def __init__(self, output_channels, kernel_shape, strides, padding, phase, scope_name, useBias=False): + self.__dict__.update(locals()) + self.G = tf.get_default_graph() + del self.self + + def quantize(self, x): + with self.G.gradient_override_map({"Sign": "QuantizeGrad"}): + return tf.sign(x) + + def set_input_shape(self, input_shape, reuse): + + self.input_shape = input_shape + batch_size, rows, cols, input_channels = input_shape + self.input_channels = input_channels + kernel_shape = tuple(self.kernel_shape) + (int(input_channels/2), + self.output_channels) # as it is 2 groups, input channel dimension is halved + assert len(kernel_shape) == 4 + assert all(isinstance(e, int) for e in kernel_shape), kernel_shape + + with tf.variable_scope(self.scope_name + '_init', reuse): + + init = tf.variance_scaling_initializer(scale=2., dtype=tf.float32) + self.kernels = tf.get_variable("k", shape=kernel_shape, initializer=init) + k_summ = tf.summary.histogram( + name="k", values=self.kernels) + + orig_input_batch_size = input_shape[0] + input_shape = list(input_shape) + input_shape[0] = 1 + dummy_batch = tf.zeros(input_shape) + if self.useBias: + dummy_output = self.fprop_withoutbias(dummy_batch, False) + else: #--default below + dummy_output = self.fprop(dummy_batch, False) + output_shape = [int(e) for e in dummy_output.get_shape()] + output_shape[0] = 1 + self.output_shape = tuple(output_shape) + + # setting bias shape + self.bias_shape = self.output_shape + + # initializing bias + if self.useBias: + bias_init = tf.zeros(self.bias_shape) + self.bias =tf.get_variable("b", initializer= bias_init) + + + def fprop(self, x, reuse): + + # need variable_scope here because the batch_norm layer creates + # variables internally + with tf.variable_scope(self.scope_name + '_fprop', reuse=reuse) as scope: + + ### groupwise convolution + x1 = tf.nn.conv2d(tf.slice(x, [0, 0, 0, 0], [-1, -1, -1, tf.cast(self.input_channels/2, tf.int32)]), tf.slice(self.kernels, [0, 0, 0, 0], [-1, -1, -1, tf.cast(self.output_channels/2, tf.int32)]), (1,) + tuple(self.strides) + (1,), self.padding) + x2 = tf.nn.conv2d(tf.slice(x, [0, 0, 0, tf.cast(self.input_channels/2, tf.int32)], [-1, -1, -1, -1]), tf.slice(self.kernels, [0, 0, 0, (tf.cast(self.output_channels/2, tf.int32))], [-1, -1, -1, -1]), (1,) + tuple(self.strides) + (1,), self.padding) + x = tf.concat([x1, x2], 3) + + # adding bias + if self.useBias: + output_shape = tf.shape(x) # Checking output shape before bias + x = tf.nn.bias_add(tf.contrib.layers.flatten(x), tf.reshape(self.bias, [-1])) + if self.padding=="SAME": # Padding same means input and output size equal + x = tf.reshape(x, output_shape) + + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + + # Special function without bias to get output shape + def fprop_withoutbias(self, x, reuse): + + # need variable_scope here because the batch_norm layer creates + # variables internally + with tf.variable_scope(self.scope_name + '_fprop', reuse=reuse) as scope: + + ### groupwise convolution + x1 = tf.nn.conv2d(tf.slice(x, [0, 0, 0, 0], [-1, -1, -1, tf.cast(self.input_channels/2, tf.int32)]), tf.slice(self.kernels, [0, 0, 0, 0], [-1, -1, -1, tf.cast(self.output_channels/2, tf.int32)]), (1,) + tuple(self.strides) + (1,), self.padding) + x2 = tf.nn.conv2d(tf.slice(x, [0, 0, 0, tf.cast(self.input_channels/2, tf.int32)], [-1, -1, -1, -1]), tf.slice(self.kernels, [0, 0, 0, (tf.cast(self.output_channels/2, tf.int32))], [-1, -1, -1, -1]), (1,) + tuple(self.strides) + (1,), self.padding) + x = tf.concat([x1, x2], 3) + + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + +class Conv2DGroup_lowprecision(Layer): + + def __init__(self, wbits, abits, output_channels, kernel_shape, strides, padding, phase, scope_name, seed=1, useBatchNorm=False, stocRound=False, useBias=False): + self.__dict__.update(locals()) + self.G = tf.get_default_graph() + del self.self + + def quantize(self, x, k): ## k= No. of quantized bits + n = float(2**k-1) ## Max value representable with k bits + + @tf.custom_gradient ## Can be used to define a custom gradient function + def _quantize(x): + if self.stocRound: # If stochastic rounding is set + xn_int = tf.floor(x*n) # Get integer part + xn_frac = tf.subtract(x*n, xn_int) # Get fractional part + xn_frac_rand = tf.distributions.Bernoulli(probs=xn_frac, dtype=tf.float32).sample() # Get random number from bernoulli distribution with prob=fractional part value + x_q = (xn_int + xn_frac_rand)/n + + return x_q, lambda dy: dy # Second part is the function evaluated during gradient, identity function + else: + return tf.round(x*n)/n, lambda dy: dy # Second part is the function evaluated during gradient, identity function + + return _quantize(x) + + def quantizeWt(self, x): + x = tf.tanh(x) ## Normalizing weights to [-1, 1] + x = x/tf.reduce_max(abs(x))*0.5 + 0.5 ## Normalizing weights to [0, 1] + return 2*self.quantize(x, self.wbits) - 1 ## Normalizing back to [0, 1] after quantizing + + def quantizeAct(self, x): + x = tf.clip_by_value(x, 0, 1.0) ## Normalizing activations to [0, 1] --> performed in nonlin(x) function of alexnet-dorefa.py + return self.quantize(x, self.abits) + + def set_input_shape(self, input_shape, reuse): + + self.input_shape = input_shape + batch_size, rows, cols, input_channels = input_shape + self.input_channels = input_channels + kernel_shape = tuple(self.kernel_shape) + (int(input_channels/2), + self.output_channels) # as it is 2 groups, input channel dimension is halved + assert len(kernel_shape) == 4 + assert all(isinstance(e, int) for e in kernel_shape), kernel_shape + + with tf.variable_scope(self.scope_name + '_init', reuse): + + if self.wbits < 32: + init = tf.truncated_normal( + kernel_shape, stddev=0.2, dtype=tf.float32) + self.kernels = tf.get_variable("k", initializer=init) + else: + init = tf.truncated_normal( + kernel_shape, stddev=0.1, dtype=tf.float32) + init = init / tf.sqrt(1e-7 + tf.reduce_sum(tf.square(init), + axis=(0, 1, 2))) + self.kernels = tf.get_variable("k", initializer=init) + + if (self.wbits < 32): ## Quantize if no. of bits less than 32 + self.kernels = self.quantizeWt(self.kernels) + k_bin_summ = tf.summary.histogram( + name="k_bin", values=self.kernels) + k_summ = tf.summary.histogram( + name="k", values=self.kernels) + + orig_input_batch_size = input_shape[0] + input_shape = list(input_shape) + input_shape[0] = 1 + dummy_batch = tf.zeros(input_shape) + # Set output shape using fprop without bias if useBias set + if self.useBias: + dummy_output = self.fprop_withoutbias(dummy_batch, False) + else: #--default below + dummy_output = self.fprop(dummy_batch, False) + output_shape = [int(e) for e in dummy_output.get_shape()] + output_shape[0] = 1 + self.output_shape = tuple(output_shape) + + self.bias_shape = self.output_shape + + if self.useBias: + bias_init = tf.zeros(self.bias_shape) + self.bias =tf.get_variable("b", initializer= bias_init) + if self.wbits < 32: ## Quantize if no. of bits less than 32 + self.bias =self.quantizeWt(self.bias) + + + def fprop(self, x, reuse): + with tf.variable_scope(self.scope_name + '_fprop', reuse=reuse) as scope: + + if self.abits < 32: + if self.useBatchNorm: ## Specifies whether we want to use Batch Normalization or not + x = tf.contrib.layers.batch_norm( + x, epsilon=BN_EPSILON, is_training=self.phase, + reuse=reuse, scope=scope) + x = self.quantizeAct(x) + ### groupwise convolution + x1 = tf.nn.conv2d(tf.slice(x, [0, 0, 0, 0], [-1, -1, -1, tf.cast(self.input_channels/2, tf.int32)]), tf.slice(self.kernels, [0, 0, 0, 0], [-1, -1, -1, tf.cast(self.output_channels/2, tf.int32)]), (1,) + tuple(self.strides) + (1,), self.padding) + x2 = tf.nn.conv2d(tf.slice(x, [0, 0, 0, tf.cast(self.input_channels/2, tf.int32)], [-1, -1, -1, -1]), tf.slice(self.kernels, [0, 0, 0, (tf.cast(self.output_channels/2, tf.int32))], [-1, -1, -1, -1]), (1,) + tuple(self.strides) + (1,), self.padding) + x = tf.concat([x1, x2], 3) + + if self.useBias: + output_shape = tf.shape(x) # Checking output shape before bias + x = tf.nn.bias_add(tf.contrib.layers.flatten(x), tf.reshape(self.bias, [-1])) + if self.padding=="SAME": # Padding same means input and output size equal + x = tf.reshape(x, output_shape) + + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + + # Special function without bias to get output shape + def fprop_withoutbias(self, x, reuse): + with tf.variable_scope(self.scope_name + '_fprop', reuse=reuse) as scope: + + if self.abits < 32: + if self.useBatchNorm: ## Specifies whether we want to use Batch Normalization or not + x = tf.contrib.layers.batch_norm( + x, epsilon=BN_EPSILON, is_training=self.phase, + reuse=reuse, scope=scope) + x = self.quantizeAct(x) + ### groupwise convolution + x1 = tf.nn.conv2d(tf.slice(x, [0, 0, 0, 0], [-1, -1, -1, tf.cast(self.input_channels/2, tf.int32)]), tf.slice(self.kernels, [0, 0, 0, 0], [-1, -1, -1, tf.cast(self.output_channels/2, tf.int32)]), (1,) + tuple(self.strides) + (1,), self.padding) + x2 = tf.nn.conv2d(tf.slice(x, [0, 0, 0, tf.cast(self.input_channels/2, tf.int32)], [-1, -1, -1, -1]), tf.slice(self.kernels, [0, 0, 0, (tf.cast(self.output_channels/2, tf.int32))], [-1, -1, -1, -1]), (1,) + tuple(self.strides) + (1,), self.padding) + x = tf.concat([x1, x2], 3) + + a_u, a_v = tf.nn.moments(tf.abs(x), axes=[0], keep_dims=False) + a_summ = tf.summary.histogram('a', values=x) + a_u_summ = tf.summary.scalar("a_u", tf.reduce_mean(a_u)) + a_v_summ = tf.summary.scalar("a_v", tf.reduce_mean(a_v)) + + return x + +class MaxPool(Layer): + + def __init__ (self, pool_size, strides): + self.pool_size = pool_size + self.strides = strides + + def set_input_shape(self, input_shape, reuse): + self.input_shape = input_shape + orig_input_batch_size = input_shape[0] + input_shape = list(input_shape) + input_shape[0] = 1 + dummy_batch = tf.zeros(input_shape) + dummy_output = self.fprop(dummy_batch, False) + output_shape = [int(e) for e in dummy_output.get_shape()] + output_shape[0] = 1 + self.output_shape = tuple(output_shape) + + def fprop(self, x, reuse): + return tf.layers.max_pooling2d(x, self.pool_size, self.strides) + +class MaxPoolSame(Layer): + + def __init__ (self, pool_size, strides): + self.pool_size = pool_size + self.strides = strides + + def set_input_shape(self, input_shape, reuse): + self.input_shape = input_shape + orig_input_batch_size = input_shape[0] + input_shape = list(input_shape) + input_shape[0] = 1 + dummy_batch = tf.zeros(input_shape) + dummy_output = self.fprop(dummy_batch, False) + output_shape = [int(e) for e in dummy_output.get_shape()] + output_shape[0] = 1 + self.output_shape = tuple(output_shape) + + def fprop(self, x, reuse): + return tf.layers.max_pooling2d(x, self.pool_size, self.strides, padding='same') + +class AvgPool(Layer): + + def __init__ (self, pool_size, strides): + self.pool_size = pool_size + self.strides = strides + + def set_input_shape(self, input_shape, reuse): + self.input_shape = input_shape + orig_input_batch_size = input_shape[0] + input_shape = list(input_shape) + input_shape[0] = 1 + dummy_batch = tf.zeros(input_shape) + dummy_output = self.fprop(dummy_batch, False) + output_shape = [int(e) for e in dummy_output.get_shape()] + output_shape[0] = 1 + self.output_shape = tuple(output_shape) + + def fprop(self, x, reuse): + return tf.layers.average_pooling2d(x, self.pool_size, self.strides) + +class ReLU(Layer): + + def __init__(self): + pass + + def set_input_shape(self, shape, reuse): + self.input_shape = shape + self.output_shape = shape + + def get_output_shape(self): + return self.output_shape + + def fprop(self, x, reuse): + return tf.nn.relu(x) + + +class SReLU(Layer): + + def __init__(self, scope_name): + self.scope_name = scope_name + pass + + def set_input_shape(self, shape, reuse): + self.input_shape = shape + self.output_shape = shape + with tf.variable_scope(self.scope_name + '_init', reuse=reuse): + self.activation_scalar = tf.get_variable( + "activation_scalar", initializer=0.05, trainable=True) + + def get_output_shape(self): + return self.output_shape + + def fprop(self, x, reuse): + with tf.variable_scope(self.scope_name + '_init', reuse=reuse): + return tf.nn.relu(x) * self.activation_scalar + + +class Softmax(Layer): + + def __init__(self, temperature): + self.temperature = temperature + + def set_input_shape(self, shape, reuse): + self.input_shape = shape + self.output_shape = shape + + def fprop(self, x, reuse): + return tf.nn.softmax(x * self.temperature) + + +class SoftmaxT1(Layer): + + def __init__(self): + pass + + def set_input_shape(self, shape, reuse): + self.input_shape = shape + self.output_shape = shape + + def fprop(self, x, reuse): + return tf.nn.softmax(x) + + +class Flatten(Layer): + + def __init__(self): + pass + + def set_input_shape(self, shape, reuse): + self.input_shape = shape + output_width = 1 + for factor in shape[1:]: + output_width *= factor + self.output_width = output_width + self.output_shape = [None, output_width] + + def fprop(self, x, reuse): + return tf.reshape(x, [-1, self.output_width]) + +# Local response Norm layer for AlexNet +class LocalNorm(Layer): + + def __init__(self): + self.__dict__.update(locals()) + + def set_input_shape(self, shape, reuse): + self.input_shape = shape + self.output_shape = shape + + def get_output_shape(self): + return self.output_shape + + def fprop(self, x, reuse): + x = tf.nn.local_response_normalization(x, + depth_radius=RADIUS, + alpha=ALPHA, + beta=BETA, + bias=BIAS) + return x + +# BatchNorm layer for low precision alexnet +class BatchNorm(Layer): + + def __init__(self, phase, scope_name, mean=None, variance=None, scale=None, offset=None): + self.__dict__.update(locals()) + + def set_input_shape(self, shape, reuse): + self.input_shape = shape + self.output_shape = shape + + def get_output_shape(self): + return self.output_shape + + def fprop(self, x, reuse): + + # Batch normalization for the training phase + if (self.mean is None) and (self.variance is None) and (self.scale is None) and (self.offset is None): + with tf.variable_scope(self.scope_name, reuse=tf.AUTO_REUSE): # Adding scope here to help in restoring variables, Saves and restores model + x = tf.layers.batch_normalization(x, training=self.phase) + else: + x = tf.nn.batch_normalization( + x, mean=self.mean, variance=self.variance, + scale=self.scale, offset=self.offset, variance_epsilon=BN_EPSILON) + return x + +## dropout layer for alexnet +class DropOut(Layer): + + def __init__(self, keep_prob, phase): + self.__dict__.update(locals()) + self.G = tf.get_default_graph() + del self.self + + def set_input_shape(self, shape, reuse): + self.input_shape = shape + self.output_shape = shape + + def get_output_shape(self): + return self.output_shape + + def fprop(self, x, reuse): + return tf.cond(self.phase, lambda: tf.nn.dropout(x, self.keep_prob), lambda: tf.identity(x)) # Dropout during training phase but not during test phase + +######################### full-precision ######################### +def make_basic_cnn(phase, temperature, detail, nb_filters=64, nb_classes=10, + input_shape=(None, 28, 28, 1)): + layers = [Conv2D(nb_filters, (8, 8), (2, 2), "SAME", phase, detail + 'conv1'), + ReLU(), + Conv2D(nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail + 'conv2'), + ReLU(), + Conv2D(nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail + 'conv3'), + ReLU(), + Flatten(), + Linear(nb_classes, detail), + Softmax(temperature)] + + model = MLP(layers, input_shape) + print('Finished making basic cnn') + return model + + +def make_scaled_rand_cnn(phase, temperature, detail, nb_filters=64, nb_classes=10, + input_shape=(None, 28, 28, 1)): + layers = [Conv2D(nb_filters, (8, 8), (2, 2), "SAME", phase, detail + 'conv1'), + ReLU(), + Conv2D(nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail + 'conv2'), + ReLU(), + Conv2DRand(nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail + 'conv3'), + SReLU(detail + 'srelu3_fp'), + Flatten(), + Linear(nb_classes, detail), + Softmax(temperature)] + + model = MLP(layers, input_shape) + print('Finished making basic cnn') + return model + +# distilled model +def make_distilled_cnn(phase, temperature, detail1, detail2, nb_filters=64, nb_classes=10, input_shape=(None, 28, 28, 1)): + # make one teacher low precision cnn with wbits precision weights and abits activations + teacher_layers = [Conv2D(nb_filters, (8, 8), + (2, 2), "SAME", phase, detail1 + 'conv1'), + ReLU(), + Conv2D(nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail1 + 'conv2_bin'), + ReLU(), + Conv2D(nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail1 + 'conv3_bin'), + ReLU(), + Flatten(), + Linear(nb_classes, detail1), + Softmax(temperature)] # Hard probs (default) + # make one student low precision cnn with wbits precision weights and abits activations + student_layers = [Conv2D(nb_filters, (8, 8), + (2, 2), "SAME", phase, detail2 + 'conv1'), + ReLU(), + Conv2D(nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail2 + 'conv2'), + ReLU(), + Conv2D(nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail2 + 'conv3'), + ReLU(), + Flatten(), + Linear(nb_classes, detail2), + Softmax(temperature)] # Hard probs (default) + + model = distilledModel(teacher_layers, student_layers, input_shape) + print('Finished making a distilled cnn') + + return model + +################## low precision version of mnist cnn ################# +def make_basic_lowprecision_cnn(phase, temperature, detail, wbits, abits, nb_filters=64, nb_classes=10, + input_shape=(None, 28, 28, 1), useBatchNorm=False, stocRound=False): + + layers = [Conv2D_lowprecision(wbits, abits, nb_filters, (8, 8), + (2, 2), "SAME", phase, detail + 'conv1', useBatchNorm=useBatchNorm, stocRound=stocRound), + ReLU(), + Conv2D_lowprecision(wbits, abits, nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail + 'conv2_bin', useBatchNorm=useBatchNorm, stocRound=stocRound), + ReLU(), + Conv2D_lowprecision(wbits, abits, nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail + 'conv3_bin', useBatchNorm=useBatchNorm, stocRound=stocRound), + ReLU(), + Flatten(), + Linear(nb_classes, detail), + Softmax(temperature)] + + model = MLP(layers, input_shape) + print('Finished making basic low precision cnn: %d weight bits, %d activation bits' %(wbits, abits)) + return model + +# Variant of low precision supporting different precisions for different layers +def make_layerwise_lowprecision_cnn(phase, temperature, detail, wbits, abits, nb_filters=64, + nb_classes=10, input_shape=(None, 28, 28, 1), + useBatchNorm=False, stocRound=False): + layers = [Conv2D_lowprecision(wbits[0], abits[0], nb_filters, (8, 8), + (2, 2), "SAME", phase, detail + 'conv1', useBatchNorm=useBatchNorm, stocRound=stocRound), + ReLU(), + Conv2D_lowprecision(wbits[1], abits[1], nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail + 'conv2_bin', useBatchNorm=useBatchNorm, stocRound=stocRound), + ReLU(), + Conv2D_lowprecision(wbits[2], abits[2], nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail + 'conv3_bin', useBatchNorm=useBatchNorm, stocRound=stocRound), + ReLU(), + Flatten(), + Linear(nb_classes, detail), + Softmax(temperature)] + + model = MLP(layers, input_shape) + print('Finished making layerwise low precision cnn: %d %d %d weight bits, %d %d %d activation bits' %(wbits[0], wbits[1], wbits[2], abits[0], abits[1], abits[2])) + return model + + +################## EMPIR version of mnist cnn ################# +def make_ensemble_three_cnn(phase, temperature, detail1, detail2, detail3, wbits1, abits1, wbits2, abits2, nb_filters=64, nb_classes=10, input_shape=(None, 28, 28, 1), useBatchNorm=False): + # make one low precision cnn with wbits precision weights and abits activations + layers1 = [Conv2D_lowprecision(wbits1, abits1, nb_filters, (8, 8), + (2, 2), "SAME", phase, detail1 + 'conv1', useBatchNorm=useBatchNorm), + ReLU(), + Conv2D_lowprecision(wbits1, abits1, nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail1 + 'conv2_bin', useBatchNorm=useBatchNorm), + ReLU(), + Conv2D_lowprecision(wbits1, abits1, nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail1 + 'conv3_bin', useBatchNorm=useBatchNorm), + ReLU(), + Flatten(), + Linear(nb_classes, detail1), + Softmax(temperature)] + # make another low precision cnn with wbits precision weights and abits activations + layers2 = [Conv2D_lowprecision(wbits2, abits2, nb_filters, (8, 8), + (2, 2), "SAME", phase, detail2 + 'conv1', useBatchNorm=useBatchNorm), + ReLU(), + Conv2D_lowprecision(wbits2, abits2, nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail2 + 'conv2_bin', useBatchNorm=useBatchNorm), + ReLU(), + Conv2D_lowprecision(wbits2, abits2, nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail2 + 'conv3_bin', useBatchNorm=useBatchNorm), + ReLU(), + Flatten(), + Linear(nb_classes, detail2), + Softmax(temperature)] + + # make a full precision cnn with full precision weights and a bits activations + layers3 = [Conv2D(nb_filters, (8, 8), (2, 2), "SAME", phase, detail3 + 'conv1'), + ReLU(), + Conv2D(nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail3 + 'conv2'), + ReLU(), + Conv2D(nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail3 + 'conv3'), + ReLU(), + Flatten(), + Linear(nb_classes, detail3), + Softmax(temperature)] + + model = ensembleThreeModel(layers1, layers2, layers3, input_shape, nb_classes) + print('Finished making ensemble of three cnns') + + return model + +def make_ensemble_three_cnn_layerwise(phase, temperature, detail1, detail2, detail3, wbits1, abits1, wbits2, abits2, nb_filters=64, nb_classes=10, input_shape=(None, 28, 28, 1), useBatchNorm=False): + # make one low precision cnn with wbits precision weights and abits activations + layers1 = [Conv2D_lowprecision(wbits1[0], abits1[0], nb_filters, (8, 8), + (2, 2), "SAME", phase, detail1 + 'conv1', useBatchNorm=useBatchNorm), + ReLU(), + Conv2D_lowprecision(wbits1[1], abits1[1], nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail1 + 'conv2_bin', useBatchNorm=useBatchNorm), + ReLU(), + Conv2D_lowprecision(wbits1[2], abits1[2], nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail1 + 'conv3_bin', useBatchNorm=useBatchNorm), + ReLU(), + Flatten(), + Linear(nb_classes, detail1), + Softmax(temperature)] + # make another low precision cnn with wbits precision weights and abits activations + layers2 = [Conv2D_lowprecision(wbits2[0], abits2[0], nb_filters, (8, 8), + (2, 2), "SAME", phase, detail2 + 'conv1', useBatchNorm=useBatchNorm), + ReLU(), + Conv2D_lowprecision(wbits2[1], abits2[1], nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail2 + 'conv2_bin', useBatchNorm=useBatchNorm), + ReLU(), + Conv2D_lowprecision(wbits2[2], abits2[2], nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail2 + 'conv3_bin', useBatchNorm=useBatchNorm), + ReLU(), + Flatten(), + Linear(nb_classes, detail2), + Softmax(temperature)] + + # make a full precision cnn with full precision weights and a bits activations + layers3 = [Conv2D(nb_filters, (8, 8), (2, 2), "SAME", phase, detail3 + 'conv1'), + ReLU(), + Conv2D(nb_filters * 2, (6, 6), + (2, 2), "VALID", phase, detail3 + 'conv2'), + ReLU(), + Conv2D(nb_filters * 2, (5, 5), + (1, 1), "VALID", phase, detail3 + 'conv3'), + ReLU(), + Flatten(), + Linear(nb_classes, detail3), + Softmax(temperature)] + + model = ensembleThreeModel(layers1, layers2, layers3, input_shape, avg, weightedAvg, alpha, nb_classes) + print('Finished making ensemble of three cnns') + + return model + +################# full-precision cifar cnn ############################ +def make_basic_cifar_cnn(phase, temperature, detail, nb_filters=32, nb_classes=10, + input_shape=(None, 28, 28, 1)): + layers = [Conv2D(nb_filters, (5, 5), (1, 1), "SAME", phase, detail + 'conv1'), + MaxPool((3, 3), (2, 2)), + ReLU(), + Conv2D(nb_filters, (5, 5), + (1, 1), "SAME", phase, detail + 'conv2'), + ReLU(), + AvgPool((3, 3), (2, 2)), + Conv2D(nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail + 'conv3'), + ReLU(), + AvgPool((3, 3), (2, 2)), + Flatten(), + HiddenLinear(64, detail + 'ip1'), + Linear(nb_classes, detail), + Softmax(temperature)] + + model = MLP(layers, input_shape) + print('Finished making basic cnn') + return model + +################## distilled version of cifar cnn ################# +def make_distilled_cifar_cnn(phase, temperature, detail1, detail2, nb_filters=32, nb_classes=10, + input_shape=(None, 28, 28, 1)): + teacher_layers = [Conv2D(nb_filters, (5, 5), (1, 1), "SAME", phase, detail1 + 'conv1'), + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Conv2D(nb_filters, (5, 5), + (1, 1), "SAME", phase, detail1 + 'conv2'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Conv2D(nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail1 + 'conv3'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Flatten(), + HiddenLinear(64, detail1 + 'ip1'), + Linear(nb_classes, detail1), + Softmax(temperature)] + + student_layers = [Conv2D(nb_filters, (5, 5), (1, 1), "SAME", phase, detail2 + 'conv1'), + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Conv2D(nb_filters, (5, 5), + (1, 1), "SAME", phase, detail2 + 'conv2'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Conv2D(nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail2 + 'conv3'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Flatten(), + HiddenLinear(64, detail2 + 'ip1'), + Linear(nb_classes, detail2), + Softmax(temperature)] + + model = distilledModel(teacher_layers, student_layers, input_shape) + print('Finished making distilled cifar cnn') + return model + + +################## low precision version of cifar cnn ################# +def make_basic_lowprecision_cifar_cnn(phase, temperature, detail, wbits, abits, nb_filters=64, nb_classes=10, + input_shape=(None, 28, 28, 1), stocRound=False): + + layers = [Conv2D_lowprecision(wbits, abits, nb_filters, (5, 5), (1, 1), "SAME", phase, detail + 'conv1', stocRound=stocRound), # VALID padding means no padding, SAME means padding by (k-1)/2 + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Conv2D_lowprecision(wbits, abits, nb_filters, (5, 5), + (1, 1), "SAME", phase, detail + 'conv2', stocRound=stocRound), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Conv2D_lowprecision(wbits, abits, nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail + 'conv3', stocRound=stocRound), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Flatten(), + HiddenLinear(64, detail + 'ip1'), + Linear(nb_classes, detail), + Softmax(temperature)] + + model = MLP(layers, input_shape) + print('Finished making basic low precision cnn: %d weight bits, %d activation bits' %(wbits, abits)) + return model + +def make_layerwise_lowprecision_cifar_cnn(phase, temperature, detail, wbits, abits, nb_filters=64, nb_classes=10, + input_shape=(None, 28, 28, 1), stocRound=False): + + layers = [Conv2D_lowprecision(wbits[0], abits[0], nb_filters, (5, 5), (1, 1), "SAME", phase, detail + 'conv1', stocRound=stocRound), + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Conv2D_lowprecision(wbits[1], abits[1], nb_filters, (5, 5), + (1, 1), "SAME", phase, detail + 'conv2', stocRound=stocRound), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Conv2D_lowprecision(wbits[2], abits[2], nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail + 'conv3', stocRound=stocRound), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Flatten(), + HiddenLinear(64, detail + 'ip1'), # first f.c. layer + Linear(nb_classes, detail), + Softmax(temperature)] + + model = MLP(layers, input_shape) + print('Finished making layerwise low precision cnn %d %d %d weight bits, %d %d %d activation bits' %(wbits[0], wbits[1], wbits[2], abits[0], abits[1], abits[2])) + return model + +################## EMPIR version of cifar cnn ################# +def make_ensemble_three_cifar_cnn(phase, temperature, detail1, detail2, detail3, wbits1, abits1, wbits2, abits2, nb_filters=32, nb_classes=10, input_shape=(None, 28, 28, 1)): + # make a low precision cnn with full precision weights and a bits activations + layers1 = [Conv2D_lowprecision(wbits1, abits1, nb_filters, (5, 5), (1, 1), "SAME", phase, detail1 + 'conv1'), # VALID padding means no padding, SAME means padding by (k-1)/2 + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Conv2D_lowprecision(wbits1, abits1, nb_filters, (5, 5), + (1, 1), "SAME", phase, detail1 + 'conv2'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride ReLU(), + Conv2D_lowprecision(wbits1, abits1, nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail1 + 'conv3'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Flatten(), + HiddenLinear(64, detail1 + 'ip1'), # first f.c. layer + Linear(nb_classes, detail1), + Softmax(temperature)] + + # make a low precision cnn with full precision weights and a bits activations + layers2 = [Conv2D_lowprecision(wbits2, abits2, nb_filters, (5, 5), (1, 1), "SAME", phase, detail2 + 'conv1'), # VALID padding means no padding, SAME means padding by (k-1)/2 + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Conv2D_lowprecision(wbits2, abits2, nb_filters, (5, 5), + (1, 1), "SAME", phase, detail2 + 'conv2'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride ReLU(), + Conv2D_lowprecision(wbits2, abits2, nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail2 + 'conv3'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Flatten(), + HiddenLinear(64, detail2 + 'ip1'), # first f.c. layer + Linear(nb_classes, detail2), + Softmax(temperature)] + + # make a full precision cnn with full precision weights and a bits activations + layers3 = [Conv2D(nb_filters, (5, 5), (1, 1), "SAME", phase, detail3 + 'conv1'), # VALID padding means no padding, SAME means padding by (k-1)/2 + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Conv2D(nb_filters, (5, 5), + (1, 1), "SAME", phase, detail3 + 'conv2'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Conv2D(nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail3 + 'conv3'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Flatten(), + HiddenLinear(64, detail3 + 'ip1'), # first f.c. layer + Linear(nb_classes, detail3), + Softmax(temperature)] + + model = ensembleThreeModel(layers1, layers2, layers3, input_shape, nb_classes) + print('Finished making ensemble of three cnns') + + return model + +def make_ensemble_three_cifar_cnn_layerwise(phase, temperature, detail1, detail2, detail3, wbits1, abits1, wbits2, abits2, nb_filters=32, nb_classes=10, + input_shape=(None, 28, 28, 1)): + # make a low precision cnn with full precision weights and a bits activations + layers1 = [Conv2D_lowprecision(wbits1[0], abits1[0], nb_filters, (5, 5), (1, 1), "SAME", phase, detail1 + 'conv1'), + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Conv2D_lowprecision(wbits1[1], abits1[1], nb_filters, (5, 5), + (1, 1), "SAME", phase, detail1 + 'conv2'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride ReLU(), + Conv2D_lowprecision(wbits1[2], abits1[2], nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail1 + 'conv3'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Flatten(), + HiddenLinear(64, detail1 + 'ip1'), # first f.c. layer + Linear(nb_classes, detail1), + Softmax(temperature)] + + # make a low precision cnn with full precision weights and a bits activations + layers2 = [Conv2D_lowprecision(wbits2[0], abits2[0], nb_filters, (5, 5), (1, 1), "SAME", phase, detail2 + 'conv1'), # VALID padding means no padding, SAME means padding by (k-1)/2 + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Conv2D_lowprecision(wbits2[1], abits2[1], nb_filters, (5, 5), + (1, 1), "SAME", phase, detail2 + 'conv2'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride ReLU(), + Conv2D_lowprecision(wbits2[2], abits2[2], nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail2 + 'conv3'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Flatten(), + HiddenLinear(64, detail2 + 'ip1'), # first f.c. layer + Linear(nb_classes, detail2), + Softmax(temperature)] + + # make a full precision cnn with full precision weights and a bits activations + layers3 = [Conv2D(nb_filters, (5, 5), (1, 1), "SAME", phase, detail3 + 'conv1'), # VALID padding means no padding, SAME means padding by (k-1)/2 + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Conv2D(nb_filters, (5, 5), + (1, 1), "SAME", phase, detail3 + 'conv2'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Conv2D(nb_filters * 2, (5, 5), + (1, 1), "SAME", phase, detail3 + 'conv3'), + ReLU(), + AvgPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + Flatten(), + HiddenLinear(64, detail3 + 'ip1'), # first f.c. layer + Linear(nb_classes, detail3), + Softmax(temperature)] + + model = ensembleThreeModel(layers1, layers2, layers3, input_shape, avg, weightedAvg, alpha, nb_classes) + print('Finished making ensemble of three cifar cnns') + + return model + +######################### full-precision alexnet for Imagenet ######################### +def make_basic_alexnet_from_scratch(phase, temperature, detail, nb_filters=32, nb_classes=10, + input_shape=(None, 28, 28, 1)): + + layers = [Conv2D(3*nb_filters, (12, 12), (4, 4), "VALID", phase, detail + 'conv1', useBias=True), + ReLU(), + Conv2DGroup(8*nb_filters, (5, 5), + (1, 1), "SAME", phase, detail + 'conv2'), + BatchNorm(phase, detail + '_batchNorm1'), + MaxPoolSame((3, 3), (2, 2)), + ReLU(), + Conv2D(12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail + 'conv3'), + BatchNorm(phase, detail + '_batchNorm2'), + MaxPoolSame((3, 3), (2, 2)), + ReLU(), + Conv2DGroup(12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail + 'conv4'), + BatchNorm(phase, detail + '_batchNorm3'), + ReLU(), + Conv2DGroup(8*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail + 'conv5'), + BatchNorm(phase, detail + '_batchNorm4'), + MaxPool((3, 3), (2, 2)), + ReLU(), + Flatten(), + HiddenLinear(4096, detail + 'ip1', useBias=True), # first f.c. layer + BatchNorm(phase, detail + '_batchNorm5'), + ReLU(), + HiddenLinear(4096, detail + 'ip2', useBias=False), + BatchNorm(phase, detail + '_batchNorm6'), + ReLU(), + Linear(nb_classes, detail, useBias=True), + Softmax(temperature)] + + model = MLP(layers, input_shape) + print('Finished making basic alexnet') + return model + +################## low precision version of alexnet ################# +def make_basic_lowprecision_alexnet(phase, temperature, detail, wbits, abits, nb_filters=32, nb_classes=10, + input_shape=(None, 28, 28, 1)): + + layers = [Conv2D(3*nb_filters, (12, 12), (4, 4), "VALID", phase, detail + 'conv1', useBias=True), + ReLU(), + Conv2DGroup_lowprecision(wbits, abits, 8*nb_filters, (5, 5), + (1, 1), "SAME", phase, detail + 'conv2'), # useBatchNorm not set here + BatchNorm(phase, detail + '_batchNorm1'), + MaxPoolSame((3, 3), (2, 2)), # pool1 (3,3) pool size and (2,2) stride + ReLU(), + Conv2D_lowprecision(wbits, abits, 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail + 'conv3'), + BatchNorm(phase, detail + '_batchNorm2'), + MaxPoolSame((3, 3), (2, 2)), # pool2 (3,3) pool size and (2,2) stride + ReLU(), + Conv2DGroup_lowprecision(wbits, abits, 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail + 'conv4'), + BatchNorm(phase, detail + '_batchNorm3'), + ReLU(), + Conv2DGroup_lowprecision(wbits, abits, 8*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail + 'conv5'), + BatchNorm(phase, detail + '_batchNorm4'), + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Flatten(), + HiddenLinear_lowprecision(wbits, abits, 4096, detail + 'ip1', useBias=True), # first f.c. layer + BatchNorm(phase, detail + '_batchNorm5'), + ReLU(), + HiddenLinear_lowprecision(wbits, abits, 4096, detail + 'ip2'), + BatchNorm(phase, detail + '_batchNorm6'), + ReLU(), + Linear(nb_classes, detail, useBias=True), # Last layer is not quantized + Softmax(temperature)] + + model = MLP(layers, input_shape) + print('Finished making basic alexnet of low precision') + return model + +def make_layerwise_lowprecision_alexnet(phase, temperature, detail, wbits, abits, nb_filters=32, nb_classes=10, + input_shape=(None, 28, 28, 1)): + + layers = [Conv2D(3*nb_filters, (12, 12), (4, 4), "VALID", phase, detail + 'conv1', useBias=True), + ReLU(), + Conv2DGroup_lowprecision(wbits[0], abits[0], 8*nb_filters, (5, 5), + (1, 1), "SAME", phase, detail + 'conv2'), # useBatchNorm not set here + BatchNorm(phase, detail + '_batchNorm1'), + MaxPoolSame((3, 3), (2, 2)), # pool1 (3,3) pool size and (2,2) stride + ReLU(), + Conv2D_lowprecision(wbits[1], abits[1], 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail + 'conv3'), + BatchNorm(phase, detail + '_batchNorm2'), + MaxPoolSame((3, 3), (2, 2)), # pool2 (3,3) pool size and (2,2) stride + ReLU(), + Conv2DGroup_lowprecision(wbits[2], abits[2], 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail + 'conv4'), + BatchNorm(phase, detail + '_batchNorm3'), + ReLU(), + Conv2DGroup_lowprecision(wbits[3], abits[3], 8*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail + 'conv5'), + BatchNorm(phase, detail + '_batchNorm4'), + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Flatten(), + HiddenLinear_lowprecision(wbits[4], abits[4], 4096, detail + 'ip1', useBias=True), # first f.c. layer + BatchNorm(phase, detail + '_batchNorm5'), + ReLU(), + HiddenLinear_lowprecision(wbits[5], abits[5], 4096, detail + 'ip2'), + BatchNorm(phase, detail + '_batchNorm6'), + ReLU(), + Linear(nb_classes, detail, useBias=True), # Last layer is not quantized + Softmax(temperature)] + + model = MLP(layers, input_shape) + print('Finished making layerwise alexnet of low precision') + return model + +################## EMPIR version of alexnet ################# +def make_ensemble_three_alexnet(phase, temperature, detail1, detail2, detail3, wbits1, abits1, wbits2, abits2, nb_filters=32, nb_classes=10, + input_shape=(None, 28, 28, 1), useBatchNorm=False): + # make a low precision cnn + layers1 = [Conv2D(3*nb_filters, (12, 12), (4, 4), "VALID", phase, detail1 + 'conv1', useBias=True), + ReLU(), + Conv2DGroup_lowprecision(wbits1, abits1, 8*nb_filters, (5, 5), + (1, 1), "SAME", phase, detail1 + 'conv2'), + BatchNorm(phase, detail1 + '_batchNorm1'), + MaxPoolSame((3, 3), (2, 2)), + ReLU(), + Conv2D_lowprecision(wbits1, abits1, 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail1 + 'conv3'), + BatchNorm(phase, detail1 + '_batchNorm2'), + MaxPoolSame((3, 3), (2, 2)), + ReLU(), + Conv2DGroup_lowprecision(wbits1, abits1, 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail1 + 'conv4'), + BatchNorm(phase, detail1 + '_batchNorm3'), + ReLU(), + Conv2DGroup_lowprecision(wbits1, abits1, 8*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail1 + 'conv5'), + BatchNorm(phase, detail1 + '_batchNorm4'), + MaxPool((3, 3), (2, 2)), + ReLU(), + Flatten(), + HiddenLinear_lowprecision(wbits1, abits1, 4096, detail1 + 'ip1', useBias=True), # first f.c. layer + BatchNorm(phase, detail1 + '_batchNorm5'), + ReLU(), + HiddenLinear_lowprecision(wbits1, abits1, 4096, detail1 + 'ip2', useBias=False), + BatchNorm(phase, detail1 + '_batchNorm6'), + ReLU(), + Linear(nb_classes, detail1, useBias=True), + Softmax(temperature)] + + # make another low precision cnn + layers2 = [Conv2D(3*nb_filters, (12, 12), (4, 4), "VALID", phase, detail2 + 'conv1', useBias=True), + ReLU(), + Conv2DGroup_lowprecision(wbits2, abits2, 8*nb_filters, (5, 5), + (1, 1), "SAME", phase, detail2 + 'conv2'), + BatchNorm(phase, detail2 + '_batchNorm1'), + MaxPoolSame((3, 3), (2, 2)), + ReLU(), + Conv2D_lowprecision(wbits2, abits2, 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail2 + 'conv3'), + BatchNorm(phase, detail2 + '_batchNorm2'), + MaxPoolSame((3, 3), (2, 2)), + ReLU(), + Conv2DGroup_lowprecision(wbits2, abits2, 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail2 + 'conv4'), + BatchNorm(phase, detail2 + '_batchNorm3'), + ReLU(), + Conv2DGroup_lowprecision(wbits2, abits2, 8*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail2 + 'conv5'), + BatchNorm(phase, detail2 + '_batchNorm4'), + MaxPool((3, 3), (2, 2)), + ReLU(), + Flatten(), + HiddenLinear_lowprecision(wbits2, abits2, 4096, detail2 + 'ip1', useBias=True), # first f.c. layer + BatchNorm(phase, detail2 + '_batchNorm5'), + ReLU(), + HiddenLinear_lowprecision(wbits2, abits2, 4096, detail2 + 'ip2', useBias=False), + BatchNorm(phase, detail2 + '_batchNorm6'), + ReLU(), + Linear(nb_classes, detail2, useBias=True), # Last layer is not quantized + Softmax(temperature)] + + # make a full precision cnn with full precision weights and activations + layers3 = [Conv2D(3*nb_filters, (12, 12), (4, 4), "VALID", phase, detail3 + 'conv1', useBias=True), + ReLU(), + Conv2DGroup(8*nb_filters, (5, 5), + (1, 1), "SAME", phase, detail3 + 'conv2'), + BatchNorm(phase, detail3 + '_batchNorm1'), + MaxPoolSame((3, 3), (2, 2)), + ReLU(), + Conv2D(12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail3 + 'conv3'), + BatchNorm(phase, detail3 + '_batchNorm2'), + MaxPoolSame((3, 3), (2, 2)), + ReLU(), + Conv2DGroup(12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail3 + 'conv4'), + BatchNorm(phase, detail3 + '_batchNorm3'), + ReLU(), + Conv2DGroup(8*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail3 + 'conv5'), + BatchNorm(phase, detail3 + '_batchNorm4'), + MaxPool((3, 3), (2, 2)), + ReLU(), + Flatten(), + HiddenLinear(4096, detail3 + 'ip1', useBias=True), # first f.c. layer + BatchNorm(phase, detail3 + '_batchNorm5'), + ReLU(), + HiddenLinear(4096, detail3 + 'ip2', useBias=False), + BatchNorm(phase, detail3 + '_batchNorm6'), + ReLU(), + Linear(nb_classes, detail3, useBias=True), + Softmax(temperature)] + + model = ensembleThreeModel(layers1, layers2, layers3, input_shape, nb_classes) + print('Finished making ensemble of three cnns') + + return model + +def make_ensemble_three_alexnet_layerwise(phase, temperature, detail1, detail2, detail3, wbits1, abits1, wbits2, abits2, nb_filters=32, nb_classes=10, + input_shape=(None, 28, 28, 1)): + # make a low precision cnn + layers1 = [Conv2D(3*nb_filters, (12, 12), (4, 4), "VALID", phase, detail1 + 'conv1', useBias=True), + ReLU(), + Conv2DGroup_lowprecision(wbits1[0], abits1[0], 8*nb_filters, (5, 5), + (1, 1), "SAME", phase, detail1 + 'conv2'), + BatchNorm(phase, detail1 + '_batchNorm1'), + MaxPoolSame((3, 3), (2, 2)), # pool1 (3,3) pool size and (2,2) stride + ReLU(), + Conv2D_lowprecision(wbits1[1], abits1[1], 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail1 + 'conv3'), + BatchNorm(phase, detail1 + '_batchNorm2'), + MaxPoolSame((3, 3), (2, 2)), # pool2 (3,3) pool size and (2,2) stride + ReLU(), + Conv2DGroup_lowprecision(wbits1[2], abits1[2], 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail1 + 'conv4'), + BatchNorm(phase, detail1 + '_batchNorm3'), + ReLU(), + Conv2DGroup_lowprecision(wbits1[3], abits1[3], 8*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail1 + 'conv5'), + BatchNorm(phase, detail1 + '_batchNorm4'), + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Flatten(), + HiddenLinear_lowprecision(wbits1[4], abits1[4], 4096, detail1 + 'ip1', useBias=True), # first f.c. layer + BatchNorm(phase, detail1 + '_batchNorm5'), + ReLU(), + HiddenLinear_lowprecision(wbits1[5], abits1[5], 4096, detail1 + 'ip2'), + BatchNorm(phase, detail1 + '_batchNorm6'), + ReLU(), + Linear(nb_classes, detail1, useBias=True), # Last layer is not quantized + Softmax(temperature)] + + # make another low precision cnn + layers2 = [Conv2D(3*nb_filters, (12, 12), (4, 4), "VALID", phase, detail2 + 'conv1', useBias=True), + ReLU(), + Conv2DGroup_lowprecision(wbits2[0], abits2[0], 8*nb_filters, (5, 5), + (1, 1), "SAME", phase, detail2 + 'conv2'), # useBatchNorm not set here + BatchNorm(phase, detail2 + '_batchNorm1'), + MaxPoolSame((3, 3), (2, 2)), # pool1 (3,3) pool size and (2,2) stride + ReLU(), + Conv2D_lowprecision(wbits2[1], abits2[1], 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail2 + 'conv3'), + BatchNorm(phase, detail2 + '_batchNorm2'), + MaxPoolSame((3, 3), (2, 2)), # pool2 (3,3) pool size and (2,2) stride + ReLU(), + Conv2DGroup_lowprecision(wbits2[2], abits2[2], 12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail2 + 'conv4'), + BatchNorm(phase, detail2 + '_batchNorm3'), + ReLU(), + Conv2DGroup_lowprecision(wbits2[3], abits2[3], 8*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail2 + 'conv5'), + BatchNorm(phase, detail2 + '_batchNorm4'), + MaxPool((3, 3), (2, 2)), # (3,3) pool size and (2,2) stride + ReLU(), + Flatten(), + HiddenLinear_lowprecision(wbits2[4], abits2[4], 4096, detail2 + 'ip1', useBias=True), # first f.c. layer + BatchNorm(phase, detail2 + '_batchNorm5'), + ReLU(), + HiddenLinear_lowprecision(wbits2[5], abits2[5], 4096, detail2 + 'ip2'), + BatchNorm(phase, detail2 + '_batchNorm6'), + ReLU(), + Linear(nb_classes, detail2, useBias=True), # Last layer is not quantized + Softmax(temperature)] + + # make a full precision cnn with full precision weights and activations + layers3 = [Conv2D(3*nb_filters, (12, 12), (4, 4), "VALID", phase, detail3 + 'conv1', useBias=True), + ReLU(), + Conv2DGroup(8*nb_filters, (5, 5), + (1, 1), "SAME", phase, detail3 + 'conv2'), + BatchNorm(phase, detail3 + '_batchNorm1'), + MaxPoolSame((3, 3), (2, 2)), + ReLU(), + Conv2D(12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail3 + 'conv3'), + BatchNorm(phase, detail3 + '_batchNorm2'), + MaxPoolSame((3, 3), (2, 2)), + ReLU(), + Conv2DGroup(12*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail3 + 'conv4'), + BatchNorm(phase, detail3 + '_batchNorm3'), + ReLU(), + Conv2DGroup(8*nb_filters, (3, 3), + (1, 1), "SAME", phase, detail3 + 'conv5'), + BatchNorm(phase, detail3 + '_batchNorm4'), + MaxPool((3, 3), (2, 2)), + ReLU(), + Flatten(), + HiddenLinear(4096, detail3 + 'ip1', useBias=True), # first f.c. layer + BatchNorm(phase, detail3 + '_batchNorm5'), + ReLU(), + HiddenLinear(4096, detail3 + 'ip2', useBias=False), + BatchNorm(phase, detail3 + '_batchNorm6'), + ReLU(), + Linear(nb_classes, detail3, useBias=True), + Softmax(temperature)] + + model = ensembleThreeModel(layers1, layers2, layers3, input_shape, nb_classes) + print('Finished making ensemble of three models') + + return model diff --git a/case_studies/empir/examples/__init__.py b/case_studies/empir/examples/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/case_studies/empir/examples/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/case_studies/empir/examples/alexnet_attack.py b/case_studies/empir/examples/alexnet_attack.py new file mode 100644 index 0000000..11cf233 --- /dev/null +++ b/case_studies/empir/examples/alexnet_attack.py @@ -0,0 +1,753 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import keras +from keras import backend +from keras.utils import np_utils + +import os +import argparse +import logging +import numpy as np +import tensorflow as tf +from tensorflow.python.platform import flags + +import sys +sys.path.insert(0, "/home/consus/a/sen9/verifiedAI/cleverhans_EMPIR") + +#from modified_cleverhans.attacks import fgsm +from modified_cleverhans.utils import set_log_level, parse_model_settings, build_model_save_path +from modified_cleverhans.attacks import FastGradientMethod +from modified_cleverhans.utils_keras import cnn_model +from modified_cleverhans.utils_tf import batch_eval, tf_model_load +from modified_cleverhans.utils_tf import model_train_imagenet, model_eval_imagenet, model_eval_ensemble_imagenet, model_eval_adv_imagenet, model_eval_ensemble_adv_imagenet +from examples import imagenet_preprocessing #for imagenet preprocessing + +from collections import OrderedDict + +FLAGS = flags.FLAGS + +ATTACK_CARLINI_WAGNER_L2 = 0 +ATTACK_JSMA = 1 +ATTACK_FGSM = 2 +ATTACK_MADRYETAL = 3 +ATTACK_BASICITER = 4 +MAX_BATCH_SIZE = 100 + +# enum adversarial training types +ADVERSARIAL_TRAINING_MADRYETAL = 1 +ADVERSARIAL_TRAINING_FGSM = 2 +MAX_EPS = 0.3 + +# Scaling input to softmax +INIT_T = 1.0 + +#ATTACK_T = 1.0 +ATTACK_T = 0.25 + +_DEFAULT_IMAGE_SIZE = 224 +_NUM_CHANNELS = 3 +_NUM_CLASSES = 1000 + +_NUM_TRAIN_FILES = 1024 +_SHUFFLE_BUFFER = 10000 + +def get_filenames(is_training, data_dir): + """Return filenames for dataset.""" + if is_training: + return [ + os.path.join(data_dir, 'Train-%05d-of-01024' % i) + for i in range(_NUM_TRAIN_FILES)] + else: + return [ + os.path.join(data_dir, 'Val-%05d-of-00128' % i) + for i in range(128)] + +def _parse_example_proto(example_serialized): + """Parses an Example proto containing a training example of an image. + The output of the build_image_data.py image preprocessing script is a dataset + containing serialized Example protocol buffers. Each Example proto contains + the following fields (values are included as examples): + image/height': _int64_feature(height), + image/width': _int64_feature(width), + image/colorspace': _bytes_feature(colorspace), + image/channels': _int64_feature(channels), + image/class/label': _int64_feature(label), + image/class/synset': _bytes_feature(synset), + image/format': _bytes_feature(image_format), + image/filename': _bytes_feature(os.path.basename(filename)), + image/encoded': _bytes_feature(image_buffer)})) + + Args: + example_serialized: scalar Tensor tf.string containing a serialized + Example protocol buffer. + Returns: + image_buffer: Tensor tf.string containing the contents of a JPEG file. + label: Tensor tf.int32 containing the label. + bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords] + where each coordinate is [0, 1) and the coordinates are arranged as + [ymin, xmin, ymax, xmax]. + """ + # Dense features in Example proto. + feature_map = { + 'image/height': tf.FixedLenFeature([], dtype=tf.int64), + 'image/width': tf.FixedLenFeature([], dtype=tf.int64), + 'image/colorspace': tf.VarLenFeature(dtype=tf.string), + 'image/channels': tf.FixedLenFeature([], dtype=tf.int64), + 'image/class/label': tf.FixedLenFeature([], dtype=tf.int64), + 'image/class/synset': tf.VarLenFeature(dtype=tf.string), + 'image/format': tf.VarLenFeature(dtype=tf.string), + 'image/filename': tf.VarLenFeature(dtype=tf.string), + 'image/encoded': tf.FixedLenFeature([], dtype=tf.string), + } + features = tf.parse_single_example(example_serialized, feature_map) + label = tf.cast(features['image/class/label'], dtype=tf.int32) + one_hot_label = tf.one_hot(label, _NUM_CLASSES, 1, 0) #convert it to a one_hot vector + + # Directly fixing values of min and max + xmin = tf.expand_dims([0.0], 0) + ymin = tf.expand_dims([0.0], 0) + xmax = tf.expand_dims([1.0], 0) + ymax = tf.expand_dims([1.0], 0) + + # Note that we impose an ordering of (y, x) just to make life difficult. + bbox = tf.concat([ymin, xmin, ymax, xmax], 0) + + # Force the variable number of bounding boxes into the shape + # [1, num_boxes, coords]. + bbox = tf.expand_dims(bbox, 0) + bbox = tf.transpose(bbox, [0, 2, 1]) + + return features['image/encoded'], one_hot_label, bbox + +# variant of the above to parse training datasets which have labels from 1 to 1000 instead of 0 to 999 +def _parse_train_example_proto(example_serialized): + """Parses an Example proto containing a training example of an image. + The output of the build_image_data.py image preprocessing script is a dataset + containing serialized Example protocol buffers. Each Example proto contains + the following fields (values are included as examples): + image/height': _int64_feature(height), + image/width': _int64_feature(width), + image/colorspace': _bytes_feature(colorspace), + image/channels': _int64_feature(channels), + image/class/label': _int64_feature(label), + image/class/synset': _bytes_feature(synset), + image/format': _bytes_feature(image_format), + image/filename': _bytes_feature(os.path.basename(filename)), + image/encoded': _bytes_feature(image_buffer)})) + + Args: + example_serialized: scalar Tensor tf.string containing a serialized + Example protocol buffer. + Returns: + image_buffer: Tensor tf.string containing the contents of a JPEG file. + label: Tensor tf.int32 containing the label. + bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords] + where each coordinate is [0, 1) and the coordinates are arranged as + [ymin, xmin, ymax, xmax]. + """ + # Dense features in Example proto. + feature_map = { + 'image/height': tf.FixedLenFeature([], dtype=tf.int64), + 'image/width': tf.FixedLenFeature([], dtype=tf.int64), + 'image/colorspace': tf.VarLenFeature(dtype=tf.string), + 'image/channels': tf.FixedLenFeature([], dtype=tf.int64), + 'image/class/label': tf.FixedLenFeature([], dtype=tf.int64), + 'image/class/synset': tf.VarLenFeature(dtype=tf.string), + 'image/format': tf.VarLenFeature(dtype=tf.string), + 'image/filename': tf.VarLenFeature(dtype=tf.string), + 'image/encoded': tf.FixedLenFeature([], dtype=tf.string), + } + features = tf.parse_single_example(example_serialized, feature_map) + label = tf.cast(features['image/class/label'], dtype=tf.int32) -1 + one_hot_label = tf.one_hot(label, _NUM_CLASSES, 1, 0) #convert it to a one_hot vector + + # Directly fixing values of min and max + xmin = tf.expand_dims([0.0], 0) + ymin = tf.expand_dims([0.0], 0) + xmax = tf.expand_dims([1.0], 0) + ymax = tf.expand_dims([1.0], 0) + + # Note that we impose an ordering of (y, x) just to make life difficult. + bbox = tf.concat([ymin, xmin, ymax, xmax], 0) + + # Force the variable number of bounding boxes into the shape + # [1, num_boxes, coords]. + bbox = tf.expand_dims(bbox, 0) + bbox = tf.transpose(bbox, [0, 2, 1]) + + return features['image/encoded'], one_hot_label, bbox + +def parse_record(raw_record, is_training, dtype): + """Parses a record containing a training example of an image. + The input record is parsed into a label and image, and the image is passed + through preprocessing steps (cropping, flipping, and so on). + Args: + raw_record: scalar Tensor tf.string containing a serialized + Example protocol buffer. + is_training: A boolean denoting whether the input is for training. + dtype: data type to use for images/features. + Returns: + Tuple with processed image tensor and one-hot-encoded label tensor. + """ + if is_training: + image_buffer, label, bbox = _parse_train_example_proto(raw_record) + else: + image_buffer, label, bbox = _parse_example_proto(raw_record) + + image = imagenet_preprocessing.preprocess_image4( # For pretrained Dorefanet network with division by standard deviation + image_buffer=image_buffer, + bbox=bbox, + output_height=_DEFAULT_IMAGE_SIZE, + output_width=_DEFAULT_IMAGE_SIZE, + num_channels=_NUM_CHANNELS, + is_training=is_training) + + image = tf.cast(image, dtype) + + return image, label + +def process_record_dataset(dataset, + is_training, + batch_size, + shuffle_buffer, + parse_record_fn, + num_epochs=1, + dtype=tf.float32, + datasets_num_private_threads=None, + num_parallel_batches=1): + """Given a Dataset with raw records, return an iterator over the records. + Args: + dataset: A Dataset representing raw records + is_training: A boolean denoting whether the input is for training. + batch_size: The number of samples per batch. + shuffle_buffer: The buffer size to use when shuffling records. A larger + value results in better randomness, but smaller values reduce startup + time and use less memory. + parse_record_fn: A function that takes a raw record and returns the + corresponding (image, label) pair. + num_epochs: The number of epochs to repeat the dataset. + dtype: Data type to use for images/features. + datasets_num_private_threads: Number of threads for a private + threadpool created for all datasets computation. + num_parallel_batches: Number of parallel batches for tf.data. + Returns: + Dataset of (image, label) pairs ready for iteration. + """ + + # Prefetches a batch at a time to smooth out the time taken to load input + # files for shuffling and processing. + dataset = dataset.prefetch(buffer_size=batch_size) + if is_training: + # Shuffles records before repeating to respect epoch boundaries. + dataset = dataset.shuffle(buffer_size=shuffle_buffer) + + # Repeats the dataset for the number of epochs to train. + + # Parses the raw records into images and labels. + dataset = dataset.apply( + tf.contrib.data.map_and_batch( + lambda value: parse_record_fn(value, is_training, dtype), + batch_size=batch_size, + num_parallel_batches=num_parallel_batches)) + + # Operations between the final prefetch and the get_next call to the iterator + # will happen synchronously during run time. We prefetch here again to + # background all of the above processing work and keep it out of the + # critical training path. Setting buffer_size to tf.contrib.data.AUTOTUNE + # allows DistributionStrategies to adjust how many batches to fetch based + # on how many devices are present. + # dataset = dataset.prefetch(buffer_size=tf.contrib.data.AUTOTUNE) + dataset = dataset.prefetch(buffer_size=1) + + return dataset + +def data_imagenet(nb_epochs, batch_size, imagenet_path): + """ + Preprocess Imagenet dataset + :return: + """ + + # Load images from dataset + test_dataset =tf.data.TFRecordDataset(get_filenames(is_training=False, data_dir=imagenet_path+'/Val')) + + train_dataset = tf.data.TFRecordDataset(get_filenames(is_training=True, data_dir=imagenet_path+'/Train')) + + train_processed = process_record_dataset(dataset=train_dataset, is_training=True, batch_size=batch_size, shuffle_buffer=_SHUFFLE_BUFFER, num_epochs = nb_epochs, parse_record_fn=parse_record) + + test_processed = process_record_dataset(dataset=test_dataset, is_training=False, batch_size=batch_size, shuffle_buffer=_SHUFFLE_BUFFER, parse_record_fn=parse_record) + + return train_processed, test_processed + +def main(argv=None): + model_path = FLAGS.model_path + targeted = True if FLAGS.targeted else False + scale = True if FLAGS.scale else False + learning_rate = FLAGS.learning_rate + nb_filters = FLAGS.nb_filters + batch_size = FLAGS.batch_size + nb_epochs = FLAGS.nb_epochs + delay = FLAGS.delay + eps = FLAGS.eps + adv = FLAGS.adv + + attack = FLAGS.attack + attack_iterations = FLAGS.attack_iterations + nb_iter = FLAGS.nb_iter + + #### EMPIR extra flags + lowprecision=FLAGS.lowprecision + abits=FLAGS.abits + wbits=FLAGS.wbits + abitsList=FLAGS.abitsList + wbitsList=FLAGS.wbitsList + stocRound=True if FLAGS.stocRound else False + rand=FLAGS.rand + model_path2 = FLAGS.model_path2 + model_path1 = FLAGS.model_path1 + model_path3 = FLAGS.model_path3 + ensembleThree=True if FLAGS.ensembleThree else False + abits2=FLAGS.abits2 + wbits2=FLAGS.wbits2 + abits2List=FLAGS.abits2List + wbits2List=FLAGS.wbits2List + #### + + save = False + train_from_scratch = False + + #### Imagenet flags + imagenet_path = FLAGS.imagenet_path + if imagenet_path is None: + print("Error: Imagenet data path not specified") + sys.exit(1) + + # Imagenet specific dimensions + img_rows = _DEFAULT_IMAGE_SIZE + img_cols = _DEFAULT_IMAGE_SIZE + channels = _NUM_CHANNELS + nb_classes = _NUM_CLASSES + + # Set TF random seed to improve reproducibility + tf.set_random_seed(1234) + + if not hasattr(backend, "tf"): + raise RuntimeError("This tutorial requires keras to be configured" + " to use the TensorFlow backend.") + + # Image dimensions ordering should follow the Theano convention + if keras.backend.image_dim_ordering() != 'tf': + keras.backend.set_image_dim_ordering('tf') + print("INFO: '~/.keras/keras.json' sets 'image_dim_ordering' to " + "'th', temporarily setting to 'tf'") + + # Create TF session and set as Keras backend session + sess = tf.Session() + keras.backend.set_session(sess) + + set_log_level(logging.WARNING) + + # Get imagenet datasets + train_dataset, test_dataset = data_imagenet(nb_epochs, batch_size, imagenet_path) + + # Creating a initializable iterators + train_iterator = train_dataset.make_initializable_iterator() + test_iterator = test_dataset.make_initializable_iterator() + + # Getting next elements from the iterators + next_test_element = test_iterator.get_next() + next_train_element = train_iterator.get_next() + + train_x, train_y = train_iterator.get_next() + test_x, test_y = test_iterator.get_next() + + # Define input TF placeholder + x = tf.placeholder(tf.float32, shape=(None, img_rows, img_cols, channels)) + y = tf.placeholder(tf.float32, shape=(None, nb_classes)) + phase = tf.placeholder(tf.bool, name="phase") + + logits_scalar = tf.placeholder_with_default( + INIT_T, shape=(), name="logits_temperature") + + if ensembleThree: + if (model_path1 is None or model_path2 is None or model_path3 is None): + train_from_scratch = True + else: + train_from_scratch = False + elif model_path is not None: + if os.path.exists(model_path): + # check for existing model in immediate subfolder + if any(f.endswith('.meta') for f in os.listdir(model_path)): + train_from_scratch = False + else: + model_path = build_model_save_path( + model_path, batch_size, nb_filters, learning_rate, nb_epochs, adv, delay) + print(model_path) + save = True + train_from_scratch = True + else: + train_from_scratch = True # train from scratch, but don't save since no path given + + if ensembleThree: + if (wbitsList is None) or (abitsList is None): # Layer wise separate quantization not specified for first model + if (wbits==0) or (abits==0): + print("Error: the number of bits for constant precision weights and activations across layers for the first model have to specified using wbits1 and abits1 flags") + sys.exit(1) + else: + fixedPrec1 = 1 + elif (len(wbitsList) != 6) or (len(abitsList) != 6): + print("Error: Need to specify the precisions for activations and weights for the atleast the four convolutional layers of alexnet excluding the first layer and 2 fully connected layers excluding the last layer of the first model") + sys.exit(1) + else: + fixedPrec1 = 0 + + if (wbits2List is None) or (abits2List is None): # Layer wise separate quantization not specified for second model + if (wbits2==0) or (abits2==0): + print("Error: the number of bits for constant precision weights and activations across layers for the second model have to specified using wbits1 and abits1 flags") + sys.exit(1) + else: + fixedPrec2 = 1 + elif (len(wbits2List) != 6) or (len(abits2List) != 6): + print("Error: Need to specify the precisions for activations and weights for the atleast the four convolutional layers of alexnet excluding the first layer and 2 fully connected layers excluding the last layer of the second model") + sys.exit(1) + else: + fixedPrec2 = 0 + + if (fixedPrec2 != 1) or (fixedPrec1 != 1): # Atleast one of the models have separate precisions per layer + fixedPrec=0 + print("Within atleast one model has separate precisions") + if (fixedPrec1 == 1): # first layer has fixed precision + abitsList = (abits, abits, abits, abits, abits, abits) + wbitsList = (wbits, wbits, wbits, wbits, wbits, wbits) + if (fixedPrec2 == 1): # second layer has fixed precision + abits2List = (abits2, abits2, abits2, abits2, abits2, abits2) + wbits2List = (wbits2, wbits2, wbits2, wbits2, wbits2, wbits2) + else: + fixedPrec=1 + + if (train_from_scratch): + print ("The ensemble model cannot be trained from scratch") + sys.exit(1) + if fixedPrec == 1: + from modified_cleverhans_tutorials.tutorial_models import make_ensemble_three_alexnet + model = make_ensemble_three_alexnet( + phase, logits_scalar, 'lp1_', 'lp2_', 'fp_', wbits, abits, wbits2, abits2, input_shape=(None, img_rows, img_cols, channels), nb_filters=nb_filters, nb_classes=nb_classes) + else: + from modified_cleverhans_tutorials.tutorial_models import make_layerwise_three_combined_alexnet + model = make_layerwise_three_combined_alexnet( + phase, logits_scalar, 'lp1_', 'lp2_', 'fp_', wbitsList, abitsList, wbits2List, abits2List, input_shape=(None, img_rows, img_cols, channels), nb_filters=nb_filters, nb_classes=nb_classes) + elif lowprecision: + if (wbitsList is None) or (abitsList is None): # Layer wise separate quantization not specified + if (wbits==0) or (abits==0): + print("Error: the number of bits for constant precision weights and activations across layers have to specified using wbits and abits flags") + sys.exit(1) + else: + fixedPrec = 1 + elif (len(wbitsList) != 6) or (len(abitsList) != 6): + print("Error: Need to specify the precisions for activations and weights for the atleast the four convolutional layers of alexnet excluding the first layer and 2 fully connected layers excluding the last layer") + sys.exit(1) + else: + fixedPrec = 0 + + if fixedPrec: + + ### For training from scratch + from modified_cleverhans_tutorials.tutorial_models import make_basic_lowprecision_alexnet + model = make_basic_lowprecision_alexnet(phase, logits_scalar, 'lp_', wbits, abits, input_shape=( + None, img_rows, img_cols, channels), nb_filters=nb_filters, nb_classes=nb_classes) + else: + from modified_cleverhans_tutorials.tutorial_models import make_layerwise_lowprecision_alexnet + model = make_layerwise_lowprecision_alexnet(phase, logits_scalar, 'lp_', wbitsList, abitsList, + input_shape=(None, img_rows, img_cols, channels), nb_filters=nb_filters, nb_classes=nb_classes) + else: + ### For training from scratch + from modified_cleverhans_tutorials.tutorial_models import make_basic_alexnet_from_scratch + model = make_basic_alexnet_from_scratch(phase, logits_scalar, 'fp_', input_shape=( + None, img_rows, img_cols, channels), nb_filters=nb_filters, nb_classes=nb_classes) + + # separate calling function for ensemble models + if ensembleThree: + preds = model.ensemble_call(x, reuse=False) + else: + ##default + preds = model(x, reuse=False) + print("Defined TensorFlow model graph.") + + rng = np.random.RandomState([2017, 8, 30]) + + def evaluate(): + # Evaluate the accuracy of the CIFAR10 model on legitimate test + # examples + eval_params = {'batch_size': batch_size} + if ensembleThree: + acc = model_eval_ensemble_imagenet( + sess, x, y, preds, test_iterator, test_x, test_y, phase=phase, args=eval_params) + else: #default below + acc = model_eval_imagenet( + sess, x, y, preds, test_iterator, test_x, test_y, phase=phase, args=eval_params) + print('Test accuracy on legitimate examples: %0.4f' % acc) + + # Train an Imagenet model + train_params = { + 'lowprecision': lowprecision, + 'nb_epochs': nb_epochs, + 'batch_size': batch_size, + 'learning_rate': learning_rate, + 'loss_name': 'train loss', + 'filename': 'model', + 'reuse_global_step': False, + 'train_scope': 'train', + 'is_training': True + } + + if adv != 0: + if adv == ADVERSARIAL_TRAINING_MADRYETAL: + from modified_cleverhans.attacks import MadryEtAl + train_attack_params = {'eps': MAX_EPS, 'eps_iter': 0.01, + 'nb_iter': nb_iter} + train_attacker = MadryEtAl(model, sess=sess) + + elif adv == ADVERSARIAL_TRAINING_FGSM: + from modified_cleverhans.attacks import FastGradientMethod + stddev = int(np.ceil((MAX_EPS * 255) // 2)) + train_attack_params = {'eps': tf.abs(tf.truncated_normal( + shape=(batch_size, 1, 1, 1), mean=0, stddev=stddev))} + train_attacker = FastGradientMethod(model, back='tf', sess=sess) + # create the adversarial trainer + train_attack_params.update({'clip_min': 0., 'clip_max': 1.}) + adv_x_train = train_attacker.generate(x, phase, **train_attack_params) + preds_adv_train = model.get_probs(adv_x_train) + + eval_attack_params = {'eps': MAX_EPS, 'clip_min': 0., 'clip_max': 1.} + adv_x_eval = train_attacker.generate(x, phase, **eval_attack_params) + preds_adv_eval = model.get_probs(adv_x_eval) # * logits_scalar + # if adv: + # from modified_cleverhans.attacks import FastGradientMethod + # fgsm = FastGradientMethod(model, back='tf', sess=sess) + # fgsm_params = {'eps': eps, 'clip_min': 0., 'clip_max': 1.} + # adv_x_train = fgsm.generate(x, phase, **fgsm_params) + # preds_adv = model.get_probs(adv_x_train) + + if train_from_scratch: + if save: + train_params.update({'log_dir': model_path}) + if adv and delay > 0: + train_params.update({'nb_epochs': delay}) + + # do clean training for 'nb_epochs' or 'delay' epochs with learning rate reducing with time + model_train_imagenet2(sess, x, y, preds, train_iterator, train_x, train_y, phase=phase, + evaluate=evaluate, args=train_params, save=save, rng=rng) + + # optionally do additional adversarial training + if adv: + print("Adversarial training for %d epochs" % (nb_epochs - delay)) + train_params.update({'nb_epochs': nb_epochs - delay}) + train_params.update({'reuse_global_step': True}) + model_train_imagenet(sess, x, y, preds, train_iterator, train_x, train_y, phase=phase, + predictions_adv=preds_adv_train, evaluate=evaluate, args=train_params, save=save, rng=rng) + else: + if ensembleThree: ## ensembleThree models have to loaded from different paths + variables = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) + # First 11 variables from path1 + stored_variables = ['lp_conv1_init/k', 'lp_conv1_init/b', 'lp_conv2_init/k', 'lp_conv3_init/k', 'lp_conv4_init/k', 'lp_conv5_init/k', 'lp_ip1init/W', 'lp_ip1init/b', 'lp_ip2init/W', 'lp_logits_init/W', 'lp_logits_init/b'] + variable_dict = dict(OrderedDict(zip(stored_variables, variables[:11]))) # only dict was messing with the order + # Restore the first set of variables from model_path1 + saver = tf.train.Saver(variable_dict) + saver.restore(sess, tf.train.latest_checkpoint(model_path1)) + # Restore the second set of variables from model_path2 + # Second 11 variables from path2 + variable_dict = dict(OrderedDict(zip(stored_variables, variables[11:22]))) + saver2 = tf.train.Saver(variable_dict) + saver2.restore(sess, tf.train.latest_checkpoint(model_path2)) + # Third 11 variables from path3 + stored_variables = ['fp_conv1_init/k', 'fp_conv1_init/b', 'fp_conv2_init/k', 'fp_conv3_init/k', 'fp_conv4_init/k', 'fp_conv5_init/k', 'fp_ip1init/W', 'fp_ip1init/b', 'fp_ip2init/W', 'fp_logits_init/W', 'fp_logits_init/b'] + variable_dict = dict(OrderedDict(zip(stored_variables, variables[22:33]))) + saver3 = tf.train.Saver(variable_dict) + saver3.restore(sess, tf.train.latest_checkpoint(model_path3)) + # Next 24 batch norm variables from path1 + stored_variables = ['lp__batchNorm1/batch_normalization/gamma', 'lp__batchNorm1/batch_normalization/beta', 'lp__batchNorm1/batch_normalization/moving_mean', 'lp__batchNorm1/batch_normalization/moving_variance', 'lp__batchNorm2/batch_normalization/gamma', 'lp__batchNorm2/batch_normalization/beta', 'lp__batchNorm2/batch_normalization/moving_mean', 'lp__batchNorm2/batch_normalization/moving_variance', 'lp__batchNorm3/batch_normalization/gamma', 'lp__batchNorm3/batch_normalization/beta', 'lp__batchNorm3/batch_normalization/moving_mean', 'lp__batchNorm3/batch_normalization/moving_variance', 'lp__batchNorm4/batch_normalization/gamma', 'lp__batchNorm4/batch_normalization/beta', 'lp__batchNorm4/batch_normalization/moving_mean', 'lp__batchNorm4/batch_normalization/moving_variance', 'lp__batchNorm5/batch_normalization/gamma', 'lp__batchNorm5/batch_normalization/beta', 'lp__batchNorm5/batch_normalization/moving_mean', 'lp__batchNorm5/batch_normalization/moving_variance', 'lp__batchNorm6/batch_normalization/gamma', 'lp__batchNorm6/batch_normalization/beta', 'lp__batchNorm6/batch_normalization/moving_mean', 'lp__batchNorm6/batch_normalization/moving_variance'] + + variable_dict = dict(OrderedDict(zip(stored_variables, variables[33:57]))) + saver = tf.train.Saver(variable_dict) + saver.restore(sess, tf.train.latest_checkpoint(model_path1)) + # Next 24 batch norm variables from path2 + variable_dict = dict(OrderedDict(zip(stored_variables, variables[57:81]))) + saver = tf.train.Saver(variable_dict) + saver.restore(sess, tf.train.latest_checkpoint(model_path2)) + # Final 24 batch norm variables from path1 + stored_variables = ['fp__batchNorm1/batch_normalization/gamma', 'fp__batchNorm1/batch_normalization/beta', 'fp__batchNorm1/batch_normalization/moving_mean', 'fp__batchNorm1/batch_normalization/moving_variance', 'fp__batchNorm2/batch_normalization/gamma', 'fp__batchNorm2/batch_normalization/beta', 'fp__batchNorm2/batch_normalization/moving_mean', 'fp__batchNorm2/batch_normalization/moving_variance', 'fp__batchNorm3/batch_normalization/gamma', 'fp__batchNorm3/batch_normalization/beta', 'fp__batchNorm3/batch_normalization/moving_mean', 'fp__batchNorm3/batch_normalization/moving_variance', 'fp__batchNorm4/batch_normalization/gamma', 'fp__batchNorm4/batch_normalization/beta', 'fp__batchNorm4/batch_normalization/moving_mean', 'fp__batchNorm4/batch_normalization/moving_variance', 'fp__batchNorm5/batch_normalization/gamma', 'fp__batchNorm5/batch_normalization/beta', 'fp__batchNorm5/batch_normalization/moving_mean', 'fp__batchNorm5/batch_normalization/moving_variance', 'fp__batchNorm6/batch_normalization/gamma', 'fp__batchNorm6/batch_normalization/beta', 'fp__batchNorm6/batch_normalization/moving_mean', 'fp__batchNorm6/batch_normalization/moving_variance'] + variable_dict = dict(OrderedDict(zip(stored_variables, variables[81:105]))) + saver = tf.train.Saver(variable_dict) + saver.restore(sess, tf.train.latest_checkpoint(model_path3)) + else: # restoring the model trained using this setup, not a downloaded one + tf_model_load(sess, model_path) + print('Restored model from %s' % model_path) + # evaluate() + + + # Evaluate the accuracy of the model on legitimate test examples + eval_params = {'batch_size': batch_size} + if ensembleThree: + accuracy = model_eval_ensemble_imagenet(sess, x, y, preds, test_iterator, test_x, test_y, phase=phase, feed={phase: False}, args=eval_params) + else: #default below + accuracy = model_eval_imagenet(sess, x, y, preds, test_iterator, test_x, test_y, phase=phase, feed={phase: False}, args=eval_params) + print('Test accuracy on legitimate test examples: {0}'.format(accuracy)) + + ########################################################################### + # Build dataset + ########################################################################### + + adv_inputs = test_x #adversarial inputs can be generated from any of the test examples + + ########################################################################### + # Craft adversarial examples using generic approach + ########################################################################### + nb_adv_per_sample = 1 + adv_ys = None + yname = "y" + + print('Crafting adversarial examples') + print("This could take some time ...") + + if ensembleThree: + model_type = 'ensembleThree' + else: + model_type = 'default' + + if attack == ATTACK_CARLINI_WAGNER_L2: + from modified_cleverhans.attacks import CarliniWagnerL2 + attacker = CarliniWagnerL2(model, back='tf', sess=sess, model_type=model_type, num_classes=nb_classes) + attack_params = {'binary_search_steps': 1, + 'max_iterations': attack_iterations, + 'learning_rate': 0.1, + 'batch_size': batch_size, + 'initial_const': 10, + } + elif attack == ATTACK_JSMA: + from modified_cleverhans.attacks import SaliencyMapMethod + attacker = SaliencyMapMethod(model, back='tf', sess=sess, model_type=model_type, num_classes=nb_classes) + attack_params = {'theta': 1., 'gamma': 0.1} + elif attack == ATTACK_FGSM: + from modified_cleverhans.attacks import FastGradientMethod + attacker = FastGradientMethod(model, back='tf', sess=sess, model_type=model_type, num_classes=nb_classes) + attack_params = {'eps': eps} + elif attack == ATTACK_MADRYETAL: + from modified_cleverhans.attacks import MadryEtAl + attacker = MadryEtAl(model, back='tf', sess=sess, model_type=model_type, num_classes=nb_classes) + attack_params = {'eps': eps, 'eps_iter': 0.01, 'nb_iter': nb_iter} + elif attack == ATTACK_BASICITER: + print('Attack: BasicIterativeMethod') + from modified_cleverhans.attacks import BasicIterativeMethod + attacker = BasicIterativeMethod(model, back='tf', sess=sess, model_type=model_type, num_classes=nb_classes) + attack_params = {'eps': eps, 'eps_iter': 0.01, 'nb_iter': nb_iter} + else: + print("Attack undefined") + sys.exit(1) + + attack_params.update({'clip_min': -2.2, 'clip_max': 2.7}) # Since max and min for imagenet turns out to be around -2.11 and 2.12 + eval_params = {'batch_size': batch_size} + ''' + adv_x = attacker.generate(x, phase, **attack_params) + # Craft adversarial examples using Fast Gradient Sign Method (FGSM) + eval_params = {'batch_size': batch_size} + X_test_adv, = batch_eval(sess, [x], [adv_x], [adv_inputs], feed={ + phase: False}, args=eval_params) + ''' + + print("Evaluating un-targeted results") + if ensembleThree: + adv_accuracy = model_eval_ensemble_adv_imagenet(sess, x, y, preds, test_iterator, + test_x, test_y, phase=phase, args=eval_params, attacker=attacker, attack_params=attack_params) + else: + adv_accuracy = model_eval_adv_imagenet(sess, x, y, preds, test_iterator, + test_x, test_y, phase=phase, args=eval_params, attacker=attacker, attack_params=attack_params) + + # Compute the number of adversarial examples that were successfully found + print('Test accuracy on adversarial examples {0:.4f}'.format(adv_accuracy)) + + + # Close TF session + sess.close() + + +if __name__ == '__main__': + + par = argparse.ArgumentParser() + + # Generic flags + par.add_argument('--gpu', help='id of GPU to use') + par.add_argument('--model_path', help='Path to save or load model') + par.add_argument('--data_dir', help='Path to training data', + default='/scratch/gallowaa/cifar10/cifar10_data') + + # Architecture and training specific flags + par.add_argument('--nb_epochs', type=int, default=6, + help='Number of epochs to train model') + par.add_argument('--nb_filters', type=int, default=32, + help='Number of filters in first layer') + par.add_argument('--batch_size', type=int, default=100, + help='Size of training batches') + par.add_argument('--learning_rate', type=float, default=0.001, + help='Learning rate') + par.add_argument('--scale', help='Scale activations of the binary model?', + action="store_true") + par.add_argument('--rand', help='Stochastic weight layer?', + action="store_true") + # EMPIR specific flags + par.add_argument('--lowprecision', help='Use other low precision models', action="store_true") + par.add_argument('--wbits', type=int, default=0, help='No. of bits in weight representation') + par.add_argument('--abits', type=int, default=0, help='No. of bits in activation representation') + par.add_argument('--wbitsList', type=int, nargs='+', help='List of No. of bits in weight representation for different layers') + par.add_argument('--abitsList', type=int, nargs='+', help='List of No. of bits in activation representation for different layers') + par.add_argument('--stocRound', help='Stochastic rounding for weights (only in training) and activations?', action="store_true") + par.add_argument('--model_path1', help='Path where saved model1 is stored and can be loaded') + par.add_argument('--model_path2', help='Path where saved model2 is stored and can be loaded') + par.add_argument('--ensembleThree', help='Use an ensemble of full precision and two low precision models that can be attacked directly and potentially trained', action="store_true") + par.add_argument('--model_path3', help='Path where saved model3 in case of combinedThree model is stored and can be loaded') + par.add_argument('--wbits2', type=int, default=0, help='No. of bits in weight representation of model2, model1 specified using wbits') + par.add_argument('--abits2', type=int, default=0, help='No. of bits in activation representation of model2, model2 specified using abits') + par.add_argument('--wbits2List', type=int, nargs='+', help='List of No. of bits in weight representation for different layers of model2') + par.add_argument('--abits2List', type=int, nargs='+', help='List of No. of bits in activation representation for different layers of model2') + + # Attack specific flags + par.add_argument('--eps', type=float, default=0.1, + help='epsilon') + par.add_argument('--attack', type=int, default=0, + help='Attack type, 0=CW, 2=FGSM') + par.add_argument('--attack_iterations', type=int, default=50, + help='Number of iterations to run CW attack; 1000 is good') + par.add_argument( + '--targeted', help='Run a targeted attack?', action="store_true") + # Adversarial training flags + par.add_argument( + '--adv', help='Adversarial training type?', type=int, default=0) + par.add_argument('--delay', type=int, + default=10, help='Nb of epochs to delay adv training by') + par.add_argument('--nb_iter', type=int, + default=40, help='Nb of iterations of PGD') + + # imagenet flags + par.add_argument('--imagenet_path', help='Path where imagenet tfrecords are stored and can be loaded, both Val and Train') + + FLAGS = par.parse_args() + + if FLAGS.gpu: + os.environ['CUDA_VISIBLE_DEVICES'] = FLAGS.gpu + + tf.app.run() diff --git a/case_studies/empir/examples/binarization_test.sh b/case_studies/empir/examples/binarization_test.sh new file mode 100644 index 0000000..0a0912c --- /dev/null +++ b/case_studies/empir/examples/binarization_test.sh @@ -0,0 +1,40 @@ +nsamples=${1:-512} + +#kwargs="" +kwargs="--sample-from-corners" + +echo "#samples: $nsamples" +echo "kwargs: $kwargs" + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "1 boundary point, 999 inner (Original attack)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd):case_studies/empir/ ./venv3.8tf/bin/python case_studies/empir/examples/cifar10_binarization_test.py \ + --ensembleThree \ + --attack=3 \ + --abits=2 \ + --wbits=4 \ + --abits2=2 \ + --wbits2=2 \ + --model_path1=case_studies/empir/weights/Model1/ \ + --model_path2=case_studies/empir/weights/Model2/ \ + --model_path3=case_studies/empir/weights/Model3/ \ + --nb_samples=$nsamples \ + $kwargs + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "1 boundary point, 999 inner (Adaptive attack)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd):case_studies/empir/ ./venv3.8tf/bin/python case_studies/empir/examples/cifar10_binarization_test.py \ + --ensembleThree \ + --attack=3 \ + --abits=2 \ + --wbits=4 \ + --abits2=2 \ + --wbits2=2 \ + --model_path1=case_studies/empir/weights/Model1/ \ + --model_path2=case_studies/empir/weights/Model2/ \ + --model_path3=case_studies/empir/weights/Model3/ \ + --nb_samples=$nsamples \ + --robust-attack \ + $kwargs diff --git a/case_studies/empir/examples/cifar10_attack.py b/case_studies/empir/examples/cifar10_attack.py new file mode 100644 index 0000000..6c8efa8 --- /dev/null +++ b/case_studies/empir/examples/cifar10_attack.py @@ -0,0 +1,540 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import logging + +logging.getLogger('tensorflow').setLevel(logging.FATAL) + +import tensorflow as tf + +tf.logging.set_verbosity(tf.logging.ERROR) + +import keras +from keras import backend +from keras.datasets import cifar10 +from keras.utils import np_utils + +import os +import argparse +import logging +import numpy as np +import tensorflow as tf +from tensorflow.python.platform import flags +import sys + +# from modified_cleverhans.attacks import fgsm +from modified_cleverhans.utils import set_log_level, parse_model_settings, \ + build_model_save_path +from modified_cleverhans.utils_tf import model_train, model_eval, \ + model_eval_ensemble, batch_eval, tf_model_load + +FLAGS = flags.FLAGS + +ATTACK_CARLINI_WAGNER_L2 = 0 +ATTACK_JSMA = 1 +ATTACK_FGSM = 2 +ATTACK_MADRYETAL = 3 +ATTACK_BASICITER = 4 +MAX_BATCH_SIZE = 100 +MAX_BATCH_SIZE = 100 + +# enum adversarial training types +ADVERSARIAL_TRAINING_MADRYETAL = 1 +ADVERSARIAL_TRAINING_FGSM = 2 +MAX_EPS = 0.3 + +# Scaling input to softmax +INIT_T = 1.0 +# ATTACK_T = 1.0 +ATTACK_T = 0.25 + + +def data_cifar10(): + """ + Preprocess CIFAR10 dataset + :return: + """ + + # These values are specific to CIFAR10 + img_rows = 32 + img_cols = 32 + nb_classes = 10 + + # the data, shuffled and split between train and test sets + (X_train, y_train), (X_test, y_test) = cifar10.load_data() + + if keras.backend.image_dim_ordering() == 'th': + X_train = X_train.reshape(X_train.shape[0], 3, img_rows, img_cols) + X_test = X_test.reshape(X_test.shape[0], 3, img_rows, img_cols) + else: + X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 3) + X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 3) + X_train = X_train.astype('float32') + X_test = X_test.astype('float32') + + X_train /= 255 + X_test /= 255 + + # convert class vectors to binary class matrices + Y_train = np_utils.to_categorical(y_train, nb_classes) + Y_test = np_utils.to_categorical(y_test, nb_classes) + + return X_train, Y_train, X_test, Y_test + + +def setup_model(): + # CIFAR10-specific dimensions + img_rows = 32 + img_cols = 32 + channels = 3 + nb_classes = 10 + + # Set TF random seed to improve reproducibility + tf.set_random_seed(1234) + + if not hasattr(backend, "tf"): + raise RuntimeError("This tutorial requires keras to be configured" + " to use the TensorFlow backend.") + + # Image dimensions ordering should follow the Theano convention + if keras.backend.image_dim_ordering() != 'tf': + keras.backend.set_image_dim_ordering('tf') + print("INFO: '~/.keras/keras.json' sets 'image_dim_ordering' to " + "'th', temporarily setting to 'tf'") + + # Create TF session and set as Keras backend session + sess = tf.Session() + keras.backend.set_session(sess) + + set_log_level(logging.WARNING) + + # Define input TF placeholder + x = tf.placeholder(tf.float32, shape=(None, img_rows, img_cols, channels)) + y = tf.placeholder(tf.float32, shape=(None, 10)) + phase = tf.placeholder(tf.bool, name="phase") + logits_scalar = tf.placeholder_with_default( + INIT_T, shape=(), name="logits_temperature") + + model_path = FLAGS.model_path + nb_filters = FLAGS.nb_filters + batch_size = FLAGS.batch_size + + #### EMPIR extra flags + lowprecision = FLAGS.lowprecision + abits = FLAGS.abits + wbits = FLAGS.wbits + abitsList = FLAGS.abitsList + wbitsList = FLAGS.wbitsList + stocRound = True if FLAGS.stocRound else False + model_path2 = FLAGS.model_path2 + model_path1 = FLAGS.model_path1 + model_path3 = FLAGS.model_path3 + ensembleThree = True if FLAGS.ensembleThree else False + abits2 = FLAGS.abits2 + wbits2 = FLAGS.wbits2 + abits2List = FLAGS.abits2List + wbits2List = FLAGS.wbits2List + distill = True if FLAGS.distill else False + #### + + if ensembleThree: + if (model_path1 is None or model_path2 is None or model_path3 is None): + raise ValueError() + elif model_path is not None: + if os.path.exists(model_path): + # check for existing model in immediate subfolder + if not any(f.endswith('.meta') for f in os.listdir(model_path)): + raise ValueError() + else: + raise ValueError() + + if ensembleThree: + if (wbitsList is None) or ( + abitsList is None): # Layer wise separate quantization not specified for first model + if (wbits == 0) or (abits == 0): + print( + "Error: the number of bits for constant precision weights and activations across layers for the first model have to specified using wbits1 and abits1 flags") + sys.exit(1) + else: + fixedPrec1 = 1 + elif (len(wbitsList) != 3) or (len(abitsList) != 3): + print( + "Error: Need to specify the precisions for activations and weights for the atleast the three convolutional layers of the first model") + sys.exit(1) + else: + fixedPrec1 = 0 + + if (wbits2List is None) or ( + abits2List is None): # Layer wise separate quantization not specified for second model + if (wbits2 == 0) or (abits2 == 0): + print( + "Error: the number of bits for constant precision weights and activations across layers for the second model have to specified using wbits1 and abits1 flags") + sys.exit(1) + else: + fixedPrec2 = 1 + elif (len(wbits2List) != 3) or (len(abits2List) != 3): + print( + "Error: Need to specify the precisions for activations and weights for the atleast the three convolutional layers of the second model") + sys.exit(1) + else: + fixedPrec2 = 0 + + if (fixedPrec2 != 1) or ( + fixedPrec1 != 1): # Atleast one of the models have separate precisions per layer + fixedPrec = 0 + print("Within atleast one model has separate precisions") + if (fixedPrec1 == 1): # first layer has fixed precision + abitsList = (abits, abits, abits) + wbitsList = (wbits, wbits, wbits) + if (fixedPrec2 == 1): # second layer has fixed precision + abits2List = (abits2, abits2, abits2) + wbits2List = (wbits2, wbits2, wbits2) + else: + fixedPrec = 1 + + if fixedPrec == 1: + from cleverhans_tutorials.tutorial_models import \ + make_ensemble_three_cifar_cnn + model = make_ensemble_three_cifar_cnn( + phase, logits_scalar, 'lp1_', 'lp2_', 'fp_', wbits, abits, wbits2, + abits2, input_shape=(None, img_rows, img_cols, channels), + nb_filters=nb_filters) + else: + from cleverhans_tutorials.tutorial_models import \ + make_ensemble_three_cifar_cnn_layerwise + model = make_ensemble_three_cifar_cnn_layerwise( + phase, logits_scalar, 'lp1_', 'lp2_', 'fp_', wbitsList, abitsList, + wbits2List, abits2List, + input_shape=(None, img_rows, img_cols, channels), + nb_filters=nb_filters) + elif lowprecision: + if (wbitsList is None) or ( + abitsList is None): # Layer wise separate quantization not specified + if (wbits == 0) or (abits == 0): + print( + "Error: the number of bits for constant precision weights and activations across layers have to specified using wbits and abits flags") + sys.exit(1) + else: + fixedPrec = 1 + elif (len(wbitsList) != 3) or (len(abitsList) != 3): + print( + "Error: Need to specify the precisions for activations and weights for the atleast the three convolutional layers") + sys.exit(1) + else: + fixedPrec = 0 + + if fixedPrec: + from cleverhans_tutorials.tutorial_models import \ + make_basic_lowprecision_cifar_cnn + model = make_basic_lowprecision_cifar_cnn( + phase, logits_scalar, 'lp_', wbits, abits, input_shape=( + None, img_rows, img_cols, channels), nb_filters=nb_filters, + stocRound=stocRound) + else: + from cleverhans_tutorials.tutorial_models import \ + make_layerwise_lowprecision_cifar_cnn + model = make_layerwise_lowprecision_cifar_cnn( + phase, logits_scalar, 'lp_', wbitsList, abitsList, input_shape=( + None, img_rows, img_cols, channels), nb_filters=nb_filters, + stocRound=stocRound) + elif distill: + from cleverhans_tutorials.tutorial_models import make_distilled_cifar_cnn + model = make_distilled_cifar_cnn(phase, logits_scalar, + 'teacher_fp_', 'fp_', + nb_filters=nb_filters, input_shape=( + None, img_rows, img_cols, channels)) + #### + else: + from cleverhans_tutorials.tutorial_models import make_basic_cifar_cnn + model = make_basic_cifar_cnn(phase, logits_scalar, 'fp_', input_shape=( + None, img_rows, img_cols, channels), nb_filters=nb_filters) + + # separate calling function for ensemble models + if ensembleThree: + preds = model.ensemble_call(x, reuse=False) + else: + ##default + preds = model(x, reuse=False) + print("Defined TensorFlow model graph.") + + if ensembleThree: + variables = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) + stored_variables = ['lp_conv1_init/k', 'lp_conv2_init/k', 'lp_conv3_init/k', + 'lp_ip1init/W', 'lp_logits_init/W'] + variable_dict = dict(zip(stored_variables, variables[:5])) + # Restore the first set of variables from model_path1 + saver = tf.train.Saver(variable_dict) + saver.restore(sess, tf.train.latest_checkpoint(model_path1)) + # Restore the second set of variables from model_path2 + variable_dict = dict(zip(stored_variables, variables[5:10])) + saver2 = tf.train.Saver(variable_dict) + saver2.restore(sess, tf.train.latest_checkpoint(model_path2)) + stored_variables = ['fp_conv1_init/k', 'fp_conv2_init/k', 'fp_conv3_init/k', + 'fp_ip1init/W', 'fp_logits_init/W'] + variable_dict = dict(zip(stored_variables, variables[10:])) + saver3 = tf.train.Saver(variable_dict) + saver3.restore(sess, tf.train.latest_checkpoint(model_path3)) + else: + tf_model_load(sess, model_path) + print('Restored model from %s' % model_path) + + return sess, model, preds, x, y, phase + + +def build_adversarial_attack(sess, model, attack, targeted, nb_classes, + ensembleThree, + nb_samples, nb_iter, eps, robust_attack): + if targeted: + att_batch_size = np.clip( + nb_samples * (nb_classes - 1), a_max=MAX_BATCH_SIZE, a_min=1) + yname = "y_target" + + else: + att_batch_size = np.minimum(nb_samples, MAX_BATCH_SIZE) + adv_ys = None + yname = "y" + + if ensembleThree: + model_type = 'ensembleThree' + else: + model_type = 'default' + + if attack == ATTACK_CARLINI_WAGNER_L2: + from modified_cleverhans.attacks import CarliniWagnerL2 + attacker = CarliniWagnerL2(model, back='tf', model_type=model_type, + num_classes=nb_classes, sess=sess) + attack_params = {'binary_search_steps': 1, + 'max_iterations': nb_iter, + 'learning_rate': 0.1, + 'batch_size': att_batch_size, + 'initial_const': 10, + } + elif attack == ATTACK_JSMA: + from modified_cleverhans.attacks import SaliencyMapMethod + attacker = SaliencyMapMethod(model, back='tf', model_type=model_type, + sess=sess, num_classes=nb_classes) + attack_params = {'theta': 1., 'gamma': 0.1} + elif attack == ATTACK_FGSM: + from modified_cleverhans.attacks import FastGradientMethod + attacker = FastGradientMethod(model, back='tf', model_type=model_type, + sess=sess, num_classes=nb_classes) + attack_params = {'eps': eps} + elif attack == ATTACK_MADRYETAL: + from modified_cleverhans.attacks import MadryEtAl + attacker = MadryEtAl(model, back='tf', model_type=model_type, sess=sess, + num_classes=nb_classes, attack_type="robust" if robust_attack else "vanilla") + attack_params = {'eps': eps, 'eps_iter': 0.01, 'nb_iter': nb_iter} + elif attack == ATTACK_BASICITER: + from modified_cleverhans.attacks import BasicIterativeMethod + attacker = BasicIterativeMethod(model, back='tf', sess=sess, + model_type=model_type, + num_classes=nb_classes) + attack_params = {'eps': eps, 'eps_iter': 0.01, 'nb_iter': nb_iter} + else: + print("Attack undefined") + sys.exit(1) + + attack_params.update({yname: adv_ys, 'clip_min': 0., 'clip_max': 1.}) + + return attacker, attack_params + + +def main(argv=None): + """ + CIFAR10 modified_cleverhans tutorial + :return: + """ + + img_rows = 32 + img_cols = 32 + channels = 3 + nb_classes = 10 + targeted = True if FLAGS.targeted else False + batch_size = FLAGS.batch_size + nb_samples = FLAGS.nb_samples + eps = FLAGS.eps + + attack = FLAGS.attack + nb_iter = FLAGS.nb_iter + + ensembleThree = True if FLAGS.ensembleThree else False + sess, model, preds, x, y, phase = setup_model() + + # Get CIFAR10 test data + X_train, Y_train, X_test, Y_test = data_cifar10() + + def evaluate(): + # Evaluate the accuracy of the CIFAR10 model on legitimate test + # examples + eval_params = {'batch_size': batch_size} + if ensembleThree: + acc = model_eval_ensemble( + sess, x, y, preds, X_test, Y_test, phase=phase, args=eval_params) + else: + acc = model_eval( + sess, x, y, preds, X_test, Y_test, phase=phase, args=eval_params) + assert X_test.shape[0] == 10000, X_test.shape + print('Test accuracy on legitimate examples: %0.4f' % acc) + + evaluate() + + # Evaluate the accuracy of the CIFAR10 model on legitimate test examples + eval_params = {'batch_size': batch_size} + if ensembleThree: + accuracy = model_eval_ensemble(sess, x, y, preds, X_test, Y_test, + phase=phase, feed={phase: False}, + args=eval_params) + else: + accuracy = model_eval(sess, x, y, preds, X_test, Y_test, phase=phase, + feed={phase: False}, args=eval_params) + + print('Test accuracy on legitimate test examples: {0}'.format(accuracy)) + + ########################################################################### + # Build dataset + ########################################################################### + + if targeted: + from modified_cleverhans.utils import build_targeted_dataset + adv_inputs, true_labels, adv_ys = build_targeted_dataset( + X_test, Y_test, np.arange(nb_samples), nb_classes, img_rows, img_cols, + channels) + else: + adv_inputs = X_test[:nb_samples] + true_labels = Y_test[:nb_samples] + + ########################################################################### + # Craft adversarial examples using generic approach + ########################################################################### + attacker, attack_params = build_adversarial_attack(sess, model, attack, + targeted, nb_classes, + ensembleThree, + nb_samples, nb_iter, eps, + robust_attack=FLAGS.robust_attack) + + if FLAGS.use_labels: + attack_params['y'] = true_labels + X_test_adv = attacker.generate_np(adv_inputs, phase, **attack_params) + #x_adv = attacker.generate(x, phase, **attack_params) + + + adv_accuracy = model_eval_ensemble(sess, x, y, preds, X_test_adv, Y_test, + phase=phase, args=eval_params) + + # Friendly output for pasting into spreadsheet + print('Accuracy: {0:.4f},'.format(accuracy)) + print('Adversarial Accuracy {0:.4f},'.format(adv_accuracy)) + + sess.close() + + +if __name__ == '__main__': + + par = argparse.ArgumentParser() + + # Generic flags + par.add_argument('--gpu', help='id of GPU to use') + par.add_argument('--model_path', help='Path to save or load model') + par.add_argument('--data_dir', help='Path to training data', + default='cifar10_data') + + # Architecture and training specific flags + par.add_argument('--nb_epochs', type=int, default=6, + help='Number of epochs to train model') + par.add_argument('--nb_filters', type=int, default=32, + help='Number of filters in first layer') + par.add_argument('--batch_size', type=int, default=128, + help='Size of training batches') + par.add_argument('--learning_rate', type=float, default=0.001, + help='Learning rate') + par.add_argument('--rand', help='Stochastic weight layer?', + action="store_true") + + # Attack specific flags + par.add_argument('--eps', type=float, default=0.1, + help='epsilon') + par.add_argument('--attack', type=int, default=0, + help='Attack type, 0=CW, 2=FGSM') + par.add_argument('--nb_samples', type=int, + default=10000, help='Nb of inputs to attack') + par.add_argument( + '--targeted', help='Run a targeted attack?', action="store_true") + # Adversarial training flags + par.add_argument( + '--adv', help='Adversarial training type?', type=int, default=0) + par.add_argument('--delay', type=int, + default=10, help='Nb of epochs to delay adv training by') + par.add_argument('--nb_iter', type=int, + default=40, + help='Nb of iterations of PGD (set to 50 for CW)') + + # EMPIR specific flags + par.add_argument('--lowprecision', help='Use other low precision models', + action="store_true") + par.add_argument('--wbits', type=int, default=0, + help='No. of bits in weight representation') + par.add_argument('--abits', type=int, default=0, + help='No. of bits in activation representation') + par.add_argument('--wbitsList', type=int, nargs='+', + help='List of No. of bits in weight representation for different layers') + par.add_argument('--abitsList', type=int, nargs='+', + help='List of No. of bits in activation representation for different layers') + par.add_argument('--stocRound', + help='Stochastic rounding for weights (only in training) and activations?', + action="store_true") + par.add_argument('--model_path1', + help='Path where saved model1 is stored and can be loaded') + par.add_argument('--model_path2', + help='Path where saved model2 is stored and can be loaded') + par.add_argument('--ensembleThree', + help='Use an ensemble of full precision and two low precision models that can be attacked directly', + action="store_true") + par.add_argument('--model_path3', + help='Path where saved model3 in case of combinedThree model is stored and can be loaded') + par.add_argument('--wbits2', type=int, default=0, + help='No. of bits in weight representation of model2, model1 specified using wbits') + par.add_argument('--abits2', type=int, default=0, + help='No. of bits in activation representation of model2, model2 specified using abits') + par.add_argument('--wbits2List', type=int, nargs='+', + help='List of No. of bits in weight representation for different layers of model2') + par.add_argument('--abits2List', type=int, nargs='+', + help='List of No. of bits in activation representation for different layers of model2') + # extra flags for defensive distillation + par.add_argument('--distill', help='Train the model using distillation', + action="store_true") + par.add_argument('--student_epochs', type=int, default=50, + help='No. of epochs for which the student model is trained') + # extra flags for input gradient regularization + par.add_argument('--inpgradreg', + help='Train the model using input gradient regularization', + action="store_true") + par.add_argument('--l2dbl', type=int, default=0, + help='l2 double backprop penalty') + par.add_argument('--l2cs', type=int, default=0, + help='l2 certainty sensitivity penalty') + + par.add_argument("--robust-attack", action="store_true") + par.add_argument("--use-labels", action="store_true") + + FLAGS = par.parse_args() + + if FLAGS.gpu: + os.environ['CUDA_VISIBLE_DEVICES'] = FLAGS.gpu + + tf.app.run() diff --git a/case_studies/empir/examples/cifar10_binarization_test.py b/case_studies/empir/examples/cifar10_binarization_test.py new file mode 100644 index 0000000..5f00769 --- /dev/null +++ b/case_studies/empir/examples/cifar10_binarization_test.py @@ -0,0 +1,561 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import logging + +import torch +from torch.utils.data import DataLoader +from torch.utils.data import TensorDataset + +from active_tests.decision_boundary_binarization import LogitRescalingType +from active_tests.decision_boundary_binarization import \ + _train_logistic_regression_classifier +from active_tests.decision_boundary_binarization import \ + interior_boundary_discrimination_attack, format_result +from cifar10_attack import setup_model + +logging.getLogger('tensorflow').setLevel(logging.FATAL) +from functools import partial +import tensorflow as tf +from keras.utils.np_utils import to_categorical + +tf.logging.set_verbosity(tf.logging.ERROR) + +import os +import argparse +import numpy as np +import tensorflow as tf +from tensorflow.python.platform import flags + +class Layer(object): + + def get_output_shape(self): + return self.output_shape + + +class Linear(Layer): + + def __init__(self, num_hid, name, useBias=False): + self.__dict__.update(locals()) + # self.num_hid = num_hid + + def set_input_shape(self, input_shape, reuse): + + # with tf.variable_scope(self.scope_name+ 'init', reuse): # this works + # with black box, but now can't load checkpoints from wb + # this works with white-box + with tf.variable_scope(self.name + '_init', reuse): + + batch_size, dim = input_shape + self.input_shape = [batch_size, dim] + self.output_shape = [batch_size, self.num_hid] + if self.useBias: + self.bias_shape = self.num_hid + init = tf.random_normal([dim, self.num_hid], dtype=tf.float32) + init = init / tf.sqrt(1e-7 + tf.reduce_sum(tf.square(init), axis=0, + keep_dims=True)) + self.W = tf.get_variable( + "W", initializer=init) + + if self.useBias: + bias_init = tf.zeros(self.bias_shape) + self.bias = tf.get_variable("b", initializer= bias_init) + + self.bias_ph = tf.placeholder(tf.float32, shape=self.bias_shape) + self.set_bias = self.bias.assign(self.bias_ph) + + self.W_ph = tf.placeholder(tf.float32, shape=[dim, self.num_hid]) + self.set_weight = self.W.assign(self.W_ph) + + def fprop(self, x, reuse): + + # with tf.variable_scope(self.scope_name + '_fprop', reuse): + # this works with white-box + with tf.variable_scope(self.name + '_fprop', reuse): + + x = tf.matmul(x, self.W) # + self.b + if self.useBias: + x = tf.nn.bias_add(tf.contrib.layers.flatten(x), tf.reshape(self.bias, [-1])) + + return x + +FLAGS = flags.FLAGS + +ATTACK_CARLINI_WAGNER_L2 = 0 +ATTACK_JSMA = 1 +ATTACK_FGSM = 2 +ATTACK_MADRYETAL = 3 +ATTACK_BASICITER = 4 +MAX_BATCH_SIZE = 100 +MAX_BATCH_SIZE = 100 + +# Scaling input to softmax +INIT_T = 1.0 +# ATTACK_T = 1.0 +ATTACK_T = 0.25 + +from cifar10_attack import data_cifar10 + +from cifar10_attack import build_adversarial_attack + + +def main(argv=None): + """ + CIFAR10 modified_cleverhans tutorial + :return: + """ + + nb_classes = 2 + targeted = True if FLAGS.targeted else False + batch_size = FLAGS.batch_size + nb_samples = FLAGS.nb_samples + eps = FLAGS.eps + + attack = FLAGS.attack + nb_iter = FLAGS.nb_iter + + ensembleThree = True if FLAGS.ensembleThree else False + sess, model, preds, x, y, phase = setup_model() + + # Get CIFAR10 test data + X_train, Y_train, X_test, Y_test = data_cifar10() + del X_train, Y_train + X_test = np.transpose(X_test, (0, 3, 1, 2)) + print(X_test.shape) + + def run_attack(m, l, sess, attack): + for x_batch, y_batch in l: + assert len(x_batch) == 1 + x_batch = x_batch.cpu().numpy() + y_batch = y_batch.cpu().numpy() + + x_batch = x_batch.transpose(0, 2, 3, 1) + + y_batch_oh = to_categorical(y_batch, num_classes=2) + x_batch_adv = attack(x_batch, y_batch_oh) + + probs = m(x_batch_adv) + preds = probs.argmax(-1) + + is_adv = preds != y_batch + + return is_adv, (torch.tensor(x_batch_adv.transpose(0, 3, 1, 2), dtype=torch.float32),\ + torch.tensor(probs, dtype=torch.float32)) + + + def train_classifier( + n_features: int, + train_loader: DataLoader, + raw_train_loader: DataLoader, + logits: torch.Tensor, + device: str, + rescale_logits: LogitRescalingType, + binarized_ensemble, + set_weight_ops, + set_bias_ops, + sess, + weights_phs, + biases_phs + ): + #del raw_train_loader + + # fit a linear readout for each of the submodels of the ensemble + assert len(train_loader.dataset.tensors[0].shape) == 3 + assert train_loader.dataset.tensors[0].shape[1] == len(weights_phs) == len( + biases_phs) + + classifier_weights = [] + classifier_biases = [] + for i in range(3): + x_ = train_loader.dataset.tensors[0][:, i] + y_ = train_loader.dataset.tensors[1] + + cls = _train_logistic_regression_classifier( + n_features, + DataLoader(TensorDataset(x_, y_), batch_size=train_loader.batch_size), + logits[:, i] if logits is not None else None, + "sklearn", + 10000, + device, + n_classes=2, + rescale_logits=rescale_logits + ) + classifier_weights.append(cls.weight.data.cpu().numpy().transpose()) + classifier_biases.append(cls.bias.data.cpu().numpy()) + + # update weights of the binary models + for op, ph, v in zip(set_weight_ops, weights_phs, classifier_weights): + sess.run(op, {ph: v}) + for op, ph, v in zip(set_bias_ops, biases_phs, classifier_biases): + sess.run(op, {ph: v}) + + """ n_corr1 = 0 + n_corr2 = 0 + n_total = 0 + for x, y in raw_train_loader: + preds1 = binarized_model(x) + preds2 = binarized_model(x, averaged=False) + import pdb; pdb.set_trace() + n_corr1 += (preds1 == y).sum() + n_corr2 += (preds2 == y).sum() + n_total += len(x) + """ + return binarized_ensemble + + from tensorflow_wrapper import TensorFlow1ToPyTorchWrapper, \ + PyTorchToTensorFlow1Wrapper + from utils import build_dataloader_from_arrays + + test_loader = build_dataloader_from_arrays(X_test, Y_test, batch_size=32) + + from modified_cleverhans.model import Model + class BinarizedEnsembleModel(Model): + def __init__(self, base_classifier, input_ph): + self.num_classes = 2 + + self.base_classifier = base_classifier + self.layer_names = [] + self.layer_names.append('combined_features') + self.layer_names.append('combined_logits') + + combined_layer_name = 'combined' ## Gives the final class prediction based on max voting + self.layer_names.append(combined_layer_name) + combinedCorrectProb_layer_name = 'combinedAvgCorrectProb' ## Gives average probability values of the models that decided the final prediction + self.layer_names.append(combinedCorrectProb_layer_name) + combinedProb_layer_name = 'combinedAvgProb' ## Gives average probability values of all the models + self.layer_names.append(combinedProb_layer_name) + + self.readout_1 = Linear(2, "binarized_ensemble_readout_1", useBias=True) + self.readout_2 = Linear(2, "binarized_ensemble_readout_2", useBias=True) + self.readout_3 = Linear(2, "binarized_ensemble_readout_3", useBias=True) + + self.readout_1.set_input_shape((-1, 64), True) + self.readout_2.set_input_shape((-1, 64), True) + self.readout_3.set_input_shape((-1, 64), True) + + self.set_weight_ops = [ + self.readout_1.set_weight, + self.readout_2.set_weight, + self.readout_3.set_weight + ] + self.set_bias_ops = [ + self.readout_1.set_bias, + self.readout_2.set_bias, + self.readout_3.set_bias, + ] + + self.weights_phs = [ + self.readout_1.W_ph, + self.readout_2.W_ph, + self.readout_3.W_ph + ] + self.biases_phs = [ + self.readout_1.bias_ph, + self.readout_2.bias_ph, + self.readout_3.bias_ph + ] + + self.input_ph = input_ph + self.ensemble_op = self.get_ensemblepreds(self.input_ph) + self.averaged_op = self.get_combinedAvgCorrectProbs(self.input_ph) + + + def __call__(self, x_, averaged=True, *args, **kwargs): + return_torch = False + return_numpy = False + if isinstance(x_, torch.Tensor): + x_ = x_.cpu().numpy() + return_torch = True + if isinstance(x_, np.ndarray): + return_numpy = True + if x_.shape[1] == 3: + x_ = x_.transpose(0, 2, 3, 1) + + x = self.input_ph + if averaged: + op = self.averaged_op + else: + op = self.ensemble_op + + else: + raise NotImplementedError("Calling this with a tf tensor is not supported yet" + " (wasn't necessary).") + #if averaged: + # op = self.get_combinedAvgCorrectProbs(x_, *args, **kwargs) + #else: + # op = self.get_ensemblepreds(x_, *args, **kwargs) + if return_numpy or return_torch: + x_ = sess.run(op, {x: x_}) + if return_torch: + x_ = torch.tensor(x_, dtype=torch.float32) + return x_ + + def fprop(self, x, reuse): + base_states = self.base_classifier.fprop(x, reuse) + + features1 = base_states["Model1_HiddenLinear10"] + features2 = base_states["Model2_HiddenLinear10"] + features3 = base_states["Model3_HiddenLinear10"] + + output1 = self.readout_1.fprop(features1, reuse) + output2 = self.readout_2.fprop(features2, reuse) + output3 = self.readout_3.fprop(features3, reuse) + + states = [] + states.append(tf.stack((features1, features2, features3), 1)) + states.append(tf.stack((output1, output2, output3), 1)) + + # Find class predictions with each model + pred1 = tf.argmax(output1, axis=-1) + pred2 = tf.argmax(output2, axis=-1) + pred3 = tf.argmax(output3, axis=-1) + comb_pred = tf.stack([pred1, pred2, pred3], axis=1) + comb_pred = tf.cast(comb_pred, dtype=tf.int32) # converting to int32 as bincount requires int32 + + # Find how many times each of the classes are predicted among the three models and identify the max class + initial_imidx = 1 + + binarray = tf.bincount(comb_pred[0], minlength=self.num_classes)# initial bincount, counts number of occurences of each integer from 0 to 10 for the 1d array, returns a 1d array + max_class = tf.argmax(binarray, axis=-1) + count_max = tf.gather(binarray, max_class) # max vote count for a class + + value = tf.cond(tf.less(count_max, 2), lambda: pred3[0], lambda: max_class) + in_class_array = tf.fill([1], value) + + ## Added below to allow better gradient calculation for max voted model + in_avgCorrectprob = tf.cond(tf.equal(value, pred3[0]), lambda: output3[0], lambda: tf.zeros_like(output3[0])) # add pred3 if it affected the final decision + in_avgCorrectprob = tf.cond(tf.equal(value, pred2[0]), lambda: tf.add(output2[0], in_avgCorrectprob), lambda: in_avgCorrectprob) # add pred2 if it affected the final decision + in_avgCorrectprob = tf.cond(tf.equal(value, pred1[0]), lambda: tf.add(output1[0], in_avgCorrectprob), lambda: in_avgCorrectprob) # add pred2 if it affected the final decision + in_avgCorrectprob_array = tf.expand_dims(tf.div(in_avgCorrectprob, tf.cast(count_max, dtype=tf.float32)), 0) + + #condition check: when true the loop body executes + def idx_loop_condition(class_array, avgCorrectprob_array, im_idx): + return tf.less(im_idx, tf.shape(pred1)[0]) + + #loop body to calculate the max voted class for each image + def idx_loop_body(class_array, avgCorrectprob_array, im_idx): + binarray_new = tf.bincount(comb_pred[im_idx], minlength=self.num_classes) # counts number of occurences of each integer from 0 to 10 for the 1d array, returns a 1d array + max_class = tf.argmax(binarray_new, axis=-1) + count_max = tf.gather(binarray_new, max_class) # max vote count for a class + + value = tf.cond(tf.less(count_max, 2), lambda: pred3[im_idx], lambda: max_class)# If the max vote is less than 2, take the prediction of the full precision model + new_array = tf.fill([1], value) + class_array = tf.concat([class_array, new_array], 0) + + ## Added below to allow better gradient calculation for max voted model + avgCorrectprob = tf.cond(tf.equal(value, pred3[im_idx]), lambda: output3[im_idx], lambda: tf.zeros_like(output3[im_idx])) # add pred3 if it affected the final decision + avgCorrectprob = tf.cond(tf.equal(value, pred2[im_idx]), lambda: tf.add(output2[im_idx], avgCorrectprob), lambda: avgCorrectprob) # add pred2 if it affected the final decision + avgCorrectprob = tf.cond(tf.equal(value, pred1[im_idx]), lambda: tf.add(output1[im_idx], avgCorrectprob), lambda: avgCorrectprob) # add pred2 if it affected the final decision + avgCorrectprob = tf.expand_dims(tf.div(avgCorrectprob, tf.cast(count_max, dtype=tf.float32)), 0) + avgCorrectprob_array = tf.concat([avgCorrectprob_array, avgCorrectprob], 0) + + return (class_array, avgCorrectprob_array, im_idx+1) + + res = tf.while_loop( + cond=idx_loop_condition, + body=idx_loop_body, + loop_vars=[in_class_array, in_avgCorrectprob_array, initial_imidx], + shape_invariants=[tf.TensorShape([None]), tf.TensorShape([None, self.num_classes]), tf.TensorShape([])], #add shape invariant saying that the first dimension of in_class_array changes and is thus None + ) + + pred_output = tf.cast(res[0], dtype=tf.int64) # no. of times each class is predicted for all images + states.append(pred_output) + + avgCorrectprob_output = res[1] # no. of times each class is predicted for all images + states.append(avgCorrectprob_output) + + avgprob = tf.div(tf.add_n([output2, output1, output3]), tf.cast(3, dtype=tf.float32)) # Average probability across all models + states.append(avgprob) + + states = dict(zip(self.get_layer_names(), states)) + return states + + binarized_model = BinarizedEnsembleModel(model, x) + attacker, attack_params = build_adversarial_attack( + sess, binarized_model, attack, + targeted, nb_classes, + ensembleThree, + nb_samples, nb_iter, eps, + robust_attack=FLAGS.robust_attack) + + base_model_outputs = model.fprop(x, reuse=True) + base_model_features = base_model_outputs["combined_features"] + base_model_logits = base_model_outputs["combined_logits"] + def _model_forward_pass(x_np, features_only=False, features_and_logits=False): + x_np = np.transpose(x_np, (0, 2, 3, 1)) + + if features_only: + return sess.run(base_model_features, {x : x_np}) + elif features_and_logits: + targets = [base_model_features, base_model_logits] + return tuple(sess.run(targets, {x : x_np})) + else: + return sess.run(base_model_logits, {x : x_np}) + + + feature_extractor = TensorFlow1ToPyTorchWrapper( + logit_forward_pass=_model_forward_pass, + logit_forward_and_backward_pass=None + ) + y = tf.placeholder(tf.float32, shape=(None, 2)) + if FLAGS.use_labels: + attack_params['y'] = y + else: + #del attack_params['y'] + attack_params['y'] = tf.stop_gradient(tf.to_float(tf.one_hot(binarized_model.get_ensemblepreds(x, reuse=True), nb_classes))) + x_adv = attacker.generate(x, phase, **attack_params) + + from argparse_utils import DecisionBoundaryBinarizationSettings + scores_logit_differences_and_validation_accuracies = \ + interior_boundary_discrimination_attack( + feature_extractor, + test_loader, + attack_fn=lambda m, l, kwargs: run_attack( + m, l, sess, lambda x_, y_: sess.run(x_adv, {x: x_, y: y_}) + ), + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=FLAGS.eps, + norm="linf", + lr=10000, + n_boundary_points=FLAGS.n_boundary_points, + n_inner_points=FLAGS.n_inner_points, + adversarial_attack_settings=None, + optimizer="sklearn" + ), + n_samples=FLAGS.nb_samples, + device="cpu", + n_samples_evaluation=200, + n_samples_asr_evaluation=200, + train_classifier_fn=partial(train_classifier, + binarized_ensemble=binarized_model, + set_weight_ops=binarized_model.set_weight_ops, + set_bias_ops=binarized_model.set_bias_ops, + sess=sess, + weights_phs=binarized_model.weights_phs, + biases_phs=binarized_model.biases_phs, + ), + fail_on_exception=True, + rescale_logits="adaptive", + decision_boundary_closeness=0.9999, + sample_training_data_from_corners=FLAGS.sample_from_corners + ) + print(format_result(scores_logit_differences_and_validation_accuracies, + FLAGS.nb_samples)) + +if __name__ == '__main__': + par = argparse.ArgumentParser() + + # Generic flags + par.add_argument('--gpu', help='id of GPU to use') + par.add_argument('--model_path', help='Path to save or load model') + par.add_argument('--data_dir', help='Path to training data', + default='cifar10_data') + + # Architecture and training specific flags + par.add_argument('--nb_epochs', type=int, default=6, + help='Number of epochs to train model') + par.add_argument('--nb_filters', type=int, default=32, + help='Number of filters in first layer') + par.add_argument('--batch_size', type=int, default=128, + help='Size of training batches') + par.add_argument('--learning_rate', type=float, default=0.001, + help='Learning rate') + par.add_argument('--rand', help='Stochastic weight layer?', + action="store_true") + + # Attack specific flags + par.add_argument('--eps', type=float, default=0.1, + help='epsilon') + par.add_argument('--attack', type=int, default=0, + help='Attack type, 0=CW, 2=FGSM') + par.add_argument('--nb_samples', type=int, + default=10000, help='Nb of inputs to attack') + par.add_argument( + '--targeted', help='Run a targeted attack?', action="store_true") + # Adversarial training flags + par.add_argument( + '--adv', help='Adversarial training type?', type=int, default=0) + par.add_argument('--delay', type=int, + default=10, help='Nb of epochs to delay adv training by') + par.add_argument('--nb_iter', type=int, + default=40, + help='Nb of iterations of PGD (set to 50 for CW)') + + # EMPIR specific flags + par.add_argument('--lowprecision', help='Use other low precision models', + action="store_true") + par.add_argument('--wbits', type=int, default=0, + help='No. of bits in weight representation') + par.add_argument('--abits', type=int, default=0, + help='No. of bits in activation representation') + par.add_argument('--wbitsList', type=int, nargs='+', + help='List of No. of bits in weight representation for different layers') + par.add_argument('--abitsList', type=int, nargs='+', + help='List of No. of bits in activation representation for different layers') + par.add_argument('--stocRound', + help='Stochastic rounding for weights (only in training) and activations?', + action="store_true") + par.add_argument('--model_path1', + help='Path where saved model1 is stored and can be loaded') + par.add_argument('--model_path2', + help='Path where saved model2 is stored and can be loaded') + par.add_argument('--ensembleThree', + help='Use an ensemble of full precision and two low precision models that can be attacked directly', + action="store_true") + par.add_argument('--model_path3', + help='Path where saved model3 in case of combinedThree model is stored and can be loaded') + par.add_argument('--wbits2', type=int, default=0, + help='No. of bits in weight representation of model2, model1 specified using wbits') + par.add_argument('--abits2', type=int, default=0, + help='No. of bits in activation representation of model2, model2 specified using abits') + par.add_argument('--wbits2List', type=int, nargs='+', + help='List of No. of bits in weight representation for different layers of model2') + par.add_argument('--abits2List', type=int, nargs='+', + help='List of No. of bits in activation representation for different layers of model2') + # extra flags for defensive distillation + par.add_argument('--distill', help='Train the model using distillation', + action="store_true") + par.add_argument('--student_epochs', type=int, default=50, + help='No. of epochs for which the student model is trained') + # extra flags for input gradient regularization + par.add_argument('--inpgradreg', + help='Train the model using input gradient regularization', + action="store_true") + par.add_argument('--l2dbl', type=int, default=0, + help='l2 double backprop penalty') + par.add_argument('--l2cs', type=int, default=0, + help='l2 certainty sensitivity penalty') + + + par.add_argument("--n-inner-points", default=999, type=int) + par.add_argument("--n-boundary-points", default=1, type=int) + + par.add_argument("--robust-attack", action="store_true") + par.add_argument("--use-labels", action="store_true") + par.add_argument("--sample-from-corners", action="store_true") + + FLAGS = par.parse_args() + + import cifar10_attack + cifar10_attack.FLAGS = FLAGS + + if FLAGS.gpu: + os.environ['CUDA_VISIBLE_DEVICES'] = FLAGS.gpu + + tf.app.run() diff --git a/case_studies/empir/examples/imagenet_preprocessing.py b/case_studies/empir/examples/imagenet_preprocessing.py new file mode 100644 index 0000000..da1a333 --- /dev/null +++ b/case_studies/empir/examples/imagenet_preprocessing.py @@ -0,0 +1,407 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +# Copyright 2016 The TensorFlow Authors. 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. +# ============================================================================== +"""Provides utilities to preprocess images. +Training images are sampled using the provided bounding boxes, and subsequently +cropped to the sampled bounding box. Images are additionally flipped randomly, +then resized to the target output size (without aspect-ratio preservation). +Images used during evaluation are resized (with aspect-ratio preservation) and +centrally cropped. +All images undergo mean color subtraction. +Note that these steps are colloquially referred to as "ResNet preprocessing," +and they differ from "VGG preprocessing," which does not use bounding boxes +and instead does an aspect-preserving resize followed by random crop during +training. (These both differ from "Inception preprocessing," which introduces +color distortion steps.) +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import tensorflow as tf +import numpy as np + +_R_MEAN = 123.68 +_G_MEAN = 116.78 +_B_MEAN = 103.94 +_CHANNEL_MEANS = [_R_MEAN, _G_MEAN, _B_MEAN] + +## SANCHARI: copied standard deviation values from dorefanet +_R_STD = 0.229*255 +_G_STD = 0.224*255 +_B_STD = 0.225*255 +_CHANNEL_STDS = [_R_STD, _G_STD, _B_STD] +##### + +# The lower bound for the smallest side of the image for aspect-preserving +# resizing. For example, if an image is 500 x 1000, it will be resized to +# _RESIZE_MIN x (_RESIZE_MIN * 2). +_RESIZE_MIN = 256 + + +def _decode_crop_and_flip(image_buffer, bbox, num_channels): + """Crops the given image to a random part of the image, and randomly flips. + We use the fused decode_and_crop op, which performs better than the two ops + used separately in series, but note that this requires that the image be + passed in as an un-decoded string Tensor. + Args: + image_buffer: scalar string Tensor representing the raw JPEG image buffer. + bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords] + where each coordinate is [0, 1) and the coordinates are arranged as + [ymin, xmin, ymax, xmax]. + num_channels: Integer depth of the image buffer for decoding. + Returns: + 3-D tensor with cropped image. + """ + # A large fraction of image datasets contain a human-annotated bounding box + # delineating the region of the image containing the object of interest. We + # choose to create a new bounding box for the object which is a randomly + # distorted version of the human-annotated bounding box that obeys an + # allowed range of aspect ratios, sizes and overlap with the human-annotated + # bounding box. If no box is supplied, then we assume the bounding box is + # the entire image. + sample_distorted_bounding_box = tf.image.sample_distorted_bounding_box( + tf.image.extract_jpeg_shape(image_buffer), + bounding_boxes=bbox, + min_object_covered=0.1, + aspect_ratio_range=[0.75, 1.33], + area_range=[0.05, 1.0], + max_attempts=100, + use_image_if_no_bounding_boxes=True) + bbox_begin, bbox_size, _ = sample_distorted_bounding_box + + # Reassemble the bounding box in the format the crop op requires. + offset_y, offset_x, _ = tf.unstack(bbox_begin) + target_height, target_width, _ = tf.unstack(bbox_size) + crop_window = tf.stack([offset_y, offset_x, target_height, target_width]) + + # Use the fused decode and crop op here, which is faster than each in series. + cropped = tf.image.decode_and_crop_jpeg( + image_buffer, crop_window, channels=num_channels) + + # Flip to add a little more random distortion in. + cropped = tf.image.random_flip_left_right(cropped) + return cropped + + +def _central_crop(image, crop_height, crop_width): + """Performs central crops of the given image list. + Args: + image: a 3-D image tensor + crop_height: the height of the image following the crop. + crop_width: the width of the image following the crop. + Returns: + 3-D tensor with cropped image. + """ + shape = tf.shape(image) + height, width = shape[0], shape[1] + + amount_to_be_cropped_h = (height - crop_height) + crop_top = amount_to_be_cropped_h // 2 + amount_to_be_cropped_w = (width - crop_width) + crop_left = amount_to_be_cropped_w // 2 + return tf.slice( + image, [crop_top, crop_left, 0], [crop_height, crop_width, -1]) + + +def _mean_image_subtraction(image, means, num_channels): + """Subtracts the given means from each image channel. + For example: + means = [123.68, 116.779, 103.939] + image = _mean_image_subtraction(image, means) + Note that the rank of `image` must be known. + Args: + image: a tensor of size [height, width, C]. + means: a C-vector of values to subtract from each channel. + num_channels: number of color channels in the image that will be distorted. + Returns: + the centered image. + Raises: + ValueError: If the rank of `image` is unknown, if `image` has a rank other + than three or if the number of channels in `image` doesn't match the + number of values in `means`. + """ + if image.get_shape().ndims != 3: + raise ValueError('Input must be of size [height, width, C>0]') + + if len(means) != num_channels: + raise ValueError('len(means) must match the number of channels') + + # We have a 1-D tensor of means; convert to 3-D. + means = tf.expand_dims(tf.expand_dims(means, 0), 0) + + return image - means + + +def _smallest_size_at_least(height, width, resize_min): + """Computes new shape with the smallest side equal to `smallest_side`. + Computes new shape with the smallest side equal to `smallest_side` while + preserving the original aspect ratio. + Args: + height: an int32 scalar tensor indicating the current height. + width: an int32 scalar tensor indicating the current width. + resize_min: A python integer or scalar `Tensor` indicating the size of + the smallest side after resize. + Returns: + new_height: an int32 scalar tensor indicating the new height. + new_width: an int32 scalar tensor indicating the new width. + """ + resize_min = tf.cast(resize_min, tf.float32) + + # Convert to floats to make subsequent calculations go smoothly. + height, width = tf.cast(height, tf.float32), tf.cast(width, tf.float32) + + smaller_dim = tf.minimum(height, width) + scale_ratio = resize_min / smaller_dim + + # Convert back to ints to make heights and widths that TF ops will accept. + new_height = tf.cast(height * scale_ratio, tf.int32) + new_width = tf.cast(width * scale_ratio, tf.int32) + + return new_height, new_width + + +def _aspect_preserving_resize(image, resize_min): + """Resize images preserving the original aspect ratio. + Args: + image: A 3-D image `Tensor`. + resize_min: A python integer or scalar `Tensor` indicating the size of + the smallest side after resize. + Returns: + resized_image: A 3-D tensor containing the resized image. + """ + shape = tf.shape(image) + height, width = shape[0], shape[1] + + new_height, new_width = _smallest_size_at_least(height, width, resize_min) + + return _resize_image(image, new_height, new_width) + + +def _resize_image(image, height, width): + """Simple wrapper around tf.resize_images. + This is primarily to make sure we use the same `ResizeMethod` and other + details each time. + Args: + image: A 3-D image `Tensor`. + height: The target height for the resized image. + width: The target width for the resized image. + Returns: + resized_image: A 3-D tensor containing the resized image. The first two + dimensions have the shape [height, width]. + """ + return tf.image.resize_images( + image, [height, width], method=tf.image.ResizeMethod.BILINEAR, + align_corners=False) + +def _lighting_noise(image): + eigval = np.asarray([0.2175, 0.0188, 0.0045][::1])*255.0 + eigvec = np.asarray([[-0.5675, 0.7192, 0.4009], + [-0.5808, -0.0045, -0.814], + [-0.5836, -0.6948, 0.4203]])[::-1, ::-1] + std = 0.1 + v = np.random.randn(3)*std #random number + v = eigval*v + inc = np.dot(eigvec, v).reshape((3,)) + inc = tf.convert_to_tensor(inc, dtype=tf.float32) + # image = np.add(image, inc) + image = tf.add(image, inc) + return image + + +def preprocess_image(image_buffer, bbox, output_height, output_width, + num_channels, is_training=False): + """Preprocesses the given image. + Preprocessing includes decoding, cropping, and resizing for both training + and eval images. Training preprocessing, however, introduces some random + distortion of the image to improve accuracy. + Args: + image_buffer: scalar string Tensor representing the raw JPEG image buffer. + bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords] + where each coordinate is [0, 1) and the coordinates are arranged as + [ymin, xmin, ymax, xmax]. + output_height: The height of the image after preprocessing. + output_width: The width of the image after preprocessing. + num_channels: Integer depth of the image buffer for decoding. + is_training: `True` if we're preprocessing the image for training and + `False` otherwise. + Returns: + A preprocessed image. + """ + if is_training: + # For training, we want to randomize some of the distortions. + image = _decode_crop_and_flip(image_buffer, bbox, num_channels) + image = _resize_image(image, output_height, output_width) + else: + # For validation, we want to decode, resize, then just crop the middle. + image = tf.image.decode_jpeg(image_buffer, channels=num_channels) + image = _aspect_preserving_resize(image, _RESIZE_MIN) + image = _central_crop(image, output_height, output_width) + + image.set_shape([output_height, output_width, num_channels]) + + return _mean_image_subtraction(image, _CHANNEL_MEANS, num_channels) + +def preprocess_image2(image_buffer, bbox, output_height, output_width, + num_channels, is_training=False): + """Preprocesses the given image. + Preprocessing includes decoding, cropping, and resizing for both training + and eval images. Training preprocessing, however, introduces some random + distortion of the image to improve accuracy. + Args: + image_buffer: scalar string Tensor representing the raw JPEG image buffer. + bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords] + where each coordinate is [0, 1) and the coordinates are arranged as + [ymin, xmin, ymax, xmax]. + output_height: The height of the image after preprocessing. + output_width: The width of the image after preprocessing. + num_channels: Integer depth of the image buffer for decoding. + is_training: `True` if we're preprocessing the image for training and + `False` otherwise. + Returns: + A preprocessed image. + """ + if is_training: + # For training, we want to randomize some of the distortions. + image = _decode_crop_and_flip(image_buffer, bbox, num_channels) + image = _resize_image(image, output_height, output_width) + else: + # For validation, we want to decode, resize, then just crop the middle. + image = tf.image.decode_jpeg(image_buffer, channels=num_channels) + image = _aspect_preserving_resize(image, _RESIZE_MIN) + image = _central_crop(image, output_height, output_width) + image = tf.to_float(image) + + image.set_shape([output_height, output_width, num_channels]) + image = tf.slice(image, [0, 0, 0], [output_height, output_width, -1]) + + # Slice the image into different channels + image_channel1 = tf.slice(image, [0, 0, 0], [-1, -1, 1]) + image_channel2 = tf.slice(image, [0, 0, 1], [-1, -1, 1]) + image_channel3 = tf.slice(image, [0, 0, 2], [-1, -1, 1]) + + # Change RGB to BGR based on the preprocessing in myalexnet_forward_newtf.py ==> helps in increasing accuracy on the pretrained model + image = tf.concat([image_channel3, image_channel2, image_channel1], 2) + + return _mean_image_subtraction(image, _CHANNEL_MEANS, num_channels) + +def preprocess_image3(image_buffer, bbox, output_height, output_width, + num_channels, is_training=False): + """Preprocesses the given image. + Preprocessing includes decoding, cropping, and resizing for both training + and eval images. Training preprocessing, however, introduces some random + distortion of the image to improve accuracy. Also changes RGB to BGR + and divides by the standard dev + Args: + image_buffer: scalar string Tensor representing the raw JPEG image buffer. + bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords] + where each coordinate is [0, 1) and the coordinates are arranged as + [ymin, xmin, ymax, xmax]. + output_height: The height of the image after preprocessing. + output_width: The width of the image after preprocessing. + num_channels: Integer depth of the image buffer for decoding. + is_training: `True` if we're preprocessing the image for training and + `False` otherwise. + Returns: + A preprocessed image. + """ + if is_training: + # For training, we want to randomize some of the distortions. + image = _decode_crop_and_flip(image_buffer, bbox, num_channels) + image = _resize_image(image, output_height, output_width) + else: + # For validation, we want to decode, resize, then just crop the middle. + image = tf.image.decode_jpeg(image_buffer, channels=num_channels) + image = _aspect_preserving_resize(image, _RESIZE_MIN) + image = _central_crop(image, output_height, output_width) + image = tf.to_float(image) + + image.set_shape([output_height, output_width, num_channels]) + image = tf.slice(image, [0, 0, 0], [output_height, output_width, -1]) + + # Slice the image into different channels + image_channel1 = tf.slice(image, [0, 0, 0], [-1, -1, 1]) + image_channel2 = tf.slice(image, [0, 0, 1], [-1, -1, 1]) + image_channel3 = tf.slice(image, [0, 0, 2], [-1, -1, 1]) + + # Change RGB to BGR based on the preprocessing in myalexnet_forward_newtf.py ==> helps in increasing accuracy + image = tf.concat([image_channel3, image_channel2, image_channel1], 2) + + image = _mean_image_subtraction(image, _CHANNEL_MEANS, num_channels) + image = tf.divide(image, _CHANNEL_STDS) + return image + +def preprocess_image4(image_buffer, bbox, output_height, output_width, + num_channels, is_training=False): + """Preprocesses the given image. + Preprocessing includes decoding, cropping, and resizing for both training + and eval images. Training preprocessing, however, introduces some random + distortion of the image to improve accuracy. Also adds lighting noise, + changes RGB to BGR and divides by the standard dev + Args: + image_buffer: scalar string Tensor representing the raw JPEG image buffer. + bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords] + where each coordinate is [0, 1) and the coordinates are arranged as + [ymin, xmin, ymax, xmax]. + output_height: The height of the image after preprocessing. + output_width: The width of the image after preprocessing. + num_channels: Integer depth of the image buffer for decoding. + is_training: `True` if we're preprocessing the image for training and + `False` otherwise. + Returns: + A preprocessed image. + """ + if is_training: + # For training, we want to randomize some of the distortions. + image = _decode_crop_and_flip(image_buffer, bbox, num_channels) + image = _resize_image(image, output_height, output_width) + else: + # For validation, we want to decode, resize, then just crop the middle. + image = tf.image.decode_jpeg(image_buffer, channels=num_channels) + image = _aspect_preserving_resize(image, _RESIZE_MIN) + image = _central_crop(image, output_height, output_width) + image = tf.to_float(image) + + image.set_shape([output_height, output_width, num_channels]) + image = tf.slice(image, [0, 0, 0], [output_height, output_width, -1]) + + # Slice the image into different channels + image_channel1 = tf.slice(image, [0, 0, 0], [-1, -1, 1]) + image_channel2 = tf.slice(image, [0, 0, 1], [-1, -1, 1]) + image_channel3 = tf.slice(image, [0, 0, 2], [-1, -1, 1]) + + # Change RGB to BGR based on the preprocessing in myalexnet_forward_newtf.py ==> helps in increasing accuracy + image = tf.concat([image_channel3, image_channel2, image_channel1], 2) + + if is_training: # add lighting noise + image = _lighting_noise(image) + + image = _mean_image_subtraction(image, _CHANNEL_MEANS, num_channels) + image = tf.divide(image, _CHANNEL_STDS) + return image diff --git a/case_studies/empir/examples/mnist_attack.py b/case_studies/empir/examples/mnist_attack.py new file mode 100644 index 0000000..c263108 --- /dev/null +++ b/case_studies/empir/examples/mnist_attack.py @@ -0,0 +1,681 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import numpy as np +from six.moves import xrange +import tensorflow as tf +from tensorflow.python.platform import flags + +import time +import argparse +import logging +import os +import sys + +from modified_cleverhans.utils import parse_model_settings, build_model_save_path +from modified_cleverhans.utils import set_log_level, AccuracyReport +from modified_cleverhans.utils_mnist import data_mnist +from modified_cleverhans.utils_tf import model_train, model_eval, model_eval_ensemble, batch_eval, tf_model_load +from modified_cleverhans.utils_tf import model_train_teacher, model_train_student, model_train_inpgrad_reg #for training with input gradient regularization + + +FLAGS = flags.FLAGS + +# Scaling input to softmax +INIT_T = 1.0 +#ATTACK_T = 1.0 +ATTACK_T = 0.25 + +# enum attack types +ATTACK_CARLINI_WAGNER_L2 = 0 +ATTACK_JSMA = 1 +ATTACK_FGSM = 2 +ATTACK_MADRYETAL = 3 +ATTACK_BASICITER = 4 + +# enum adversarial training types +ADVERSARIAL_TRAINING_MADRYETAL = 1 +ADVERSARIAL_TRAINING_FGSM = 2 +MAX_EPS = 0.3 + +MAX_BATCH_SIZE = 100 + + +def mnist_attack(train_start=0, train_end=60000, test_start=0, + test_end=10000, viz_enabled=True, nb_epochs=6, + batch_size=128, nb_filters=64, + nb_samples=10, learning_rate=0.001, + eps=0.3, attack=0, + attack_iterations=100, model_path=None, + targeted=False, rand=False, + stocRound=False, lowprecision=False, + wbits=0, abits=0, wbitsList=0, abitsList=0, wbits2=0, abits2=0, wbits2List=0, abits2List=0, + ensembleThree=False, model_path1=None, model_path2=None, model_path3=None, + distill = False, inpgradreg = False, l2dbl = 0, l2cs = 0, + debug=None, test=False, + data_dir=None, delay=0, adv=0, nb_iter=40): + """ + MNIST tutorial for generic attack + :param train_start: index of first training set example + :param train_end: index of last training set example + :param test_start: index of first test set example + :param test_end: index of last test set example + :param viz_enabled: (boolean) activate plots of adversarial examples + :param nb_epochs: number of epochs to train model + :param batch_size: size of training batches + :param nb_classes: number of output classes + :param nb_samples: number of test inputs to attack + :param learning_rate: learning rate for training + :param model_path: path to the model file + :param targeted: should we run a targeted attack? or untargeted? + :return: an AccuracyReport object + """ + # Object used to keep track of (and return) key accuracies + report = AccuracyReport() + + # MNIST-specific dimensions + img_rows = 28 + img_cols = 28 + channels = 1 + nb_classes = 10 + + # Set TF random seed to improve reproducibility + tf.set_random_seed(1237) + + # Create TF session + sess = tf.Session() + print("Created TensorFlow session.") + + if debug: + set_log_level(logging.DEBUG) + else: + set_log_level(logging.WARNING) # for running on sharcnet + + # Get MNIST test data + X_train, Y_train, X_test, Y_test = data_mnist(datadir=data_dir, + train_start=train_start, + train_end=train_end, + test_start=test_start, + test_end=test_end) + + # Define input TF placeholder + x = tf.placeholder(tf.float32, shape=(None, img_rows, img_cols, channels)) + y = tf.placeholder(tf.float32, shape=(None, nb_classes)) + phase = tf.placeholder(tf.bool, name='phase') + + # for attempting to break unscaled network. + logits_scalar = tf.placeholder_with_default( + INIT_T, shape=(), name="logits_temperature") + + save = False + train_from_scratch = False + if ensembleThree: + if (model_path1 is None or model_path2 is None or model_path3 is None): + train_from_scratch = True + else: + train_from_scratch = False + elif model_path is not None: + if os.path.exists(model_path): + # check for existing model in immediate subfolder + if any(f.endswith('.meta') for f in os.listdir(model_path)): + train_from_scratch = False + else: + model_path = build_model_save_path( + model_path, batch_size, nb_filters, learning_rate, nb_epochs, adv, delay) + print(model_path) + save = True + train_from_scratch = True + else: + train_from_scratch = True # train from scratch, but don't save since no path given + + # Define TF model graph + if ensembleThree: + if (wbitsList is None) or (abitsList is None): # Layer wise separate quantization not specified for first model + if (wbits==0) or (abits==0): + print("Error: the number of bits for constant precision weights and activations across layers for the first model have to specified using wbits1 and abits1 flags") + sys.exit(1) + else: + fixedPrec1 = 1 + elif (len(wbitsList) != 3) or (len(abitsList) != 3): + print("Error: Need to specify the precisions for activations and weights for the atleast the three convolutional layers of the first model") + sys.exit(1) + else: + fixedPrec1 = 0 + + if (wbits2List is None) or (abits2List is None): # Layer wise separate quantization not specified for second model + if (wbits2==0) or (abits2==0): + print("Error: the number of bits for constant precision weights and activations across layers for the second model have to specified using wbits1 and abits1 flags") + sys.exit(1) + else: + fixedPrec2 = 1 + elif (len(wbits2List) != 3) or (len(abits2List) != 3): + print("Error: Need to specify the precisions for activations and weights for the atleast the three convolutional layers of the second model") + sys.exit(1) + else: + fixedPrec2 = 0 + + if (fixedPrec2 != 1) or (fixedPrec1 != 1): # Atleast one of the models have separate precisions per layer + fixedPrec=0 + print("Within atleast one model has separate precisions") + if (fixedPrec1 == 1): # first layer has fixed precision + abitsList = (abits, abits, abits) + wbitsList = (wbits, wbits, wbits) + if (fixedPrec2 == 1): # second layer has fixed precision + abits2List = (abits2, abits2, abits2) + wbits2List = (wbits2, wbits2, wbits2) + else: + fixedPrec=1 + + if (train_from_scratch): + print ("The ensemble model cannot be trained from scratch") + sys.exit(1) + if fixedPrec == 1: + from modified_cleverhans_tutorials.tutorial_models import make_ensemble_three_cnn + model = make_ensemble_three_cnn( + phase, logits_scalar, 'lp1_', 'lp2_', 'fp_', wbits, abits, wbits2, abits2, nb_filters=nb_filters) + else: + from modified_cleverhans_tutorials.tutorial_models import make_layerwise_three_combined_cnn + model = make_layerwise_three_combined_cnn( + phase, logits_scalar, 'lp1_', 'lp2_', 'fp_', wbitsList, abitsList, wbits2List, abits2List, nb_filters=nb_filters) + elif lowprecision: # For generic DoReFa net style low precision + if (wbitsList is None) or (abitsList is None): # Layer wise separate quantization not specified + if (wbits==0) or (abits==0): + print("Error: the number of bits for constant precision weights and activations across layers have to specified using wbits and abits flags") + sys.exit(1) + else: + fixedPrec = 1 + elif (len(wbitsList) != 3) or (len(abitsList) != 3): + print("Error: Need to specify the precisions for activations and weights for the atleast the three convolutional layers") + sys.exit(1) + else: + fixedPrec = 0 + + if fixedPrec: + from modified_cleverhans_tutorials.tutorial_models import make_basic_lowprecision_cnn + model = make_basic_lowprecision_cnn( + phase, logits_scalar, 'lp_', wbits, abits, nb_filters=nb_filters, stocRound=stocRound) + else: + from modified_cleverhans_tutorials.tutorial_models import make_layerwise_lowprecision_cnn + model = make_layerwise_lowprecision_cnn( + phase, logits_scalar, 'lp_', wbitsList, abitsList, nb_filters=nb_filters, stocRound=stocRound) + elif distill: + from modified_cleverhans_tutorials.tutorial_models import make_distilled_cnn + model = make_distilled_cnn(phase, logits_scalar, + 'teacher_fp_', 'fp_', nb_filters=nb_filters) + else: + if rand: + print('rand=True') + from modified_cleverhans_tutorials.tutorial_models import make_scaled_rand_cnn + model = make_scaled_rand_cnn( + phase, logits_scalar, 'fp_rand', nb_filters=nb_filters) + else: + from modified_cleverhans_tutorials.tutorial_models import make_basic_cnn + model = make_basic_cnn(phase, logits_scalar, + 'fp_', nb_filters=nb_filters) + + # separate predictions of teacher for distilled training + if distill: + teacher_preds = model.teacher_call(x, reuse=False) + teacher_logits = model.get_teacher_logits(x, reuse=False) + # separate calling function for ensemble models + if ensembleThree: + preds = model.ensemble_call(x, reuse=False) + else: + ##default + preds = model(x, reuse=False) # * logits_scalar + print("Defined TensorFlow model graph.") + + ########################################################################### + # Training the model using TensorFlow + ########################################################################### + rng = np.random.RandomState([2017, 8, 30]) + + # Train an MNIST model + train_params = { + 'nb_epochs': nb_epochs, + 'batch_size': batch_size, + 'learning_rate': learning_rate, + 'loss_name': 'train loss', + 'filename': 'model', + 'reuse_global_step': False, + 'train_scope': 'train', + 'is_training': True + } + + if adv != 0: + if adv == ADVERSARIAL_TRAINING_MADRYETAL: + from modified_cleverhans.attacks import MadryEtAl + train_attack_params = {'eps': MAX_EPS, 'eps_iter': 0.01, + 'nb_iter': nb_iter} + train_attacker = MadryEtAl(model, sess=sess) + + elif adv == ADVERSARIAL_TRAINING_FGSM: + from modified_cleverhans.attacks import FastGradientMethod + stddev = int(np.ceil((MAX_EPS * 255) // 2)) + train_attack_params = {'eps': tf.abs(tf.truncated_normal( + shape=(batch_size, 1, 1, 1), mean=0, stddev=stddev))} + train_attacker = FastGradientMethod(model, back='tf', sess=sess) + # create the adversarial trainer + train_attack_params.update({'clip_min': 0., 'clip_max': 1.}) + adv_x_train = train_attacker.generate(x, phase, **train_attack_params) + preds_adv_train = model.get_probs(adv_x_train) + + eval_attack_params = {'eps': MAX_EPS, 'clip_min': 0., 'clip_max': 1.} + adv_x_eval = train_attacker.generate(x, phase, **eval_attack_params) + preds_adv_eval = model.get_probs(adv_x_eval) # * logits_scalar + + def evaluate(): + # Evaluate the accuracy of the MNIST model on clean test examples + eval_params = {'batch_size': batch_size} + if ensembleThree: + acc = model_eval_ensemble( + sess, x, y, preds, X_test, Y_test, phase=phase, args=eval_params) + else: + acc = model_eval( + sess, x, y, preds, X_test, Y_test, phase=phase, args=eval_params) + report.clean_train_clean_eval = acc + assert X_test.shape[0] == test_end - test_start, X_test.shape + print('Test accuracy on legitimate examples: %0.4f' % acc) + + if adv != 0: + # Accuracy of the adversarially trained model on adversarial + # examples + acc = model_eval( + sess, x, y, preds_adv_eval, X_test, Y_test, phase=phase, args=eval_params) + print('Test accuracy on adversarial examples: %0.4f' % acc) + + acc = model_eval( + sess, x, y, preds_adv_eval, X_test, Y_test, + phase=phase, args=eval_params, feed={logits_scalar: ATTACK_T}) + print('Test accuracy on adversarial examples (scaled): %0.4f' % acc) + + if train_from_scratch: + if save: + train_params.update({'log_dir': model_path}) + if adv and delay > 0: + train_params.update({'nb_epochs': delay}) + + # do clean training for 'nb_epochs' or 'delay' epochs + if distill: + temperature = 100 # 1 means the teacher predictions are used as it is + teacher_scaled_preds_val = model_train_teacher(sess, x, y, teacher_preds, teacher_logits, + temperature, X_train, Y_train, phase=phase, args=train_params, rng=rng) + eval_params = {'batch_size': batch_size} + teacher_acc = model_eval( + sess, x, y, teacher_preds, X_test, Y_test, phase=phase, args=eval_params) + print('Test accuracy of the teacher model on legitimate examples: %0.4f' % teacher_acc) + print('Training the student model...') + student_train_params = { + 'nb_epochs': 50, + 'batch_size': batch_size, + 'learning_rate': learning_rate, + 'loss_name': 'train loss', + 'filename': 'model', + 'reuse_global_step': False, + 'train_scope': 'train', + 'is_training': True + } + if save: + student_train_params.update({'log_dir': model_path}) + y_teacher = tf.placeholder(tf.float32, shape=(None, nb_classes)) + model_train_student(sess, x, y, preds, temperature, X_train, Y_train, y_teacher=y_teacher, + teacher_preds=teacher_scaled_preds_val, alpha=0.5, beta=0.5, phase=phase, evaluate=evaluate, args=student_train_params, save=save, rng=rng) + elif inpgradreg: + model_train_inpgrad_reg(sess, x, y, preds, X_train, Y_train, phase=phase, + evaluate=evaluate, l2dbl = l2dbl, l2cs = l2cs, args=train_params, save=save, rng=rng) + elif test: + model_train(sess, x, y, preds, X_train, Y_train, phase=phase, + evaluate=evaluate, args=train_params, save=save, rng=rng) + else: + model_train(sess, x, y, preds, X_train, Y_train, + phase=phase, args=train_params, save=save, rng=rng) + + # optionally do additional adversarial training + if adv: + print("Adversarial training for %d epochs" % (nb_epochs - delay)) + train_params.update({'nb_epochs': nb_epochs - delay}) + train_params.update({'reuse_global_step': True}) + if test: + model_train(sess, x, y, preds, X_train, Y_train, phase=phase, + predictions_adv=preds_adv_train, evaluate=evaluate, args=train_params, + save=save, rng=rng) + else: + model_train(sess, x, y, preds, X_train, Y_train, phase=phase, + predictions_adv=preds_adv_train, args=train_params, + save=save, rng=rng) + else: + if ensembleThree: ## Ensemble models have to loaded from different paths + variables = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) + stored_variables = ['lp_conv1_init/k', 'lp_conv2_bin_init/k', 'lp_conv3_bin_init/k', 'lp_logits_init/W'] + variable_dict = dict(zip(stored_variables, variables[:4])) + # Restore the first set of variables from model_path1 + saver = tf.train.Saver(variable_dict) + saver.restore(sess, tf.train.latest_checkpoint(model_path1)) + # Restore the second set of variables from model_path2 + variable_dict = dict(zip(stored_variables, variables[4:8])) + saver2 = tf.train.Saver(variable_dict) + saver2.restore(sess, tf.train.latest_checkpoint(model_path2)) + stored_variables = ['fp_conv1_init/k', 'fp_conv2_init/k', 'fp_conv3_init/k', 'fp_logits_init/W'] + variable_dict = dict(zip(stored_variables, variables[8:])) + saver3 = tf.train.Saver(variable_dict) + saver3.restore(sess, tf.train.latest_checkpoint(model_path3)) + else: #default below + tf_model_load(sess, model_path) + print('Restored model from %s' % model_path) + evaluate() + + # Evaluate the accuracy of the MNIST model on legitimate test examples + eval_params = {'batch_size': batch_size} + if ensembleThree: ## Ensemble models have to be evaluated with a separate function + accuracy = model_eval_ensemble(sess, x, y, preds, X_test, Y_test, phase=phase, feed={phase: False}, args=eval_params) + else: #default below + accuracy = model_eval(sess, x, y, preds, X_test, Y_test, phase=phase, + feed={phase: False}, args=eval_params) + assert X_test.shape[0] == test_end - test_start, X_test.shape + print('Test accuracy on legitimate test examples: {0}'.format(accuracy)) + report.clean_train_clean_eval = accuracy + + ########################################################################### + # Build dataset + ########################################################################### + if viz_enabled: + assert nb_samples == nb_classes + idxs = [np.where(np.argmax(Y_test, axis=1) == i)[0][0] + for i in range(nb_classes)] + viz_rows = nb_classes if targeted else 2 + # Initialize our array for grid visualization + grid_shape = (nb_classes, viz_rows, img_rows, img_cols, channels) + grid_viz_data = np.zeros(grid_shape, dtype='f') + + if targeted: + from modified_cleverhans.utils import build_targeted_dataset + if viz_enabled: + from modified_cleverhans.utils import grid_visual + adv_inputs, true_labels, adv_ys = build_targeted_dataset( + X_test, Y_test, idxs, nb_classes, img_rows, img_cols, channels) + else: + adv_inputs, true_labels, adv_ys = build_targeted_dataset( + X_test, Y_test, np.arange(nb_samples), nb_classes, img_rows, img_cols, channels) + else: + if viz_enabled: + from modified_cleverhans.utils import pair_visual + adv_inputs = X_test[idxs] + else: + adv_inputs = X_test[:nb_samples] + + ########################################################################### + # Craft adversarial examples using generic approach + ########################################################################### + if targeted: + att_batch_size = np.clip( + nb_samples * (nb_classes - 1), a_max=MAX_BATCH_SIZE, a_min=1) + nb_adv_per_sample = nb_classes - 1 + yname = "y_target" + + else: + att_batch_size = np.minimum(nb_samples, MAX_BATCH_SIZE) + nb_adv_per_sample = 1 + adv_ys = None + yname = "y" + + print('Crafting ' + str(nb_samples) + ' * ' + str(nb_adv_per_sample) + + ' adversarial examples') + print("This could take some time ...") + + if ensembleThree: + model_type = 'ensembleThree' + else: + model_type = 'default' + + if attack == ATTACK_CARLINI_WAGNER_L2: + print('Attack: CarliniWagnerL2') + from modified_cleverhans.attacks import CarliniWagnerL2 + attacker = CarliniWagnerL2(model, back='tf', model_type=model_type, num_classes=nb_classes, sess=sess) + attack_params = {'binary_search_steps': 1, + 'max_iterations': attack_iterations, + 'learning_rate': 0.1, + 'batch_size': att_batch_size, + 'initial_const': 10, + } + elif attack == ATTACK_JSMA: + print('Attack: SaliencyMapMethod') + from modified_cleverhans.attacks import SaliencyMapMethod + attacker = SaliencyMapMethod(model, back='tf', model_type=model_type, num_classes=nb_classes, sess=sess) + attack_params = {'theta': 1., 'gamma': 0.1} + elif attack == ATTACK_FGSM: + print('Attack: FastGradientMethod') + from modified_cleverhans.attacks import FastGradientMethod + attacker = FastGradientMethod(model, back='tf', model_type=model_type, num_classes=nb_classes, sess=sess) + attack_params = {'eps': eps} + elif attack == ATTACK_MADRYETAL: + print('Attack: MadryEtAl') + from modified_cleverhans.attacks import MadryEtAl + attacker = MadryEtAl(model, back='tf', model_type=model_type, num_classes=nb_classes, sess=sess) + attack_params = {'eps': eps, 'eps_iter': 0.01, 'nb_iter': nb_iter} + elif attack == ATTACK_BASICITER: + print('Attack: BasicIterativeMethod') + from modified_cleverhans.attacks import BasicIterativeMethod + attacker = BasicIterativeMethod(model, back='tf', model_type=model_type, num_classes=nb_classes, sess=sess) + attack_params = {'eps': eps, 'eps_iter': 0.01, 'nb_iter': nb_iter} + else: + print("Attack undefined") + sys.exit(1) + + attack_params.update({yname: adv_ys, 'clip_min': 0., 'clip_max': 1.}) + adv_np = attacker.generate_np(adv_inputs, phase, **attack_params) + + ''' + name = 'm_fgsm_eps%s_n%s.npy' % (eps, nb_samples) + fpath = os.path.join( + '/scratch/gallowaa/mnist/adversarial_examples/modified_cleverhans/', name) + np.savez(fpath, x=adv_np, y=Y_test[:nb_samples]) + ''' + ''' + adv_x = attacker.generate(x, phase, **attack_params) + adv_np, = batch_eval(sess, [x], [adv_x], [adv_inputs], feed={ + phase: False}, args=eval_params) + ''' + eval_params = {'batch_size': att_batch_size} + if targeted: + print("Evaluating targeted results") + adv_accuracy = model_eval(sess, x, y, preds, adv_np, true_labels, phase=phase, + args=eval_params) + + else: + print("Evaluating untargeted results") + if viz_enabled: + if ensembleThree: + adv_accuracy = model_eval_ensemble(sess, x, y, preds, adv_np, Y_test[idxs], phase=phase, args=eval_params) + else: #default below + adv_accuracy = model_eval(sess, x, y, preds, adv_np, Y_test[ + idxs], phase=phase, args=eval_params) + else: + if ensembleThree: + adv_accuracy = model_eval_ensemble(sess, x, y, preds, adv_np, Y_test[:nb_samples], phase=phase, args=eval_params) + else: #default below + adv_accuracy = model_eval(sess, x, y, preds, adv_np, Y_test[ + :nb_samples], phase=phase, args=eval_params) + + if viz_enabled: + n = nb_classes - 1 + for i in range(nb_classes): + if targeted: + for j in range(nb_classes): + if i != j: + if j != 0 and i != n: + grid_viz_data[i, j] = adv_np[j * n + i] + if j == 0 and i > 0 or i == n and j > 0: + grid_viz_data[i, j] = adv_np[j * n + i - 1] + else: + grid_viz_data[i, j] = adv_inputs[j * n] + else: + grid_viz_data[j, 0] = adv_inputs[j] + grid_viz_data[j, 1] = adv_np[j] + print(grid_viz_data.shape) + + print('--------------------------------------') + + # Compute the number of adversarial examples that were successfully found + print('Test accuracy on adversarial examples {0:.4f}'.format(adv_accuracy)) + report.clean_train_adv_eval = 1. - adv_accuracy + + # Compute the average distortion introduced by the algorithm + percent_perturbed = np.mean(np.sum((adv_np - adv_inputs)**2, + axis=(1, 2, 3))**.5) + print('Avg. L_2 norm of perturbations {0:.4f}'.format(percent_perturbed)) + + # Compute number of modified features (L_0 norm) + nb_changed = np.where(adv_np != adv_inputs)[0].shape[0] + percent_perturb = np.mean(float(nb_changed) / adv_np.reshape(-1).shape[0]) + + # Compute the average distortion introduced by the algorithm + print('Avg. rate of perturbed features {0:.4f}'.format(percent_perturb)) + + # Friendly output for pasting into spreadsheet + print('{0:.4f}'.format(accuracy)) + print('{0:.4f}'.format(adv_accuracy)) + print('{0:.4f}'.format(percent_perturbed)) + print('{0:.4f}'.format(percent_perturb)) + + # Close TF session + sess.close() + + # Finally, block & display a grid of all the adversarial examples + if viz_enabled: + import matplotlib.pyplot as plt + _ = grid_visual(grid_viz_data) + + return report + + +def main(argv=None): + mnist_attack(viz_enabled=FLAGS.viz_enabled, + nb_epochs=FLAGS.nb_epochs, + batch_size=FLAGS.batch_size, + nb_samples=FLAGS.nb_samples, + nb_filters=FLAGS.nb_filters, + learning_rate=FLAGS.lr, + eps=FLAGS.eps, + attack=FLAGS.attack, + attack_iterations=FLAGS.attack_iterations, + model_path=FLAGS.model_path, + targeted=FLAGS.targeted, + rand=FLAGS.rand, + debug=FLAGS.debug, + test=FLAGS.test, + data_dir=FLAGS.data_dir, + lowprecision=FLAGS.lowprecision, + abits=FLAGS.abits, + wbits=FLAGS.wbits, + abitsList=FLAGS.abitsList, + wbitsList=FLAGS.wbitsList, + abits2=FLAGS.abits2, + wbits2=FLAGS.wbits2, + abits2List=FLAGS.abits2List, + wbits2List=FLAGS.wbits2List, + stocRound=FLAGS.stocRound, + model_path1=FLAGS.model_path1, + model_path2=FLAGS.model_path2, + model_path3=FLAGS.model_path3, + ensembleThree=FLAGS.ensembleThree, + distill = FLAGS.distill, + inpgradreg = FLAGS.inpgradreg, + l2dbl = FLAGS.l2dbl, + l2cs = FLAGS.l2cs, + delay=FLAGS.delay, + adv=FLAGS.adv, + nb_iter=FLAGS.nb_iter) + + +if __name__ == '__main__': + + par = argparse.ArgumentParser() + + # Generic flags + par.add_argument('--gpu', help='id of GPU to use') + par.add_argument('--model_path', help='Path to save or load model') + par.add_argument('--data_dir', help='Path to training data', + default='/tmp/mnist') + par.add_argument( + '--viz_enabled', help='Visualize adversarial ex.', action="store_true") + par.add_argument( + '--debug', help='Sets log level to DEBUG, otherwise INFO', action="store_true") + par.add_argument( + '--test', help='Test while training, takes longer', action="store_true") + + # Architecture and training specific flags + par.add_argument('--nb_epochs', type=int, default=15, + help='Number of epochs to train model') + par.add_argument('--nb_filters', type=int, default=64, + help='Number of filters in first layer') + par.add_argument('--batch_size', type=int, default=128, + help='Size of training batches') + par.add_argument('--lr', type=float, default=0.001, + help='Learning rate') + par.add_argument('--rand', help='Stochastic weight layer?', + action="store_true") + + # Attack specific flags + par.add_argument('--attack', type=int, default=0, + help='Attack type, 0=CW, 1=JSMA') + par.add_argument("--eps", type=float, default=0.3) + par.add_argument('--attack_iterations', type=int, default=50, + help='Number of iterations to run CW attack; 1000 is good') + par.add_argument('--nb_samples', type=int, + default=10000, help='Nb of inputs to attack') + par.add_argument( + '--targeted', help='Run a targeted attack?', action="store_true") + + # EMPIR specific flags + par.add_argument('--lowprecision', help='Use other low precision models absed on DoReFa net', action="store_true") # For DoReFa net style quantization + par.add_argument('--wbits', type=int, default=0, help='No. of bits in weight representation') + par.add_argument('--abits', type=int, default=0, help='No. of bits in activation representation') + par.add_argument('--wbitsList', type=int, nargs='+', help='List of No. of bits in weight representation for different layers') + par.add_argument('--abitsList', type=int, nargs='+', help='List of No. of bits in activation representation for different layers') + par.add_argument('--stocRound', help='Stochastic rounding for weights (only in training) and activations?', + action="store_true") + par.add_argument('--model_path1', help='Path where saved model1 is stored and can be loaded') + par.add_argument('--model_path2', help='Path where saved model2 is stored and can be loaded') + par.add_argument('--model_path3', help='Path where saved model3 is stored and can be loaded') + par.add_argument('--ensembleThree', help='Use an ensemble of full precision and two low precision models', action="store_true") + par.add_argument('--wbits2', type=int, default=0, help='No. of bits in weight representation of model2, model1 specified using wbits') + par.add_argument('--abits2', type=int, default=0, help='No. of bits in activation representation of model2, model2 specified using abits') + par.add_argument('--wbits2List', type=int, nargs='+', help='List of No. of bits in weight representation for different layers of model2') + par.add_argument('--abits2List', type=int, nargs='+', help='List of No. of bits in activation representation for different layers of model2') + # extra flags for defensive distillation + par.add_argument('--distill', help='Train the model using distillation', action="store_true") + par.add_argument('--student_epochs', type=int, default=50, help='No. of epochs for which the student model is trained') + # extra flags for input gradient regularization + par.add_argument('--inpgradreg', help='Train the model using input gradient regularization', action="store_true") + par.add_argument('--l2dbl', type=int, default=0, help='l2 double backprop penalty') + par.add_argument('--l2cs', type=int, default=0, help='l2 certainty sensitivity penalty') + # Adversarial training flags + par.add_argument( + '--adv', help='Adversarial training type?', type=int, default=0) + par.add_argument('--delay', type=int, + default=10, help='Nb of epochs to delay adv training by') + par.add_argument('--nb_iter', type=int, + default=40, help='Nb of iterations of PGD') + + FLAGS = par.parse_args() + + if FLAGS.gpu: + os.environ['CUDA_VISIBLE_DEVICES'] = FLAGS.gpu + + tf.app.run() diff --git a/case_studies/empir/modified_cleverhans/__init__.py b/case_studies/empir/modified_cleverhans/__init__.py new file mode 100644 index 0000000..9f196eb --- /dev/null +++ b/case_studies/empir/modified_cleverhans/__init__.py @@ -0,0 +1,19 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from modified_cleverhans.devtools.version import dev_version + +# Attach a hex digest to the version string to keep track of changes +# in the development branch +__version__ = '2.0.0-' + dev_version() diff --git a/case_studies/empir/modified_cleverhans/attacks.py b/case_studies/empir/modified_cleverhans/attacks.py new file mode 100644 index 0000000..dd3a0d8 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/attacks.py @@ -0,0 +1,1304 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from abc import ABCMeta +import numpy as np +from six.moves import xrange +import warnings +import collections + +import modified_cleverhans.utils as utils +from modified_cleverhans.model import Model, CallableModelWrapper + +_logger = utils.create_logger("cleverhans.attacks") + + +class Attack(object): + + """ + Abstract base class for all attack classes. + """ + __metaclass__ = ABCMeta + + def __init__(self, model, back='tf', sess=None, model_type='default', num_classes=10): + """ + :param model: An instance of the cleverhans.model.Model class. + :param back: The backend to use. Either 'tf' (default) or 'th' + (support for Theano is however deprecated and will + be removed on 2017-11-08). + :param sess: The tf session to run graphs in (use None for Theano) + """ + if not(back == 'tf' or back == 'th'): + raise ValueError("Backend argument must either be 'tf' or 'th'.") + + if back == 'th' and sess is not None: + raise Exception("A session should not be provided when using th.") + elif back == 'tf' and sess is None: + import tensorflow as tf + sess = tf.get_default_session() + + if not isinstance(model, Model): + if hasattr(model, '__call__'): + warnings.warn("CleverHans support for supplying a callable" + " instead of an instance of the" + " cleverhans.model.Model class is" + " deprecated and will be dropped on 2018-01-11.") + else: + raise ValueError("The model argument should be an instance of" + " the cleverhans.model.Model class.") + if back == 'th': + warnings.warn("CleverHans support for Theano is deprecated and " + "will be dropped on 2017-11-08.") + + # Prepare attributes + self.model = model + self.back = back + self.sess = sess + self.model_type = model_type # for EMPIR added model_type + self.num_classes = num_classes # for EMPIR added number of classes + + # We are going to keep track of old graphs and cache them. + self.graphs = {} + + # When calling generate_np, arguments in the following set should be + # fed into the graph, as they are not structural items that require + # generating a new graph. + # This dict should map names of arguments to the types they should + # have. + # (Usually, the target class will be a feedable keyword argument.) + self.feedable_kwargs = {} + + # When calling generate_np, arguments in the following set should NOT + # be fed into the graph, as they ARE structural items that require + # generating a new graph. + # This list should contain the names of the structural arguments. + self.structural_kwargs = [] + + def generate(self, x, phase, **kwargs): + """ + Generate the attack's symbolic graph for adversarial examples. This + method should be overriden in any child class that implements an + attack that is expressable symbolically. Otherwise, it will wrap the + numerical implementation as a symbolic operator. + :param x: The model's symbolic inputs. + :param **kwargs: optional parameters used by child classes. + :return: A symbolic representation of the adversarial examples. + """ + if self.back == 'th': + raise NotImplementedError('Theano version not implemented.') + + # the set of arguments that are structural properties of the attack + # if these arguments are different, we must construct a new graph + fixed = dict((k, v) for k, v in kwargs.items() + if k in self.structural_kwargs) + + # the set of arguments that are passed as placeholders to the graph + # on each call, and can change without constructing a new graph + feedable = dict((k, v) for k, v in kwargs.items() + if k in self.feedable_kwargs) + + if len(fixed) + len(feedable) < len(kwargs): + warnings.warn("Supplied extra keyword arguments that are not " + "used in the graph computation. They have been " + "ignored.") + + if not all(isinstance(value, collections.Hashable) + for value in fixed.values()): + # we have received a fixed value that isn't hashable + # this means we can't cache this graph for later use, + # and it will have to be discarded later + hash_key = None + else: + # create a unique key for this set of fixed paramaters + hash_key = tuple(sorted(fixed.items())) + + if hash_key not in self.graphs: + self.construct_graph(phase, fixed, feedable, x, hash_key) + + x, new_kwargs, x_adv = self.graphs[hash_key] + + return x_adv + + def construct_graph(self, phase, fixed, feedable, x_val, hash_key): + """ + Construct the graph required to run the attack through generate_np. + :param fixed: Structural elements that require defining a new graph. + :param feedable: Arguments that can be fed to the same graph when + they take different values. + :param x_val: symbolic adversarial example + :param hash_key: the key used to store this graph in our cache + """ + # try our very best to create a TF placeholder for each of the + # feedable keyword arguments, and check the types are one of + # the allowed types + import tensorflow as tf + + class_name = str(self.__class__).split(".")[-1][:-2] + _logger.info("Constructing new graph for attack " + class_name) + + # remove the None arguments, they are just left blank + for k in list(feedable.keys()): + if feedable[k] is None: + del feedable[k] + + # process all of the rest and create placeholders for them + new_kwargs = dict(x for x in fixed.items()) + for name, value in feedable.items(): + given_type = self.feedable_kwargs[name] + if isinstance(value, np.ndarray): + new_shape = [None] + list(value.shape[1:]) + new_kwargs[name] = tf.placeholder(given_type, new_shape) + elif isinstance(value, utils.known_number_types): + new_kwargs[name] = tf.placeholder(given_type, shape=[]) + else: + raise ValueError("Could not identify type of argument " + + name + ": " + str(value)) + + # x is a special placeholder we always want to have + x_shape = [None] + list(x_val.shape)[1:] + x = tf.placeholder(tf.float32, shape=x_shape) + + # now we generate the graph that we want + x_adv = self.generate(x, phase, **new_kwargs) + + self.graphs[hash_key] = (x, new_kwargs, x_adv) + + if len(self.graphs) >= 10: + warnings.warn("Calling generate_np() with multiple different " + "structural paramaters is inefficient and should" + " be avoided. Calling generate() is preferred.") + + def generate_np(self, x_val, phase, **kwargs): + """ + Generate adversarial examples and return them as a NumPy array. + Sub-classes *should not* implement this method unless they must + perform special handling of arguments. + :param x_val: A NumPy array with the original inputs. + :param **kwargs: optional parameters used by child classes. + :return: A NumPy array holding the adversarial examples. + """ + if self.back == 'th': + raise NotImplementedError('Theano version not implemented.') + if self.sess is None: + raise ValueError("Cannot use `generate_np` when no `sess` was" + " provided") + + # the set of arguments that are structural properties of the attack + # if these arguments are different, we must construct a new graph + fixed = dict((k, v) for k, v in kwargs.items() + if k in self.structural_kwargs) + + # the set of arguments that are passed as placeholders to the graph + # on each call, and can change without constructing a new graph + feedable = dict((k, v) for k, v in kwargs.items() + if k in self.feedable_kwargs) + + if len(fixed) + len(feedable) < len(kwargs): + warnings.warn("Supplied extra keyword arguments that are not " + "used in the graph computation. They have been " + "ignored.") + + if not all(isinstance(value, collections.Hashable) + for value in fixed.values()): + # we have received a fixed value that isn't hashable + # this means we can't cache this graph for later use, + # and it will have to be discarded later + hash_key = None + else: + # create a unique key for this set of fixed paramaters + hash_key = tuple(sorted(fixed.items())) + + if hash_key not in self.graphs: + self.construct_graph(phase, fixed, feedable, x_val, hash_key) + + x, new_kwargs, x_adv = self.graphs[hash_key] + + feed_dict = {x: x_val, phase: False} + + for name in feedable: + feed_dict[new_kwargs[name]] = feedable[name] + + return self.sess.run(x_adv, feed_dict) + + def get_or_guess_labels(self, x, kwargs): + """ + Get the label to use in generating an adversarial example for x. + The kwargs are fed directly from the kwargs of the attack. + If 'y' is in kwargs, then assume it's an untargeted attack and + use that as the label. + If 'y_target' is in kwargs, then assume it's a targeted attack and + use that as the label. + Otherwise, use the model's prediction as the label and perform an + untargeted attack. + """ + import tensorflow as tf + + if 'y' in kwargs and 'y_target' in kwargs: + raise ValueError("Can not set both 'y' and 'y_target'.") + elif 'y' in kwargs: + labels = kwargs['y'] + elif 'y_target' in kwargs: + labels = kwargs['y_target'] + else: + if self.model_type == 'ensembleThree': + preds = self.model.get_ensemblepreds(x, reuse=True) + original_predictions = tf.to_float(tf.one_hot(preds, self.num_classes)) # preds just gives the class number above + else: + preds = self.model.get_probs(x, reuse=True) + preds_max = tf.reduce_max(preds, 1, keep_dims=True) + original_predictions = tf.to_float(tf.equal(preds, + preds_max)) + labels = tf.stop_gradient(original_predictions) + if isinstance(labels, np.ndarray): + nb_classes = labels.shape[1] + else: + nb_classes = labels.get_shape().as_list()[1] + return labels, nb_classes + + def parse_params(self, params=None): + """ + Take in a dictionary of parameters and applies attack-specific checks + before saving them as attributes. + :param params: a dictionary of attack-specific parameters + :return: True when parsing was successful + """ + return True + + +class FastGradientMethod(Attack): + + """ + This attack was originally implemented by Goodfellow et al. (2015) with the + infinity norm (and is known as the "Fast Gradient Sign Method"). This + implementation extends the attack to other norms, and is therefore called + the Fast Gradient Method. + Paper link: https://arxiv.org/abs/1412.6572 + """ + + def __init__(self, model, back='tf', sess=None, model_type='default', num_classes=10): + """ + Create a FastGradientMethod instance. + Note: the model parameter should be an instance of the + cleverhans.model.Model abstraction provided by CleverHans. + """ + super(FastGradientMethod, self).__init__(model, back, sess, model_type, num_classes) + self.feedable_kwargs = {'eps': np.float32, + 'y': np.float32, + 'y_target': np.float32, + 'clip_min': np.float32, + 'clip_max': np.float32} + self.structural_kwargs = ['ord'] + + if not isinstance(self.model, Model): + self.model = CallableModelWrapper(self.model, 'probs') + + def generate(self, x, phase, **kwargs): + """ + Generate symbolic graph for adversarial examples and return. + :param x: The model's symbolic inputs. + :param eps: (optional float) attack step size (input variation) + :param ord: (optional) Order of the norm (mimics NumPy). + Possible values: np.inf, 1 or 2. + :param y: (optional) A tensor with the model labels. Only provide + this parameter if you'd like to use true labels when crafting + adversarial samples. Otherwise, model predictions are used as + labels to avoid the "label leaking" effect (explained in this + paper: https://arxiv.org/abs/1611.01236). Default is None. + Labels should be one-hot-encoded. + :param y_target: (optional) A tensor with the labels to target. Leave + y_target=None if y is also set. Labels should be + one-hot-encoded. + :param clip_min: (optional float) Minimum input component value + :param clip_max: (optional float) Maximum input component value + """ + # Parse and save attack-specific parameters + assert self.parse_params(**kwargs) + + if self.back == 'tf': + from .attacks_tf import fgm + else: + from .attacks_th import fgm + + labels, nb_classes = self.get_or_guess_labels(x, kwargs) + + if self.model_type == 'ensembleThree': ## for EMPIR: extra if condition for covering the multiple combined model case + return fgm(x, self.model.get_combinedAvgCorrectProbs(x, reuse=True), y=labels, eps=self.eps, + ord=self.ord, clip_min=self.clip_min, + clip_max=self.clip_max, + targeted=(self.y_target is not None)) + else: + return fgm(x, self.model.get_probs(x, reuse=True), y=labels, eps=self.eps, + ord=self.ord, clip_min=self.clip_min, + clip_max=self.clip_max, + targeted=(self.y_target is not None)) + + def parse_params(self, eps=0.3, ord=np.inf, y=None, y_target=None, + clip_min=None, clip_max=None, **kwargs): + """ + Take in a dictionary of parameters and applies attack-specific checks + before saving them as attributes. + + Attack-specific parameters: + :param eps: (optional float) attack step size (input variation) + :param ord: (optional) Order of the norm (mimics NumPy). + Possible values: np.inf, 1 or 2. + :param y: (optional) A tensor with the model labels. Only provide + this parameter if you'd like to use true labels when crafting + adversarial samples. Otherwise, model predictions are used as + labels to avoid the "label leaking" effect (explained in this + paper: https://arxiv.org/abs/1611.01236). Default is None. + Labels should be one-hot-encoded. + :param y_target: (optional) A tensor with the labels to target. Leave + y_target=None if y is also set. Labels should be + one-hot-encoded. + :param clip_min: (optional float) Minimum input component value + :param clip_max: (optional float) Maximum input component value + """ + # Save attack-specific parameters + + self.eps = eps + self.ord = ord + self.y = y + self.y_target = y_target + self.clip_min = clip_min + self.clip_max = clip_max + + if self.y is not None and self.y_target is not None: + raise ValueError("Must not set both y and y_target") + # Check if order of the norm is acceptable given current implementation + if self.ord not in [np.inf, int(1), int(2)]: + raise ValueError("Norm order must be either np.inf, 1, or 2.") + if self.back == 'th' and self.ord != np.inf: + raise NotImplementedError("The only FastGradientMethod norm " + "implemented for Theano is np.inf.") + return True + + +class BasicIterativeMethod(Attack): + + """ + The Basic Iterative Method (Kurakin et al. 2016). The original paper used + hard labels for this attack; no label smoothing. + Paper link: https://arxiv.org/pdf/1607.02533.pdf + """ + + def __init__(self, model, back='tf', sess=None, model_type='default', num_classes=10): + """ + Create a BasicIterativeMethod instance. + Note: the model parameter should be an instance of the + cleverhans.model.Model abstraction provided by CleverHans. + """ + super(BasicIterativeMethod, self).__init__(model, back, sess, model_type, num_classes) + self.feedable_kwargs = {'eps': np.float32, + 'eps_iter': np.float32, + 'y': np.float32, + 'y_target': np.float32, + 'clip_min': np.float32, + 'clip_max': np.float32} + self.structural_kwargs = ['ord', 'nb_iter'] + + if not isinstance(self.model, Model): + self.model = CallableModelWrapper(self.model, 'probs') + + def generate(self, x, phase, **kwargs): + """ + Generate symbolic graph for adversarial examples and return. + :param x: The model's symbolic inputs. + :param eps: (required float) maximum distortion of adversarial example + compared to original input + :param eps_iter: (required float) step size for each attack iteration + :param nb_iter: (required int) Number of attack iterations. + :param y: (optional) A tensor with the model labels. + :param y_target: (optional) A tensor with the labels to target. Leave + y_target=None if y is also set. Labels should be + one-hot-encoded. + :param ord: (optional) Order of the norm (mimics Numpy). + Possible values: np.inf, 1 or 2. + :param clip_min: (optional float) Minimum input component value + :param clip_max: (optional float) Maximum input component value + """ + import tensorflow as tf + + # Parse and save attack-specific parameters + assert self.parse_params(**kwargs) + + # Initialize loop variables + eta = 0 + + # Fix labels to the first model predictions for loss computation + if self.model_type == 'ensembleThree': + model_preds = self.model.get_combinedAvgCorrectProbs(x, reuse=True) + else: + model_preds = self.model.get_probs(x, reuse=True) + preds_max = tf.reduce_max(model_preds, 1, keep_dims=True) + if self.y_target is not None: + y = self.y_target + targeted = True + elif self.y is not None: + y = self.y + targeted = False + else: + y = tf.to_float(tf.equal(model_preds, preds_max)) + y = tf.stop_gradient(y) + targeted = False + + y_kwarg = 'y_target' if targeted else 'y' + fgm_params = {'eps': self.eps_iter, y_kwarg: y, 'ord': self.ord, + 'clip_min': self.clip_min, 'clip_max': self.clip_max} + + for i in range(self.nb_iter): + FGM = FastGradientMethod(self.model, back=self.back, + sess=self.sess) + # FGM = FastGradientMethod(self.model, back=self.back, model_type=self.model_type, + # num_classes=self.num_classes, sess=self.sess) + # Compute this step's perturbation + eta = FGM.generate(x + eta, phase, **fgm_params) - x + + # Clipping perturbation eta to self.ord norm ball + if self.ord == np.inf: + eta = tf.clip_by_value(eta, -self.eps, self.eps) + elif self.ord in [1, 2]: + reduc_ind = list(xrange(1, len(eta.get_shape()))) + if self.ord == 1: + norm = tf.reduce_sum(tf.abs(eta), + reduction_indices=reduc_ind, + keep_dims=True) + elif self.ord == 2: + norm = tf.sqrt(tf.reduce_sum(tf.square(eta), + reduction_indices=reduc_ind, + keep_dims=True)) + eta = eta * self.eps / norm + + # Define adversarial example (and clip if necessary) + adv_x = x + eta + if self.clip_min is not None and self.clip_max is not None: + adv_x = tf.clip_by_value(adv_x, self.clip_min, self.clip_max) + + return adv_x + + def parse_params(self, eps=0.3, eps_iter=0.05, nb_iter=10, y=None, + ord=np.inf, clip_min=None, clip_max=None, + y_target=None, **kwargs): + """ + Take in a dictionary of parameters and applies attack-specific checks + before saving them as attributes. + + Attack-specific parameters: + :param eps: (required float) maximum distortion of adversarial example + compared to original input + :param eps_iter: (required float) step size for each attack iteration + :param nb_iter: (required int) Number of attack iterations. + :param y: (optional) A tensor with the model labels. + :param y_target: (optional) A tensor with the labels to target. Leave + y_target=None if y is also set. Labels should be + one-hot-encoded. + :param ord: (optional) Order of the norm (mimics Numpy). + Possible values: np.inf, 1 or 2. + :param clip_min: (optional float) Minimum input component value + :param clip_max: (optional float) Maximum input component value + """ + + # Save attack-specific parameters + self.eps = eps + self.eps_iter = eps_iter + self.nb_iter = nb_iter + self.y = y + self.y_target = y_target + self.ord = ord + self.clip_min = clip_min + self.clip_max = clip_max + + if self.y is not None and self.y_target is not None: + raise ValueError("Must not set both y and y_target") + # Check if order of the norm is acceptable given current implementation + if self.ord not in [np.inf, 1, 2]: + raise ValueError("Norm order must be either np.inf, 1, or 2.") + if self.back == 'th': + error_string = "BasicIterativeMethod is not implemented in Theano" + raise NotImplementedError(error_string) + + return True + + +class SaliencyMapMethod(Attack): + + """ + The Jacobian-based Saliency Map Method (Papernot et al. 2016). + Paper link: https://arxiv.org/pdf/1511.07528.pdf + """ + + def __init__(self, model, back='tf', sess=None, model_type='default', num_classes=10): + """ + Create a SaliencyMapMethod instance. + Note: the model parameter should be an instance of the + cleverhans.model.Model abstraction provided by CleverHans. + """ + super(SaliencyMapMethod, self).__init__(model, back, sess, model_type, num_classes) + + if not isinstance(self.model, Model): + self.model = CallableModelWrapper(self.model, 'probs') + + if self.back == 'th': + error = "Theano version of SaliencyMapMethod not implemented." + raise NotImplementedError(error) + + import tensorflow as tf + self.feedable_kwargs = {'y_target': tf.float32, + 'phase': tf.bool} + self.structural_kwargs = ['theta', 'gamma', + 'clip_max', 'clip_min'] + + def generate(self, x, phase, **kwargs): + """ + Generate symbolic graph for adversarial examples and return. + :param x: The model's symbolic inputs. + :param theta: (optional float) Perturbation introduced to modified + components (can be positive or negative) + :param gamma: (optional float) Maximum percentage of perturbed features + :param clip_min: (optional float) Minimum component value for clipping + :param clip_max: (optional float) Maximum component value for clipping + :param y_target: (optional) Target tensor if the attack is targeted + """ + import tensorflow as tf + from .attacks_tf import jacobian_graph, jsma_batch + + # Parse and save attack-specific parameters + assert self.parse_params(**kwargs) + + # Define Jacobian graph wrt to this input placeholder + if self.model_type == 'ensembleThree': + preds = self.model.get_combinedAvgCorrectProbs(x, reuse=True) + else: + preds = self.model.get_probs(x, reuse=True) + nb_classes = preds.get_shape().as_list()[-1] + grads = jacobian_graph(preds, x, nb_classes) + + # Define appropriate graph (targeted / random target labels) + if self.y_target is not None: + def jsma_wrap(x_val, y_target): + return jsma_batch(self.sess, x, preds, grads, x_val, + self.theta, self.gamma, self.clip_min, + self.clip_max, nb_classes, + y_target=y_target, feed={phase: False}) + + # Attack is targeted, target placeholder will need to be fed + wrap = tf.py_func(jsma_wrap, [x, self.y_target], tf.float32) + else: + def jsma_wrap(x_val): + return jsma_batch(self.sess, x, preds, grads, x_val, + self.theta, self.gamma, self.clip_min, + self.clip_max, nb_classes, + y_target=None, feed={phase: False}) + + # Attack is untargeted, target values will be chosen at random + wrap = tf.py_func(jsma_wrap, [x], tf.float32) + + return wrap + + def parse_params(self, theta=1., gamma=np.inf, nb_classes=None, + clip_min=0., clip_max=1., y_target=None, **kwargs): + """ + Take in a dictionary of parameters and applies attack-specific checks + before saving them as attributes. + + Attack-specific parameters: + :param theta: (optional float) Perturbation introduced to modified + components (can be positive or negative) + :param gamma: (optional float) Maximum percentage of perturbed features + :param nb_classes: (optional int) Number of model output classes + :param clip_min: (optional float) Minimum component value for clipping + :param clip_max: (optional float) Maximum component value for clipping + :param y_target: (optional) Target tensor if the attack is targeted + """ + + if nb_classes is not None: + warnings.warn("The nb_classes argument is depricated and will " + "be removed on 2018-02-11") + self.theta = theta + self.gamma = gamma + self.clip_min = clip_min + self.clip_max = clip_max + self.y_target = y_target + + return True + + +class VirtualAdversarialMethod(Attack): + + """ + This attack was originally proposed by Miyato et al. (2016) and was used + for virtual adversarial training. + Paper link: https://arxiv.org/abs/1507.00677 + + """ + + def __init__(self, model, back='tf', sess=None, model_type='default', num_classes=10): + """ + Note: the model parameter should be an instance of the + cleverhans.model.Model abstraction provided by CleverHans. + """ + super(VirtualAdversarialMethod, self).__init__(model, back, sess, model_type, num_classes) + + if self.back == 'th': + error = "For the Theano version of VAM please call vatm directly." + raise NotImplementedError(error) + + import tensorflow as tf + self.feedable_kwargs = {'eps': tf.float32, 'xi': tf.float32, + 'clip_min': tf.float32, + 'clip_max': tf.float32} + self.structural_kwargs = ['num_iterations'] + + if not isinstance(self.model, Model): + self.model = CallableModelWrapper(self.model, 'logits') + + def generate(self, x, phase, **kwargs): + """ + Generate symbolic graph for adversarial examples and return. + :param x: The model's symbolic inputs. + :param eps: (optional float ) the epsilon (input variation parameter) + :param num_iterations: (optional) the number of iterations + :param xi: (optional float) the finite difference parameter + :param clip_min: (optional float) Minimum input component value + :param clip_max: (optional float) Maximum input component value + """ + # Parse and save attack-specific parameters + assert self.parse_params(**kwargs) + + return vatm(self.model, x, self.model.get_logits(x), eps=self.eps, + num_iterations=self.num_iterations, xi=self.xi, + clip_min=self.clip_min, clip_max=self.clip_max) + + def parse_params(self, eps=2.0, num_iterations=1, xi=1e-6, clip_min=None, + clip_max=None, **kwargs): + """ + Take in a dictionary of parameters and applies attack-specific checks + before saving them as attributes. + + Attack-specific parameters: + :param eps: (optional float )the epsilon (input variation parameter) + :param num_iterations: (optional) the number of iterations + :param xi: (optional float) the finite difference parameter + :param clip_min: (optional float) Minimum input component value + :param clip_max: (optional float) Maximum input component value + """ + # Save attack-specific parameters + self.eps = eps + self.num_iterations = num_iterations + self.xi = xi + self.clip_min = clip_min + self.clip_max = clip_max + return True + + +class CarliniWagnerL2(Attack): + """ + This attack was originally proposed by Carlini and Wagner. It is an + iterative attack that finds adversarial examples on many defenses that + are robust to other attacks. + Paper link: https://arxiv.org/abs/1608.04644 + + At a high level, this attack is an iterative attack using Adam and + a specially-chosen loss function to find adversarial examples with + lower distortion than other attacks. This comes at the cost of speed, + as this attack is often much slower than others. + """ + + def __init__(self, model, back='tf', sess=None, model_type='default', num_classes=10): + """ + Note: the model parameter should be an instance of the + cleverhans.model.Model abstraction provided by CleverHans. + """ + super(CarliniWagnerL2, self).__init__(model, back, sess, model_type, num_classes) + + if self.back == 'th': + raise NotImplementedError('Theano version not implemented.') + + import tensorflow as tf + self.feedable_kwargs = {'y': tf.float32, + 'y_target': tf.float32, + 'phase': tf.bool} + + self.structural_kwargs = ['batch_size', 'confidence', + 'targeted', 'learning_rate', + 'binary_search_steps', 'max_iterations', + 'abort_early', 'initial_const', + 'clip_min', 'clip_max'] + + if not isinstance(self.model, Model): + self.model = CallableModelWrapper(self.model, 'logits') + + def generate(self, x, phase, **kwargs): + """ + Return a tensor that constructs adversarial examples for the given + input. Generate uses tf.py_func in order to operate over tensors. + + :param x: (required) A tensor with the inputs. + :param y: (optional) A tensor with the true labels for an untargeted + attack. If None (and y_target is None) then use the + original labels the classifier assigns. + :param y_target: (optional) A tensor with the target labels for a + targeted attack. + :param confidence: Confidence of adversarial examples: higher produces + examples with larger l2 distortion, but more + strongly classified as adversarial. + :param batch_size: Number of attacks to run simultaneously. + :param learning_rate: The learning rate for the attack algorithm. + Smaller values produce better results but are + slower to converge. + :param binary_search_steps: The number of times we perform binary + search to find the optimal tradeoff- + constant between norm of the purturbation + and confidence of the classification. + :param max_iterations: The maximum number of iterations. Setting this + to a larger value will produce lower distortion + results. Using only a few iterations requires + a larger learning rate, and will produce larger + distortion results. + :param abort_early: If true, allows early aborts if gradient descent + is unable to make progress (i.e., gets stuck in + a local minimum). + :param initial_const: The initial tradeoff-constant to use to tune the + relative importance of size of the pururbation + and confidence of classification. + If binary_search_steps is large, the initial + constant is not important. A smaller value of + this constant gives lower distortion results. + :param clip_min: (optional float) Minimum input component value + :param clip_max: (optional float) Maximum input component value + """ + import tensorflow as tf + from .attacks_tf import CarliniWagnerL2 as CWL2 + self.parse_params(**kwargs) + + labels, nb_classes = self.get_or_guess_labels(x, kwargs) + + attack = CWL2(self.sess, self.model, self.batch_size, + self.confidence, 'y_target' in kwargs, + self.learning_rate, self.binary_search_steps, + self.max_iterations, self.abort_early, + self.initial_const, self.clip_min, self.clip_max, + nb_classes, x.get_shape().as_list()[1:]) + + def cw_wrap(x_val, y_val): + return np.array(attack.attack(x_val, y_val, phase), dtype=np.float32) + wrap = tf.py_func(cw_wrap, [x, labels], tf.float32) + + return wrap + + def parse_params(self, y=None, y_target=None, nb_classes=None, + batch_size=1, confidence=0, + learning_rate=5e-3, + binary_search_steps=5, max_iterations=1000, + abort_early=True, initial_const=1e-2, + clip_min=0, clip_max=1): + + # ignore the y and y_target argument + if nb_classes is not None: + warnings.warn("The nb_classes argument is depricated and will " + "be removed on 2018-02-11") + self.batch_size = batch_size + self.confidence = confidence + self.learning_rate = learning_rate + self.binary_search_steps = binary_search_steps + self.max_iterations = max_iterations + self.abort_early = abort_early + self.initial_const = initial_const + self.clip_min = clip_min + self.clip_max = clip_max + + +class ElasticNetMethod(Attack): + """ + This attack features L1-oriented adversarial examples and includes + the C&W L2 attack as a special case (when beta is set to 0). + Adversarial examples attain similar performance to those + generated by the C&W L2 attack, and more importantly, + have improved transferability properties and + complement adversarial training. + Paper link: https://arxiv.org/abs/1709.04114 + """ + + def __init__(self, model, back='tf', sess=None, model_type='default', num_classes=10): + """ + Note: the model parameter should be an instance of the + cleverhans.model.Model abstraction provided by CleverHans. + """ + super(ElasticNetMethod, self).__init__(model, back, sess, model_type, num_classes) + + if self.back == 'th': + raise NotImplementedError('Theano version not implemented.') + + import tensorflow as tf + self.feedable_kwargs = {'y': tf.float32, + 'y_target': tf.float32} + + self.structural_kwargs = ['beta', 'batch_size', 'confidence', + 'targeted', 'learning_rate', + 'binary_search_steps', 'max_iterations', + 'abort_early', 'initial_const', + 'clip_min', 'clip_max'] + + if not isinstance(self.model, Model): + self.model = CallableModelWrapper(self.model, 'logits') + + def generate(self, x, phase, **kwargs): + """ + Return a tensor that constructs adversarial examples for the given + input. Generate uses tf.py_func in order to operate over tensors. + + :param x: (required) A tensor with the inputs. + :param y: (optional) A tensor with the true labels for an untargeted + attack. If None (and y_target is None) then use the + original labels the classifier assigns. + :param y_target: (optional) A tensor with the target labels for a + targeted attack. + :param beta: Trades off L2 distortion with L1 distortion: higher + produces examples with lower L1 distortion, at the + cost of higher L2 (and typically Linf) distortion + :param confidence: Confidence of adversarial examples: higher produces + examples with larger l2 distortion, but more + strongly classified as adversarial. + :param batch_size: Number of attacks to run simultaneously. + :param learning_rate: The learning rate for the attack algorithm. + Smaller values produce better results but are + slower to converge. + :param binary_search_steps: The number of times we perform binary + search to find the optimal tradeoff- + constant between norm of the perturbation + and confidence of the classification. + :param max_iterations: The maximum number of iterations. Setting this + to a larger value will produce lower distortion + results. Using only a few iterations requires + a larger learning rate, and will produce larger + distortion results. + :param abort_early: If true, allows early abort when the total + loss starts to increase (greatly speeds up attack, + but hurts performance, particularly on ImageNet) + :param initial_const: The initial tradeoff-constant to use to tune the + relative importance of size of the perturbation + and confidence of classification. + If binary_search_steps is large, the initial + constant is not important. A smaller value of + this constant gives lower distortion results. + :param clip_min: (optional float) Minimum input component value + :param clip_max: (optional float) Maximum input component value + """ + import tensorflow as tf + self.parse_params(**kwargs) + + from .attacks_tf import ElasticNetMethod as EAD + labels, nb_classes = self.get_or_guess_labels(x, kwargs) + + attack = EAD(self.sess, self.model, self.beta, + self.batch_size, self.confidence, + 'y_target' in kwargs, self.learning_rate, + self.binary_search_steps, self.max_iterations, + self.abort_early, self.initial_const, + self.clip_min, self.clip_max, + nb_classes, x.get_shape().as_list()[1:]) + + def ead_wrap(x_val, y_val): + return np.array(attack.attack(x_val, y_val), dtype=np.float32) + wrap = tf.py_func(ead_wrap, [x, labels], tf.float32) + + return wrap + + def parse_params(self, y=None, y_target=None, + nb_classes=None, beta=1e-3, + batch_size=9, confidence=0, + learning_rate=1e-2, + binary_search_steps=9, max_iterations=1000, + abort_early=False, initial_const=1e-3, + clip_min=0, clip_max=1): + + # ignore the y and y_target argument + if nb_classes is not None: + warnings.warn("The nb_classes argument is depricated and will " + "be removed on 2018-02-11") + self.beta = beta + self.batch_size = batch_size + self.confidence = confidence + self.learning_rate = learning_rate + self.binary_search_steps = binary_search_steps + self.max_iterations = max_iterations + self.abort_early = abort_early + self.initial_const = initial_const + self.clip_min = clip_min + self.clip_max = clip_max + + +class DeepFool(Attack): + + """ + DeepFool is an untargeted & iterative attack which is based on an + iterative linearization of the classifier. The implementation here + is w.r.t. the L2 norm. + Paper link: "https://arxiv.org/pdf/1511.04599.pdf" + """ + + def __init__(self, model, back='tf', sess=None, model_type='default', num_classes=10): + """ + Create a DeepFool instance. + """ + super(DeepFool, self).__init__(model, back, sess, model_type, num_classes) + + if self.back == 'th': + raise NotImplementedError('Theano version not implemented.') + + self.structural_kwargs = ['over_shoot', 'max_iter', 'clip_max', + 'clip_min', 'nb_candidate'] + + if not isinstance(self.model, Model): + self.model = CallableModelWrapper(self.model, 'logits') + + def generate(self, x, phase, **kwargs): + """ + Generate symbolic graph for adversarial examples and return. + :param x: The model's symbolic inputs. + :param nb_candidate: The number of classes to test against, i.e., + deepfool only consider nb_candidate classes when + attacking(thus accelerate speed). The nb_candidate + classes are chosen according to the prediction + confidence during implementation. + :param overshoot: A termination criterion to prevent vanishing updates + :param max_iter: Maximum number of iteration for deepfool + :param nb_classes: The number of model output classes + :param clip_min: Minimum component value for clipping + :param clip_max: Maximum component value for clipping + """ + + import tensorflow as tf + from .attacks_tf import jacobian_graph, deepfool_batch + + # Parse and save attack-specific parameters + assert self.parse_params(**kwargs) + + # Define graph wrt to this input placeholder + logits = self.model.get_logits(x) + self.nb_classes = logits.get_shape().as_list()[-1] + assert self.nb_candidate <= self.nb_classes,\ + 'nb_candidate should not be greater than nb_classes' + preds = tf.reshape(tf.nn.top_k(logits, k=self.nb_candidate)[0], + [-1, self.nb_candidate]) + # grads will be the shape [batch_size, nb_candidate, image_size] + grads = tf.stack(jacobian_graph(preds, x, self.nb_candidate), axis=1) + + # Define graph + def deepfool_wrap(x_val): + return deepfool_batch(self.sess, x, preds, logits, grads, x_val, + self.nb_candidate, self.overshoot, + self.max_iter, self.clip_min, self.clip_max, + self.nb_classes) + return tf.py_func(deepfool_wrap, [x], tf.float32) + + def parse_params(self, nb_candidate=10, overshoot=0.02, max_iter=50, + nb_classes=None, clip_min=0., clip_max=1., **kwargs): + """ + :param nb_candidate: The number of classes to test against, i.e., + deepfool only consider nb_candidate classes when + attacking(thus accelerate speed). The nb_candidate + classes are chosen according to the prediction + confidence during implementation. + :param overshoot: A termination criterion to prevent vanishing updates + :param max_iter: Maximum number of iteration for deepfool + :param nb_classes: The number of model output classes + :param clip_min: Minimum component value for clipping + :param clip_max: Maximum component value for clipping + """ + if nb_classes is not None: + warnings.warn("The nb_classes argument is depricated and will " + "be removed on 2018-02-11") + self.nb_candidate = nb_candidate + self.overshoot = overshoot + self.max_iter = max_iter + self.clip_min = clip_min + self.clip_max = clip_max + + return True + + +def fgsm(x, predictions, eps, back='tf', clip_min=None, clip_max=None): + """ + A wrapper for the Fast Gradient Sign Method. + It calls the right function, depending on the + user's backend. + :param x: the input + :param predictions: the model's output + (Note: in the original paper that introduced this + attack, the loss was computed by comparing the + model predictions with the hard labels (from the + dataset). Instead, this version implements the loss + by comparing the model predictions with the most + likely class. This tweak is recommended since the + discovery of label leaking in the following paper: + https://arxiv.org/abs/1611.01236) + :param eps: the epsilon (input variation parameter) + :param back: switch between TensorFlow ('tf') and + Theano ('th') implementation + :param clip_min: optional parameter that can be used to set a minimum + value for components of the example returned + :param clip_max: optional parameter that can be used to set a maximum + value for components of the example returned + :return: a tensor for the adversarial example + """ + warnings.warn("attacks.fgsm is deprecated and will be removed on " + "2017-09-27. Instantiate an object from FastGradientMethod.") + if back == 'tf': + # Compute FGSM using TensorFlow + from .attacks_tf import fgm + return fgm(x, predictions, y=None, eps=eps, ord=np.inf, + clip_min=clip_min, clip_max=clip_max) + elif back == 'th': + # Compute FGSM using Theano + from .attacks_th import fgm + return fgm(x, predictions, eps, clip_min=clip_min, clip_max=clip_max) + + +def vatm(model, x, logits, eps, back='tf', num_iterations=1, xi=1e-6, + clip_min=None, clip_max=None): + """ + A wrapper for the perturbation methods used for virtual adversarial + training : https://arxiv.org/abs/1507.00677 + It calls the right function, depending on the + user's backend. + :param model: the model which returns the network unnormalized logits + :param x: the input placeholder + :param logits: the model's unnormalized output tensor + :param eps: the epsilon (input variation parameter) + :param num_iterations: the number of iterations + :param xi: the finite difference parameter + :param clip_min: optional parameter that can be used to set a minimum + value for components of the example returned + :param clip_max: optional parameter that can be used to set a maximum + value for components of the example returned + :return: a tensor for the adversarial example + + """ + if back == 'tf': + # Compute VATM using TensorFlow + from .attacks_tf import vatm as vatm_tf + return vatm_tf(model, x, logits, eps, num_iterations=num_iterations, + xi=xi, clip_min=clip_min, clip_max=clip_max) + elif back == 'th': + # Compute VATM using Theano + from .attacks_th import vatm as vatm_th + return vatm_th(model, x, logits, eps, num_iterations=num_iterations, + xi=xi, clip_min=clip_min, clip_max=clip_max) + + +def jsma(sess, x, predictions, grads, sample, target, theta, gamma=np.inf, + increase=True, back='tf', clip_min=None, clip_max=None): + """ + A wrapper for the Jacobian-based saliency map approach. + It calls the right function, depending on the + user's backend. + :param sess: TF session + :param x: the input + :param predictions: the model's symbolic output (linear output, + pre-softmax) + :param sample: (1 x 1 x img_rows x img_cols) numpy array with sample input + :param target: target class for input sample + :param theta: delta for each feature adjustment + :param gamma: a float between 0 - 1 indicating the maximum distortion + percentage + :param increase: boolean; true if we are increasing pixels, false otherwise + :param back: switch between TensorFlow ('tf') and + Theano ('th') implementation + :param clip_min: optional parameter that can be used to set a minimum + value for components of the example returned + :param clip_max: optional parameter that can be used to set a maximum + value for components of the example returned + :return: an adversarial sample + """ + warnings.warn("attacks.jsma is deprecated and will be removed on " + "2017-09-27. Instantiate an object from SaliencyMapMethod.") + if back == 'tf': + # Compute Jacobian-based saliency map attack using TensorFlow + from .attacks_tf import jsma + return jsma(sess, x, predictions, grads, sample, target, theta, gamma, + clip_min, clip_max) + elif back == 'th': + raise NotImplementedError("Theano jsma not implemented.") + + +class MadryEtAl(Attack): + + """ + The Projected Gradient Descent Attack (Madry et al. 2016). + Paper link: https://arxiv.org/pdf/1706.06083.pdf + """ + + def __init__(self, model, back='tf', sess=None, model_type='default', num_classes=10, + attack_type='vanilla'): + """ + Create a MadryEtAl instance. + """ + super(MadryEtAl, self).__init__(model, back, sess, model_type, num_classes) + self.feedable_kwargs = {'eps': np.float32, + 'eps_iter': np.float32, + 'y': np.float32, + 'y_target': np.float32, + 'clip_min': np.float32, + 'clip_max': np.float32} + self.attack_type = attack_type + self.structural_kwargs = ['ord', 'nb_iter'] + + if not isinstance(self.model, Model): + self.model = CallableModelWrapper(self.model, 'probs') + + def generate(self, x, phase, **kwargs): + """ + Generate symbolic graph for adversarial examples and return. + :param x: The model's symbolic inputs. + :param eps: (required float) maximum distortion of adversarial example + compared to original input + :param eps_iter: (required float) step size for each attack iteration + :param nb_iter: (required int) Number of attack iterations. + :param y: (optional) A tensor with the model labels. + :param y_target: (optional) A tensor with the labels to target. Leave + y_target=None if y is also set. Labels should be + one-hot-encoded. + :param ord: (optional) Order of the norm (mimics Numpy). + Possible values: np.inf, 1 or 2. + :param clip_min: (optional float) Minimum input component value + :param clip_max: (optional float) Maximum input component value + """ + + # Parse and save attack-specific parameters + assert self.parse_params(**kwargs) + + labels, nb_classes = self.get_or_guess_labels(x, kwargs) + self.targeted = self.y_target is not None + + # Initialize loop variables + adv_x = self.attack(x) + + return adv_x + + def parse_params(self, eps=0.3, eps_iter=0.01, nb_iter=40, y=None, + ord=np.inf, clip_min=None, clip_max=None, + y_target=None, **kwargs): + """ + Take in a dictionary of parameters and applies attack-specific checks + before saving them as attributes. + + Attack-specific parameters: + :param eps: (required float) maximum distortion of adversarial example + compared to original input + :param eps_iter: (required float) step size for each attack iteration + :param nb_iter: (required int) Number of attack iterations. + :param y: (optional) A tensor with the model labels. + :param y_target: (optional) A tensor with the labels to target. Leave + y_target=None if y is also set. Labels should be + one-hot-encoded. + :param ord: (optional) Order of the norm (mimics Numpy). + Possible values: np.inf, 1 or 2. + :param clip_min: (optional float) Minimum input component value + :param clip_max: (optional float) Maximum input component value + """ + + # Save attack-specific parameters + self.eps = eps + self.eps_iter = eps_iter + self.nb_iter = nb_iter + self.y = y + self.y_target = y_target + self.ord = ord + self.clip_min = clip_min + self.clip_max = clip_max + + if self.y is not None and self.y_target is not None: + raise ValueError("Must not set both y and y_target") + # Check if order of the norm is acceptable given current implementation + if self.ord not in [np.inf, 1, 2]: + raise ValueError("Norm order must be either np.inf, 1, or 2.") + if self.back == 'th': + error_string = ("ProjectedGradientDescentMethod is" + " not implemented in Theano") + raise NotImplementedError(error_string) + + return True + + def attack_single_step(self, x, eta, y): + """ + Given the original image and the perturbation computed so far, computes + a new perturbation. + + :param x: A tensor with the original input. + :param eta: A tensor the same shape as x that holds the perturbation. + :param y: A tensor with the target labels or ground-truth labels. + """ + import tensorflow as tf + from modified_cleverhans.utils_tf import model_loss, clip_eta + + adv_x = x + eta + if self.attack_type != "robust": + if self.model_type == 'ensembleThree': ## for EMPIR extra if condition for covering the multiple combined model case + preds = self.model.get_combinedAvgCorrectProbs(adv_x, reuse=True) + else: + preds = self.model.get_probs(adv_x, reuse=True) + loss = model_loss(y, preds) + else: + # modification from zimmerrol to make sure their loss was correctly implemented + preds = self.model.get_layer(adv_x, True, 'combined_logits') + preds = tf.reduce_sum(preds, 1) + loss = model_loss(y, preds) + if self.targeted: + loss = -loss + grad, = tf.gradients(loss, adv_x) + scaled_signed_grad = self.eps_iter * tf.sign(grad) + adv_x = adv_x + scaled_signed_grad + adv_x = tf.clip_by_value(adv_x, self.clip_min, self.clip_max) + eta = adv_x - x + eta = clip_eta(eta, self.ord, self.eps) + return x, eta + + def attack(self, x, **kwargs): + """ + This method creates a symbolic graph that given an input image, + first randomly perturbs the image. The + perturbation is bounded to an epsilon ball. Then multiple steps of + gradient descent is performed to increase the probability of a target + label or decrease the probability of the ground-truth label. + + :param x: A tensor with the input image. + """ + import tensorflow as tf + from modified_cleverhans.utils_tf import clip_eta + + eta = tf.random_uniform(tf.shape(x), -self.eps, self.eps) + eta = clip_eta(eta, self.ord, self.eps) + + if self.y is not None: + y = self.y + else: + if self.model_type == 'ensembleThree': ## for EMPIR extra if condition for covering the ensemble model case + preds = self.model.get_combinedAvgCorrectProbs(x) + # default below + else: + preds = self.model.get_probs(x) + preds_max = tf.reduce_max(preds, 1, keep_dims=True) + y = tf.to_float(tf.equal(preds, preds_max)) + y = y / tf.reduce_sum(y, 1, keep_dims=True) + y = tf.stop_gradient(y) + + for i in range(self.nb_iter): + x, eta = self.attack_single_step(x, eta, y) + + adv_x = x + eta + if self.clip_min is not None and self.clip_max is not None: + adv_x = tf.clip_by_value(adv_x, self.clip_min, self.clip_max) + + return adv_x diff --git a/case_studies/empir/modified_cleverhans/attacks_tf.py b/case_studies/empir/modified_cleverhans/attacks_tf.py new file mode 100644 index 0000000..e9880f6 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/attacks_tf.py @@ -0,0 +1,1198 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import copy +import numpy as np +from six.moves import xrange +import tensorflow as tf +import warnings + +from . import utils_tf +from . import utils + +_logger = utils.create_logger("cleverhans.attacks.tf") + + +def fgsm(x, predictions, eps=0.3, clip_min=None, clip_max=None): + return fgm(x, predictions, y=None, eps=eps, ord=np.inf, clip_min=clip_min, + clip_max=clip_max) + + +def fgm(x, preds, y=None, eps=0.3, ord=np.inf, + clip_min=None, clip_max=None, + targeted=False): + """ + TensorFlow implementation of the Fast Gradient Method. + :param x: the input placeholder + :param preds: the model's output tensor (the attack expects the + probabilities, i.e., the output of the softmax) + :param y: (optional) A placeholder for the model labels. If targeted + is true, then provide the target label. Otherwise, only provide + this parameter if you'd like to use true labels when crafting + adversarial samples. Otherwise, model predictions are used as + labels to avoid the "label leaking" effect (explained in this + paper: https://arxiv.org/abs/1611.01236). Default is None. + Labels should be one-hot-encoded. + :param eps: the epsilon (input variation parameter) + :param ord: (optional) Order of the norm (mimics NumPy). + Possible values: np.inf, 1 or 2. + :param clip_min: Minimum float value for adversarial example components + :param clip_max: Maximum float value for adversarial example components + :param targeted: Is the attack targeted or untargeted? Untargeted, the + default, will try to make the label incorrect. Targeted + will instead try to move in the direction of being more + like y. + :return: a tensor for the adversarial example + """ + + if y is None: + # Using model predictions as ground truth to avoid label leaking + preds_max = tf.reduce_max(preds, 1, keep_dims=True) + y = tf.to_float(tf.equal(preds, preds_max)) + y = tf.stop_gradient(y) + y = y / tf.reduce_sum(y, 1, keep_dims=True) + + # Compute loss + loss = utils_tf.model_loss(y, preds, mean=False) + if targeted: + loss = -loss + + # Define gradient of loss wrt input + grad, = tf.gradients(loss, x) + + if ord == np.inf: + # Take sign of gradient + normalized_grad = tf.sign(grad) + # The following line should not change the numerical results. + # It applies only because `normalized_grad` is the output of + # a `sign` op, which has zero derivative anyway. + # It should not be applied for the other norms, where the + # perturbation has a non-zero derivative. + normalized_grad = tf.stop_gradient(normalized_grad) + elif ord == 1: + red_ind = list(xrange(1, len(x.get_shape()))) + normalized_grad = grad / tf.reduce_sum(tf.abs(grad), + reduction_indices=red_ind, + keep_dims=True) + elif ord == 2: + red_ind = list(xrange(1, len(x.get_shape()))) + square = tf.reduce_sum(tf.square(grad), + reduction_indices=red_ind, + keep_dims=True) + normalized_grad = grad / tf.sqrt(square) + else: + raise NotImplementedError("Only L-inf, L1 and L2 norms are " + "currently implemented.") + + # Multiply by constant epsilon + scaled_grad = eps * normalized_grad + print('scaled_grad.get_shape() = ') + print(scaled_grad.get_shape()) + + # Add perturbation to original example to obtain adversarial example + adv_x = x + scaled_grad + + # If clipping is needed, reset all values outside of [clip_min, clip_max] + if (clip_min is not None) and (clip_max is not None): + adv_x = tf.clip_by_value(adv_x, clip_min, clip_max) + + return adv_x + + +def vatm(model, x, logits, eps, num_iterations=1, xi=1e-6, + clip_min=None, clip_max=None, scope=None): + """ + Tensorflow implementation of the perturbation method used for virtual + adversarial training: https://arxiv.org/abs/1507.00677 + :param model: the model which returns the network unnormalized logits + :param x: the input placeholder + :param logits: the model's unnormalized output tensor (the input to + the softmax layer) + :param eps: the epsilon (input variation parameter) + :param num_iterations: the number of iterations + :param xi: the finite difference parameter + :param clip_min: optional parameter that can be used to set a minimum + value for components of the example returned + :param clip_max: optional parameter that can be used to set a maximum + value for components of the example returned + :param seed: the seed for random generator + :return: a tensor for the adversarial example + """ + with tf.name_scope(scope, "virtual_adversarial_perturbation"): + d = tf.random_normal(tf.shape(x)) + for i in range(num_iterations): + d = xi * utils_tf.l2_batch_normalize(d) + logits_d = model.get_logits(x + d, reuse=True) + kl = utils_tf.kl_with_logits(logits, logits_d) + Hd = tf.gradients(kl, d)[0] + d = tf.stop_gradient(Hd) + d = eps * utils_tf.l2_batch_normalize(d) + adv_x = x + d + if (clip_min is not None) and (clip_max is not None): + adv_x = tf.clip_by_value(adv_x, clip_min, clip_max) + return adv_x + + +def apply_perturbations(i, j, X, increase, theta, clip_min, clip_max): + """ + TensorFlow implementation for apply perturbations to input features based + on salency maps + :param i: index of first selected feature + :param j: index of second selected feature + :param X: a matrix containing our input features for our sample + :param increase: boolean; true if we are increasing pixels, false otherwise + :param theta: delta for each feature adjustment + :param clip_min: mininum value for a feature in our sample + :param clip_max: maximum value for a feature in our sample + : return: a perturbed input feature matrix for a target class + """ + + # perturb our input sample + if increase: + X[0, i] = np.minimum(clip_max, X[0, i] + theta) + X[0, j] = np.minimum(clip_max, X[0, j] + theta) + else: + X[0, i] = np.maximum(clip_min, X[0, i] - theta) + X[0, j] = np.maximum(clip_min, X[0, j] - theta) + + return X + + +def saliency_map(grads_target, grads_other, search_domain, increase): + """ + TensorFlow implementation for computing saliency maps + :param grads_target: a matrix containing forward derivatives for the + target class + :param grads_other: a matrix where every element is the sum of forward + derivatives over all non-target classes at that index + :param search_domain: the set of input indices that we are considering + :param increase: boolean; true if we are increasing pixels, false otherwise + :return: (i, j, search_domain) the two input indices selected and the + updated search domain + """ + # Compute the size of the input (the number of features) + nf = len(grads_target) + + # Remove the already-used input features from the search space + invalid = list(set(range(nf)) - search_domain) + increase_coef = (2 * int(increase) - 1) + grads_target[invalid] = - increase_coef * np.max(np.abs(grads_target)) + grads_other[invalid] = increase_coef * np.max(np.abs(grads_other)) + + # Create a 2D numpy array of the sum of grads_target and grads_other + target_sum = grads_target.reshape((1, nf)) + grads_target.reshape((nf, 1)) + other_sum = grads_other.reshape((1, nf)) + grads_other.reshape((nf, 1)) + + # Create a mask to only keep features that match saliency map conditions + if increase: + scores_mask = ((target_sum > 0) & (other_sum < 0)) + else: + scores_mask = ((target_sum < 0) & (other_sum > 0)) + + # Create a 2D numpy array of the scores for each pair of candidate features + scores = scores_mask * (-target_sum * other_sum) + + # A pixel can only be selected (and changed) once + np.fill_diagonal(scores, 0) + + # Extract the best two pixels + best = np.argmax(scores) + p1, p2 = best % nf, best // nf + + # Remove used pixels from our search domain + search_domain.discard(p1) + search_domain.discard(p2) + + return p1, p2, search_domain + + +def jacobian(sess, x, grads, target, X, nb_features, nb_classes, feed=None): + """ + TensorFlow implementation of the foward derivative / Jacobian + :param x: the input placeholder + :param grads: the list of TF gradients returned by jacobian_graph() + :param target: the target misclassification class + :param X: numpy array with sample input + :param nb_features: the number of features in the input + :return: matrix of forward derivatives flattened into vectors + """ + # Prepare feeding dictionary for all gradient computations + feed_dict = {x: X} + if feed is not None: + feed_dict.update(feed) + + # Initialize a numpy array to hold the Jacobian component values + jacobian_val = np.zeros((nb_classes, nb_features), dtype=np.float32) + + # Compute the gradients for all classes + for class_ind, grad in enumerate(grads): + run_grad = sess.run(grad, feed_dict) + jacobian_val[class_ind] = np.reshape(run_grad, (1, nb_features)) + + # Sum over all classes different from the target class to prepare for + # saliency map computation in the next step of the attack + other_classes = utils.other_classes(nb_classes, target) + grad_others = np.sum(jacobian_val[other_classes, :], axis=0) + + return jacobian_val[target], grad_others + + +def jacobian_graph(predictions, x, nb_classes): + """ + Create the Jacobian graph to be ran later in a TF session + :param predictions: the model's symbolic output (linear output, + pre-softmax) + :param x: the input placeholder + :param nb_classes: the number of classes the model has + :return: + """ + # This function will return a list of TF gradients + list_derivatives = [] + + # Define the TF graph elements to compute our derivatives for each class + for class_ind in xrange(nb_classes): + derivatives, = tf.gradients(predictions[:, class_ind], x) + list_derivatives.append(derivatives) + + return list_derivatives + + +def jsma(sess, x, predictions, grads, sample, target, theta, gamma, clip_min, + clip_max, feed=None): + """ + TensorFlow implementation of the JSMA (see https://arxiv.org/abs/1511.07528 + for details about the algorithm design choices). + :param sess: TF session + :param x: the input placeholder + :param predictions: the model's symbolic output (the attack expects the + probabilities, i.e., the output of the softmax, but will + also work with logits typically) + :param grads: symbolic gradients + :param sample: numpy array with sample input + :param target: target class for sample input + :param theta: delta for each feature adjustment + :param gamma: a float between 0 - 1 indicating the maximum distortion + percentage + :param clip_min: minimum value for components of the example returned + :param clip_max: maximum value for components of the example returned + :return: an adversarial sample + """ + + # Copy the source sample and define the maximum number of features + # (i.e. the maximum number of iterations) that we may perturb + adv_x = copy.copy(sample) + # count the number of features. For MNIST, 1x28x28 = 784; for + # CIFAR, 3x32x32 = 3072; etc. + nb_features = np.product(adv_x.shape[1:]) + # reshape sample for sake of standardization + original_shape = adv_x.shape + adv_x = np.reshape(adv_x, (1, nb_features)) + # compute maximum number of iterations + max_iters = np.floor(nb_features * gamma / 2) + + # Find number of classes based on grads + nb_classes = len(grads) + + increase = bool(theta > 0) + + # Compute our initial search domain. We optimize the initial search domain + # by removing all features that are already at their maximum values (if + # increasing input features---otherwise, at their minimum value). + if increase: + search_domain = set([i for i in xrange(nb_features) + if adv_x[0, i] < clip_max]) + else: + search_domain = set([i for i in xrange(nb_features) + if adv_x[0, i] > clip_min]) + + # Initialize the loop variables + iteration = 0 + adv_x_original_shape = np.reshape(adv_x, original_shape) + current = utils_tf.model_argmax(sess, x, predictions, adv_x_original_shape, + feed=feed) + + _logger.debug("Starting JSMA attack up to {} iterations".format(max_iters)) + # Repeat this main loop until we have achieved misclassification + while (current != target and iteration < max_iters and + len(search_domain) > 1): + # Reshape the adversarial example + adv_x_original_shape = np.reshape(adv_x, original_shape) + + # Compute the Jacobian components + grads_target, grads_others = jacobian(sess, x, grads, target, + adv_x_original_shape, + nb_features, nb_classes, + feed=feed) + + if iteration % ((max_iters + 1) // 5) == 0 and iteration > 0: + _logger.debug("Iteration {} of {}".format(iteration, + int(max_iters))) + # Compute the saliency map for each of our target classes + # and return the two best candidate features for perturbation + i, j, search_domain = saliency_map( + grads_target, grads_others, search_domain, increase) + + # Apply the perturbation to the two input features selected previously + adv_x = apply_perturbations( + i, j, adv_x, increase, theta, clip_min, clip_max) + + # Update our current prediction by querying the model + current = utils_tf.model_argmax(sess, x, predictions, + adv_x_original_shape, feed=feed) + + # Update loop variables + iteration = iteration + 1 + + if current == target: + _logger.info("Attack succeeded using {} iterations".format(iteration)) + else: + _logger.info(("Failed to find adversarial example " + + "after {} iterations").format(iteration)) + + # Compute the ratio of pixels perturbed by the algorithm + percent_perturbed = float(iteration * 2) / nb_features + + # Report success when the adversarial example is misclassified in the + # target class + if current == target: + return np.reshape(adv_x, original_shape), 1, percent_perturbed + else: + return np.reshape(adv_x, original_shape), 0, percent_perturbed + + +def jsma_batch(sess, x, pred, grads, X, theta, gamma, clip_min, clip_max, + nb_classes, y_target=None, feed=None, **kwargs): + """ + Applies the JSMA to a batch of inputs + :param sess: TF session + :param x: the input placeholder + :param pred: the model's symbolic output + :param grads: symbolic gradients + :param X: numpy array with sample inputs + :param theta: delta for each feature adjustment + :param gamma: a float between 0 - 1 indicating the maximum distortion + percentage + :param clip_min: minimum value for components of the example returned + :param clip_max: maximum value for components of the example returned + :param nb_classes: number of model output classes + :param y_target: target class for sample input + :return: adversarial examples + """ + if 'targets' in kwargs: + warnings.warn('The targets parameter is deprecated, use y_target.' + 'targets will be removed on 2018-02-03.') + y_target = kwargs['targets'] + + X_adv = np.zeros(X.shape) + + for ind, val in enumerate(X): + val = np.expand_dims(val, axis=0) + if y_target is None: + # No y_target provided, randomly choose from other classes + from .utils_tf import model_argmax + gt = model_argmax(sess, x, pred, val, feed=feed) + + # Randomly choose from the incorrect classes for each sample + from .utils import random_targets + target = random_targets(gt, nb_classes)[0] + else: + target = y_target[ind] + + X_adv[ind], _, _ = jsma(sess, x, pred, grads, val, np.argmax(target), + theta, gamma, clip_min, clip_max, feed=feed) + + return np.asarray(X_adv, dtype=np.float32) + + +def jacobian_augmentation(sess, x, X_sub_prev, Y_sub, grads, lmbda, + keras_phase=None, feed=None): + """ + Augment an adversary's substitute training set using the Jacobian + of a substitute model to generate new synthetic inputs. + See https://arxiv.org/abs/1602.02697 for more details. + See cleverhans_tutorials/mnist_blackbox.py for example use case + :param sess: TF session in which the substitute model is defined + :param x: input TF placeholder for the substitute model + :param X_sub_prev: substitute training data available to the adversary + at the previous iteration + :param Y_sub: substitute training labels available to the adversary + at the previous iteration + :param grads: Jacobian symbolic graph for the substitute + (should be generated using attacks_tf.jacobian_graph) + :param keras_phase: (deprecated) if not None, holds keras learning_phase + :return: augmented substitute data (will need to be labeled by oracle) + """ + assert len(x.get_shape()) == len(np.shape(X_sub_prev)) + assert len(grads) >= np.max(Y_sub) + 1 + assert len(X_sub_prev) == len(Y_sub) + + if keras_phase is not None: + warnings.warn("keras_phase argument is deprecated and will be removed" + " on 2017-09-28. Instead, use K.set_learning_phase(0) at" + " the start of your script and serve with tensorflow.") + + # Prepare input_shape (outside loop) for feeding dictionary below + input_shape = list(x.get_shape()) + input_shape[0] = 1 + + # Create new numpy array for adversary training data + # with twice as many components on the first dimension. + X_sub = np.vstack([X_sub_prev, X_sub_prev]) + + # For each input in the previous' substitute training iteration + for ind, input in enumerate(X_sub_prev): + # Select gradient corresponding to the label predicted by the oracle + grad = grads[Y_sub[ind]] + + # Prepare feeding dictionary + feed_dict = {x: np.reshape(input, input_shape)} + if feed is not None: + feed_dict.update(feed) + + # Compute sign matrix + grad_val = sess.run([tf.sign(grad)], feed_dict=feed_dict)[0] + + # Create new synthetic point in adversary substitute training set + X_sub[2 * ind] = X_sub[ind] + lmbda * grad_val + + # Return augmented training data (needs to be labeled afterwards) + return X_sub + + +class CarliniWagnerL2(object): + + def __init__(self, sess, model, batch_size, confidence, + targeted, learning_rate, + binary_search_steps, max_iterations, + abort_early, initial_const, + clip_min, clip_max, num_labels, shape): + """ + Return a tensor that constructs adversarial examples for the given + input. Generate uses tf.py_func in order to operate over tensors. + + :param sess: a TF session. + :param model: a cleverhans.model.Model object. + :param batch_size: Number of attacks to run simultaneously. + :param confidence: Confidence of adversarial examples: higher produces + examples with larger l2 distortion, but more + strongly classified as adversarial. + :param targeted: boolean controlling the behavior of the adversarial + examples produced. If set to False, they will be + misclassified in any wrong class. If set to True, + they will be misclassified in a chosen target class. + :param learning_rate: The learning rate for the attack algorithm. + Smaller values produce better results but are + slower to converge. + :param binary_search_steps: The number of times we perform binary + search to find the optimal tradeoff- + constant between norm of the purturbation + and confidence of the classification. + :param max_iterations: The maximum number of iterations. Setting this + to a larger value will produce lower distortion + results. Using only a few iterations requires + a larger learning rate, and will produce larger + distortion results. + :param abort_early: If true, allows early aborts if gradient descent + is unable to make progress (i.e., gets stuck in + a local minimum). + :param initial_const: The initial tradeoff-constant to use to tune the + relative importance of size of the pururbation + and confidence of classification. + If binary_search_steps is large, the initial + constant is not important. A smaller value of + this constant gives lower distortion results. + :param clip_min: (optional float) Minimum input component value. + :param clip_max: (optional float) Maximum input component value. + :param num_labels: the number of classes in the model's output. + :param shape: the shape of the model's input tensor. + """ + + self.sess = sess + self.TARGETED = targeted + self.LEARNING_RATE = learning_rate + self.MAX_ITERATIONS = max_iterations + self.BINARY_SEARCH_STEPS = binary_search_steps + self.ABORT_EARLY = abort_early + self.CONFIDENCE = confidence + self.initial_const = initial_const + self.batch_size = batch_size + self.clip_min = clip_min + self.clip_max = clip_max + self.model = model + + self.repeat = binary_search_steps >= 10 + + self.shape = shape = tuple([batch_size] + list(shape)) + + # the variable we're going to optimize over + modifier = tf.Variable(np.zeros(shape, dtype=np.float32)) + + # these are variables to be more efficient in sending data to tf + self.timg = tf.Variable(np.zeros(shape), dtype=tf.float32, + name='timg') + self.tlab = tf.Variable(np.zeros((batch_size, num_labels)), + dtype=tf.float32, name='tlab') + self.const = tf.Variable(np.zeros(batch_size), dtype=tf.float32, + name='const') + + # and here's what we use to assign them + self.assign_timg = tf.placeholder(tf.float32, shape, + name='assign_timg') + self.assign_tlab = tf.placeholder(tf.float32, (batch_size, num_labels), + name='assign_tlab') + self.assign_const = tf.placeholder(tf.float32, [batch_size], + name='assign_const') + + # the resulting instance, tanh'd to keep bounded from clip_min + # to clip_max + self.newimg = (tf.tanh(modifier + self.timg) + 1) / 2 + self.newimg = self.newimg * (clip_max - clip_min) + clip_min + + # prediction BEFORE-SOFTMAX of the model + self.output = model.get_logits(self.newimg, reuse=True) + + # distance to the input data + self.other = (tf.tanh(self.timg) + 1) / \ + 2 * (clip_max - clip_min) + clip_min + self.l2dist = tf.reduce_sum(tf.square(self.newimg - self.other), + list(range(1, len(shape)))) + + # compute the probability of the label class versus the maximum other + real = tf.reduce_sum((self.tlab) * self.output, 1) + other = tf.reduce_max( + (1 - self.tlab) * self.output - self.tlab * 10000, + 1) + + if self.TARGETED: + # if targeted, optimize for making the other class most likely + loss1 = tf.maximum(0.0, other - real + self.CONFIDENCE) + else: + # if untargeted, optimize for making this class least likely. + loss1 = tf.maximum(0.0, real - other + self.CONFIDENCE) + + # sum up the losses + self.loss2 = tf.reduce_sum(self.l2dist) + self.loss1 = tf.reduce_sum(self.const * loss1) + self.loss = self.loss1 + self.loss2 + + # Setup the adam optimizer and keep track of variables we're creating + start_vars = set(x.name for x in tf.global_variables()) + optimizer = tf.train.AdamOptimizer(self.LEARNING_RATE) + self.train = optimizer.minimize(self.loss, var_list=[modifier]) + end_vars = tf.global_variables() + new_vars = [x for x in end_vars if x.name not in start_vars] + + # these are the variables to initialize when we run + self.setup = [] + self.setup.append(self.timg.assign(self.assign_timg)) + self.setup.append(self.tlab.assign(self.assign_tlab)) + self.setup.append(self.const.assign(self.assign_const)) + + self.init = tf.variables_initializer(var_list=[modifier] + new_vars) + + def attack(self, imgs, targets, phase): + """ + Perform the L_2 attack on the given instance for the given targets. + + If self.targeted is true, then the targets represents the target labels + If self.targeted is false, then targets are the original class labels + """ + + r = [] + for i in range(0, len(imgs), self.batch_size): + _logger.debug(("Running CWL2 attack on instance " + + "{} of {}").format(i, len(imgs))) + r.extend(self.attack_batch(imgs[i:i + self.batch_size], + targets[i:i + self.batch_size], phase)) + return np.array(r) + + def attack_batch(self, imgs, labs, phase): + """ + Run the attack on a batch of instance and labels. + """ + def compare(x, y): + if not isinstance(x, (float, int, np.int64)): + x = np.copy(x) + if self.TARGETED: + x[y] -= self.CONFIDENCE + else: + x[y] += self.CONFIDENCE + x = np.argmax(x) + if self.TARGETED: + return x == y + else: + return x != y + + batch_size = self.batch_size + + oimgs = np.clip(imgs, self.clip_min, self.clip_max) + + # re-scale instances to be within range [0, 1] + imgs = (imgs - self.clip_min) / (self.clip_max - self.clip_min) + imgs = np.clip(imgs, 0, 1) + # now convert to [-1, 1] + imgs = (imgs * 2) - 1 + # convert to tanh-space + imgs = np.arctanh(imgs * .999999) + + # set the lower and upper bounds accordingly + lower_bound = np.zeros(batch_size) + CONST = np.ones(batch_size) * self.initial_const + upper_bound = np.ones(batch_size) * 1e10 + + # placeholders for the best l2, score, and instance attack found so far + o_bestl2 = [1e10] * batch_size + o_bestscore = [-1] * batch_size + o_bestattack = np.copy(oimgs) + + for outer_step in range(self.BINARY_SEARCH_STEPS): + # completely reset adam's internal state. + self.sess.run(self.init) + batch = imgs[:batch_size] + batchlab = labs[:batch_size] + + bestl2 = [1e10] * batch_size + bestscore = [-1] * batch_size + _logger.debug(" Binary search step {} of {}". + format(outer_step, self.BINARY_SEARCH_STEPS)) + + # The last iteration (if we run many steps) repeat the search once. + if self.repeat and outer_step == self.BINARY_SEARCH_STEPS - 1: + CONST = upper_bound + + # set the variables so that we don't have to send them over again + self.sess.run(self.setup, {self.assign_timg: batch, + self.assign_tlab: batchlab, + self.assign_const: CONST, + phase: False}) + + prev = 1e6 + for iteration in range(self.MAX_ITERATIONS): + # perform the attack + _, l, l2s, scores, nimg = self.sess.run([self.train, + self.loss, + self.l2dist, + self.output, + self.newimg], + feed_dict={phase: False}) + + if iteration % ((self.MAX_ITERATIONS // 10) or 1) == 0: + _logger.debug((" Iteration {} of {}: loss={:.3g} " + + "l2={:.3g} f={:.3g}") + .format(iteration, self.MAX_ITERATIONS, + l, np.mean(l2s), np.mean(scores))) + + # check if we should abort search if we're getting nowhere. + if self.ABORT_EARLY and \ + iteration % ((self.MAX_ITERATIONS // 10) or 1) == 0: + if l > prev * .9999: + msg = " Failed to make progress; stop early" + _logger.debug(msg) + break + prev = l + + # adjust the best result found so far + for e, (l2, sc, ii) in enumerate(zip(l2s, scores, nimg)): + lab = np.argmax(batchlab[e]) + if l2 < bestl2[e] and compare(sc, lab): + bestl2[e] = l2 + bestscore[e] = np.argmax(sc) + if l2 < o_bestl2[e] and compare(sc, lab): + o_bestl2[e] = l2 + o_bestscore[e] = np.argmax(sc) + o_bestattack[e] = ii + + # adjust the constant as needed + for e in range(batch_size): + if compare(bestscore[e], np.argmax(batchlab[e])) and \ + bestscore[e] != -1: + # success, divide const by two + upper_bound[e] = min(upper_bound[e], CONST[e]) + if upper_bound[e] < 1e9: + CONST[e] = (lower_bound[e] + upper_bound[e]) / 2 + else: + # failure, either multiply by 10 if no solution found yet + # or do binary search with the known upper bound + lower_bound[e] = max(lower_bound[e], CONST[e]) + if upper_bound[e] < 1e9: + CONST[e] = (lower_bound[e] + upper_bound[e]) / 2 + else: + CONST[e] *= 10 + _logger.debug(" Successfully generated adversarial examples " + + "on {} of {} instances.". + format(sum(upper_bound < 1e9), batch_size)) + o_bestl2 = np.array(o_bestl2) + mean = np.mean(np.sqrt(o_bestl2[o_bestl2 < 1e9])) + _logger.debug(" Mean successful distortion: {:.4g}".format(mean)) + + # return the best solution found + o_bestl2 = np.array(o_bestl2) + return o_bestattack + + +class ElasticNetMethod(object): + + def __init__(self, sess, model, beta, + batch_size, confidence, + targeted, learning_rate, + binary_search_steps, max_iterations, + abort_early, initial_const, + clip_min, clip_max, num_labels, shape): + """ + EAD Attack with the EN Decision Rule + + Return a tensor that constructs adversarial examples for the given + input. Generate uses tf.py_func in order to operate over tensors. + + :param sess: a TF session. + :param model: a cleverhans.model.Model object. + :param beta: Trades off L2 distortion with L1 distortion: higher + produces examples with lower L1 distortion, at the + cost of higher L2 (and typically Linf) distortion + :param batch_size: Number of attacks to run simultaneously. + :param confidence: Confidence of adversarial examples: higher produces + examples with larger l2 distortion, but more + strongly classified as adversarial. + :param targeted: boolean controlling the behavior of the adversarial + examples produced. If set to False, they will be + misclassified in any wrong class. If set to True, + they will be misclassified in a chosen target class. + :param learning_rate: The learning rate for the attack algorithm. + Smaller values produce better results but are + slower to converge. + :param binary_search_steps: The number of times we perform binary + search to find the optimal tradeoff- + constant between norm of the perturbation + and confidence of the classification. + :param max_iterations: The maximum number of iterations. Setting this + to a larger value will produce lower distortion + results. Using only a few iterations requires + a larger learning rate, and will produce larger + distortion results. + :param abort_early: If true, allows early abort when the total + loss starts to increase (greatly speeds up attack, + but hurts performance, particularly on ImageNet) + :param initial_const: The initial tradeoff-constant to use to tune the + relative importance of size of the perturbation + and confidence of classification. + If binary_search_steps is large, the initial + constant is not important. A smaller value of + this constant gives lower distortion results. + :param clip_min: (optional float) Minimum input component value. + :param clip_max: (optional float) Maximum input component value. + :param num_labels: the number of classes in the model's output. + :param shape: the shape of the model's input tensor. + """ + + self.sess = sess + self.TARGETED = targeted + self.LEARNING_RATE = learning_rate + self.MAX_ITERATIONS = max_iterations + self.BINARY_SEARCH_STEPS = binary_search_steps + self.ABORT_EARLY = abort_early + self.CONFIDENCE = confidence + self.initial_const = initial_const + self.batch_size = batch_size + self.clip_min = clip_min + self.clip_max = clip_max + self.model = model + + self.beta = beta + self.beta_t = tf.cast(self.beta, tf.float32) + + self.repeat = binary_search_steps >= 10 + + self.shape = shape = tuple([batch_size] + list(shape)) + + # these are variables to be more efficient in sending data to tf + self.timg = tf.Variable(np.zeros(shape), dtype=tf.float32, + name='timg') + self.newimg = tf.Variable(np.zeros(shape), dtype=tf.float32, + name='newimg') + self.slack = tf.Variable(np.zeros(shape), dtype=tf.float32, + name='slack') + self.tlab = tf.Variable(np.zeros((batch_size, num_labels)), + dtype=tf.float32, name='tlab') + self.const = tf.Variable(np.zeros(batch_size), dtype=tf.float32, + name='const') + + # and here's what we use to assign them + self.assign_timg = tf.placeholder(tf.float32, shape, + name='assign_timg') + self.assign_newimg = tf.placeholder(tf.float32, shape, + name='assign_newimg') + self.assign_slack = tf.placeholder(tf.float32, shape, + name='assign_slack') + self.assign_tlab = tf.placeholder(tf.float32, (batch_size, + num_labels), + name='assign_tlab') + self.assign_const = tf.placeholder(tf.float32, [batch_size], + name='assign_const') + + self.global_step = tf.Variable(0, trainable=False) + self.global_step_t = tf.cast(self.global_step, tf.float32) + + """Fast Iterative Shrinkage Thresholding""" + """--------------------------------""" + self.zt = tf.divide(self.global_step_t, + self.global_step_t + tf.cast(3, tf.float32)) + + cond1 = tf.cast(tf.greater(tf.subtract(self.slack, self.timg), + self.beta_t), tf.float32) + cond2 = tf.cast(tf.less_equal(tf.abs(tf.subtract(self.slack, + self.timg)), + self.beta_t), tf.float32) + cond3 = tf.cast(tf.less(tf.subtract(self.slack, self.timg), + tf.negative(self.beta_t)), tf.float32) + + upper = tf.minimum(tf.subtract(self.slack, self.beta_t), + tf.cast(self.clip_max, tf.float32)) + lower = tf.maximum(tf.add(self.slack, self.beta_t), + tf.cast(self.clip_min, tf.float32)) + + self.assign_newimg = tf.multiply(cond1, upper) + self.assign_newimg += tf.multiply(cond2, self.timg) + self.assign_newimg += tf.multiply(cond3, lower) + + self.assign_slack = self.assign_newimg + self.assign_slack += tf.multiply(self.zt, + self.assign_newimg - self.newimg) + + self.setter = tf.assign(self.newimg, self.assign_newimg) + self.setter_y = tf.assign(self.slack, self.assign_slack) + """--------------------------------""" + + # prediction BEFORE-SOFTMAX of the model + self.output = model.get_logits(self.newimg, reuse=True) + self.output_y = model.get_logits(self.slack, reuse=True) + + # distance to the input data + self.l2dist = tf.reduce_sum(tf.square(self.newimg - self.timg), + list(range(1, len(shape)))) + self.l2dist_y = tf.reduce_sum(tf.square(self.slack - self.timg), + list(range(1, len(shape)))) + self.l1dist = tf.reduce_sum(tf.abs(self.newimg - self.timg), + list(range(1, len(shape)))) + self.l1dist_y = tf.reduce_sum(tf.abs(self.slack - self.timg), + list(range(1, len(shape)))) + self.elasticdist = self.l2dist + tf.multiply(self.l1dist, + self.beta_t) + self.elasticdist_y = self.l2dist_y + tf.multiply(self.l1dist_y, + self.beta_t) + + # compute the probability of the label class versus the maximum other + real = tf.reduce_sum((self.tlab) * self.output, 1) + real_y = tf.reduce_sum((self.tlab) * self.output_y, 1) + other = tf.reduce_max((1 - self.tlab) * self.output - + (self.tlab * 10000), 1) + other_y = tf.reduce_max((1 - self.tlab) * self.output_y - + (self.tlab * 10000), 1) + + if self.TARGETED: + # if targeted, optimize for making the other class most likely + loss1 = tf.maximum(0.0, other - real + self.CONFIDENCE) + loss1_y = tf.maximum(0.0, other_y - real_y + self.CONFIDENCE) + else: + # if untargeted, optimize for making this class least likely. + loss1 = tf.maximum(0.0, real - other + self.CONFIDENCE) + loss1_y = tf.maximum(0.0, real_y - other_y + self.CONFIDENCE) + + # sum up the losses + self.loss21 = tf.reduce_sum(self.l1dist) + self.loss21_y = tf.reduce_sum(self.l1dist_y) + self.loss2 = tf.reduce_sum(self.l2dist) + self.loss2_y = tf.reduce_sum(self.l2dist_y) + self.loss1 = tf.reduce_sum(self.const * loss1) + self.loss1_y = tf.reduce_sum(self.const * loss1_y) + self.loss2 = tf.reduce_sum(self.l2dist) + + self.loss_opt = self.loss1_y + self.loss2_y + self.loss = self.loss1 + self.loss2 + \ + tf.multiply(self.beta_t, self.loss21) + + self.learning_rate = tf.train.polynomial_decay(self.LEARNING_RATE, + self.global_step, + self.MAX_ITERATIONS, + 0, power=0.5) + + # Setup the optimizer and keep track of variables we're creating + start_vars = set(x.name for x in tf.global_variables()) + optimizer = tf.train.GradientDescentOptimizer(self.learning_rate) + self.train = optimizer.minimize(self.loss_opt, + var_list=[self.slack], + global_step=self.global_step) + end_vars = tf.global_variables() + new_vars = [x for x in end_vars if x.name not in start_vars] + + # these are the variables to initialize when we run + self.setup = [] + self.setup.append(self.timg.assign(self.assign_timg)) + self.setup.append(self.tlab.assign(self.assign_tlab)) + self.setup.append(self.const.assign(self.assign_const)) + + self.init = tf.variables_initializer(var_list=[self.global_step] + + [self.slack] + [self.newimg] + + new_vars) + + def attack(self, imgs, targets): + """ + Perform the EAD attack on the given instance for the given targets. + + If self.targeted is true, then the targets represents the target labels + If self.targeted is false, then targets are the original class labels + """ + + r = [] + for i in range(0, len(imgs), self.batch_size): + _logger.debug(("Running EAD attack on instance " + + "{} of {}").format(i, len(imgs))) + r.extend(self.attack_batch(imgs[i:i + self.batch_size], + targets[i:i + self.batch_size], phase)) + return np.array(r) + + def attack_batch(self, imgs, labs, phase): + """ + Run the attack on a batch of instance and labels. + """ + def compare(x, y): + if not isinstance(x, (float, int, np.int64)): + x = np.copy(x) + if self.TARGETED: + x[y] -= self.CONFIDENCE + else: + x[y] += self.CONFIDENCE + x = np.argmax(x) + if self.TARGETED: + return x == y + else: + return x != y + + batch_size = self.batch_size + + imgs = np.clip(imgs, self.clip_min, self.clip_max) + + # set the lower and upper bounds accordingly + lower_bound = np.zeros(batch_size) + CONST = np.ones(batch_size) * self.initial_const + upper_bound = np.ones(batch_size) * 1e10 + + # placeholders for the best en, score, and instance attack found so far + o_besten = [1e10] * batch_size + o_bestscore = [-1] * batch_size + o_bestattack = np.copy(imgs) + + for outer_step in range(self.BINARY_SEARCH_STEPS): + # completely reset the optimizer's internal state. + self.sess.run(self.init) + batch = imgs[:batch_size] + batchlab = labs[:batch_size] + + besten = [1e10] * batch_size + bestscore = [-1] * batch_size + _logger.debug(" Binary search step {} of {}". + format(outer_step, self.BINARY_SEARCH_STEPS)) + + # The last iteration (if we run many steps) repeat the search once. + if self.repeat and outer_step == self.BINARY_SEARCH_STEPS - 1: + CONST = upper_bound + + # set the variables so that we don't have to send them over again + self.sess.run(self.setup, {self.assign_timg: batch, + self.assign_tlab: batchlab, + self.assign_const: CONST}) + self.sess.run(self.setter, feed_dict={self.assign_newimg: batch}) + self.sess.run(self.setter_y, feed_dict={self.assign_slack: batch}) + prev = 1e6 + for iteration in range(self.MAX_ITERATIONS): + # perform the attack + self.sess.run([self.train]) + self.sess.run([self.setter, self.setter_y]) + l, l2s, l1s, elastic = self.sess.run([self.loss, + self.l2dist, + self.l1dist, + self.elasticdist]) + scores, nimg = self.sess.run([self.output, self.newimg]) + + if iteration % ((self.MAX_ITERATIONS // 10) or 1) == 0: + _logger.debug((" Iteration {} of {}: loss={:.3g} " + + "l2={:.3g} l1={:.3g} f={:.3g}") + .format(iteration, self.MAX_ITERATIONS, + l, np.mean(l2s), np.mean(l1s), + np.mean(scores))) + + # check if we should abort search if we're getting nowhere. + if self.ABORT_EARLY and \ + iteration % ((self.MAX_ITERATIONS // 10) or 1) == 0: + if l > prev * .9999: + msg = " Failed to make progress; stop early" + _logger.debug(msg) + break + prev = l + + # adjust the best result found so far + for e, (en, sc, ii) in enumerate(zip(elastic, scores, nimg)): + lab = np.argmax(batchlab[e]) + if en < besten[e] and compare(sc, lab): + besten[e] = en + bestscore[e] = np.argmax(sc) + if en < o_besten[e] and compare(sc, lab): + o_besten[e] = en + o_bestscore[e] = np.argmax(sc) + o_bestattack[e] = ii + + # adjust the constant as needed + for e in range(batch_size): + if compare(bestscore[e], np.argmax(batchlab[e])) and \ + bestscore[e] != -1: + # success, divide const by two + upper_bound[e] = min(upper_bound[e], CONST[e]) + if upper_bound[e] < 1e9: + CONST[e] = (lower_bound[e] + upper_bound[e]) / 2 + else: + # failure, either multiply by 10 if no solution found yet + # or do binary search with the known upper bound + lower_bound[e] = max(lower_bound[e], CONST[e]) + if upper_bound[e] < 1e9: + CONST[e] = (lower_bound[e] + upper_bound[e]) / 2 + else: + CONST[e] *= 10 + _logger.debug(" Successfully generated adversarial examples " + + "on {} of {} instances.". + format(sum(upper_bound < 1e9), batch_size)) + o_besten = np.array(o_besten) + mean = np.mean(np.sqrt(o_besten[o_besten < 1e9])) + _logger.debug(" Elastic Mean successful distortion: {:.4g}". + format(mean)) + + # return the best solution found + o_besten = np.array(o_besten) + return o_bestattack + + +def deepfool_batch(sess, x, pred, logits, grads, X, nb_candidate, overshoot, + max_iter, clip_min, clip_max, nb_classes, feed=None): + """ + Applies DeepFool to a batch of inputs + :param sess: TF session + :param x: The input placeholder + :param pred: The model's sorted symbolic output of logits, only the top + nb_candidate classes are contained + :param logits: The model's unnormalized output tensor (the input to + the softmax layer) + :param grads: Symbolic gradients of the top nb_candidate classes, procuded + from gradient_graph + :param X: Numpy array with sample inputs + :param nb_candidate: The number of classes to test against, i.e., + deepfool only consider nb_candidate classes when + attacking(thus accelerate speed). The nb_candidate + classes are chosen according to the prediction + confidence during implementation. + :param overshoot: A termination criterion to prevent vanishing updates + :param max_iter: Maximum number of iteration for DeepFool + :param clip_min: Minimum value for components of the example returned + :param clip_max: Maximum value for components of the example returned + :param nb_classes: Number of model output classes + :return: Adversarial examples + """ + X_adv = deepfool_attack(sess, x, pred, logits, grads, X, nb_candidate, + overshoot, max_iter, clip_min, clip_max, feed=feed) + + return np.asarray(X_adv, dtype=np.float32) + + +def deepfool_attack(sess, x, predictions, logits, grads, sample, nb_candidate, + overshoot, max_iter, clip_min, clip_max, feed=None): + """ + TensorFlow implementation of DeepFool. + Paper link: see https://arxiv.org/pdf/1511.04599.pdf + :param sess: TF session + :param x: The input placeholder + :param predictions: The model's sorted symbolic output of logits, only the + top nb_candidate classes are contained + :param logits: The model's unnormalized output tensor (the input to + the softmax layer) + :param grads: Symbolic gradients of the top nb_candidate classes, procuded + from gradient_graph + :param sample: Numpy array with sample input + :param nb_candidate: The number of classes to test against, i.e., + deepfool only consider nb_candidate classes when + attacking(thus accelerate speed). The nb_candidate + classes are chosen according to the prediction + confidence during implementation. + :param overshoot: A termination criterion to prevent vanishing updates + :param max_iter: Maximum number of iteration for DeepFool + :param clip_min: Minimum value for components of the example returned + :param clip_max: Maximum value for components of the example returned + :return: Adversarial examples + """ + import copy + + adv_x = copy.copy(sample) + # Initialize the loop variables + iteration = 0 + current = utils_tf.model_argmax(sess, x, logits, adv_x, feed=feed) + if current.shape == (): + current = np.array([current]) + w = np.squeeze(np.zeros(sample.shape[1:])) # same shape as original image + r_tot = np.zeros(sample.shape) + original = current # use original label as the reference + + _logger.debug("Starting DeepFool attack up to {} iterations". + format(max_iter)) + # Repeat this main loop until we have achieved misclassification + while (np.any(current == original) and iteration < max_iter): + + if iteration % 5 == 0 and iteration > 0: + _logger.info("Attack result at iteration {} is {}".format( + iteration, + current)) + gradients = sess.run(grads, feed_dict={x: adv_x}) + predictions_val = sess.run(predictions, feed_dict={x: adv_x}) + for idx in range(sample.shape[0]): + pert = np.inf + if current[idx] != original[idx]: + continue + for k in range(1, nb_candidate): + w_k = gradients[idx, k, ...] - gradients[idx, 0, ...] + f_k = predictions_val[idx, k] - predictions_val[idx, 0] + # adding value 0.00001 to prevent f_k = 0 + pert_k = (abs(f_k) + 0.00001) / np.linalg.norm(w_k.flatten()) + if pert_k < pert: + pert = pert_k + w = w_k + r_i = pert * w / np.linalg.norm(w) + r_tot[idx, ...] = r_tot[idx, ...] + r_i + + adv_x = np.clip(r_tot + sample, clip_min, clip_max) + current = utils_tf.model_argmax(sess, x, logits, adv_x, feed=feed) + if current.shape == (): + current = np.array([current]) + # Update loop variables + iteration = iteration + 1 + + # need more revision, including info like how many succeed + _logger.info("Attack result at iteration {} is {}".format(iteration, + current)) + _logger.info("{} out of {}".format(sum(current != original), + sample.shape[0]) + + " becomes adversarial examples at iteration {}".format( + iteration)) + # need to clip this image into the given range + adv_x = np.clip((1 + overshoot) * r_tot + sample, clip_min, clip_max) + return adv_x diff --git a/case_studies/empir/modified_cleverhans/attacks_th.py b/case_studies/empir/modified_cleverhans/attacks_th.py new file mode 100644 index 0000000..5f7057e --- /dev/null +++ b/case_studies/empir/modified_cleverhans/attacks_th.py @@ -0,0 +1,114 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import numpy as np + +import theano +import warnings +from theano import gradient, tensor as T +from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams + +from . import utils_th + +floatX = theano.config.floatX + + +def fgsm(x, predictions, eps, clip_min=None, clip_max=None): + return fgm(x, predictions, y=None, eps=eps, ord=np.inf, clip_min=clip_min, + clip_max=clip_max) + + +def fgm(x, predictions, y=None, eps=0.3, ord=np.inf, clip_min=None, + clip_max=None): + """ + Theano implementation of the Fast Gradient + Sign method. + :param x: the input placeholder + :param predictions: the model's output tensor + :param y: the output placeholder. Use None (the default) to avoid the + label leaking effect. + :param eps: the epsilon (input variation parameter) + :param ord: (optional) Order of the norm (mimics Numpy). + Possible values: np.inf (other norms not implemented yet). + :param clip_min: optional parameter that can be used to set a minimum + value for components of the example returned + :param clip_max: optional parameter that can be used to set a maximum + value for components of the example returned + :return: a tensor for the adversarial example + """ + warnings.warn("CleverHans support for Theano is deprecated and " + "will be dropped on 2017-11-08.") + assert ord == np.inf, "Theano implementation not available for this norm." + eps = np.asarray(eps, dtype=floatX) + + if y is None: + # Using model predictions as ground truth to avoid label leaking + y = T.eq(predictions, T.max(predictions, axis=1, keepdims=True)) + y = T.cast(y, utils_th.floatX) + y = y / T.sum(y, 1, keepdims=True) + # Compute loss + loss = utils_th.model_loss(y, predictions, mean=True) + + # Define gradient of loss wrt input + grad = T.grad(loss, x) + + # Take sign of gradient + signed_grad = T.sgn(grad) + + # Multiply by constant epsilon + scaled_signed_grad = eps * signed_grad + + # Add perturbation to original example to obtain adversarial example + adv_x = gradient.disconnected_grad(x + scaled_signed_grad) + + # If clipping is needed, reset all values outside of [clip_min, clip_max] + if (clip_min is not None) and (clip_max is not None): + adv_x = T.clip(adv_x, clip_min, clip_max) + + return adv_x + + +def vatm(model, x, predictions, eps, num_iterations=1, xi=1e-6, + clip_min=None, clip_max=None, seed=12345): + """ + Theano implementation of the perturbation method used for virtual + adversarial training: https://arxiv.org/abs/1507.00677 + :param model: the model which returns the network unnormalized logits + :param x: the input placeholder + :param predictions: the model's unnormalized output tensor + :param eps: the epsilon (input variation parameter) + :param num_iterations: the number of iterations + :param xi: the finite difference parameter + :param clip_min: optional parameter that can be used to set a minimum + value for components of the example returned + :param clip_max: optional parameter that can be used to set a maximum + value for components of the example returned + :param seed: the seed for random generator + :return: a tensor for the adversarial example + """ + eps = np.asarray(eps, dtype=floatX) + xi = np.asarray(xi, dtype=floatX) + rng = RandomStreams(seed=seed) + d = rng.normal(size=x.shape, dtype=x.dtype) + for i in range(num_iterations): + d = xi * utils_th.l2_batch_normalize(d) + logits_d = model(x + d) + kl = utils_th.kl_with_logits(predictions, logits_d) + Hd = T.grad(kl.sum(), d) + d = gradient.disconnected_grad(Hd) + d = eps * utils_th.l2_batch_normalize(d) + adv_x = gradient.disconnected_grad(x + d) + if (clip_min is not None) and (clip_max is not None): + adv_x = T.clip(adv_x, clip_min, clip_max) + return adv_x diff --git a/case_studies/empir/modified_cleverhans/devtools/LICENSE.txt b/case_studies/empir/modified_cleverhans/devtools/LICENSE.txt new file mode 100644 index 0000000..eaac7d7 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/devtools/LICENSE.txt @@ -0,0 +1,30 @@ +The devtools module is a derivative work from the devtools module of pylearn2. +We reproduce the corresponding license here. + +Copyright (c) 2011--2014, Université de Montréal +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/case_studies/empir/modified_cleverhans/devtools/__init__.py b/case_studies/empir/modified_cleverhans/devtools/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/case_studies/empir/modified_cleverhans/devtools/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/case_studies/empir/modified_cleverhans/devtools/checks.py b/case_studies/empir/modified_cleverhans/devtools/checks.py new file mode 100644 index 0000000..085277b --- /dev/null +++ b/case_studies/empir/modified_cleverhans/devtools/checks.py @@ -0,0 +1,43 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +"""Functionality for building tests. + +We have to call this file "checks" and not anything with "test" as a +substring or nosetests will execute it. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np +import time +import unittest + + +class CleverHansTest(unittest.TestCase): + + def setUp(self): + self.test_start = time.time() + # seed the randomness + np.random.seed(1234) + + def tearDown(self): + print(self.id(), "took", time.time() - self.test_start, "seconds") + + def assertClose(self, x, y, *args, **kwargs): + # self.assertTrue(np.allclose(x, y)) doesn't give a useful message + # on failure + assert np.allclose(x, y, *args, **kwargs), (x, y) diff --git a/case_studies/empir/modified_cleverhans/devtools/list_files.py b/case_studies/empir/modified_cleverhans/devtools/list_files.py new file mode 100644 index 0000000..bfcf9b9 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/devtools/list_files.py @@ -0,0 +1,100 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +"""Code for listing files that belong to the library.""" +import logging +import cleverhans +import os +__authors__ = "Ian Goodfellow" +__copyright__ = "Copyright 2010-2012, Universite de Montreal" +__credits__ = ["Ian Goodfellow"] +__license__ = "3-clause BSD" +__maintainer__ = "LISA Lab" +__email__ = "pylearn-dev@googlegroups" + +logger = logging.getLogger(__name__) + + +def list_files(suffix=""): + """ + Returns a list of all files in CleverHans with the given suffix. + + Parameters + ---------- + suffix : str + + Returns + ------- + + file_list : list + A list of all files in CleverHans whose filepath ends with `suffix` + """ + + cleverhans_path = os.path.abspath(cleverhans.__path__[0]) + repo_path = os.path.abspath(os.path.join(cleverhans_path, os.pardir)) + + file_list = _list_files(cleverhans_path, suffix) + + tutorials_path = os.path.join(repo_path, "cleverhans_tutorials") + tutorials_files = _list_files(tutorials_path, suffix) + tutorials_files = [os.path.join(os.pardir, path) for path in + tutorials_files] + examples_path = os.path.join(repo_path, "examples") + examples_files = _list_files(examples_path, suffix) + examples_files = [os.path.join(os.pardir, path) for path in + examples_files] + + file_list = file_list + tutorials_files + examples_files + + return file_list + + +def _list_files(path, suffix=""): + """ + Returns a list of all files ending in `suffix` contained within `path`. + + Parameters + ---------- + path : str + a filepath + suffix : str + + Returns + ------- + l : list + A list of all files ending in `suffix` contained within `path`. + (If `path` is a file rather than a directory, it is considered + to "contain" itself) + """ + if os.path.isdir(path): + incomplete = os.listdir(path) + complete = [os.path.join(path, entry) for entry in incomplete] + lists = [_list_files(subpath, suffix) for subpath in complete] + flattened = [] + for l in lists: + for elem in l: + flattened.append(elem) + return flattened + else: + assert os.path.exists(path), "couldn't find file '%s'" % path + if path.endswith(suffix): + return [path] + return [] + + +if __name__ == '__main__': + # Print all .py files in the library + result = list_files('.py') + for path in result: + logger.info(path) diff --git a/case_studies/empir/modified_cleverhans/devtools/mocks.py b/case_studies/empir/modified_cleverhans/devtools/mocks.py new file mode 100644 index 0000000..2bf75b3 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/devtools/mocks.py @@ -0,0 +1,40 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +"""Utility functions for mocking up tests. + +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + + +def random_feed_dict(rng, placeholders): + """ + Returns random data to be used with `feed_dict`. + :param rng: A numpy.random.RandomState instance + :param placeholders: List of tensorflow placeholders + :return: A dict mapping placeholders to random numpy values + """ + + output = {} + + for placeholder in placeholders: + if placeholder.dtype != 'float32': + raise NotImplementedError() + value = rng.randn(*placeholder.shape).astype('float32') + output[placeholder] = value + + return output diff --git a/case_studies/empir/modified_cleverhans/devtools/tests/__init__.py b/case_studies/empir/modified_cleverhans/devtools/tests/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/case_studies/empir/modified_cleverhans/devtools/tests/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/case_studies/empir/modified_cleverhans/devtools/tests/docscrape.py b/case_studies/empir/modified_cleverhans/devtools/tests/docscrape.py new file mode 100644 index 0000000..7361a38 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/devtools/tests/docscrape.py @@ -0,0 +1,853 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +"""Extract reference documentation from the NumPy source tree. + +""" + +from __future__ import print_function + +import inspect +from nose.plugins.skip import SkipTest +import re +import sys + +import six + + +class Reader(object): + + """A line-based string reader. + + """ + + def __init__(self, data): + """ + Parameters + ---------- + data : str + String with lines separated by '\n'. + + """ + if isinstance(data, list): + self._str = data + else: + self._str = data.split('\n') # store string as list of lines + + self.reset() + + def __getitem__(self, n): + return self._str[n] + + def reset(self): + self._l = 0 # current line nr + + def read(self): + if not self.eof(): + out = self[self._l] + self._l += 1 + return out + else: + return '' + + def seek_next_non_empty_line(self): + for l in self[self._l:]: + if l.strip(): + break + else: + self._l += 1 + + def eof(self): + return self._l >= len(self._str) + + def read_to_condition(self, condition_func): + start = self._l + for line in self[start:]: + if condition_func(line): + return self[start:self._l] + self._l += 1 + if self.eof(): + return self[start:self._l + 1] + return [] + + def read_to_next_empty_line(self): + self.seek_next_non_empty_line() + + def is_empty(line): + return not line.strip() + return self.read_to_condition(is_empty) + + def read_to_next_unindented_line(self): + def is_unindented(line): + return (line.strip() and (len(line.lstrip()) == len(line))) + return self.read_to_condition(is_unindented) + + def peek(self, n=0): + if self._l + n < len(self._str): + return self[self._l + n] + else: + return '' + + def is_empty(self): + return not ''.join(self._str).strip() + + def __iter__(self): + for line in self._str: + yield line + + +class NumpyDocString(object): + + def __init__(self, docstring, name=None): + if name: + self.name = name + docstring = docstring.split('\n') + + # De-indent paragraph + try: + indent = min(len(s) - len(s.lstrip()) for s in docstring + if s.strip()) + except ValueError: + indent = 0 + + for n, line in enumerate(docstring): + docstring[n] = docstring[n][indent:] + + self._doc = Reader(docstring) + self._parsed_data = { + 'Signature': '', + 'Summary': '', + 'Extended Summary': [], + 'Parameters': [], + 'Other Parameters': [], + 'Returns': [], + 'Raises': [], + 'Warns': [], + 'See Also': [], + 'Notes': [], + 'References': '', + 'Examples': '', + 'index': {}, + 'Attributes': [], + 'Methods': [], + } + self.section_order = [] + + self._parse() + + def __getitem__(self, key): + return self._parsed_data[key] + + def __setitem__(self, key, val): + if key not in self._parsed_data: + raise ValueError("Unknown section %s" % key) + else: + self._parsed_data[key] = val + + def _is_at_section(self): + self._doc.seek_next_non_empty_line() + + if self._doc.eof(): + return False + + l1 = self._doc.peek().strip() # e.g. Parameters + + if l1.startswith('.. index::'): + return True + + l2 = self._doc.peek(1).strip() # ---------- + return (len(l1) == len(l2) and l2 == '-' * len(l1)) + + def _strip(self, doc): + i = 0 + j = 0 + for i, line in enumerate(doc): + if line.strip(): + break + + for j, line in enumerate(doc[::-1]): + if line.strip(): + break + + return doc[i:len(doc) - j] + + def _read_to_next_section(self): + section = self._doc.read_to_next_empty_line() + + while not self._is_at_section() and not self._doc.eof(): + if not self._doc.peek(-1).strip(): # previous line was empty + section += [''] + + section += self._doc.read_to_next_empty_line() + + return section + + def _read_sections(self): + while not self._doc.eof(): + data = self._read_to_next_section() + name = data[0].strip() + + if name.startswith('..'): # index section + yield name, data[1:] + elif len(data) < 2: + yield StopIteration + else: + yield name, self._strip(data[2:]) + + def _parse_param_list(self, content): + r = Reader(content) + params = [] + while not r.eof(): + header = r.read().strip() + if ' : ' in header: + arg_name, arg_type = header.split(' : ')[:2] + else: + arg_name, arg_type = header, '' + + desc = r.read_to_next_unindented_line() + for n, line in enumerate(desc): + desc[n] = line.strip() + desc = desc # '\n'.join(desc) + + params.append((arg_name, arg_type, desc)) + + return params + + def _parse_see_also(self, content): + """ + func_name : Descriptive text + continued text + another_func_name : Descriptive text + func_name1, func_name2, func_name3 + + """ + functions = [] + current_func = None + rest = [] + for line in content: + if not line.strip(): + continue + if ':' in line: + if current_func: + functions.append((current_func, rest)) + r = line.split(':', 1) + current_func = r[0].strip() + r[1] = r[1].strip() + if r[1]: + rest = [r[1]] + else: + rest = [] + elif not line.startswith(' '): + if current_func: + functions.append((current_func, rest)) + current_func = None + rest = [] + if ',' in line: + for func in line.split(','): + func = func.strip() + if func: + functions.append((func, [])) + elif line.strip(): + current_func = line.strip() + elif current_func is not None: + rest.append(line.strip()) + if current_func: + functions.append((current_func, rest)) + return functions + + def _parse_index(self, section, content): + """ + .. index: default + :refguide: something, else, and more + + """ + def strip_each_in(lst): + return [s.strip() for s in lst] + + out = {} + section = section.split('::') + if len(section) > 1: + out['default'] = strip_each_in(section[1].split(','))[0] + for line in content: + line = line.split(':') + if len(line) > 2: + out[line[1]] = strip_each_in(line[2].split(',')) + return out + + def _parse_summary(self): + """Grab signature (if given) and summary""" + summary = self._doc.read_to_next_empty_line() + summary_str = "\n".join([s.strip() for s in summary]) + if re.compile('^([\w. ]+=)?[\w\.]+\(.*\)$').match(summary_str): + self['Signature'] = summary_str + if not self._is_at_section(): + self['Summary'] = self._doc.read_to_next_empty_line() + elif re.compile('^[\w]+\n[-]+').match(summary_str): + self['Summary'] = '' + self._doc.reset() + else: + self['Summary'] = summary + + if not self._is_at_section(): + self['Extended Summary'] = self._read_to_next_section() + + def _parse(self): + self._doc.reset() + self._parse_summary() + for (section, content) in self._read_sections(): + if not section.startswith('..'): + section = ' '.join([s.capitalize() + for s in section.split(' ')]) + if section in ('Parameters', 'Other Parameters', 'Returns', + 'Raises', 'Warns', 'Attributes', 'Methods'): + self[section] = self._parse_param_list(content) + self.section_order.append(section) + elif section.startswith('.. index::'): + self['index'] = self._parse_index(section, content) + self.section_order.append('index') + elif section.lower() == 'see also': + self['See Also'] = self._parse_see_also(content) + self.section_order.append('See Also') + else: + self[section] = content + self.section_order.append(section) + + # string conversion routines + + def _str_header(self, name, symbol='-'): + return [name, len(name) * symbol] + + def _str_indent(self, doc, indent=4): + out = [] + for line in doc: + out += [' ' * indent + line] + return out + + def _str_signature(self): + if not self['Signature']: + return [] + return ["*%s*" % self['Signature'].replace('*', '\*')] + [''] + + def _str_summary(self): + return self['Summary'] + [''] + + def _str_extended_summary(self): + return self['Extended Summary'] + [''] + + def _str_param_list(self, name): + out = [] + if self[name]: + out += self._str_header(name) + for param, param_type, desc in self[name]: + out += ['%s : %s' % (param, param_type)] + out += self._str_indent(desc) + out += [''] + return out + + def _str_section(self, name): + out = [] + if self[name]: + out += self._str_header(name) + out += self[name] + out += [''] + return out + + def _str_see_also(self): + if not self['See Also']: + return [] + out = [] + out += self._str_header("See Also") + last_had_desc = True + for func, desc in self['See Also']: + if desc or last_had_desc: + out += [''] + out += ["`%s`_" % func] + else: + out[-1] += ", `%s`_" % func + if desc: + out += self._str_indent(desc) + last_had_desc = True + else: + last_had_desc = False + out += [''] + return out + + def _str_index(self): + idx = self['index'] + out = [] + out += ['.. index:: %s' % idx.get('default', '')] + for section, references in six.iteritems(idx): + if section == 'default': + continue + out += [' :%s: %s' % (section, ', '.join(references))] + return out + + def __str__(self): + out = [] + out += self._str_signature() + out += self._str_summary() + out += self._str_extended_summary() + for param_list in ('Parameters', 'Other Parameters', + 'Returns', 'Raises', 'Warns'): + out += self._str_param_list(param_list) + out += self._str_see_also() + for s in ('Notes', 'References', 'Examples'): + out += self._str_section(s) + out += self._str_index() + return '\n'.join(out) + + # -- + + def get_errors(self, check_order=True): + errors = [] + self._doc.reset() + for j, line in enumerate(self._doc): + if len(line) > 75: + if hasattr(self, 'name'): + errors.append("%s: Line %d exceeds 75 chars" + ": \"%s\"..." % (self.name, j + 1, + line[:30])) + else: + errors.append("Line %d exceeds 75 chars" + ": \"%s\"..." % (j + 1, line[:30])) + + if check_order: + canonical_order = ['Signature', 'Summary', 'Extended Summary', + 'Attributes', 'Methods', 'Parameters', + 'Other Parameters', 'Returns', 'Raises', + 'Warns', + 'See Also', 'Notes', 'References', 'Examples', + 'index'] + + canonical_order_copy = list(canonical_order) + + for s in self.section_order: + while canonical_order_copy and s != canonical_order_copy[0]: + canonical_order_copy.pop(0) + if not canonical_order_copy: + errors.append( + "Sections in wrong order (starting at %s). The" + " right order is %s" % (s, canonical_order)) + + return errors + + +def indent(str, indent=4): + indent_str = ' ' * indent + if str is None: + return indent_str + lines = str.split('\n') + return '\n'.join(indent_str + l for l in lines) + + +class NumpyFunctionDocString(NumpyDocString): + + def __init__(self, docstring, function): + super(NumpyFunctionDocString, self).__init__(docstring) + args, varargs, keywords, defaults = inspect.getargspec(function) + if (args and args != ['self']) or varargs or keywords or defaults: + self.has_parameters = True + else: + self.has_parameters = False + + def _parse(self): + self._parsed_data = { + 'Signature': '', + 'Summary': '', + 'Extended Summary': [], + 'Parameters': [], + 'Other Parameters': [], + 'Returns': [], + 'Raises': [], + 'Warns': [], + 'See Also': [], + 'Notes': [], + 'References': '', + 'Examples': '', + 'index': {}, + } + return NumpyDocString._parse(self) + + def get_errors(self): + errors = NumpyDocString.get_errors(self) + + if not self['Signature']: + # This check is currently too restrictive. + # Disabling it for now. + # errors.append("No function signature") + pass + + if not self['Summary']: + errors.append("No function summary line") + + if len(" ".join(self['Summary'])) > 3 * 80: + errors.append("Brief function summary is longer than 3 lines") + + if not self['Parameters'] and self.has_parameters: + errors.append("No Parameters section") + + return errors + + +class NumpyClassDocString(NumpyDocString): + + def __init__(self, docstring, class_name, class_object): + super(NumpyClassDocString, self).__init__(docstring) + self.class_name = class_name + methods = dict((name, func) for name, func + in inspect.getmembers(class_object)) + + self.has_parameters = False + if '__init__' in methods: + # verify if __init__ is a Python function. If it isn't + # (e.g. the function is implemented in C), getargspec will fail + if not inspect.ismethod(methods['__init__']): + return + args, varargs, keywords, defaults = inspect.getargspec( + methods['__init__']) + if (args and args != ['self']) or varargs or keywords or defaults: + self.has_parameters = True + + def _parse(self): + self._parsed_data = { + 'Signature': '', + 'Summary': '', + 'Extended Summary': [], + 'Parameters': [], + 'Other Parameters': [], + 'Raises': [], + 'Warns': [], + 'See Also': [], + 'Notes': [], + 'References': '', + 'Examples': '', + 'index': {}, + 'Attributes': [], + 'Methods': [], + } + return NumpyDocString._parse(self) + + def __str__(self): + out = [] + out += self._str_signature() + out += self._str_summary() + out += self._str_extended_summary() + for param_list in ('Attributes', 'Methods', 'Parameters', 'Raises', + 'Warns'): + out += self._str_param_list(param_list) + out += self._str_see_also() + for s in ('Notes', 'References', 'Examples'): + out += self._str_section(s) + out += self._str_index() + return '\n'.join(out) + + def get_errors(self): + errors = NumpyDocString.get_errors(self) + if not self['Parameters'] and self.has_parameters: + errors.append("%s class has no Parameters section" + % self.class_name) + return errors + + +class NumpyModuleDocString(NumpyDocString): + + """ + Module doc strings: no parsing is done. + + """ + + def _parse(self): + self.out = [] + + def __str__(self): + return "\n".join(self._doc._str) + + def get_errors(self): + errors = NumpyDocString.get_errors(self, check_order=False) + return errors + + +def header(text, style='-'): + return text + '\n' + style * len(text) + '\n' + + +class SphinxDocString(NumpyDocString): + # string conversion routines + + def _str_header(self, name, symbol='`'): + return ['**' + name + '**'] + [symbol * (len(name) + 4)] + + def _str_indent(self, doc, indent=4): + out = [] + for line in doc: + out += [' ' * indent + line] + return out + + def _str_signature(self): + return ['``%s``' % self['Signature'].replace('*', '\*')] + [''] + + def _str_summary(self): + return self['Summary'] + [''] + + def _str_extended_summary(self): + return self['Extended Summary'] + [''] + + def _str_param_list(self, name): + out = [] + if self[name]: + out += self._str_header(name) + out += [''] + for param, param_type, desc in self[name]: + out += self._str_indent(['**%s** : %s' % (param, param_type)]) + out += [''] + out += self._str_indent(desc, 8) + out += [''] + return out + + def _str_section(self, name): + out = [] + if self[name]: + out += self._str_header(name) + out += [''] + content = self._str_indent(self[name]) + out += content + out += [''] + return out + + def _str_index(self): + idx = self['index'] + out = [] + out += ['.. index:: %s' % idx.get('default', '')] + for section, references in six.iteritems(idx): + if section == 'default': + continue + out += [' :%s: %s' % (section, ', '.join(references))] + return out + + def __str__(self, indent=0): + out = [] + out += self._str_summary() + out += self._str_extended_summary() + for param_list in ('Parameters', 'Returns', 'Raises', 'Warns'): + out += self._str_param_list(param_list) + for s in ('Notes', 'References', 'Examples'): + out += self._str_section(s) + # out += self._str_index() + out = self._str_indent(out, indent) + return '\n'.join(out) + + +class FunctionDoc(object): + + def __init__(self, func): + self._f = func + + def __str__(self): + out = '' + doclines = inspect.getdoc(self._f) or '' + try: + doc = SphinxDocString(doclines) + except Exception as e: + print('*' * 78) + print("ERROR: '%s' while parsing `%s`" % (e, self._f)) + print('*' * 78) + # print "Docstring follows:" + # print doclines + # print '='*78 + return out + + if doc['Signature']: + out += '%s\n' % header('**%s**' % + doc['Signature'].replace('*', '\*'), '-') + else: + try: + # try to read signature + argspec = inspect.getargspec(self._f) + argspec = inspect.formatargspec(*argspec) + argspec = argspec.replace('*', '\*') + out += header('%s%s' % (self._f.__name__, argspec), '-') + except TypeError as e: + out += '%s\n' % header('**%s()**' % self._f.__name__, '-') + + out += str(doc) + return out + + +class ClassDoc(object): + + def __init__(self, cls, modulename=''): + if not inspect.isclass(cls): + raise ValueError("Initialise using an object") + self._cls = cls + + if modulename and not modulename.endswith('.'): + modulename += '.' + self._mod = modulename + self._name = cls.__name__ + + @property + def methods(self): + return [name for name, func in inspect.getmembers(self._cls) + if not name.startswith('_') and callable(func)] + + def __str__(self): + out = '' + + def replace_header(match): + return '"' * (match.end() - match.start()) + + for m in self.methods: + print("Parsing `%s`" % m) + out += str(FunctionDoc(getattr(self._cls, m))) + '\n\n' + out += '.. index::\n single: %s; %s\n\n' % (self._name, m) + + return out + + +def handle_function(val, name): + func_errors = [] + docstring = inspect.getdoc(val) + if docstring is None: + func_errors.append((name, '**missing** function-level docstring')) + else: + func_errors = [ + (name, e) for e in + NumpyFunctionDocString(docstring, val).get_errors() + ] + return func_errors + + +def handle_module(val, name): + module_errors = [] + docstring = val + if docstring is None: + module_errors.append((name, '**missing** module-level docstring')) + else: + module_errors = [ + (name, e) for e in NumpyModuleDocString(docstring).get_errors() + ] + return module_errors + + +def handle_method(method, method_name, class_name): + method_errors = [] + + # Skip out-of-library inherited methods + module = inspect.getmodule(method) + if module is not None: + if not module.__name__.startswith('pylearn2'): + return method_errors + + docstring = inspect.getdoc(method) + if docstring is None: + method_errors.append((class_name, method_name, + '**missing** method-level docstring')) + else: + method_errors = [ + (class_name, method_name, e) for e in + NumpyFunctionDocString(docstring, method).get_errors() + ] + return method_errors + + +def handle_class(val, class_name): + cls_errors = [] + docstring = inspect.getdoc(val) + if docstring is None: + cls_errors.append((class_name, + '**missing** class-level docstring')) + else: + cls_errors = [ + (e,) for e in + NumpyClassDocString(docstring, class_name, val).get_errors() + ] + # Get public methods and parse their docstrings + methods = dict(((name, func) for name, func in inspect.getmembers(val) + if not name.startswith('_') and callable(func) and + type(func) is not type)) + for m_name, method in six.iteritems(methods): + # skip error check if the method was inherited + # from a parent class (which means it wasn't + # defined in this source file) + if inspect.getmodule(method) is not None: + continue + cls_errors.extend(handle_method(method, m_name, class_name)) + return cls_errors + + +def docstring_errors(filename, global_dict=None): + """ + Run a Python file, parse the docstrings of all the classes + and functions it declares, and return them. + + Parameters + ---------- + filename : str + Filename of the module to run. + + global_dict : dict, optional + Globals dictionary to pass along to `execfile()`. + + Returns + ------- + all_errors : list + Each entry of the list is a tuple, of length 2 or 3, with + format either + + (func_or_class_name, docstring_error_description) + or + (class_name, method_name, docstring_error_description) + """ + if global_dict is None: + global_dict = {} + if '__file__' not in global_dict: + global_dict['__file__'] = filename + if '__doc__' not in global_dict: + global_dict['__doc__'] = None + try: + with open(filename) as f: + code = compile(f.read(), filename, 'exec') + exec(code, global_dict) + except SystemExit: + pass + except SkipTest: + raise AssertionError("Couldn't verify format of " + filename + + "due to SkipTest") + all_errors = [] + for key, val in six.iteritems(global_dict): + if not key.startswith('_'): + module_name = "" + if hasattr(inspect.getmodule(val), '__name__'): + module_name = inspect.getmodule(val).__name__ + if (inspect.isfunction(val) or inspect.isclass(val)) and\ + (inspect.getmodule(val) is None + or module_name == '__builtin__'): + if inspect.isfunction(val): + all_errors.extend(handle_function(val, key)) + elif inspect.isclass(val): + all_errors.extend(handle_class(val, key)) + elif key == '__doc__': + all_errors.extend(handle_module(val, key)) + if all_errors: + all_errors.insert(0, ("%s:" % filename,)) + return all_errors + + +if __name__ == "__main__": + all_errors = docstring_errors(sys.argv[1]) + if len(all_errors) > 0: + print("*" * 30, "docstring errors", "*" * 30) + for line in all_errors: + print(':'.join(line)) + sys.exit(int(len(all_errors) > 0)) diff --git a/case_studies/empir/modified_cleverhans/devtools/tests/test_format.py b/case_studies/empir/modified_cleverhans/devtools/tests/test_format.py new file mode 100644 index 0000000..1213400 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/devtools/tests/test_format.py @@ -0,0 +1,130 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Unit tests for format checking +""" + +from __future__ import print_function + +from nose.plugins.skip import SkipTest + +import os + +import modified_cleverhans +from modified_cleverhans.devtools.tests.docscrape import docstring_errors +from modified_cleverhans.devtools.list_files import list_files +from pycodestyle import StyleGuide + +# Enter a manual list of files that are allowed to violate PEP8 here +whitelist_pep8 = [ +] + +# The NIPS 2017 competition code is allowed to violate PEP8 because it +# follows the Google style guide instead (e.g., 2 spaces instead of 4) +whitelist_pep8.extend([os.path.relpath(path, cleverhans.__path__[0]) + for path in list_files() + if "nips17_adversarial_competition" in path]) + + +whitelist_docstrings = [ +] + + +def test_format_pep8(): + """ + Test if pep8 is respected. + """ + pep8_checker = StyleGuide() + files_to_check = [] + for path in list_files(".py"): + rel_path = os.path.relpath(path, cleverhans.__path__[0]) + if rel_path in whitelist_pep8: + continue + else: + files_to_check.append(path) + report = pep8_checker.check_files(files_to_check) + if report.total_errors > 0: + raise AssertionError("PEP8 Format not respected") + + +def print_files_information_pep8(): + """ + Print the list of files which can be removed from the whitelist and the + list of files which do not respect PEP8 formatting that aren't in the + whitelist + """ + infracting_files = [] + non_infracting_files = [] + pep8_checker = StyleGuide(quiet=True) + for path in list_files(".py"): + number_of_infractions = pep8_checker.input_file(path) + rel_path = os.path.relpath(path, cleverhans.__path__[0]) + if number_of_infractions > 0: + if rel_path not in whitelist_pep8: + infracting_files.append(path) + else: + if rel_path in whitelist_pep8: + non_infracting_files.append(path) + print("Files that must be corrected or added to whitelist:") + for file in infracting_files: + print(file) + print("Files that can be removed from whitelist:") + for file in non_infracting_files: + print(file) + + +def test_format_docstrings(): + """ + Test if docstrings are well formatted. + """ + # Disabled for now + return True + + try: + verify_format_docstrings() + except SkipTest as e: + import traceback + traceback.print_exc(e) + raise AssertionError( + "Some file raised SkipTest on import, and inadvertently" + " canceled the documentation testing." + ) + + +def verify_format_docstrings(): + """ + Implementation of `test_format_docstrings`. The implementation is + factored out so it can be placed inside a guard against SkipTest. + """ + format_infractions = [] + + for path in list_files(".py"): + rel_path = os.path.relpath(path, cleverhans.__path__[0]) + if rel_path in whitelist_docstrings: + continue + try: + format_infractions.extend(docstring_errors(path)) + except Exception as e: + format_infractions.append(["%s failed to run so format cannot " + "be checked. Error message:\n %s" % + (rel_path, e)]) + + if len(format_infractions) > 0: + msg = "\n".join(':'.join(line) for line in format_infractions) + raise AssertionError("Docstring format not respected:\n%s" % msg) + + +if __name__ == "__main__": + print_files_information_pep8() diff --git a/case_studies/empir/modified_cleverhans/devtools/version.py b/case_studies/empir/modified_cleverhans/devtools/version.py new file mode 100644 index 0000000..3362df5 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/devtools/version.py @@ -0,0 +1,36 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Utility functions for keeping track of the version of CleverHans. + +These functions provide a finer level of granularity than the +manually specified version string attached to each release. +""" +import hashlib +from cleverhans.devtools.list_files import list_files + + +def dev_version(): + """ + Returns a hexdigest of all the python files in the module. + """ + + m = hashlib.md5() + py_files = sorted(list_files(suffix=".py")) + for filename in py_files: + with open(filename, 'rb') as f: + content = f.read() + m.update(content) + return m.hexdigest() diff --git a/case_studies/empir/modified_cleverhans/model.py b/case_studies/empir/modified_cleverhans/model.py new file mode 100644 index 0000000..57706e0 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/model.py @@ -0,0 +1,181 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from abc import ABCMeta + + +class Model(object): + + """ + An abstract interface for model wrappers that exposes model symbols + needed for making an attack. This abstraction removes the dependency on + any specific neural network package (e.g. Keras) from the core + code of CleverHans. It can also simplify exposing the hidden features of a + model when a specific package does not directly expose them. + """ + __metaclass__ = ABCMeta + + def __init__(self): + pass + + def __call__(self, *args, **kwargs): + """ + For compatibility with functions used as model definitions (taking + an input tensor and returning the tensor giving the output + of the model on that input). + """ + return self.get_probs(*args, **kwargs) + + def get_layer(self, x, reuse, layer): + """ + Expose the hidden features of a model given a layer name. + :param x: A symbolic representation of the network input + :param layer: The name of the hidden layer to return features at. + :return: A symbolic representation of the hidden features + :raise: NoSuchLayerError if `layer` is not in the model. + """ + # Return the symbolic representation for this layer. + output = self.fprop(x, reuse) + try: + requested = output[layer] + except KeyError: + raise NoSuchLayerError() + return requested + + def get_logits(self, x, reuse): + """ + :param x: A symbolic representation of the network input + :return: A symbolic representation of the output logits (i.e., the + values fed as inputs to the softmax layer). + """ + return self.get_layer(x, reuse, 'logits') + + def get_probs(self, x, reuse=True): + """ + :param x: A symbolic representation of the network input + :return: A symbolic representation of the output probabilities (i.e., + the output values produced by the softmax layer). + """ + try: + return self.get_layer(x, reuse, 'probs') + except NoSuchLayerError: + import tensorflow as tf + return tf.nn.softmax(self.get_logits(x, True)) + + def get_layer_names(self): + """ + :return: a list of names for the layers that can be exposed by this + model abstraction. + """ + + if hasattr(self, 'layer_names'): + return self.layer_names + + raise NotImplementedError('`get_layer_names` not implemented.') + + def fprop(self, x, reuse): + """ + Exposes all the layers of the model returned by get_layer_names. + :param x: A symbolic representation of the network input + :return: A dictionary mapping layer names to the symbolic + representation of their output. + """ + raise NotImplementedError('`fprop` not implemented.') + + # special call for the ensemble model + def ensemble_call(self, *args, **kwargs): + """ + For compatibility with functions used as model definitions (taking + an input tensor and returning the tensor giving the output + of the model on that input). + """ + return self.get_ensemblepreds(*args, **kwargs) + + def get_ensemblepreds(self, x, reuse=True): + """ + :param x: A symbolic representation of the network input + :return: A symbolic representation of the ensemble output predictions + """ + try: + return self.get_layer(x, reuse, 'combined') + except NoSuchLayerError: + raise NotImplementedError('`combinedLayer` not implemented.') + + # Returns the average probability of the models that were finally used in the prediction after max voting + def get_combinedAvgCorrectProbs(self, x, reuse=True): + """ + :param x: A symbolic representation of the network input + :return: A symbolic representation of the output probabilities (i.e., + the output values produced by the softmax layer). + """ + try: + return self.get_layer(x, reuse, 'combinedAvgCorrectProb') + except NoSuchLayerError: + raise NotImplementedError('`combinedAvgCorrectProbLayer` not implemented.') + + # special functions for the teacher model in training with distillation + def get_teacher_logits(self, x, reuse): + """ + :param x: A symbolic representation of the network input + :return: A symbolic representation of the output logits (i.e., the + values fed as inputs to the softmax layer). + """ + return self.get_layer(x, reuse, 'teacher_logits') + + def get_teacher_probs(self, x, reuse=True): + """ + :param x: A symbolic representation of the network input + :return: A symbolic representation of the output probabilities (i.e., + the output values produced by the softmax layer). + """ + try: + return self.get_layer(x, reuse, 'teacher_probs') + except NoSuchLayerError: + import tensorflow as tf + return tf.nn.softmax(self.get_teacher_logits(x, True)) + + def teacher_call(self, *args, **kwargs): + """ + For compatibility with functions used as model definitions (taking + an input tensor and returning the tensor giving the output + of the model on that input). + """ + return self.get_teacher_probs(*args, **kwargs) + + +class CallableModelWrapper(Model): + + def __init__(self, callable_fn, output_layer): + """ + Wrap a callable function that takes a tensor as input and returns + a tensor as output with the given layer name. + :param callable_fn: The callable function taking a tensor and + returning a given layer as output. + :param output_layer: A string of the output layer returned by the + function. (Usually either "probs" or "logits".) + """ + + self.output_layer = output_layer + self.callable_fn = callable_fn + + def get_layer_names(self): + return [self.output_layer] + + def fprop(self, x, reuse): + return {self.output_layer: self.callable_fn(x)} + + +class NoSuchLayerError(ValueError): + + """Raised when a layer that does not exist is requested.""" diff --git a/case_studies/empir/modified_cleverhans/utils.py b/case_studies/empir/modified_cleverhans/utils.py new file mode 100644 index 0000000..1e7fc29 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/utils.py @@ -0,0 +1,397 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import os +import sys +import numpy as np +from collections import OrderedDict +from six.moves import xrange +import warnings +import logging + +known_number_types = (int, float, np.float16, np.float32, np.float64, + np.int8, np.int16, np.int32, np.int32, np.int64, + np.uint8, np.uint16, np.uint32, np.uint64) + + +class _ArgsWrapper(object): + + """ + Wrapper that allows attribute access to dictionaries + """ + + def __init__(self, args): + if not isinstance(args, dict): + args = vars(args) + self.args = args + + def __getattr__(self, name): + return self.args.get(name) + + +class AccuracyReport(object): + + """ + An object summarizing the accuracy results for experiments involving + training on clean examples or adversarial examples, then evaluating + on clean or adversarial examples. + """ + + def __init__(self): + self.clean_train_clean_eval = 0. + self.clean_train_adv_eval = 0. + self.adv_train_clean_eval = 0. + self.adv_train_adv_eval = 0. + + # Training data accuracy results to be used by tutorials + self.train_clean_train_clean_eval = 0. + self.train_clean_train_adv_eval = 0. + self.train_adv_train_clean_eval = 0. + self.train_adv_train_adv_eval = 0. + + +def batch_indices(batch_nb, data_length, batch_size): + """ + This helper function computes a batch start and end index + :param batch_nb: the batch number + :param data_length: the total length of the data being parsed by batches + :param batch_size: the number of inputs in each batch + :return: pair of (start, end) indices + """ + # Batch start and end index + start = int(batch_nb * batch_size) + end = int((batch_nb + 1) * batch_size) + + # When there are not enough inputs left, we reuse some to complete the + # batch + if end > data_length: + shift = end - data_length + start -= shift + end -= shift + + return start, end + + +def other_classes(nb_classes, class_ind): + """ + Returns a list of class indices excluding the class indexed by class_ind + :param nb_classes: number of classes in the task + :param class_ind: the class index to be omitted + :return: list of class indices excluding the class indexed by class_ind + """ + if class_ind < 0 or class_ind >= nb_classes: + error_str = "class_ind must be within the range (0, nb_classes - 1)" + raise ValueError(error_str) + + other_classes_list = list(range(nb_classes)) + other_classes_list.remove(class_ind) + + return other_classes_list + + +def to_categorical(y, num_classes=None): + """ + Converts a class vector (integers) to binary class matrix. + This is adapted from the Keras function with the same name. + :param y: class vector to be converted into a matrix + (integers from 0 to num_classes). + :param num_classes: num_classes: total number of classes. + :return: A binary matrix representation of the input. + """ + y = np.array(y, dtype='int').ravel() + if not num_classes: + num_classes = np.max(y) + 1 + n = y.shape[0] + categorical = np.zeros((n, num_classes)) + categorical[np.arange(n), y] = 1 + return categorical + + +def random_targets(gt, nb_classes): + """ + Take in an array of correct labels and randomly select a different label + for each label in the array. This is typically used to randomly select a + target class in targeted adversarial examples attacks (i.e., when the + search algorithm takes in both a source class and target class to compute + the adversarial example). + :param gt: the ground truth (correct) labels. They can be provided as a + 1D vector or 2D array of one-hot encoded labels. + :param nb_classes: The number of classes for this task. The random class + will be chosen between 0 and nb_classes such that it + is different from the correct class. + :return: A numpy array holding the randomly-selected target classes + encoded as one-hot labels. + """ + # If the ground truth labels are encoded as one-hot, convert to labels. + if len(gt.shape) == 2: + gt = np.argmax(gt, axis=1) + + # This vector will hold the randomly selected labels. + result = np.zeros(gt.shape, dtype=np.int32) + + for class_ind in xrange(nb_classes): + # Compute all indices in that class. + in_cl = gt == class_ind + size = np.sum(in_cl) + + # Compute the set of potential targets for this class. + potential_targets = other_classes(nb_classes, class_ind) + + # Draw with replacement random targets among the potential targets. + result[in_cl] = np.random.choice(potential_targets, size=size) + + # Encode vector of random labels as one-hot labels. + result = to_categorical(result, nb_classes) + result = result.astype(np.int32) + + return result + + +def pair_visual(original, adversarial, figure=None): + """ + This function displays two images: the original and the adversarial sample + :param original: the original input + :param adversarial: the input after perterbations have been applied + :param figure: if we've already displayed images, use the same plot + :return: the matplot figure to reuse for future samples + """ + import matplotlib.pyplot as plt + + # Ensure our inputs are of proper shape + assert(len(original.shape) == 2 or len(original.shape) == 3) + + # To avoid creating figures per input sample, reuse the sample plot + if figure is None: + plt.ion() + figure = plt.figure() + figure.canvas.set_window_title('Cleverhans: Pair Visualization') + + # Add the images to the plot + perterbations = adversarial - original + for index, image in enumerate((original, perterbations, adversarial)): + figure.add_subplot(1, 3, index + 1) + plt.axis('off') + + # If the image is 2D, then we have 1 color channel + if len(image.shape) == 2: + plt.imshow(image, cmap='gray') + else: + plt.imshow(image) + + # Give the plot some time to update + plt.pause(0.01) + + # Draw the plot and return + plt.show() + return figure + + +def grid_visual(data): + """ + This function displays a grid of images to show full misclassification + :param data: grid data of the form; + [nb_classes : nb_classes : img_rows : img_cols : nb_channels] + :return: if necessary, the matplot figure to reuse + """ + import matplotlib.pyplot as plt + + # Ensure interactive mode is disabled and initialize our graph + plt.ioff() + figure = plt.figure() + figure.canvas.set_window_title('Cleverhans: Grid Visualization') + + # Add the images to the plot + num_cols = data.shape[0] + num_rows = data.shape[1] + num_channels = data.shape[4] + current_row = 0 + for y in xrange(num_rows): + for x in xrange(num_cols): + figure.add_subplot(num_rows, num_cols, (x + 1) + (y * num_cols)) + plt.axis('off') + + if num_channels == 1: + plt.imshow(data[x, y, :, :, 0], cmap='gray') + else: + plt.imshow(data[x, y, :, :, :]) + + # Draw the plot and return + plt.show() + return figure + + +def conv_2d(*args, **kwargs): + from modified_cleverhans.utils_keras import conv_2d + warnings.warn("utils.conv_2d is deprecated and may be removed on or after" + " 2018-01-05. Switch to utils_keras.conv_2d.") + return conv_2d(*args, **kwargs) + + +def cnn_model(*args, **kwargs): + from modified_cleverhans.utils_keras import cnn_model + warnings.warn("utils.cnn_model is deprecated and may be removed on or" + " after 2018-01-05. Switch to utils_keras.cnn_model.") + return cnn_model(*args, **kwargs) + + +def set_log_level(level, name="cleverhans"): + """ + Sets the threshold for the cleverhans logger to level + :param level: the logger threshold. You can find values here: + https://docs.python.org/2/library/logging.html#levels + :param name: the name used for the cleverhans logger + """ + logging.getLogger(name).setLevel(level) + + +def create_logger(name): + """ + Create a logger object with the given name. + + If this is the first time that we call this method, then initialize the + formatter. + """ + base = logging.getLogger("cleverhans") + if len(base.handlers) == 0: + ch = logging.StreamHandler() + formatter = logging.Formatter('[%(levelname)s %(asctime)s %(name)s] ' + + '%(message)s') + ch.setFormatter(formatter) + base.addHandler(ch) + + return base + + +def deterministic_dict(normal_dict): + """ + Returns a version of `normal_dict` whose iteration order is always the same + """ + out = OrderedDict() + for key in sorted(normal_dict.keys()): + out[key] = normal_dict[key] + return out + + +def parse_model_settings(model_path): + + tokens = model_path.split('/') + precision_list = ['bin', 'binsc', 'fp'] + precision = '' + start_index = 0 + adv = False + + for p in precision_list: + if p in tokens: + start_index = tokens.index(p) + precision = p + try: + nb_filters = int(tokens[start_index + 1].split('_')[1]) + batch_size = int(tokens[start_index + 2].split('_')[1]) + learning_rate = float(tokens[start_index + 3].split('_')[1]) + nb_epochs = int(tokens[start_index + 4].split('_')[1]) + + adv_index = start_index + 5 + if adv_index < len(tokens): + adv = True if 'adv' in tokens[adv_index] else False + + print("Got %s model" % precision) + print("Got %d filters" % nb_filters) + print("Got batch_size %d" % batch_size) + print("Got batch_size %f" % learning_rate) + print("Got %d epochs" % nb_epochs) + except: + print("Could not parse tokens!") + sys.exit(1) + + return nb_filters, batch_size, learning_rate, nb_epochs, adv + + +def build_model_save_path(root_path, batch_size, nb_filters, lr, epochs, adv, delay): + + model_path = os.path.join(root_path, precision) + model_path += 'k_' + str(nb_filters) + '/' + model_path += 'bs_' + str(batch_size) + '/' + model_path += 'lr_' + str(lr) + '/' + model_path += 'ep_' + str(epochs) + + if adv: + model_path += '/adv_%d' % delay + + # optionally create this dir if it does not already exist, + # otherwise, increment + model_path = create_dir_if_not_exists(model_path) + + return model_path + + +def create_dir_if_not_exists(path): + if not os.path.exists(path): + path += '/1' + os.makedirs(path) + else: + digits = [] + sub_dirs = next(os.walk(path))[1] + [digits.append(s) for s in sub_dirs if s.isdigit()] + sub = '/' + str(int(max(digits)) + 1) if len(digits) > 0 else '/1' + path += sub + os.makedirs(path) + print('Logging to:%s' % path) + return path + + +def build_targeted_dataset(X_test, Y_test, indices, nb_classes, img_rows, img_cols, img_channels): + """ + Build a dataset for targeted attacks, each source image is repeated nb_classes -1 + times, and target labels are assigned that do not overlap with true label. + :param X_test: clean source images + :param Y_test: true labels for X_test + :param indices: indices of source samples to use + :param nb_classes: number of classes in classification problem + :param img_rows: number of pixels along rows of image + :param img_cols: number of pixels along columns of image + """ + + nb_samples = len(indices) + nb_target_classes = nb_classes - 1 + X = X_test[indices] + Y = Y_test[indices] + + adv_inputs = np.array( + [[instance] * nb_target_classes for + instance in X], dtype=np.float32) + adv_inputs = adv_inputs.reshape( + (nb_samples * nb_target_classes, img_rows, img_cols, img_channels)) + + true_labels = np.array( + [[instance] * nb_target_classes for + instance in Y], dtype=np.float32) + true_labels = true_labels.reshape( + nb_samples * nb_target_classes, nb_classes) + + target_labels = np.zeros((nb_samples * nb_target_classes, nb_classes)) + + for n in range(nb_samples): + one_hot = np.zeros((nb_target_classes, nb_classes)) + one_hot[np.arange(nb_target_classes), np.arange(nb_classes) + != np.argmax(Y[n])] = 1.0 + start = n * nb_target_classes + end = start + nb_target_classes + target_labels[start:end] = one_hot + + return adv_inputs, true_labels, target_labels diff --git a/case_studies/empir/modified_cleverhans/utils_keras.py b/case_studies/empir/modified_cleverhans/utils_keras.py new file mode 100644 index 0000000..c6110ce --- /dev/null +++ b/case_studies/empir/modified_cleverhans/utils_keras.py @@ -0,0 +1,213 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Model construction utilities based on keras +""" +from .model import Model + +import keras +from keras.utils import np_utils +from keras.models import Sequential +from keras.layers import Dense, Activation, Flatten + +from distutils.version import LooseVersion +if LooseVersion(keras.__version__) >= LooseVersion('2.0.0'): + from keras.layers import Conv2D +else: + from keras.layers import Convolution2D + + +def conv_2d(filters, kernel_shape, strides, padding, input_shape=None): + """ + Defines the right convolutional layer according to the + version of Keras that is installed. + :param filters: (required integer) the dimensionality of the output + space (i.e. the number output of filters in the + convolution) + :param kernel_shape: (required tuple or list of 2 integers) specifies + the strides of the convolution along the width and + height. + :param padding: (required string) can be either 'valid' (no padding around + input or feature map) or 'same' (pad to ensure that the + output feature map size is identical to the layer input) + :param input_shape: (optional) give input shape if this is the first + layer of the model + :return: the Keras layer + """ + if LooseVersion(keras.__version__) >= LooseVersion('2.0.0'): + if input_shape is not None: + return Conv2D(filters=filters, kernel_size=kernel_shape, + strides=strides, padding=padding, + input_shape=input_shape) + else: + return Conv2D(filters=filters, kernel_size=kernel_shape, + strides=strides, padding=padding) + else: + if input_shape is not None: + return Convolution2D(filters, kernel_shape[0], kernel_shape[1], + subsample=strides, border_mode=padding, + input_shape=input_shape) + else: + return Convolution2D(filters, kernel_shape[0], kernel_shape[1], + subsample=strides, border_mode=padding) + + +def cnn_model(logits=False, input_ph=None, img_rows=28, img_cols=28, + channels=1, nb_filters=64, nb_classes=10): + """ + Defines a CNN model using Keras sequential model + :param logits: If set to False, returns a Keras model, otherwise will also + return logits tensor + :param input_ph: The TensorFlow tensor for the input + (needed if returning logits) + ("ph" stands for placeholder but it need not actually be a + placeholder) + :param img_rows: number of row in the image + :param img_cols: number of columns in the image + :param channels: number of color channels (e.g., 1 for MNIST) + :param nb_filters: number of convolutional filters per layer + :param nb_classes: the number of output classes + :return: + """ + model = Sequential() + + # Define the layers successively (convolution layers are version dependent) + if keras.backend.image_dim_ordering() == 'th': + input_shape = (channels, img_rows, img_cols) + else: + input_shape = (img_rows, img_cols, channels) + + layers = [conv_2d(nb_filters, (8, 8), (2, 2), "same", + input_shape=input_shape), + Activation('relu'), + conv_2d((nb_filters * 2), (6, 6), (2, 2), "valid"), + Activation('relu'), + conv_2d((nb_filters * 2), (5, 5), (1, 1), "valid"), + Activation('relu'), + Flatten(), + Dense(nb_classes)] + + for layer in layers: + model.add(layer) + + if logits: + logits_tensor = model(input_ph) + model.add(Activation('softmax')) + + if logits: + return model, logits_tensor + else: + return model + + +class KerasModelWrapper(Model): + """ + An implementation of `Model` that wraps a Keras model. It + specifically exposes the hidden features of a model by creating new models. + The symbolic graph is reused and so there is little overhead. Splitting + in-place operations can incur an overhead. + """ + + def __init__(self, model=None): + """ + Create a wrapper for a Keras model + :param model: A Keras model + """ + super(KerasModelWrapper, self).__init__() + + if model is None: + raise ValueError('model argument must be supplied.') + + self.model = model + self.keras_model = None + + def _get_softmax_name(self): + """ + Looks for the name of the softmax layer. + :return: Softmax layer name + """ + for i, layer in enumerate(self.model.layers): + cfg = layer.get_config() + if 'activation' in cfg and cfg['activation'] == 'softmax': + return layer.name + + raise Exception("No softmax layers found") + + def _get_logits_name(self): + """ + Looks for the name of the layer producing the logits. + :return: name of layer producing the logits + """ + softmax_name = self._get_softmax_name() + softmax_layer = self.model.get_layer(softmax_name) + node = softmax_layer.inbound_nodes[0] + logits_name = node.inbound_layers[0].name + + return logits_name + + def get_logits(self, x): + """ + :param x: A symbolic representation of the network input. + :return: A symbolic representation of the logits + """ + logits_name = self._get_logits_name() + + return self.get_layer(x, logits_name) + + def get_probs(self, x): + """ + :param x: A symbolic representation of the network input. + :return: A symbolic representation of the probs + """ + name = self._get_softmax_name() + + return self.get_layer(x, name) + + def get_layer_names(self): + """ + :return: Names of all the layers kept by Keras + """ + layer_names = [x.name for x in self.model.layers] + return layer_names + + def fprop(self, x): + """ + Exposes all the layers of the model returned by get_layer_names. + :param x: A symbolic representation of the network input + :return: A dictionary mapping layer names to the symbolic + representation of their output. + """ + from keras.models import Model as KerasModel + + if self.keras_model is None: + # Get the input layer + new_input = self.model.get_input_at(0) + + # Make a new model that returns each of the layers as output + out_layers = [x_layer.output for x_layer in self.model.layers] + self.keras_model = KerasModel(new_input, out_layers) + + # and get the outputs for that model on the input x + outputs = self.keras_model(x) + + # Keras only returns a list for outputs of length >= 1, if the model + # is only one layer, wrap a list + if len(self.model.layers) == 1: + outputs = [outputs] + + # compute the dict to return + fprop_dict = dict(zip(self.get_layer_names(), outputs)) + + return fprop_dict diff --git a/case_studies/empir/modified_cleverhans/utils_mnist.py b/case_studies/empir/modified_cleverhans/utils_mnist.py new file mode 100644 index 0000000..6f3219a --- /dev/null +++ b/case_studies/empir/modified_cleverhans/utils_mnist.py @@ -0,0 +1,87 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import numpy as np +import sys +import warnings + +from . import utils + + +def data_mnist(datadir='/tmp/', train_start=0, train_end=60000, test_start=0, + test_end=10000): + """ + Load and preprocess MNIST dataset + :param datadir: path to folder where data should be stored + :param train_start: index of first training set example + :param train_end: index of last training set example + :param test_start: index of first test set example + :param test_end: index of last test set example + :return: tuple of four arrays containing training data, training labels, + testing data and testing labels. + """ + assert isinstance(train_start, int) + assert isinstance(train_end, int) + assert isinstance(test_start, int) + assert isinstance(test_end, int) + + if 'tensorflow' in sys.modules: + from tensorflow.examples.tutorials.mnist import input_data + mnist = input_data.read_data_sets(datadir, one_hot=True, reshape=False) + X_train = np.vstack((mnist.train.images, mnist.validation.images)) + Y_train = np.vstack((mnist.train.labels, mnist.validation.labels)) + X_test = mnist.test.images + Y_test = mnist.test.labels + else: + warnings.warn("CleverHans support for Theano is deprecated and " + "will be dropped on 2017-11-08.") + import keras + from keras.datasets import mnist + from keras.utils import np_utils + + # These values are specific to MNIST + img_rows = 28 + img_cols = 28 + nb_classes = 10 + + # the data, shuffled and split between train and test sets + (X_train, y_train), (X_test, y_test) = mnist.load_data() + + if keras.backend.image_dim_ordering() == 'th': + X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols) + X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols) + + X_train = X_train.astype('float32') + X_test = X_test.astype('float32') + X_train /= 255 + X_test /= 255 + + # convert class vectors to binary class matrices + Y_train = np_utils.to_categorical(y_train, nb_classes) + Y_test = np_utils.to_categorical(y_test, nb_classes) + + X_train = X_train[train_start:train_end] + Y_train = Y_train[train_start:train_end] + X_test = X_test[test_start:test_end] + Y_test = Y_test[test_start:test_end] + + print('X_train shape:', X_train.shape) + print('X_test shape:', X_test.shape) + + return X_train, Y_train, X_test, Y_test diff --git a/case_studies/empir/modified_cleverhans/utils_tf.py b/case_studies/empir/modified_cleverhans/utils_tf.py new file mode 100644 index 0000000..009db6a --- /dev/null +++ b/case_studies/empir/modified_cleverhans/utils_tf.py @@ -0,0 +1,1578 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from distutils.version import LooseVersion +import math +import numpy as np +import os +from six.moves import xrange +import tensorflow as tf +import time +import warnings +import logging + +from .utils import batch_indices, _ArgsWrapper, create_logger, set_log_level + +FLAGS = tf.app.flags.FLAGS + +_logger = create_logger("cleverhans.utils.tf") + + +class _FlagsWrapper(_ArgsWrapper): + + """ + Wrapper that tries to find missing parameters in TensorFlow FLAGS + for backwards compatibility. + + Plain _ArgsWrapper should be used instead if the support for FLAGS + is removed. + """ + + def __getattr__(self, name): + val = self.args.get(name) + if val is None: + warnings.warn('Setting parameters ({}) from TensorFlow FLAGS is ' + 'deprecated.'.format(name)) + val = FLAGS.__getattr__(name) + return val + + +def model_loss(y, model, mean=True): + """ + Define loss of TF graph + :param y: correct labels + :param model: output of the model + :param mean: boolean indicating whether should return mean of loss + or vector of losses for each input of the batch + :return: return mean of loss if True, otherwise return vector with per + sample loss + """ + op = model.op + if "softmax" in str(op).lower(): + logits, = op.inputs + else: + logits = model + + out = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y) + + if mean: + out = tf.reduce_mean(out) + return out + + +def initialize_uninitialized_global_variables(sess): + """ + Only initializes the variables of a TensorFlow session that were not + already initialized. + :param sess: the TensorFlow session + :return: + """ + # List all global variables + global_vars = tf.global_variables() + + # Find initialized status for all variables + is_var_init = [tf.is_variable_initialized(var) for var in global_vars] + is_initialized = sess.run(is_var_init) + + # List all variables that were not initialized previously + not_initialized_vars = [var for (var, init) in + zip(global_vars, is_initialized) if not init] + + # Initialize all uninitialized variables found, if any + if len(not_initialized_vars): + sess.run(tf.variables_initializer(not_initialized_vars)) + + +def sign_changes_count_op(prv_k, k): + + print(k) + print(prv_k) + return tf.cast(np.product(k.shape[:]), tf.int32) - tf.reduce_sum( + tf.cast(tf.equal(prv_k, k), tf.int32)) + + +def normalized_sign_changes_op(prv_k, k): + + return 1.0 - tf.reduce_sum(tf.cast(tf.equal( + prv_k, k), tf.float32)) / tf.cast(np.product(k.shape[:]), tf.float32) + + +def create_kernel_placeholder(model, i): + + return tf.placeholder( + tf.float32, [model.layers[i].kernels.shape[0], model.layers[i].kernels.shape[1], + model.layers[i].kernels.shape[2], model.layers[i].kernels.shape[3]]) + + +def model_train(sess, x, y, predictions, X_train, Y_train, model=None, phase=None, + writer=None, save=False, predictions_adv=None, init_all=False, + evaluate=None, verbose=True, feed=None, args=None, rng=None): + """ + Train a TF graph + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_train: numpy array with training inputs + :param Y_train: numpy array with training outputs + :param save: boolean controlling the save operation + :param predictions_adv: if set with the adversarial example tensor, + will run adversarial training + :param init_all: (boolean) If set to true, all TF variables in the session + are (re)initialized, otherwise only previously + uninitialized variables are initialized before training. + :param evaluate: function that is run after each training iteration + (typically to display the test/validation accuracy). + :param verbose: (boolean) all print statements disabled when set to False. + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `nb_epochs`, `learning_rate`, + `batch_size` + If save is True, should also contain 'log_dir' + and 'filename' + :param rng: Instance of numpy.random.RandomState + :return: True if model trained + """ + args = _FlagsWrapper(args or {}) + + # Check that necessary arguments were given (see doc above) + assert args.nb_epochs, "Number of epochs was not given in args dict" + assert args.learning_rate, "Learning rate was not given in args dict" + assert args.batch_size, "Batch size was not given in args dict" + + if save: + assert args.log_dir, "Directory for save was not given in args dict" + assert args.filename, "Filename for save was not given in args dict" + + if not verbose: + set_log_level(logging.WARNING) + warnings.warn("verbose argument is deprecated and will be removed" + " on 2018-02-11. Instead, use utils.set_log_level()." + " For backward compatibility, log_level was set to" + " logging.WARNING (30).") + + if rng is None: + rng = np.random.RandomState() + + # Define loss + loss = model_loss(y, predictions) + if predictions_adv is not None: + loss = (loss + model_loss(y, predictions_adv)) / 2 + + with tf.variable_scope(args.train_scope, reuse=args.reuse_global_step): + global_step = tf.get_variable( + "global_step", dtype=tf.int32, initializer=tf.constant(0), trainable=False) + + train_step = tf.train.AdamOptimizer(learning_rate=args.learning_rate) + train_step = train_step.minimize(loss) + + if writer is not None: + + assert args.loss_name, "Name of scalar summary loss" + training_summary = tf.summary.scalar(args.loss_name, loss) + merge_op = tf.summary.merge_all() + + with sess.as_default(): + if hasattr(tf, "global_variables_initializer"): + if init_all: + tf.global_variables_initializer().run() + else: + initialize_uninitialized_global_variables(sess) + else: + warnings.warn("Update your copy of tensorflow; future versions of " + "CleverHans may drop support for this version.") + sess.run(tf.initialize_all_variables()) + + init_step = sess.run(global_step) + + for epoch in xrange(args.nb_epochs): + # Compute number of batches + nb_batches = int(math.ceil(float(len(X_train)) / args.batch_size)) + assert nb_batches * args.batch_size >= len(X_train) + + # Indices to shuffle training set + index_shuf = list(range(len(X_train))) + rng.shuffle(index_shuf) + + prev = time.time() + for batch in range(nb_batches): + + step = init_step + (epoch * nb_batches + batch) + + # Compute batch start and end indices + start, end = batch_indices( + batch, len(X_train), args.batch_size) + + # Perform one training step + feed_dict = {x: X_train[index_shuf[start:end]], + y: Y_train[index_shuf[start:end]], + phase: args.is_training} + if feed is not None: + feed_dict.update(feed) + sess.run(train_step, feed_dict=feed_dict) + + if batch % 100 == 0: + if writer is not None: + loss_val, merged_summ = sess.run( + [loss, merge_op], feed_dict=feed_dict) + writer.add_summary(merged_summ, step) + writer.flush() + else: + loss_val = sess.run(loss, feed_dict=feed_dict) + + #print('epoch %d, batch %d, step %d, loss %.4f' % + # (epoch, batch, step, loss_val)) + + assert end >= len(X_train) # Check that all examples were used + cur = time.time() + if verbose: + _logger.info("Epoch " + str(epoch) + " took " + + str(cur - prev) + " seconds") + if evaluate is not None: + evaluate() + #global_step = step + if save: + save_path = os.path.join(args.log_dir, args.filename) + #save_path = args.log_dir + saver = tf.train.Saver() + if not os.path.exists(args.log_dir): + os.makedirs(args.log_dir) + saver.save(sess, save_path, global_step=step) + _logger.info("Completed model training and saved at: " + + str(save_path)) + else: + _logger.info("Completed model training.") + + return True + +# Variation of model_train for the teacher model in distillation +def model_train_teacher(sess, x, y, predictions, logits, temperature, X_train, Y_train, model=None, phase=None, + writer=None, save=False, predictions_adv=None, init_all=False, + evaluate=None, verbose=True, feed=None, args=None, rng=None): + """ + Train a TF graph + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_train: numpy array with training inputs + :param Y_train: numpy array with training outputs + :param save: boolean controlling the save operation + :param predictions_adv: if set with the adversarial example tensor, + will run adversarial training + :param init_all: (boolean) If set to true, all TF variables in the session + are (re)initialized, otherwise only previously + uninitialized variables are initialized before training. + :param evaluate: function that is run after each training iteration + (typically to display the test/validation accuracy). + :param verbose: (boolean) all print statements disabled when set to False. + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `nb_epochs`, `learning_rate`, + `batch_size` + If save is True, should also contain 'log_dir' + and 'filename' + :param rng: Instance of numpy.random.RandomState + :return: True if model trained + """ + args = _FlagsWrapper(args or {}) + + # Check that necessary arguments were given (see doc above) + assert args.nb_epochs, "Number of epochs was not given in args dict" + assert args.learning_rate, "Learning rate was not given in args dict" + assert args.batch_size, "Batch size was not given in args dict" + + if save: + assert args.log_dir, "Directory for save was not given in args dict" + assert args.filename, "Filename for save was not given in args dict" + + if not verbose: + set_log_level(logging.WARNING) + warnings.warn("verbose argument is deprecated and will be removed" + " on 2018-02-11. Instead, use utils.set_log_level()." + " For backward compatibility, log_level was set to" + " logging.WARNING (30).") + + if rng is None: + rng = np.random.RandomState() + + # Define loss + # loss = model_loss(y, predictions) + loss = model_loss_temp(y, predictions, temperature) + if predictions_adv is not None: + loss = (loss + model_loss(y, predictions_adv)) / 2 + + with tf.variable_scope(args.train_scope, reuse=args.reuse_global_step): + teacher_global_step = tf.get_variable( + "teacher_global_step", dtype=tf.int32, initializer=tf.constant(0), trainable=False) + + train_step = tf.train.AdamOptimizer(learning_rate=args.learning_rate) + train_step = train_step.minimize(loss) + + scaled_preds = tf.nn.softmax(logits / temperature) + scaled_preds_train = np.zeros([len(X_train), np.size(Y_train, 1)]) + + if writer is not None: + + assert args.loss_name, "Name of scalar summary loss" + training_summary = tf.summary.scalar(args.loss_name, loss) + merge_op = tf.summary.merge_all() + + with sess.as_default(): + if hasattr(tf, "global_variables_initializer"): + if init_all: + tf.global_variables_initializer().run() + else: + initialize_uninitialized_global_variables(sess) + else: + warnings.warn("Update your copy of tensorflow; future versions of " + "CleverHans may drop support for this version.") + sess.run(tf.initialize_all_variables()) + + init_step = sess.run(teacher_global_step) + + for epoch in xrange(args.nb_epochs): + # Compute number of batches + nb_batches = int(math.ceil(float(len(X_train)) / args.batch_size)) + assert nb_batches * args.batch_size >= len(X_train) + + # Indices to shuffle training set + index_shuf = list(range(len(X_train))) + rng.shuffle(index_shuf) + + prev = time.time() + for batch in range(nb_batches): + + step = init_step + (epoch * nb_batches + batch) + + # Compute batch start and end indices + start, end = batch_indices( + batch, len(X_train), args.batch_size) + + # Perform one training step + feed_dict = {x: X_train[index_shuf[start:end]], + y: Y_train[index_shuf[start:end]], + phase: args.is_training} + if feed is not None: + feed_dict.update(feed) + sess.run(train_step, feed_dict=feed_dict) + if epoch == args.nb_epochs - 1: + scaled_predicted = sess.run(scaled_preds, feed_dict=feed_dict) + scaled_preds_train[start:end] = scaled_predicted + + if batch % 100 == 0: + if writer is not None: + loss_val, merged_summ = sess.run( + [loss, merge_op], feed_dict=feed_dict) + writer.add_summary(merged_summ, step) + writer.flush() + else: + loss_val = sess.run(loss, feed_dict=feed_dict) + + #print('epoch %d, batch %d, step %d, loss %.4f' % + # (epoch, batch, step, loss_val)) + + assert end >= len(X_train) # Check that all examples were used + cur = time.time() + if verbose: + _logger.info("Epoch " + str(epoch) + " took " + + str(cur - prev) + " seconds") + if evaluate is not None: + evaluate() + #teacher_global_step = step + if save: + save_path = os.path.join(args.log_dir, args.filename) + #save_path = args.log_dir + saver = tf.train.Saver() + if not os.path.exists(args.log_dir): + os.makedirs(args.log_dir) + saver.save(sess, save_path, global_step=step) + _logger.info("Completed model training and saved at: " + + str(save_path)) + else: + _logger.info("Completed model training.") + + return scaled_preds_train + +# Modified version of model_train for model loss calculation with a different temperature +def model_train_student(sess, x, y, predictions, temperature, X_train, Y_train, y_teacher=None, + teacher_preds=None, alpha=0.5, beta=0.5, model=None, phase=None, writer=None, save=False, + predictions_adv=None, init_all=False, evaluate=None, verbose=True, feed=None, args=None, rng=None): + """ + Train a TF graph + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_train: numpy array with training inputs + :param Y_train: numpy array with training outputs + :param save: boolean controlling the save operation + :param predictions_adv: if set with the adversarial example tensor, + will run adversarial training + :param init_all: (boolean) If set to true, all TF variables in the session + are (re)initialized, otherwise only previously + uninitialized variables are initialized before training. + :param evaluate: function that is run after each training iteration + (typically to display the test/validation accuracy). + :param verbose: (boolean) all print statements disabled when set to False. + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `nb_epochs`, `learning_rate`, + `batch_size` + If save is True, should also contain 'log_dir' + and 'filename' + :param rng: Instance of numpy.random.RandomState + :return: True if model trained + """ + args = _FlagsWrapper(args or {}) + + # Check that necessary arguments were given (see doc above) + assert args.nb_epochs, "Number of epochs was not given in args dict" + assert args.learning_rate, "Learning rate was not given in args dict" + assert args.batch_size, "Batch size was not given in args dict" + + if save: + assert args.log_dir, "Directory for save was not given in args dict" + assert args.filename, "Filename for save was not given in args dict" + + if not verbose: + set_log_level(logging.WARNING) + warnings.warn("verbose argument is deprecated and will be removed" + " on 2018-02-11. Instead, use utils.set_log_level()." + " For backward compatibility, log_level was set to" + " logging.WARNING (30).") + + if rng is None: + rng = np.random.RandomState() + + # Define loss + # Incorporating both hard and soft labels for training + if y_teacher is not None: + loss = alpha*model_loss(y, predictions) + beta*model_loss_temp(y_teacher, predictions, temperature) + else: + loss = model_loss(y, predictions) + + with tf.variable_scope(args.train_scope, reuse=args.reuse_global_step): + global_step = tf.get_variable( + "global_step", dtype=tf.int32, initializer=tf.constant(0), trainable=False) + + train_step = tf.train.AdamOptimizer(learning_rate=args.learning_rate) + train_step = train_step.minimize(loss) + + if writer is not None: + assert args.loss_name, "Name of scalar summary loss" + training_summary = tf.summary.scalar(args.loss_name, loss) + merge_op = tf.summary.merge_all() + + with sess.as_default(): + if hasattr(tf, "global_variables_initializer"): + if init_all: + tf.global_variables_initializer().run() + else: + initialize_uninitialized_global_variables(sess) + else: + warnings.warn("Update your copy of tensorflow; future versions of " + "CleverHans may drop support for this version.") + sess.run(tf.initialize_all_variables()) + + init_step = sess.run(global_step) + + for epoch in xrange(args.nb_epochs): + # Compute number of batches + nb_batches = int(math.ceil(float(len(X_train)) / args.batch_size)) + assert nb_batches * args.batch_size >= len(X_train) + + # Indices to shuffle training set + index_shuf = list(range(len(X_train))) + rng.shuffle(index_shuf) + + prev = time.time() + for batch in range(nb_batches): + + step = init_step + (epoch * nb_batches + batch) + + # Compute batch start and end indices + start, end = batch_indices( + batch, len(X_train), args.batch_size) + + # Perform one training step + feed_dict = {x: X_train[index_shuf[start:end]], + y: Y_train[index_shuf[start:end]], + y_teacher: teacher_preds[index_shuf[start:end]], + phase: args.is_training} + if feed is not None: + feed_dict.update(feed) + sess.run(train_step, feed_dict=feed_dict) + + if batch % 100 == 0: + if writer is not None: + loss_val, merged_summ = sess.run( + [loss, merge_op], feed_dict=feed_dict) + writer.add_summary(merged_summ, step) + writer.flush() + else: + loss_val = sess.run(loss, feed_dict=feed_dict) + + #print('epoch %d, batch %d, step %d, loss %.4f' % + # (epoch, batch, step, loss_val)) + + assert end >= len(X_train) # Check that all examples were used + cur = time.time() + if verbose: + _logger.info("Epoch " + str(epoch) + " took " + + str(cur - prev) + " seconds") + if evaluate is not None: + evaluate() + #global_step = step + if save: + save_path = os.path.join(args.log_dir, args.filename) + #save_path = args.log_dir + saver = tf.train.Saver() + if not os.path.exists(args.log_dir): + os.makedirs(args.log_dir) + saver.save(sess, save_path, global_step=step) + _logger.info("Completed model training and saved at: " + + str(save_path)) + else: + _logger.info("Completed model training.") + + return True + +def model_train_inpgrad_reg(sess, x, y, predictions, X_train, Y_train, model=None, phase=None, + writer=None, save=False, predictions_adv=None, init_all=False, + evaluate=None, l2dbl = 0, l2cs = 0, verbose=True, feed=None, args=None, rng=None): + """ + Train a TF graph + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_train: numpy array with training inputs + :param Y_train: numpy array with training outputs + :param save: boolean controlling the save operation + :param predictions_adv: if set with the adversarial example tensor, + will run adversarial training + :param init_all: (boolean) If set to true, all TF variables in the session + are (re)initialized, otherwise only previously + uninitialized variables are initialized before training. + :param evaluate: function that is run after each training iteration + (typically to display the test/validation accuracy). + :param verbose: (boolean) all print statements disabled when set to False. + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `nb_epochs`, `learning_rate`, + `batch_size` + If save is True, should also contain 'log_dir' + and 'filename' + :param rng: Instance of numpy.random.RandomState + :return: True if model trained + """ + args = _FlagsWrapper(args or {}) + + # Check that necessary arguments were given (see doc above) + assert args.nb_epochs, "Number of epochs was not given in args dict" + assert args.learning_rate, "Learning rate was not given in args dict" + assert args.batch_size, "Batch size was not given in args dict" + + if save: + assert args.log_dir, "Directory for save was not given in args dict" + assert args.filename, "Filename for save was not given in args dict" + + if not verbose: + set_log_level(logging.WARNING) + warnings.warn("verbose argument is deprecated and will be removed" + " on 2018-02-11. Instead, use utils.set_log_level()." + " For backward compatibility, log_level was set to" + " logging.WARNING (30).") + + if rng is None: + rng = np.random.RandomState() + + # Define loss + loss = model_loss(y, predictions) + model_loss_inpgrad_reg(x, y, predictions, l2dbl, l2cs) + if predictions_adv is not None: + loss = (loss + model_loss(x, y, predictions_adv)) / 2 + + with tf.variable_scope(args.train_scope, reuse=args.reuse_global_step): + global_step = tf.get_variable( + "global_step", dtype=tf.int32, initializer=tf.constant(0), trainable=False) + + train_step = tf.train.AdamOptimizer(learning_rate=args.learning_rate) + train_step = train_step.minimize(loss) + + if writer is not None: + assert args.loss_name, "Name of scalar summary loss" + training_summary = tf.summary.scalar(args.loss_name, loss) + merge_op = tf.summary.merge_all() + + with sess.as_default(): + if hasattr(tf, "global_variables_initializer"): + if init_all: + tf.global_variables_initializer().run() + else: + initialize_uninitialized_global_variables(sess) + else: + warnings.warn("Update your copy of tensorflow; future versions of " + "CleverHans may drop support for this version.") + sess.run(tf.initialize_all_variables()) + + init_step = sess.run(global_step) + + for epoch in xrange(args.nb_epochs): + # Compute number of batches + nb_batches = int(math.ceil(float(len(X_train)) / args.batch_size)) + assert nb_batches * args.batch_size >= len(X_train) + + # Indices to shuffle training set + index_shuf = list(range(len(X_train))) + rng.shuffle(index_shuf) + + prev = time.time() + for batch in range(nb_batches): + + step = init_step + (epoch * nb_batches + batch) + + # Compute batch start and end indices + start, end = batch_indices( + batch, len(X_train), args.batch_size) + + # Perform one training step + feed_dict = {x: X_train[index_shuf[start:end]], + y: Y_train[index_shuf[start:end]], + phase: args.is_training} + if feed is not None: + feed_dict.update(feed) + sess.run(train_step, feed_dict=feed_dict) + + if batch % 100 == 0: + if writer is not None: + loss_val, merged_summ = sess.run( + [loss, merge_op], feed_dict=feed_dict) + writer.add_summary(merged_summ, step) + writer.flush() + else: + loss_val = sess.run(loss, feed_dict=feed_dict) + + #print('epoch %d, batch %d, step %d, loss %.4f' % + # (epoch, batch, step, loss_val)) + + assert end >= len(X_train) # Check that all examples were used + cur = time.time() + if verbose: + _logger.info("Epoch " + str(epoch) + " took " + + str(cur - prev) + " seconds") + if evaluate is not None: + evaluate() + #global_step = step + if save: + save_path = os.path.join(args.log_dir, args.filename) + #save_path = args.log_dir + saver = tf.train.Saver() + if not os.path.exists(args.log_dir): + os.makedirs(args.log_dir) + saver.save(sess, save_path, global_step=step) + _logger.info("Completed model training and saved at: " + + str(save_path)) + else: + _logger.info("Completed model training.") + + return True + +# Imagenet training +def model_train_imagenet(sess, x, y, predictions, train_iterator, X_train, Y_train, model=None, phase=None, + writer=None, save=False, predictions_adv=None, init_all=False, + evaluate=None, verbose=True, feed=None, args=None, rng=None): + """ + Train a TF graph + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_train: numpy array with training inputs + :param Y_train: numpy array with training outputs + :param save: boolean controlling the save operation + :param predictions_adv: if set with the adversarial example tensor, + will run adversarial training + :param init_all: (boolean) If set to true, all TF variables in the session + are (re)initialized, otherwise only previously + uninitialized variables are initialized before training. + :param evaluate: function that is run after each training iteration + (typically to display the test/validation accuracy). + :param verbose: (boolean) all print statements disabled when set to False. + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `nb_epochs`, `learning_rate`, + `batch_size` + If save is True, should also contain 'log_dir' + and 'filename' + :param rng: Instance of numpy.random.RandomState + :return: True if model trained + """ + args = _FlagsWrapper(args or {}) + + # Check that necessary arguments were given (see doc above) + assert args.nb_epochs, "Number of epochs was not given in args dict" + assert args.learning_rate, "Learning rate was not given in args dict" + assert args.batch_size, "Batch size was not given in args dict" + + if save: + assert args.log_dir, "Directory for save was not given in args dict" + assert args.filename, "Filename for save was not given in args dict" + + if not verbose: + set_log_level(logging.WARNING) + warnings.warn("verbose argument is deprecated and will be removed" + " on 2018-02-11. Instead, use utils.set_log_level()." + " For backward compatibility, log_level was set to" + " logging.WARNING (30).") + + if rng is None: + rng = np.random.RandomState() + + # Define loss + loss = model_loss(y, predictions) + if predictions_adv is not None: + loss = (loss + model_loss(y, predictions_adv)) / 2 + + with tf.variable_scope(args.train_scope, reuse=args.reuse_global_step): + global_step = tf.get_variable( + "global_step", dtype=tf.int32, initializer=tf.constant(0), trainable=False) + learning_rate_tensor = tf.placeholder(tf.float32, shape=[]) + + if args.lowprecision: + update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) + with tf.control_dependencies(update_ops): + train_step = tf.train.AdamOptimizer(learning_rate=learning_rate_tensor, epsilon=1e-5) #Copied epsilon from dorefanet + train_step = train_step.minimize(loss) + # Find the batch norm variables + all_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) + batch_vars = [var for var in all_vars if ('batchNorm' in var.name) and (('moving_mean' in var.name) or ('moving_variance' in var.name))] # Gives the moving mean and moving vaiance variables which are not part of trainable variables but have to be restored + save_vars = tf.trainable_variables() + batch_vars# Declare save variable to have both batch norm and other trainable variables + else: + train_step = tf.train.AdamOptimizer(learning_rate=learning_rate_tensor, epsilon=1e-5) #Copied epsilon from dorefanet + train_step = train_step.minimize(loss) + + if writer is not None: + assert args.loss_name, "Name of scalar summary loss" + training_summary = tf.summary.scalar(args.loss_name, loss) + merge_op = tf.summary.merge_all() + + with sess.as_default(): + if hasattr(tf, "global_variables_initializer"): + if init_all: + tf.global_variables_initializer().run() + else: + initialize_uninitialized_global_variables(sess) + else: + warnings.warn("Update your copy of tensorflow; future versions of " + "CleverHans may drop support for this version.") + sess.run(tf.initialize_all_variables()) + + init_step = sess.run(global_step) + step = init_step + + for epoch in xrange(args.nb_epochs): + prev = time.time() + + # Initialize the iterator + sess.run(train_iterator.initializer) + + if args.lowprecision: + if (epoch == 60): + args.learning_rate = 4e-5 + if (epoch == 75): + args.learning_rate = 8e-6 + else: # for FP models decreasing lr after different number of epochs based on tensorpack model + if (epoch == 30) or (epoch == 60) or (epoch == 80): + args.learning_rate = args.learning_rate/10 + + # Try feeding new values till end + num_batches = 0 + try: + while True: + # Perform one training epoch + X_array, Y_array = sess.run([X_train, Y_train]) # Get np arrays of X and Y + feed_dict = {x: X_array, + y: Y_array, + phase: args.is_training, + learning_rate_tensor: args.learning_rate} + + sess.run(train_step, feed_dict=feed_dict) + loss_val = sess.run(loss, feed_dict=feed_dict) + num_batches = num_batches+1 + + except tf.errors.OutOfRangeError: + pass + print('epoch %d, loss %.4f' % + (epoch, loss_val)) + + cur = time.time() + if verbose: + _logger.info("Epoch " + str(epoch) + " took " + + str(cur - prev) + " seconds") + if evaluate is not None: + evaluate() + step = step + num_batches # Training steps in batches + # save every 10 epochs + if save and (epoch % 10 == 0): + save_path = os.path.join(args.log_dir, args.filename) + #save_path = args.log_dir + if args.lowprecision: # The batch norm variables also need to be saved + saver = tf.train.Saver(save_vars) + else: + saver = tf.train.Saver() + if not os.path.exists(args.log_dir): + os.makedirs(args.log_dir) + saver.save(sess, save_path, global_step=step) + _logger.info("Completed model training and saved at: " + + str(save_path)) + # Save at the end as well + if save: + save_path = os.path.join(args.log_dir, args.filename) + #save_path = args.log_dir + if args.lowprecision: # The batch norm variables also need to be saved + saver = tf.train.Saver(save_vars) + else: + saver = tf.train.Saver() + if not os.path.exists(args.log_dir): + os.makedirs(args.log_dir) + saver.save(sess, save_path, global_step=step) + _logger.info("Completed model training and saved at: " + + str(save_path)) + else: + _logger.info("Completed model training.") + + return True + +def model_eval(sess, x, y, predictions=None, X_test=None, Y_test=None, phase=None, writer=None, + feed=None, args=None, model=None): + """ + Compute the accuracy of a TF model on some data + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_test: numpy array with training inputs + :param Y_test: numpy array with training outputs + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `batch_size` + :param model: (deprecated) if not None, holds model output predictions + :return: a float with the accuracy value + """ + args = _FlagsWrapper(args or {}) + + assert args.batch_size, "Batch size was not given in args dict" + if X_test is None or Y_test is None: + raise ValueError("X_test argument and Y_test argument " + "must be supplied.") + if model is None and predictions is None: + raise ValueError("One of model argument " + "or predictions argument must be supplied.") + if model is not None: + warnings.warn("model argument is deprecated. " + "Switch to predictions argument. " + "model argument will be removed after 2018-01-05.") + if predictions is None: + predictions = model + else: + raise ValueError("Exactly one of model argument" + " and predictions argument should be specified.") + + # Define accuracy symbolically + if LooseVersion(tf.__version__) >= LooseVersion('1.0.0'): + correct_preds = tf.equal(tf.argmax(y, axis=-1), + tf.argmax(predictions, axis=-1)) + else: + correct_preds = tf.equal(tf.argmax(y, axis=tf.rank(y) - 1), + tf.argmax(predictions, + axis=tf.rank(predictions) - 1)) + + acc_value = tf.reduce_mean(tf.to_float(correct_preds)) + + # Init result var + accuracy = 0.0 + + if writer is not None: + eval_summary = tf.summary.scalar('acc', acc_value) + + with sess.as_default(): + + # Compute number of batches + nb_batches = int(math.ceil(float(len(X_test)) / args.batch_size)) + assert nb_batches * args.batch_size >= len(X_test) + + for batch in range(nb_batches): + if batch % 100 == 0 and batch > 0: + _logger.debug("Batch " + str(batch)) + + # Must not use the `batch_indices` function here, because it + # repeats some examples. + # It's acceptable to repeat during training, but not eval. + start = batch * args.batch_size + end = min(len(X_test), start + args.batch_size) + cur_batch_size = end - start + + # The last batch may be smaller than all others, so we need to + # account for variable batch size here + feed_dict = {x: X_test[start:end], + y: Y_test[start:end], + phase: False} + if feed is not None: + feed_dict.update(feed) + + if writer is not None: + cur_acc, eval_summ = sess.run( + [acc_value, eval_summary], feed_dict=feed_dict) + writer.add_summary(eval_summ, batch) + writer.flush() + else: + cur_acc = acc_value.eval(feed_dict=feed_dict) + accuracy += (cur_batch_size * cur_acc) + + assert end >= len(X_test) + + # Divide by number of examples to get final value + accuracy /= len(X_test) + + return accuracy + + +def model_eval_ensemble(sess, x, y, predictions=None, X_test=None, Y_test=None, phase=None, writer=None, + feed=None, args=None, model=None): + """ + Compute the accuracy of a TF model on some data + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_test: numpy array with training inputs + :param Y_test: numpy array with training outputs + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `batch_size` + :param model: (deprecated) if not None, holds model output predictions + :return: a float with the accuracy value + """ + args = _FlagsWrapper(args or {}) + + assert args.batch_size, "Batch size was not given in args dict" + if X_test is None or Y_test is None: + raise ValueError("X_test argument and Y_test argument " + "must be supplied.") + if model is None and (predictions is None): + raise ValueError("One of model argument " + "or both predictions argument must be supplied.") + if model is not None: + warnings.warn("model argument is deprecated. " + "Switch to predictions argument. " + "model argument will be removed after 2018-01-05.") + if predictions is None: + predictions = model + else: + raise ValueError("Exactly one of model argument" + " and predictions argument should be specified.") + + # Define accuracy symbolically + if LooseVersion(tf.__version__) >= LooseVersion('1.0.0'): + correct_preds = tf.equal(tf.argmax(y, axis=-1), + predictions) + else: + correct_preds = tf.equal(tf.argmax(y, axis=tf.rank(y) - 1), + predictions) + + acc_value = tf.reduce_mean(tf.to_float(correct_preds)) + + # Init result var + accuracy = 0.0 + + if writer is not None: + eval_summary = tf.summary.scalar('acc', acc_value) + + with sess.as_default(): + + # Compute number of batches + nb_batches = int(math.ceil(float(len(X_test)) / args.batch_size)) + assert nb_batches * args.batch_size >= len(X_test) + + for batch in range(nb_batches): + if batch % 100 == 0 and batch > 0: + _logger.debug("Batch " + str(batch)) + + # Must not use the `batch_indices` function here, because it + # repeats some examples. + # It's acceptable to repeat during training, but not eval. + start = batch * args.batch_size + end = min(len(X_test), start + args.batch_size) + cur_batch_size = end - start + + # The last batch may be smaller than all others, so we need to + # account for variable batch size here + feed_dict = {x: X_test[start:end], + y: Y_test[start:end], + phase: False} + if feed is not None: + feed_dict.update(feed) + + if writer is not None: + cur_acc, eval_summ = sess.run( + [acc_value, eval_summary], feed_dict=feed_dict) + writer.add_summary(eval_summ, batch) + writer.flush() + else: + cur_acc = acc_value.eval(feed_dict=feed_dict) + accuracy += (cur_batch_size * cur_acc) + + assert end >= len(X_test) + + # Divide by number of examples to get final value + accuracy /= len(X_test) + + return accuracy + +def model_eval_imagenet(sess, x, y, predictions=None, test_iterator=None, X_test=None, Y_test=None, phase=None, writer=None, + feed=None, args=None, model=None): + """ + Compute the accuracy of a TF model on some data + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_test: numpy array with training inputs + :param Y_test: numpy array with training outputs + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `batch_size` + :param model: (deprecated) if not None, holds model output predictions + :return: a float with the accuracy value + """ + args = _FlagsWrapper(args or {}) + + assert args.batch_size, "Batch size was not given in args dict" + if X_test is None or Y_test is None: + raise ValueError("X_test argument and Y_test argument " + "must be supplied.") + if model is None and predictions is None: + raise ValueError("One of model argument " + "or predictions argument must be supplied.") + if model is not None: + warnings.warn("model argument is deprecated. " + "Switch to predictions argument. " + "model argument will be removed after 2018-01-05.") + if predictions is None: + predictions = model + else: + raise ValueError("Exactly one of model argument" + " and predictions argument should be specified.") + + # Define accuracy symbolically + if LooseVersion(tf.__version__) >= LooseVersion('1.0.0'): + correct_preds = tf.equal(tf.argmax(y, axis=-1), + tf.argmax(predictions, axis=-1)) + else: + correct_preds = tf.equal(tf.argmax(y, axis=tf.rank(y) - 1), + tf.argmax(predictions, + axis=tf.rank(predictions) - 1)) + + acc_value = tf.reduce_mean(tf.to_float(correct_preds)) + + # Init result var + accuracy = 0.0 + + if writer is not None: + eval_summary = tf.summary.scalar('acc', acc_value) + + + with sess.as_default(): + + # Initialize the iterator + sess.run(test_iterator.initializer) + + # Try feeding new values till end + num_batches = 0 + try: + while True: + X_array, Y_array = sess.run([X_test, Y_test]) + feed_dict = {x: X_array, + y: Y_array, + phase: False} + if feed is not None: + feed_dict.update(feed) + num_batches = num_batches + 1 + + if writer is not None: + cur_acc, eval_summ = sess.run( + [acc_value, eval_summary], feed_dict=feed_dict) + writer.add_summary(eval_summ, batch) + writer.flush() + else: + cur_acc = acc_value.eval(feed_dict=feed_dict) + accuracy += cur_acc + except tf.errors.OutOfRangeError: + pass + + # Divide by number of examples to get final value + accuracy = accuracy/num_batches + + return accuracy + +def model_eval_adv_imagenet(sess, x, y, predictions=None, test_iterator=None, X_test=None, Y_test=None, + phase=None, writer=None, feed=None, attacker=None, args=None, model=None, attack_params=None): + """ + Compute the accuracy of a TF model on some data + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_test: numpy array with training inputs + :param Y_test: numpy array with training outputs + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param feed_adv: An optional dictionary for generating adversarial attacks that is appended to the feeding + :param args: dict or argparse `Namespace` object. + Should contain `batch_size` + :param model: (deprecated) if not None, holds model output predictions + :return: a float with the accuracy value + """ + args = _FlagsWrapper(args or {}) + + assert args.batch_size, "Batch size was not given in args dict" + if X_test is None or Y_test is None: + raise ValueError("X_test argument and Y_test argument " + "must be supplied.") + if model is None and predictions is None: + raise ValueError("One of model argument " + "or predictions argument must be supplied.") + if model is not None: + warnings.warn("model argument is deprecated. " + "Switch to predictions argument. " + "model argument will be removed after 2018-01-05.") + if predictions is None: + predictions = model + else: + raise ValueError("Exactly one of model argument" + " and predictions argument should be specified.") + + # Define accuracy symbolically + if LooseVersion(tf.__version__) >= LooseVersion('1.0.0'): + correct_preds = tf.equal(tf.argmax(y, axis=-1), + tf.argmax(predictions, axis=-1)) + else: + correct_preds = tf.equal(tf.argmax(y, axis=tf.rank(y) - 1), + tf.argmax(predictions, + axis=tf.rank(predictions) - 1)) + + acc_value = tf.reduce_mean(tf.to_float(correct_preds)) + + # Init result var + accuracy = 0.0 + + if writer is not None: + eval_summary = tf.summary.scalar('acc', acc_value) + + + with sess.as_default(): + + # Initialize the iterator + sess.run(test_iterator.initializer) + + num_batches = 0 + try: + while True: + X_array, Y_array = sess.run([X_test, Y_test]) + X_shape = X_array.shape + if X_array.shape[0] < args.batch_size: # Last batch discarded to avoid error with CW attack + break + + # Generate the adversarial examples + X_adv_array = attacker.generate_np(X_array, phase, **attack_params) + + feed_dict = {x: X_adv_array, + y: Y_array, + phase: False} + if feed is not None: + feed_dict.update(feed) + num_batches = num_batches + 1 + + if writer is not None: + cur_acc, eval_summ = sess.run( + [acc_value, eval_summary], feed_dict=feed_dict) + writer.add_summary(eval_summ, batch) + writer.flush() + else: + cur_acc = acc_value.eval(feed_dict=feed_dict) + accuracy += cur_acc + except tf.errors.OutOfRangeError: + pass + + + # Divide by number of examples to get final value + accuracy = accuracy/num_batches # accuracy was already reduce mean across that batch so we have to divide number of batches + + return accuracy + +def model_eval_ensemble_imagenet(sess, x, y, predictions=None, test_iterator=None, X_test=None, Y_test=None, phase=None, writer=None, + feed=None, args=None, model=None): + """ + Compute the accuracy of a TF model on some data + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_test: numpy array with training inputs + :param Y_test: numpy array with training outputs + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `batch_size` + :param model: (deprecated) if not None, holds model output predictions + :return: a float with the accuracy value + """ + args = _FlagsWrapper(args or {}) + + assert args.batch_size, "Batch size was not given in args dict" + if X_test is None or Y_test is None: + raise ValueError("X_test argument and Y_test argument " + "must be supplied.") + if model is None and (predictions is None): + raise ValueError("One of model argument " + "or both predictions argument must be supplied.") + if model is not None: + warnings.warn("model argument is deprecated. " + "Switch to predictions argument. " + "model argument will be removed after 2018-01-05.") + if predictions is None: + predictions = model + else: + raise ValueError("Exactly one of model argument" + " and predictions argument should be specified.") + + # Define accuracy symbolically + if LooseVersion(tf.__version__) >= LooseVersion('1.0.0'): + correct_preds = tf.equal(tf.argmax(y, axis=-1), + predictions) + else: + correct_preds = tf.equal(tf.argmax(y, axis=tf.rank(y) - 1), + predictions) + + acc_value = tf.reduce_mean(tf.to_float(correct_preds)) + + # Init result var + accuracy = 0.0 + + if writer is not None: + eval_summary = tf.summary.scalar('acc', acc_value) + + with sess.as_default(): + + # Initialize the iterator + sess.run(test_iterator.initializer) + + # Try feeding new values till end + num_batches = 0 + try: + while True: + X_array, Y_array = sess.run([X_test, Y_test]) + feed_dict = {x: X_array, + y: Y_array, + phase: False} + if feed is not None: + feed_dict.update(feed) + num_batches = num_batches + 1 + + if writer is not None: + cur_acc, eval_summ = sess.run( + [acc_value, eval_summary], feed_dict=feed_dict) + writer.add_summary(eval_summ, batch) + writer.flush() + else: + cur_acc = acc_value.eval(feed_dict=feed_dict) + accuracy += cur_acc + except tf.errors.OutOfRangeError: + pass + + # Divide by number of examples to get final value + accuracy = accuracy/num_batches + + return accuracy + +def model_eval_ensemble_adv_imagenet(sess, x, y, predictions=None, test_iterator=None, X_test=None, Y_test=None, phase=None, writer=None, + feed=None, attacker=None, args=None, model=None, attack_params=None): + """ + Compute the accuracy of a TF model on some data + :param sess: TF session to use when training the graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param X_test: numpy array with training inputs + :param Y_test: numpy array with training outputs + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `batch_size` + :param model: (deprecated) if not None, holds model output predictions + :return: a float with the accuracy value + """ + args = _FlagsWrapper(args or {}) + + assert args.batch_size, "Batch size was not given in args dict" + if X_test is None or Y_test is None: + raise ValueError("X_test argument and Y_test argument " + "must be supplied.") + if model is None and (predictions is None): + raise ValueError("One of model argument " + "or both predictions argument must be supplied.") + if model is not None: + warnings.warn("model argument is deprecated. " + "Switch to predictions argument. " + "model argument will be removed after 2018-01-05.") + if predictions is None: + predictions = model + else: + raise ValueError("Exactly one of model argument" + " and predictions argument should be specified.") + + # Define accuracy symbolically + if LooseVersion(tf.__version__) >= LooseVersion('1.0.0'): + correct_preds = tf.equal(tf.argmax(y, axis=-1), + predictions) + else: + correct_preds = tf.equal(tf.argmax(y, axis=tf.rank(y) - 1), + predictions) + + acc_value = tf.reduce_mean(tf.to_float(correct_preds)) + + # Init result var + accuracy = 0.0 + + if writer is not None: + eval_summary = tf.summary.scalar('acc', acc_value) + + with sess.as_default(): + + # Initialize the iterator + sess.run(test_iterator.initializer) + + num_batches = 0 + try: + while True: + X_array, Y_array = sess.run([X_test, Y_test]) + X_shape = X_array.shape + if X_array.shape[0] < args.batch_size: + break + + # Generate the adversarial examples + X_adv_array = attacker.generate_np(X_array, phase, **attack_params) + + feed_dict = {x: X_adv_array, + y: Y_array, + phase: False} + if feed is not None: + feed_dict.update(feed) + num_batches = num_batches + 1 + + if writer is not None: + cur_acc, eval_summ = sess.run( + [acc_value, eval_summary], feed_dict=feed_dict) + writer.add_summary(eval_summ, batch) + writer.flush() + else: + cur_acc = acc_value.eval(feed_dict=feed_dict) + accuracy += cur_acc + except tf.errors.OutOfRangeError: + pass + + # Divide by number of examples to get final value + accuracy = accuracy/num_batches + return accuracy + +def tf_model_load(sess, file_path=None): + """ + + :param sess: the session object to restore + :param file_path: path to the restored session, if None is + taken from FLAGS.log_dir and FLAGS.filename + :return: + """ + with sess.as_default(): + saver = tf.train.Saver() + if file_path is None: + file_path = os.path.join(FLAGS.log_dir, FLAGS.filename) + saver.restore(sess, tf.train.latest_checkpoint(file_path)) + + return True + + +def batch_eval(sess, tf_inputs, tf_outputs, numpy_inputs, feed=None, + args=None): + """ + A helper function that computes a tensor on numpy inputs by batches. + + :param sess: + :param tf_inputs: + :param tf_outputs: + :param numpy_inputs: + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :param args: dict or argparse `Namespace` object. + Should contain `batch_size` + """ + args = _FlagsWrapper(args or {}) + + assert args.batch_size, "Batch size was not given in args dict" + + n = len(numpy_inputs) + assert n > 0 + assert n == len(tf_inputs) + m = numpy_inputs[0].shape[0] + for i in xrange(1, n): + assert numpy_inputs[i].shape[0] == m + out = [] + for _ in tf_outputs: + out.append([]) + with sess.as_default(): + for start in xrange(0, m, args.batch_size): + batch = start // args.batch_size + if batch % 100 == 0 and batch > 0: + _logger.debug("Batch " + str(batch)) + + # Compute batch start and end indices + start = batch * args.batch_size + end = start + args.batch_size + numpy_input_batches = [numpy_input[start:end] + for numpy_input in numpy_inputs] + cur_batch_size = numpy_input_batches[0].shape[0] + assert cur_batch_size <= args.batch_size + for e in numpy_input_batches: + assert e.shape[0] == cur_batch_size + + feed_dict = dict(zip(tf_inputs, numpy_input_batches)) + if feed is not None: + feed_dict.update(feed) + numpy_output_batches = sess.run(tf_outputs, feed_dict=feed_dict) + for e in numpy_output_batches: + assert e.shape[0] == cur_batch_size, e.shape + for out_elem, numpy_output_batch in zip(out, numpy_output_batches): + out_elem.append(numpy_output_batch) + + out = [np.concatenate(x, axis=0) for x in out] + for e in out: + assert e.shape[0] == m, e.shape + return out + + +def model_argmax(sess, x, predictions, samples, feed=None): + """ + Helper function that computes the current class prediction + :param sess: TF session + :param x: the input placeholder + :param predictions: the model's symbolic output + :param samples: numpy array with input samples (dims must match x) + :param feed: An optional dictionary that is appended to the feeding + dictionary before the session runs. Can be used to feed + the learning phase of a Keras model for instance. + :return: the argmax output of predictions, i.e. the current predicted class + """ + feed_dict = {x: samples} + if feed is not None: + feed_dict.update(feed) + probabilities = sess.run(predictions, feed_dict) + + if samples.shape[0] == 1: + return np.argmax(probabilities) + else: + return np.argmax(probabilities, axis=1) + + +def l2_batch_normalize(x, epsilon=1e-12, scope=None): + """ + Helper function to normalize a batch of vectors. + :param x: the input placeholder + :param epsilon: stabilizes division + :return: the batch of l2 normalized vector + """ + with tf.name_scope(scope, "l2_batch_normalize") as scope: + x_shape = tf.shape(x) + x = tf.contrib.layers.flatten(x) + x /= (epsilon + tf.reduce_max(tf.abs(x), 1, keep_dims=True)) + square_sum = tf.reduce_sum(tf.square(x), 1, keep_dims=True) + x_inv_norm = tf.rsqrt(np.sqrt(epsilon) + square_sum) + x_norm = tf.multiply(x, x_inv_norm) + return tf.reshape(x_norm, x_shape, scope) + + +def kl_with_logits(p_logits, q_logits, scope=None, + loss_collection=tf.GraphKeys.REGULARIZATION_LOSSES): + """Helper function to compute kl-divergence KL(p || q) + """ + with tf.name_scope(scope, "kl_divergence") as name: + p = tf.nn.softmax(p_logits) + p_log = tf.nn.log_softmax(p_logits) + q_log = tf.nn.log_softmax(q_logits) + loss = tf.reduce_mean(tf.reduce_sum(p * (p_log - q_log), axis=1), + name=name) + tf.losses.add_loss(loss, loss_collection) + return loss + +def clip_eta(eta, ord, eps): + """ + Helper function to clip the perturbation to epsilon norm ball. + :param eta: A tensor with the current perturbation. + :param ord: Order of the norm (mimics Numpy). + Possible values: np.inf, 1 or 2. + :param eps: Epilson, bound of the perturbation. + """ + + # Clipping perturbation eta to self.ord norm ball + if ord not in [np.inf, 1, 2]: + raise ValueError('ord must be np.inf, 1, or 2.') + if ord == np.inf: + eta = tf.clip_by_value(eta, -eps, eps) + elif ord in [1, 2]: + reduc_ind = list(xrange(1, len(eta.get_shape()))) + if ord == 1: + norm = tf.reduce_sum(tf.abs(eta), + reduction_indices=reduc_ind, + keep_dims=True) + elif ord == 2: + norm = tf.sqrt(tf.reduce_sum(tf.square(eta), + reduction_indices=reduc_ind, + keep_dims=True)) + eta = eta * eps / norm + return eta diff --git a/case_studies/empir/modified_cleverhans/utils_th.py b/case_studies/empir/modified_cleverhans/utils_th.py new file mode 100644 index 0000000..1c203f1 --- /dev/null +++ b/case_studies/empir/modified_cleverhans/utils_th.py @@ -0,0 +1,340 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import math +import numpy as np +import six +import time +import warnings + +from collections import OrderedDict + +from .utils import batch_indices, _ArgsWrapper + +import theano +import theano.tensor as T + +import keras + +floatX = theano.config.floatX + +_TEST_PHASE = np.uint8(0) +_TRAIN_PHASE = np.uint8(1) + + +def get_or_compute_grads(loss_or_grads, params): + if isinstance(loss_or_grads, list): + return loss_or_grads + else: + return theano.grad(loss_or_grads, params) + + +def adadelta(loss_or_grads, params, learning_rate=1.0, rho=0.95, epsilon=1e-6): + """ From Lasagne + """ + grads = get_or_compute_grads(loss_or_grads, params) + updates = OrderedDict() + + # Using theano constant to prevent upcasting of float32 + one = T.constant(1) + + for param, grad in zip(params, grads): + value = param.get_value(borrow=True) + # accu: accumulate gradient magnitudes + accu = theano.shared(np.zeros(value.shape, dtype=value.dtype), + broadcastable=param.broadcastable) + # delta_accu: accumulate update magnitudes (recursively!) + delta_accu = theano.shared(np.zeros(value.shape, dtype=value.dtype), + broadcastable=param.broadcastable) + + # update accu (as in rmsprop) + accu_new = rho * accu + (one - rho) * grad ** 2 + updates[accu] = accu_new + + # compute parameter update, using the 'old' delta_accu + update = (grad * T.sqrt(delta_accu + epsilon) / + T.sqrt(accu_new + epsilon)) + updates[param] = param - learning_rate * update + + # update delta_accu (as accu, but accumulating updates) + delta_accu_new = rho * delta_accu + (one - rho) * update ** 2 + updates[delta_accu] = delta_accu_new + + return updates + + +def model_loss(y, model, mean=True): + """ + Define loss of Theano graph + :param y: correct labels + :param model: output of the model + :return: return mean of loss if True, otherwise return vector with per + sample loss + """ + warnings.warn("CleverHans support for Theano is deprecated and " + "will be dropped on 2017-11-08.") + + from_logits = "softmax" not in str(model).lower() + + if from_logits: + model = T.nnet.softmax(model) + + out = T.nnet.categorical_crossentropy(model, y) + + if mean: + out = T.mean(out) + return out + + +def th_model_train(x, y, predictions, params, X_train, Y_train, save=False, + predictions_adv=None, evaluate=None, args=None): + """ + Train a Theano graph + :param x: input placeholder + :param y: output placeholder (for labels) + :param predictions: model output predictions + :param params: model trainable weights + :param X_train: numpy array with training inputs + :param Y_train: numpy array with training outputs + :param save: boolean controling the save operation + :param predictions_adv: if set with the adversarial example tensor, + will run adversarial training + :param args: dict or argparse `Namespace` object. + Should contain `nb_epochs`, `learning_rate`, + `batch_size` + :return: True if model trained + """ + warnings.warn("CleverHans support for Theano is deprecated and " + "will be dropped on 2017-11-08.") + + args = _ArgsWrapper(args or {}) + + print("Starting model training using Theano.") + + # Define loss + loss = model_loss(y, predictions) + if predictions_adv is not None: + loss = (loss + model_loss(y, predictions_adv)) / 2 + + print("Defined optimizer.") + + train_step = theano.function( + inputs=[x, y], + outputs=[loss], + givens={keras.backend.learning_phase(): _TRAIN_PHASE}, + allow_input_downcast=True, + on_unused_input='ignore', + updates=adadelta( + loss, params, learning_rate=args.learning_rate, rho=0.95, + epsilon=1e-08) + ) + + for epoch in six.moves.xrange(args.nb_epochs): + print("Epoch " + str(epoch)) + + # Compute number of batches + nb_batches = int(math.ceil(float(len(X_train)) / args.batch_size)) + assert nb_batches * args.batch_size >= len(X_train) + + prev = time.time() + for batch in range(nb_batches): + + # Compute batch start and end indices + start, end = batch_indices(batch, len(X_train), args.batch_size) + + # Perform one training step + train_step(X_train[start:end], Y_train[start:end]) + assert end >= len(X_train) # Check that all examples were used + cur = time.time() + print("\tEpoch took " + str(cur - prev) + " seconds") + prev = cur + if evaluate is not None: + evaluate() + + return True + + +def th_model_eval(x, y, model, X_test, Y_test, args=None): + """ + Compute the accuracy of a Theano model on some data + :param x: input placeholder + :param y: output placeholder (for labels) + :param model: model output predictions + :param X_test: numpy array with training inputs + :param Y_test: numpy array with training outputs + :param args: dict or argparse `Namespace` object. + Should contain `batch_size` + :return: a float with the accuracy value + """ + warnings.warn("CleverHans support for Theano is deprecated and " + "will be dropped on 2017-11-08.") + + args = _ArgsWrapper(args or {}) + + # Define symbol for accuracy + acc_value = keras.metrics.categorical_accuracy(y, model) + # Keras 2.0 categorical_accuracy no longer calculates the mean internally + # T.mean is called in here and is backward compatible with previous + # versions of Keras + acc_value = T.mean(acc_value) + + # Init result var + accuracy = 0.0 + + nb_batches = int(math.ceil(float(len(X_test)) / args.batch_size)) + assert nb_batches * args.batch_size >= len(X_test) + + eval_step = theano.function( + inputs=[x, y], + outputs=acc_value, + givens={keras.backend.learning_phase(): _TEST_PHASE}, + on_unused_input="ignore", + allow_input_downcast=True, + updates=None + ) + + for batch in range(nb_batches): + if batch % 100 == 0 and batch > 0: + print("Batch " + str(batch)) + + # Must not use the `batch_indices` function here, because it + # repeats some examples. + # It's acceptable to repeat during training, but not eval. + start = batch * args.batch_size + end = min(len(X_test), start + args.batch_size) + cur_batch_size = end - start + + # The last batch may be smaller than all others, so we need to + # account for variable batch size here + accuracy += cur_batch_size * \ + eval_step(X_test[start:end], Y_test[start:end]) + assert end >= len(X_test) + + # Divide by number of examples to get final value + accuracy /= len(X_test) + + return accuracy + + +def batch_eval(th_inputs, th_outputs, numpy_inputs, args=None): + """ + A helper function that computes a tensor on numpy inputs by batches. + + :param th_inputs: + :param th_outputs: + :param numpy_inputs: + :param args: dict or argparse `Namespace` object. + Should contain `batch_size` + """ + warnings.warn("CleverHans support for Theano is deprecated and " + "will be dropped on 2017-11-08.") + + args = _ArgsWrapper(args or {}) + + n = len(numpy_inputs) + assert n > 0 + assert n == len(th_inputs) + m = numpy_inputs[0].shape[0] + for i in six.moves.xrange(1, n): + assert numpy_inputs[i].shape[0] == m + out = [] + for _ in th_outputs: + out.append([]) + + eval_step = theano.function( + inputs=th_inputs, + outputs=th_outputs, + givens={keras.backend.learning_phase(): _TEST_PHASE}, + allow_input_downcast=True, + updates=None + ) + + for start in six.moves.xrange(0, m, args.batch_size): + batch = start // args.batch_size + if batch % 100 == 0 and batch > 0: + print("Batch " + str(batch)) + + # Compute batch start and end indices + start = batch * args.batch_size + end = start + args.batch_size + numpy_input_batches = [numpy_input[start:end] + for numpy_input in numpy_inputs] + cur_batch_size = numpy_input_batches[0].shape[0] + assert cur_batch_size <= args.batch_size + for e in numpy_input_batches: + assert e.shape[0] == cur_batch_size + + numpy_output_batches = eval_step(*numpy_input_batches) + for e in numpy_output_batches: + assert e.shape[0] == cur_batch_size, e.shape + for out_elem, numpy_output_batch in zip(out, numpy_output_batches): + out_elem.append(numpy_output_batch) + + out = [np.concatenate(x, axis=0) for x in out] + for e in out: + assert e.shape[0] == m, e.shape + return out + + +def model_argmax(x, predictions, sample): + """ + Helper function that computes the current class prediction + :param x: the input placeholder + :param predictions: the model's symbolic output + :param sample: (1 x 1 x img_rows x img_cols) numpy array with sample input + :return: the argmax output of predictions, i.e. the current predicted class + """ + warnings.warn("CleverHans support for Theano is deprecated and " + "will be dropped on 2017-11-08.") + + probabilities = theano.function( + inputs=[x], + outputs=predictions, + givens={keras.backend.learning_phase(): _TEST_PHASE}, + allow_input_downcast=True, + updates=None + )(x) + + return np.argmax(probabilities) + + +def l2_batch_normalize(x, epsilon=1e-12): + """ + Helper function to normalize a batch of vectors. + :param x: the input placeholder + :param epsilon: stabilizes division + :return: the batch of l2 normalized vector + """ + epsilon = np.asarray(epsilon, dtype=floatX) + x_shape = x.shape + x = T.reshape(x, (x.shape[0], -1)) + x /= (epsilon + T.max(T.abs_(x), 1, keepdims=True)) + square_sum = T.sum(T.sqr(x), 1, keepdims=True) + x /= T.sqrt(np.sqrt(epsilon) + square_sum) + return x.reshape(x_shape) + + +def kl_with_logits(q_logits, p_logits): + """Helper function to compute kl-divergence KL(q || p) + """ + q = T.nnet.softmax(q_logits) + q_log = T.nnet.logsoftmax(q_logits) + p_log = T.nnet.logsoftmax(p_logits) + loss = T.sum(q * (q_log - p_log), axis=1) + return loss diff --git a/case_studies/error_correcting_codes/AttackModel.py b/case_studies/error_correcting_codes/AttackModel.py new file mode 100644 index 0000000..c9ae723 --- /dev/null +++ b/case_studies/error_correcting_codes/AttackModel.py @@ -0,0 +1,219 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Run this to attack a trained model via TrainModel. +Use the "loadFullModel" submethod to load in an already trained model (trained via TrainModel) +The main attack function is "runAttacks" which runs attacks on trained models +""" +import pdb + +from cleverhans.attacks import Noise, CarliniWagnerL2, MaxConfidence, FastGradientMethod, BasicIterativeMethod, DeepFool, MomentumIterativeMethod, ProjectedGradientDescent +from Model_Implementations import Model_Softmax_Baseline, Model_Logistic_Baseline, Model_Logistic_Ensemble, Model_Tanh_Ensemble, Model_Tanh_Baseline +from tensorflow.keras.datasets import mnist, cifar10 +from tensorflow.keras import backend +import tensorflow as tf; import numpy as np +import scipy.linalg +from scipy import stats +import matplotlib.pyplot as plt + + + + +model_path = 'checkpoints/ECOC/tanh32/checkpoints' #path with saved model parameters +sess = backend.get_session() +backend.set_learning_phase(0) #need to do this to get CleverHans to work with batchnorm + + + +#Dataset-specific parameters - should be same as those used in TrainModel +DATA_DESC = 'CIFAR10'; (X_train, Y_train), (X_test, Y_test) = cifar10.load_data() +epochs=None; weight_save_freq=None +num_classes=10 #how many classes (categories) are in this dataset? +Y_train = np.squeeze(Y_train); Y_test = np.squeeze(Y_test) +num_filters_std = [32, 64, 128]; num_filters_ens=[32, 64, 128]; num_filters_ens_2=16; dropout_rate_std=0.0; dropout_rate_ens=0.0; weight_decay = 0 +model_rep_baseline=2; model_rep_ens=2; DATA_AUGMENTATION_FLAG=1; BATCH_NORMALIZATION_FLAG=1 +num_channels = 3; inp_shape = (32,32,3); lr=1e-4; batch_size=80; +noise_stddev = 0.032; blend_factor = .032 + +#Attack parameters +eps_val = 8/255.0; PGD_iters = 200; eps_iter=(2/3)*eps_val; +eps_range = np.linspace(0, 0.33, 10) +noise_eps=0.1 + + +# DATA PRE-PROCESSING +X_train = (X_train/255).astype(np.float32); X_test = (X_test/255).astype(np.float32) +#reshape (add third (image) channel) +X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2],num_channels); X_test = X_test.reshape(X_test.shape[0], X_test.shape[1], X_test.shape[2],num_channels) +X_valid = X_test[1000:2000]; Y_valid = Y_test[1000:2000]; #validation data, used to attack model +#X_train = X_train-0.5; X_test = X_test-0.5; X_valid = X_valid-0.5; #map to range (-0.5,0.5) +data_dict = {'X_train':X_train, 'Y_train_cat':Y_train, 'X_test':X_test, 'Y_test_cat':Y_test} +X_random = np.random.rand(X_valid.shape[0],X_valid.shape[1],X_valid.shape[2],X_valid.shape[3])-0.5; X_random = X_random.astype(np.float32) + + + + +#Model definition of the model we want to attack; should be same as the definition used in TrainModel +## ENSEMBLE TANH 32 MODEL DEFINITION +name = 'tanh_32_diverse' + '_' + DATA_DESC; +seed = 59; +code_length = 32; +num_codes = code_length; +num_chunks = 4; +base_model = None; + +def output_activation(x): + return tf.nn.tanh(x) + +M = scipy.linalg.hadamard(code_length).astype(np.float32) +M[np.arange(0, num_codes, + 2), 0] = -1 # replace first col, which for scipy's Hadamard construction is always 1, hence not a useful classifier; this change still ensures all codewords have dot product <=0; since our decoder ignores negative correlations anyway, this has no net effect on probability estimation +np.random.seed(seed) +np.random.shuffle(M) +idx = np.random.permutation(code_length) +M = M[0:num_codes, idx[0:code_length]] +params_dict = {'BATCH_NORMALIZATION_FLAG': BATCH_NORMALIZATION_FLAG, + 'DATA_AUGMENTATION_FLAG': DATA_AUGMENTATION_FLAG, 'M': M, + 'base_model': base_model, 'num_chunks': num_chunks, + 'model_rep': model_rep_ens, + 'output_activation': output_activation, + 'num_filters_ens': num_filters_ens, + 'num_filters_ens_2': num_filters_ens_2, 'batch_size': batch_size, + 'epochs': epochs, 'dropout_rate': dropout_rate_ens, 'lr': lr, + 'blend_factor': blend_factor, 'inp_shape': inp_shape, + 'noise_stddev': noise_stddev, + 'weight_save_freq': weight_save_freq, 'name': name, + 'model_path': model_path, + 'zero_one_input': True + } +m4 = Model_Tanh_Ensemble({}, params_dict) +m4.loadFullModel() # load in the saved model, which should have already been trained first via TrainModel + +m4.legend = 'TEns32'; + +m4.X_valid = X_valid; m4.Y_valid = Y_valid; +m4.X_test = X_test; m4.Y_test = Y_test; +m4.X_random = X_random; +#m4.minval = -0.5; m4.maxval = 0.5 +m4.minval = 0; m4.maxval = 1 + + + +def benignAccuracy(model, X, Y): + + acc_vec=[]; probs_benign_list=[] + for rep in np.arange(0, X.shape[0], 1000): + x = X[rep:rep+1000] + probs_benign = sess.run(model.predict(tf.convert_to_tensor(x))) + print(probs_benign.shape) + acc= np.mean(np.argmax(probs_benign, 1)==Y[rep:rep+1000]) + acc_vec += [acc] + probs_benign_list += list(np.max(probs_benign, 1)) + + acc = np.mean(acc_vec) + print("Accuracy for model " + model.params_dict['name'] + " : ", acc) + return probs_benign_list + + +def wbAttack(model, attack, att_params, X, Y): + sess = backend.get_session() + modelCH = model.modelCH() + adv_model = attack(modelCH, sess=sess) + + acc_vec=[]; probs_adv_list=[] + inc=64 + for rep in np.arange(0, X.shape[0], inc): + x = X[rep:rep+inc] + y = Y[rep:rep+inc] + X_adv = adv_model.generate(tf.convert_to_tensor(x), **att_params).eval(session=sess) + temp = sess.run(model.predict(tf.convert_to_tensor(X_adv))) + print(temp.shape) + preds = np.argmax(temp, 1) + acc = np.mean(np.equal(preds, y)) + probs_adv = np.max(sess.run(model.predict(tf.convert_to_tensor(X_adv))), 1) + probs_adv = probs_adv[preds != y] + acc= np.mean(np.equal(preds, y)) + acc_vec += [acc] + probs_adv_list += list(probs_adv) + + + acc = np.mean(acc_vec) + print("Adv accuracy for model " + model.params_dict['name'] + " : ", acc) + return probs_adv_list, acc, X_adv + + + + + +def runAttacks(models_list): + #CW attack + for model in models_list: + + print(""); print(""); print(""); + print("Running tests on model: ", model.params_dict['name']) + + print("Clean accuracy of model:") + probs_benign = benignAccuracy(model, model.X_test, model.Y_test) + print("") + + print("Running PGD attack:") + att_params = {'clip_min': model.minval, 'clip_max':model.maxval, 'eps':eps_val, 'eps_iter':eps_iter, 'nb_iter':PGD_iters,'ord':np.inf} + probs_adv, junk, X_adv = wbAttack(model, ProjectedGradientDescent, att_params, model.X_valid, model.Y_valid) + print("") + +# print("Running CW attack:") +# att_params = {'clip_min': model.minval, 'clip_max':model.maxval, 'binary_search_steps':10, 'learning_rate':1e-3} +# probs_adv, junk, X_adv = wbAttack(model, CarliniWagnerL2, att_params, model.X_valid[0:100], model.Y_valid[0:100]) +# print("") +# +# print("Running Blind Spot attack, alpha=0.8:") +# att_params = {'clip_min': model.minval, 'clip_max':model.maxval, 'binary_search_steps':10, 'learning_rate':1e-3} +# probs_adv, junk, X_adv = wbAttack(model, CarliniWagnerL2, att_params, 0.8*model.X_valid[0:100], model.Y_valid[0:100]) +# print("") + + + #Random ATTACK (0 SNR inputs) + print("Running random attack:") + probs_random = np.max(sess.run(model.predict(tf.convert_to_tensor(model.X_random))), 1) + print('Prob. that ', model.params_dict['name'], ' < 0.9 on random data: ', np.mean(probs_random<0.9)) + + #Noise ATTACK (low SNR inputs) + print("Running Noise attack:") + att_params = {'clip_min': model.minval, 'clip_max':model.maxval, 'eps':noise_eps} + probs_noise, junk, X_adv = wbAttack(model, Noise, att_params, model.X_valid, model.Y_valid) + print("") + + return probs_benign, probs_adv, probs_noise + + + + +models_list = [m4] +probs_benign, probs_adv, probs_noise = runAttacks(models_list) + +plt.figure(1) +kernel = stats.gaussian_kde(probs_benign, bw_method=0.5) +plt.plot(np.arange(0, 1, .01), kernel.pdf(np.arange(0, 1, .01)), linewidth=4) + +plt.figure(2) +kernel = stats.gaussian_kde(probs_adv, bw_method=0.5) +plt.plot(np.arange(0, 1, .01), kernel.pdf(np.arange(0, 1, .01)), linewidth=4) + +plt.figure(3) +kernel = stats.gaussian_kde(probs_noise, bw_method=0.5) +plt.plot(np.arange(0, 1, .01), kernel.pdf(np.arange(0, 1, .01)), linewidth=4) + diff --git a/case_studies/error_correcting_codes/ClassBlender.py b/case_studies/error_correcting_codes/ClassBlender.py new file mode 100644 index 0000000..b67c832 --- /dev/null +++ b/case_studies/error_correcting_codes/ClassBlender.py @@ -0,0 +1,68 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This code blends two classes together as a convex combination; a type of simple data augmentation +""" + +from tensorflow.keras.layers import Layer +from tensorflow.keras import backend as K +import tensorflow as tf + +import numpy as np + + +class ClassBlender(Layer): + """Only active at training time since it is a regularization layer. + # Arguments + attenuation: how much to attenuate the input + # Input shape + Arbitrary. + # Output shape + Same as the input shape. + """ + + def __init__(self, attenuation, batch_size, **kwargs): + super(ClassBlender, self).__init__(**kwargs) + self.supports_masking = True + self.attenuation = attenuation + self.batch_size = batch_size + + + + + def call(self, inputs, training=None): + def blended(): + + inputs_permuted = tf.random_shuffle(inputs) + angles = (180*(2*np.random.rand(self.batch_size)-1))*np.pi/180 + shifts = 4*(2*np.random.rand(self.batch_size, 2)-1) + inputs_permuted_translated = tf.contrib.image.translate(inputs_permuted, shifts) + inputs_permuted_translated_rotated = tf.contrib.image.rotate(inputs_permuted_translated,angles) + inputs_adjusted = inputs_permuted_translated_rotated + + inputs_adjusted = tf.clip_by_value(inputs_adjusted,-0.5,0.5) + + + return (1.0-self.attenuation)*inputs + self.attenuation*inputs_adjusted + + + return K.in_train_phase(blended, inputs, training=training) + + def get_config(self): + config = {'attenuation': self.attenuation, 'batch_size':self.batch_size} + base_config = super(ClassBlender, self).get_config() + return dict(list(base_config.items()) + list(config.items())) diff --git a/case_studies/error_correcting_codes/Clipper.py b/case_studies/error_correcting_codes/Clipper.py new file mode 100644 index 0000000..993bab2 --- /dev/null +++ b/case_studies/error_correcting_codes/Clipper.py @@ -0,0 +1,56 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +""" + +from tensorflow.keras.layers import Layer +from tensorflow.keras import backend as K +import tensorflow as tf + +import numpy as np + + +class Clipper(Layer): + """clips input to lie wihin valid pixel range + Only active at training time since it is a regularization layer. + # Arguments + attenuation: how much to attenuate the input + # Input shape + Arbitrary. + # Output shape + Same as the input shape. + """ + + def __init__(self, **kwargs): + super(Clipper, self).__init__(**kwargs) + self.supports_masking = True + + + + def call(self, inputs, training=None): + def augmented(): + return tf.clip_by_value(inputs,-0.5,0.5) + + return K.in_train_phase(augmented, augmented, training=training) + + + + + def get_config(self): + config = {} + base_config = super(Clipper, self).get_config() + return dict(list(base_config.items()) + list(config.items())) diff --git a/case_studies/error_correcting_codes/DataAugmenter.py b/case_studies/error_correcting_codes/DataAugmenter.py new file mode 100644 index 0000000..4c62fa8 --- /dev/null +++ b/case_studies/error_correcting_codes/DataAugmenter.py @@ -0,0 +1,69 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +""" + +from tensorflow.keras.layers import Layer +from tensorflow.keras import backend as K +import tensorflow as tf + +import numpy as np + + +class DataAugmenter(Layer): + """Shifts and scales input + Only active at training time since it is a regularization layer. + # Arguments + attenuation: how much to attenuate the input + # Input shape + Arbitrary. + # Output shape + Same as the input shape. + """ + + def __init__(self, batch_size, **kwargs): + super(DataAugmenter, self).__init__(**kwargs) + self.supports_masking = True + self.batch_size = batch_size + + + + + def call(self, inputs, training=None): + def augmented(): + angles = (15*(2*np.random.rand(self.batch_size)-1))*np.pi/180 + shifts = 4*(2*np.random.rand(self.batch_size, 2)-1) + inputs_shifted = tf.contrib.image.translate(inputs, shifts) + inputs_shifted_rotated = tf.contrib.image.rotate(inputs_shifted,angles) + + random_number = tf.random_uniform([self.batch_size]) + inputs_shifted_rotated_flipped = tf.where(random_number<0.5, tf.image.flip_left_right(inputs_shifted_rotated), inputs_shifted_rotated) + + # modificaiton by zimmerrol to make sure keras shape computation works + inputs_shifted_rotated_flipped = tf.ensure_shape(inputs_shifted_rotated_flipped, inputs.shape) + + return inputs_shifted_rotated_flipped + + + + return K.in_train_phase(augmented, inputs, training=training) + + def get_config(self): + config = {} + config['batch_size'] = self.batch_size + base_config = super(DataAugmenter, self).get_config() + return dict(list(base_config.items()) + list(config.items())) diff --git a/case_studies/error_correcting_codes/Grayscaler.py b/case_studies/error_correcting_codes/Grayscaler.py new file mode 100644 index 0000000..1ef5b54 --- /dev/null +++ b/case_studies/error_correcting_codes/Grayscaler.py @@ -0,0 +1,56 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +""" + +from tensorflow.keras.layers import Layer +from tensorflow.keras import backend as K +import tensorflow as tf + +import numpy as np + + +class Grayscaler(Layer): + """Converts input to grayscale + Only active at training time since it is a regularization layer. + # Arguments + attenuation: how much to attenuate the input + # Input shape + Arbitrary. + # Output shape + Same as the input shape. + """ + + def __init__(self, **kwargs): + super(Grayscaler, self).__init__(**kwargs) + self.supports_masking = True + + + + def call(self, inputs, training=None): + def augmented(): + return tf.image.rgb_to_grayscale(inputs) + + return K.in_train_phase(augmented, augmented, training=training) + + + + + def get_config(self): + config = {} + base_config = super(Grayscaler, self).get_config() + return dict(list(base_config.items()) + list(config.items())) diff --git a/case_studies/error_correcting_codes/LICENSE b/case_studies/error_correcting_codes/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/case_studies/error_correcting_codes/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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 this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/case_studies/error_correcting_codes/Model.py b/case_studies/error_correcting_codes/Model.py new file mode 100644 index 0000000..272f4a6 --- /dev/null +++ b/case_studies/error_correcting_codes/Model.py @@ -0,0 +1,407 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This defines a general "Model", i.e. architecture and decoding operations. It is an abstract base class for all models, +e.g. the baseline softmax model or the ensemble Tanh model +""" +import tensorflow as tf +from utils_keras import KerasModelWrapper as CleverHansKerasModelWrapper + +from tensorflow.keras.layers import BatchNormalization, Dropout, Lambda, Input, Dense, Conv2D, Flatten, Activation, Concatenate, GaussianNoise +from tensorflow.keras.utils import plot_model +from tensorflow.keras import regularizers +from tensorflow.keras.models import load_model +from tensorflow.keras.optimizers import Adam +from tensorflow.keras.callbacks import Callback +from tensorflow.keras.models import Model as KerasModel + +import pickle +import numpy as np +from ClassBlender import ClassBlender +from DataAugmenter import DataAugmenter +from Clipper import Clipper +from Grayscaler import Grayscaler + + + +class WeightsSaver(Callback): + def __init__(self, N): + self.N = N + self.epoch = 0 + + def specifyFilePath(self, path): + self.full_path = path #full path to file, including file name + + def on_epoch_end(self, epoch, logs={}): + if self.epoch % self.N == 0: + print("SAVING WEIGHTS") + w= self.model.get_weights() + pklfile= self.full_path + '_' + str(self.epoch) + '.pkl' + fpkl= open(pklfile, 'wb') + pickle.dump(w, fpkl) + fpkl.close() + self.epoch += 1 + + + +#Abstract base class for all model classes +class Model(object): + + def __init__(self, data_dict, params_dict): + self.data_dict = data_dict + self.params_dict = params_dict + self.input = Input(shape=self.params_dict['inp_shape'], name='input') + self.TRAIN_FLAG=1 + if len(data_dict) > 0: + self.encodeData() + else: + import warnings + warnings.warn("no data passed; cannot encode it") + + + #map categorical class labels (numbers) to encoded (e.g., one hot or ECOC) vectors + def encodeData(self): + self.Y_train = np.zeros((self.data_dict['X_train'].shape[0], self.params_dict['M'].shape[1])) + self.Y_test = np.zeros((self.data_dict['X_test'].shape[0], self.params_dict['M'].shape[1])) + for k in np.arange(self.params_dict['M'].shape[1]): + self.Y_train[:,k] = self.params_dict['M'][self.data_dict['Y_train_cat'], k] + self.Y_test[:,k] = self.params_dict['M'][self.data_dict['Y_test_cat'], k] + + + + #define the neural network + def defineModel(self): + + outputs=[] + self.penultimate = [] + self.penultimate2 = [] + + features = [] + + n = int(self.params_dict['M'].shape[1]/self.params_dict['num_chunks']) + for k in np.arange(0,self.params_dict['num_chunks']): + + x = self.input + + if self.params_dict.get('zero_one_input', False): + x = x - 0.5 + + if self.params_dict['inp_shape'][2]>1: + x_gs = Grayscaler()(x) + else: + x_gs = x + + if (self.TRAIN_FLAG==1): + x = GaussianNoise(self.params_dict['noise_stddev'], input_shape=self.params_dict['inp_shape'])(x) + x_gs = GaussianNoise(self.params_dict['noise_stddev'], input_shape=self.params_dict['inp_shape'])(x_gs) + + if self.params_dict['DATA_AUGMENTATION_FLAG']>0: + x = DataAugmenter(self.params_dict['batch_size'])(x) + x_gs = DataAugmenter(self.params_dict['batch_size'])(x_gs) + + x = ClassBlender(self.params_dict['blend_factor'], self.params_dict['batch_size'])(x) + x_gs = ClassBlender(self.params_dict['blend_factor'], self.params_dict['batch_size'])(x_gs) + + + #x = Lambda(lambda x: x-0.5)(x) + + x = Clipper()(x) + x_gs = Clipper()(x_gs) + + # TODO: verify that this modifcation makes sense + + # Added trainable=self.TRAIN_FLAG==1 for all batchnorm layers to make + # sure they stay fixed during eval (modification by AUTHOR) + + for rep in np.arange(self.params_dict['model_rep']): + x = Conv2D(self.params_dict['num_filters_ens'][0], (5,5), activation='elu', padding='same')(x) + if self.params_dict['BATCH_NORMALIZATION_FLAG']>0: + x = BatchNormalization()(x) + + + x = Conv2D(self.params_dict['num_filters_ens'][0], (3,3), strides=(2,2), activation='elu', padding='same')(x) + if self.params_dict['BATCH_NORMALIZATION_FLAG']>0: + x = BatchNormalization()(x) + + + for rep in np.arange(self.params_dict['model_rep']): + x = Conv2D(self.params_dict['num_filters_ens'][1], (3, 3), activation='elu', padding='same')(x) + if self.params_dict['BATCH_NORMALIZATION_FLAG']>0: + x = BatchNormalization()(x) + + x = Conv2D(self.params_dict['num_filters_ens'][1], (3,3), strides=(2,2), activation='elu', padding='same')(x) + if self.params_dict['BATCH_NORMALIZATION_FLAG']>0: + x = BatchNormalization()(x) + + for rep in np.arange(self.params_dict['model_rep']): + x = Conv2D(self.params_dict['num_filters_ens'][2], (3, 3), activation='elu', padding='same')(x) + if self.params_dict['BATCH_NORMALIZATION_FLAG']>0: + x = BatchNormalization()(x) + + + x = Conv2D(self.params_dict['num_filters_ens'][2], (3,3), strides=(2,2), activation='elu', padding='same')(x) + #x = BatchNormalization()(x) + + + + pens = [] + out=[] + for k2 in np.arange(n): + x0 = Conv2D(self.params_dict['num_filters_ens_2'], (5, 5), strides=(2,2), activation='elu', padding='same')(x_gs) + x0 = Conv2D(self.params_dict['num_filters_ens_2'], (3, 3), strides=(2,2), activation='elu', padding='same')(x0) + x0 = Conv2D(self.params_dict['num_filters_ens_2'], (3, 3), strides=(2,2), activation='elu', padding='same')(x0) + + x_= Concatenate()([x0, x]) + + x_ = Conv2D(self.params_dict['num_filters_ens_2'], (2, 2), activation='elu', padding='same')(x_) + + x_ = Conv2D(self.params_dict['num_filters_ens_2'], (2, 2), activation='elu', padding='same')(x_) + + x_ = Flatten()(x_) + + features.append(x_) + + x_ = Dense(16, activation='elu')(x_) + x_ = Dense(8, activation='elu')(x_) + x_ = Dense(4, activation='elu')(x_) + x0 = Dense(2, activation='linear')(x_) + + pens += [x0] + + x1 = Dense(1, activation='linear', name='w_'+str(k)+'_'+str(k2)+'_'+self.params_dict['name'], kernel_regularizer=regularizers.l2(0.0))(x0) + out += [x1] + + self.penultimate += [pens] + + if len(pens) > 1: + self.penultimate2 += [Concatenate()(pens)] + else: + self.penultimate2 += pens + + if len(out)>1: + outputs += [Concatenate()(out)] + else: + outputs += out + + self.features = features + + self.model = KerasModel(inputs=self.input, outputs=outputs) + # print(self.model.summary()) + #plot_model(self.model, to_file=self.params_dict['model_path'] + '/' + self.params_dict['name'] + '.png') + + return outputs + + + def defineLoss(self): + error = "Sub-classes must implement defineLoss." + raise NotImplementedError(error) + + + def defineMetric(self): + error = "Sub-classes must implement defineMetric." + raise NotImplementedError(error) + + + def trainModel(self): + opt = Adam(lr=self.params_dict['lr']) + + self.model.compile(optimizer=opt, loss=[self.defineLoss(k) for k in np.arange(self.params_dict['num_chunks'])], metrics=self.defineMetric()) + WS = WeightsSaver(self.params_dict['weight_save_freq']) + WS.specifyFilePath(self.params_dict['model_path'] + self.params_dict['name']) + + Y_train_list=[] + Y_test_list=[] + + start = 0 + for k in np.arange(self.params_dict['num_chunks']): + end = start + int(self.params_dict['M'].shape[1]/self.params_dict['num_chunks']) + Y_train_list += [self.Y_train[:,start:end]] + Y_test_list += [self.Y_test[:,start:end]] + start=end + + + self.model.fit(self.data_dict['X_train'], Y_train_list, + epochs=self.params_dict['epochs'], + batch_size=self.params_dict['batch_size'], + shuffle=True, + validation_data=[self.data_dict['X_test'], Y_test_list], + callbacks=[WS]) + + + + self.saveModel() + + + + + def resumeTrainModel(self): + + Y_train_list=[] + Y_test_list=[] + + start = 0 + for k in np.arange(self.params_dict['num_chunks']): + end = start + int(self.params_dict['M'].shape[1]/self.params_dict['num_chunks']) + Y_train_list += [self.Y_train[:,start:end]] + Y_test_list += [self.Y_test[:,start:end]] + start=end + + def hinge_loss(y_true, y_pred): + loss = tf.reduce_mean(tf.maximum(1.0-y_true*y_pred, 0)) + return loss + + def hinge_pred(y_true, y_pred): + corr = tf.to_float((y_pred*y_true)>0) + return tf.reduce_mean(corr) + + self.model = load_model(self.params_dict['model_path'] + self.params_dict['name'] + '_final.h5', custom_objects={'DataAugmenter':DataAugmenter, 'ClassBlender':ClassBlender, 'Clipper':Clipper, 'Grayscaler':Grayscaler, 'hinge_loss':hinge_loss, 'hinge_pred':hinge_pred}) + WS = WeightsSaver(self.params_dict['weight_save_freq']) + WS.specifyFilePath(self.params_dict['model_path'] + self.params_dict['name']) + + + self.model.fit(self.data_dict['X_train'], Y_train_list, + epochs=self.params_dict['epochs'], + batch_size=self.params_dict['batch_size'], + shuffle=True, + validation_data=[self.data_dict['X_test'], Y_test_list], + callbacks=[WS]) + + + + self.saveModel() + + + + #this function takes the output of the NN and maps into logits (which will be passed into softmax to give a prob. dist.) + #It effectively does a Hamming decoding by taking the inner product of the output with each column of the coding matrix (M) + #obviously, the better the match, the larger the dot product is between the output and a given row + #it is simply a log ReLU on the output + def outputDecoder(self, x, M=None): + if M is None: + M = self.params_dict['M'] + mat1 = tf.matmul(x, M, transpose_b=True) + + if not self.params_dict['adaptive_attack']: + mat1 = tf.maximum(mat1, 0) + mat1 = tf.log(mat1+1e-6) #floor negative values + return mat1 + + + def defineBinarizedModel(self): + assert hasattr(self, "penultimate2"), "model needs to be defined first" + + readouts = [] + individual_logits = [] + for k in range(len(self.features)): + readout = Dense(1, activation='linear', + name='binarized_readout_' + str(k), + kernel_regularizer=regularizers.l2(0.0) + ) + logit = readout(self.features[k]) + logit = Lambda(self.params_dict['output_activation'])(logit) + readouts.append(readout) + individual_logits.append(logit) + + if len(individual_logits)>1: + logits = Concatenate()(individual_logits) + else: #if only a single chunk + logits = individual_logits[0] + M = np.stack([np.ones(logits.shape[-1]), -np.ones(logits.shape[-1])], 0).astype(np.float32) + logits = Lambda( + lambda x: self.outputDecoder( + x, + M=M + ))(logits) + + probs = Activation('softmax')(logits) #return probs + + self.binarized_logit = logits + self.binarized_probs = probs + self.binarized_readouts = readouts + + self.model_binarized = KerasModel(inputs=self.input, outputs=self.binarized_probs) + + + def defineFullModel(self): + self.TRAIN_FLAG=0 + outputs = self.defineModel() + + if len(outputs)>1: + self.raw_output = Concatenate()(outputs) + else: #if only a single chunk + self.raw_output = outputs[0] + + #pass output logits through activation + for idx,o in enumerate(outputs): + outputs[idx] = Lambda(self.params_dict['output_activation'])(o) + + if len(outputs)>1: + x = Concatenate()(outputs) + else: #if only a single chunk + x = outputs[0] + + x = Lambda(self.outputDecoder)(x) #logits + logits = x + x = Activation('softmax')(x) #return probs + + self.logits = logits + self.probabilities = x + + if self.params_dict['base_model'] == None: + self.model_full = KerasModel(inputs=self.input, outputs=x) + else: + self.model_full = KerasModel(inputs=self.params_dict['base_model'].input, outputs=x) + + + #CleverHans model wrapper; returns a model that CH can attack + def modelCH(self): + return CleverHansKerasModelWrapper(self.model_full) + + def modelBinarizedCH(self): + return CleverHansKerasModelWrapper(self.model_binarized) + + + def saveModel(self): + w= self.model.get_weights() + pklfile= self.params_dict['model_path'] + self.params_dict['name'] + '_final.pkl' + fpkl= open(pklfile, 'wb') + pickle.dump(w, fpkl) + fpkl.close() + self.model.save(self.params_dict['model_path'] + self.params_dict['name'] + '_final.h5') + + + + def loadModel(self): + pklfile= self.params_dict['model_path'] + self.params_dict['name'] + '_final.pkl' + f= open(pklfile, 'rb') + weigh= pickle.load(f); + f.close(); + self.defineModel() + self.model.set_weights(weigh) + + + def loadFullModel(self): + pklfile= self.params_dict['model_path'] + self.params_dict['name'] + '_final.pkl' + f= open(pklfile, 'rb') + weigh= pickle.load(f); + f.close(); + self.defineFullModel() + self.model_full.set_weights(weigh) + + + def predict(self, X): + return self.model_full(X) diff --git a/case_studies/error_correcting_codes/Model_Implementations.py b/case_studies/error_correcting_codes/Model_Implementations.py new file mode 100644 index 0000000..cb5f93e --- /dev/null +++ b/case_studies/error_correcting_codes/Model_Implementations.py @@ -0,0 +1,250 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Full implementation of all methods of Abstract class "Model" +""" + +import tensorflow as tf +import numpy as np +from tensorflow.keras.layers import AveragePooling2D, BatchNormalization, Dropout, Multiply, Lambda, Input, Dense, Conv2D, MaxPooling2D, Flatten, Activation, UpSampling2D, Concatenate, GaussianNoise +from tensorflow.keras.utils import plot_model +from tensorflow.keras import metrics, regularizers, optimizers +from tensorflow.keras.models import Model as KerasModel +from Model import Model +from tensorflow.keras import losses, metrics +from ClassBlender import ClassBlender +from DataAugmenter import DataAugmenter + + + +#Full architectural definition for all "baseline" models used in the paper +def defineModelBaseline(self): + outputs=[] + self.penultimate = [] + self.penultimate2 = [] + + x = self.input + + x = GaussianNoise(self.params_dict['noise_stddev'], input_shape=self.params_dict['inp_shape'])(x) + if (self.TRAIN_FLAG==1): + if self.params_dict['DATA_AUGMENTATION_FLAG']>0: + x = DataAugmenter(self.params_dict['batch_size'])(x) + x = ClassBlender(self.params_dict['blend_factor'], self.params_dict['batch_size'])(x) + + x = Lambda(lambda x: tf.clip_by_value(x,-0.5,0.5))(x) + + for rep in np.arange(self.params_dict['model_rep']): + x = Conv2D(self.params_dict['num_filters_std'][0], (5,5), activation='elu', padding='same', kernel_regularizer=regularizers.l2(self.params_dict['weight_decay']))(x) + if self.params_dict['BATCH_NORMALIZATION_FLAG']>0: + x = BatchNormalization()(x) + + x = Conv2D(self.params_dict['num_filters_std'][0], (3,3), strides=(2,2), activation='elu', padding='same')(x) + + for rep in np.arange(self.params_dict['model_rep']): + x = Conv2D(self.params_dict['num_filters_std'][1], (3, 3), activation='elu', padding='same', kernel_regularizer=regularizers.l2(self.params_dict['weight_decay']))(x) + if self.params_dict['BATCH_NORMALIZATION_FLAG']>0: + x = BatchNormalization()(x) + + x = Conv2D(self.params_dict['num_filters_std'][1], (3,3), strides=(2,2), activation='elu', padding='same')(x) + x_=x + + for rep in np.arange(self.params_dict['model_rep']): + x_ = Conv2D(self.params_dict['num_filters_std'][2], (3, 3), activation='elu', padding='same', kernel_regularizer=regularizers.l2(self.params_dict['weight_decay']))(x_) + if self.params_dict['BATCH_NORMALIZATION_FLAG']>0: + x_ = BatchNormalization()(x_) + + x_ = Conv2D(self.params_dict['num_filters_std'][2], (3,3), strides=(2,2), activation='elu', padding='same')(x_) + + x_ = Flatten()(x_) + + x_ = Dense(128, activation='elu')(x_) + x_ = Dense(64, activation='elu')(x_) + x0 = Dense(64, activation='linear')(x_) + x1 = Dense(self.params_dict['M'].shape[1], activation='linear', kernel_regularizer=regularizers.l2(0.0))(x0) + + outputs = [x1] + self.model = KerasModel(inputs=self.input, outputs=outputs) + print(self.model.summary()) + plot_model(self.model, to_file=self.params_dict['model_path'] + '/' + self.params_dict['name'] + '.png') + + return outputs + + + + + +class Model_Softmax_Baseline(Model): + + def __init__(self, data_dict, params_dict): + super(Model_Softmax_Baseline, self).__init__(data_dict, params_dict) + + + def defineModel(self): + return defineModelBaseline(self) + + + + def defineLoss(self, idx): + def loss_fn(y_true, y_pred): + loss = tf.keras.backend.categorical_crossentropy(y_true, y_pred, from_logits=True) + return loss + return loss_fn + + + def defineMetric(self): + return [metrics.categorical_accuracy] + + + + + + + + + + + + + + +class Model_Logistic_Baseline(Model): + + def __init__(self, data_dict, params_dict): + super(Model_Logistic_Baseline, self).__init__(data_dict, params_dict) + + + def defineModel(self): + return defineModelBaseline(self) + + + + def defineLoss(self, idx): + def loss_fn(y_true, y_pred): + loss = tf.keras.backend.binary_crossentropy(y_true, y_pred, from_logits=True) + return loss + return loss_fn + + + + + def defineMetric(self): + def sigmoid_pred(y_true, y_pred): + + corr = tf.to_float((y_pred*(2*y_true-1))>0) + return tf.reduce_mean(corr) + + return [sigmoid_pred] + + + + + + + + + + + + +class Model_Tanh_Baseline(Model): + + def __init__(self, data_dict, params_dict): + super(Model_Tanh_Baseline, self).__init__(data_dict, params_dict) + + + + def defineModel(self): + return defineModelBaseline(self) + + + + def defineLoss(self, idx): + def hinge_loss(y_true, y_pred): + loss = tf.reduce_mean(tf.maximum(1.0-y_true*y_pred, 0)) + return loss + + return hinge_loss + + + + + def defineMetric(self): + def tanh_pred(y_true, y_pred): + corr = tf.to_float((y_pred*y_true)>0) + return tf.reduce_mean(corr) + return [tanh_pred] + + + + + + + + + + +class Model_Logistic_Ensemble(Model): + + def __init__(self, data_dict, params_dict): + super(Model_Logistic_Ensemble, self).__init__(data_dict, params_dict) + + def defineLoss(self, idx): + def loss_fn(y_true, y_pred): + loss = tf.keras.backend.binary_crossentropy(y_true, y_pred, from_logits=True) + return loss + return loss_fn + + + + def defineMetric(self): + def sigmoid_pred(y_true, y_pred): + + corr = tf.to_float((y_pred*(2*y_true-1))>0) + return tf.reduce_mean(corr) + + return [sigmoid_pred] + + + + + + + +class Model_Tanh_Ensemble(Model): + + def __init__(self, data_dict, params_dict): + super(Model_Tanh_Ensemble, self).__init__(data_dict, params_dict) + + + + def defineLoss(self, idx): + + def hinge_loss(y_true, y_pred): + loss = tf.reduce_mean(tf.maximum(1.0-y_true*y_pred, 0)) + return loss + + return hinge_loss + + + + def defineMetric(self): + def hinge_pred(y_true, y_pred): + corr = tf.to_float((y_pred*y_true)>0) + return tf.reduce_mean(corr) + return [hinge_pred] + + \ No newline at end of file diff --git a/case_studies/error_correcting_codes/README.md b/case_studies/error_correcting_codes/README.md new file mode 100644 index 0000000..bf9516c --- /dev/null +++ b/case_studies/error_correcting_codes/README.md @@ -0,0 +1,13 @@ +# robust-ecoc +This is the github repository for the paper "Error Correcting Output Codes Improve Probability Estimation and Adversarial Robustness of Deep Neural Networks" by Gunjan Verma and Ananthram Swami. + +All code is in Python 3.6 using Keras and Tensorflow. Adversarial attacks are done with CleverHans 3.0.1. The two main files to reproduce results in the paper are: + +1. TrainModel.py. Use this script to train a model. +2. AttackModel.py. Attack (e.g. adversarial PGD attack) the trained model outputted by (1). + +In addition, there are a few notable supporting files if one desires to modify the internal implementation + +3. Model.py. Abstract base class implementing a baseline or ensemble model. Look at the implementation of "defineModel" in this file to see or modify the neural network architecture used by all ensemble models. + +4. Model_Implementations.py. Implements model-specific methods of (3). Look at the implementation of "defineModelBaseline" in this file to see or modify the neural network architecture used by all baseline models. diff --git a/case_studies/error_correcting_codes/TrainModel.py b/case_studies/error_correcting_codes/TrainModel.py new file mode 100644 index 0000000..c0e5de7 --- /dev/null +++ b/case_studies/error_correcting_codes/TrainModel.py @@ -0,0 +1,206 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +#!/usr/bin/henv python3 +# -*- coding: utf-8 -*- + +""" +This script trains a model that uses ECOC coding. It defines many types of models (baseline and ensemble). +Uncomment the final two lines corresponding to the model of interest from one of the below model definition "code blocks" to train that model. +Next run "AttackModel" to then attack this model. +""" + +# IMPORTS +import tensorflow as tf; +import numpy as np +from tensorflow.keras.datasets import mnist, cifar10 +from Model_Implementations import Model_Softmax_Baseline, \ + Model_Logistic_Baseline, Model_Logistic_Ensemble, Model_Tanh_Ensemble, \ + Model_Tanh_Baseline +import scipy.linalg + +# GENERAL PARAMETERS - SET THESE APPROPRIATELY +model_path = 'checkpoints' # path to save model weights to +weight_save_freq = 10 # how frequently (in epochs, e.g. every 10 epochs) to save weights to disk +tf.set_random_seed(1) + +########DATASET-SPECIFIC PARAMETERS: CHOOSE THIS BLOCK FOR MNIST +# DATA_DESC = 'MNIST'; (X_train, Y_train), (X_test, Y_test) = mnist.load_data() +# Y_train = np.squeeze(Y_train); Y_test = np.squeeze(Y_test) +# num_channels = 1; inp_shape = (28,28,1); num_classes=10 +##MODEL-SPECIFIC PARAMETERS: MNIST +##PARAMETERS RELATED TO SGD OPTIMIZATION +# epochs=150; batch_size=200; lr=3e-4; +##MODEL DEFINTION PARAMETERS +# num_filters_std = [64, 64, 64]; num_filters_ens=[32, 32, 32]; num_filters_ens_2=4; +# dropout_rate_std=0.0; dropout_rate_ens=0.0; weight_decay = 0 +# noise_stddev = 0.3; blend_factor=0.3; +# model_rep_baseline=1; model_rep_ens=2; +# DATA_AUGMENTATION_FLAG=0; BATCH_NORMALIZATION_FLAG=0 +########END: DATASET-SPECIFIC PARAMETERS: MNIST + + +##########DATASET-SPECIFIC PARAMETERS: CHOOSE THIS BLOCK FOR CIFAR10 +DATA_DESC = 'CIFAR10'; +(X_train, Y_train), (X_test, Y_test) = cifar10.load_data() +Y_train = np.squeeze(Y_train); +Y_test = np.squeeze(Y_test) +num_channels = 3; +inp_shape = (32, 32, 3); +num_classes = 10 +# MODEL-SPECIFIC PARAMETERS: CIFAR10 +# PARAMETERS RELATED TO SGD OPTIMIZATION +epochs = 400; +batch_size = 200; +lr = 2e-4; +# MODEL DEFINTION PARAMETERS +num_filters_std = [32, 64, 128]; +num_filters_ens = [32, 64, 128]; +num_filters_ens_2 = 16; +dropout_rate_std = 0.0; +dropout_rate_ens = 0.0; +weight_decay = 0 +noise_stddev = 0.032; +blend_factor = 0.032; +model_rep_baseline = 2; +model_rep_ens = 2; +DATA_AUGMENTATION_FLAG = 1; +BATCH_NORMALIZATION_FLAG = 1 +##########END: DATASET-SPECIFIC PARAMETERS: CIFAR10 + + +# DATA PRE-PROCESSING +X_train = (X_train / 255).astype(np.float32); +X_test = (X_test / 255).astype(np.float32); # scale data to (0,1) +X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2], + num_channels); +X_test = X_test.reshape(X_test.shape[0], X_test.shape[1], X_test.shape[2], + num_channels) +X_valid = X_test[0:1000]; +Y_valid = Y_test[ + 0:1000]; # validation data (to monitor accuracy during training) +X_train = X_train - 0.5; +X_test = X_test - 0.5; +X_valid = X_valid - 0.5; # map to range (-0.5,0.5) +data_dict = {'X_train': X_train, 'Y_train_cat': Y_train, 'X_test': X_test, + 'Y_test_cat': Y_test} + +### TRAIN MODEL. each block below corresponds to one of the models in Table 1 of the paper. In order to train, +# uncomment the final two lines of the block of interest and then run this script + +""" +### BASELINE SOFTMAX MODEL DEFINITION +name = 'softmax_baseline'+'_'+DATA_DESC; num_chunks=1 +M = np.eye(num_classes).astype(np.float32) +output_activation = 'softmax'; base_model=None +params_dict = {'weight_decay':weight_decay, 'num_filters_std':num_filters_std, 'BATCH_NORMALIZATION_FLAG':BATCH_NORMALIZATION_FLAG, 'DATA_AUGMENTATION_FLAG':DATA_AUGMENTATION_FLAG, 'M':M, 'model_rep':model_rep_baseline, 'base_model':base_model, 'num_chunks':num_chunks, 'output_activation':output_activation, 'batch_size':batch_size, 'epochs':epochs, 'lr':lr, 'dropout_rate':dropout_rate_std, 'blend_factor':blend_factor, 'inp_shape':inp_shape, 'noise_stddev':noise_stddev, 'weight_save_freq':weight_save_freq, 'name':name, 'model_path':model_path} +#m0 = Model_Softmax_Baseline(data_dict, params_dict) +#m0.defineModel(); m0.trainModel() + + +## BASELINE LOGISTIC MODEL DEFINITION +name = 'logistic_baseline'+'_'+DATA_DESC; num_chunks=1 +M = np.eye(num_classes).astype(np.float32) +output_activation = 'sigmoid'; base_model=None +params_dict = {'weight_decay':weight_decay, 'num_filters_std':num_filters_std, 'BATCH_NORMALIZATION_FLAG':BATCH_NORMALIZATION_FLAG, 'DATA_AUGMENTATION_FLAG':DATA_AUGMENTATION_FLAG, 'M':M, 'model_rep':model_rep_baseline, 'base_model':base_model, 'num_chunks':num_chunks, 'output_activation':output_activation, 'batch_size':batch_size, 'epochs':epochs, 'lr':lr, 'dropout_rate':dropout_rate_std, 'blend_factor':blend_factor, 'inp_shape':inp_shape, 'noise_stddev':noise_stddev, 'weight_save_freq':weight_save_freq, 'name':name, 'model_path':model_path} +#m1 = Model_Logistic_Baseline(data_dict, params_dict) +#m1.defineModel(); m1.trainModel() + + +## BASELINE TANH MODEL DEFINITION +name = 'Tanh_baseline_16'+'_'+DATA_DESC; seed = 59; num_chunks=1; code_length=16; num_codes=num_classes; code_length_true=code_length +M = scipy.linalg.hadamard(code_length).astype(np.float32) +M[np.arange(0, num_codes,2), 0]= -1#replace first col, which for this Hadamard construction is always 1, hence not a useful bit +np.random.seed(seed); np.random.shuffle(M) +idx=np.random.permutation(code_length) +M = M[0:num_codes, idx[0:code_length_true]] +base_model=None +def output_activation(x): + return tf.nn.tanh(x) +params_dict = {'weight_decay':weight_decay, 'num_filters_std':num_filters_std, 'BATCH_NORMALIZATION_FLAG':BATCH_NORMALIZATION_FLAG, 'DATA_AUGMENTATION_FLAG':DATA_AUGMENTATION_FLAG, 'M':M, 'model_rep':model_rep_baseline, 'base_model':base_model, 'num_chunks':num_chunks, 'output_activation':output_activation, 'batch_size':batch_size, 'epochs':epochs, 'dropout_rate':dropout_rate_std, 'lr':lr, 'blend_factor':blend_factor, 'inp_shape':inp_shape, 'noise_stddev':noise_stddev, 'weight_save_freq':weight_save_freq, 'name':name, 'model_path':model_path} +#m2 = Model_Tanh_Baseline(data_dict, params_dict) +#m2.defineModel(); m2.trainModel() + +## ENSEMBLE LOGISTIC MODEL DEFINITION +name = 'logistic_diverse'+'_'+DATA_DESC; num_chunks=2 +M = np.eye(num_classes).astype(np.float32) +base_model=None +def output_activation(x): + return tf.nn.sigmoid(x) +params_dict = {'BATCH_NORMALIZATION_FLAG':BATCH_NORMALIZATION_FLAG, 'DATA_AUGMENTATION_FLAG':DATA_AUGMENTATION_FLAG, 'M':M, 'base_model':base_model, 'num_chunks':num_chunks, 'model_rep': model_rep_ens, 'output_activation':output_activation, 'num_filters_ens':num_filters_ens, 'num_filters_ens_2':num_filters_ens_2,'batch_size':batch_size, 'epochs':epochs, 'dropout_rate':dropout_rate_ens, 'lr':lr, 'blend_factor':blend_factor, 'inp_shape':inp_shape, 'noise_stddev':noise_stddev, 'weight_save_freq':weight_save_freq, 'name':name, 'model_path':model_path} +#m3 = Model_Logistic_Ensemble(data_dict, params_dict) +#m3.defineModel(); m3.trainModel() + + + +#COMMENTS FOR ALL TANH ENSEMBLE MODELS: +#1. num_chunks refers to how many models comprise the ensemble (4 is used in the paper); code_length/num_chunks shoould be an integer +#2. output_activation is the function to apply to the logits +# a. one can use anything which gives support to positive and negative values (since output code has +1/-1 elements); tanh or identity maps both work +# b. in order to alleviate potential concerns of gradient masking with tanh, one can use identity as well +#3. M is the actual coding matrix (referred to in the paper as H). Each row is a codeword +# note that any random shuffle of a Hadmard matrix's rows or columns is still orthogonal +#4. There is nothing particularly special about the seed (which effectively determines the coding matrix). +# We tried several seeds from 0-60 and found that all give comparable model performance (e.g. benign and adversarial accuracy). + +## ENSEMBLE TANH 16 MODEL DEFINITION +name = 'tanh_16_diverse'+'_'+DATA_DESC; seed = 59; code_length=16; num_codes=code_length; num_chunks=4; base_model=None; +def output_activation(x): + return tf.nn.tanh(x) +M = scipy.linalg.hadamard(code_length).astype(np.float32) +M[np.arange(0, num_codes,2), 0]= -1#replace first col, which for scipy's Hadamard construction is always 1, hence not a useful classifier; this change still ensures all codewords have dot product <=0; since our decoder ignores negative correlations anyway, this has no net effect on probability estimation +np.random.seed(seed) +np.random.shuffle(M) +idx=np.random.permutation(code_length) +M = M[0:num_codes, idx[0:code_length]] +params_dict = {'BATCH_NORMALIZATION_FLAG':BATCH_NORMALIZATION_FLAG, 'DATA_AUGMENTATION_FLAG':DATA_AUGMENTATION_FLAG, 'M':M, 'base_model':base_model, 'num_chunks':num_chunks, 'model_rep': model_rep_ens, 'output_activation':output_activation, 'num_filters_ens':num_filters_ens, 'num_filters_ens_2':num_filters_ens_2,'batch_size':batch_size, 'epochs':epochs, 'dropout_rate':dropout_rate_ens, 'lr':lr, 'blend_factor':blend_factor, 'inp_shape':inp_shape, 'noise_stddev':noise_stddev, 'weight_save_freq':weight_save_freq, 'name':name, 'model_path':model_path} +#m4 = Model_Tanh_Ensemble(data_dict, params_dict) +#m4.defineModel(); m4.trainModel() +""" + +## ENSEMBLE TANH 32 MODEL DEFINITION +name = 'tanh_32_diverse' + '_' + DATA_DESC; +seed = 59; +code_length = 32; +num_codes = code_length; +num_chunks = 4; +base_model = None; + + +def output_activation(x): + return tf.nn.tanh(x) + + +M = scipy.linalg.hadamard(code_length).astype(np.float32) +M[np.arange(0, num_codes, + 2), 0] = -1 # replace first col, which for scipy's Hadamard construction is always 1, hence not a useful classifier; this change still ensures all codewords have dot product <=0; since our decoder ignores negative correlations anyway, this has no net effect on probability estimation +np.random.seed(seed) +np.random.shuffle(M) +idx = np.random.permutation(code_length) +M = M[0:num_codes, idx[0:code_length]] +params_dict = {'BATCH_NORMALIZATION_FLAG': BATCH_NORMALIZATION_FLAG, + 'DATA_AUGMENTATION_FLAG': DATA_AUGMENTATION_FLAG, 'M': M, + 'base_model': base_model, 'num_chunks': num_chunks, + 'model_rep': model_rep_ens, + 'output_activation': output_activation, + 'num_filters_ens': num_filters_ens, + 'num_filters_ens_2': num_filters_ens_2, 'batch_size': batch_size, + 'epochs': epochs, 'dropout_rate': dropout_rate_ens, 'lr': lr, + 'blend_factor': blend_factor, 'inp_shape': inp_shape, + 'noise_stddev': noise_stddev, + 'weight_save_freq': weight_save_freq, 'name': name, + 'model_path': model_path} +m5 = Model_Tanh_Ensemble(data_dict, params_dict) +m5.defineModel(); +m5.trainModel() diff --git a/case_studies/error_correcting_codes/adversarial_evaluation.py b/case_studies/error_correcting_codes/adversarial_evaluation.py new file mode 100644 index 0000000..bd28850 --- /dev/null +++ b/case_studies/error_correcting_codes/adversarial_evaluation.py @@ -0,0 +1,285 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Run this to attack a trained model via TrainModel. +Use the "loadFullModel" submethod to load in an already trained model (trained via TrainModel) +The main attack function is "runAttacks" which runs attacks on trained models +""" + +import logging +logging.getLogger('tensorflow').setLevel(logging.FATAL) +import tensorflow as tf +tf.logging.set_verbosity(tf.logging.ERROR) + +from cleverhans.attacks import ProjectedGradientDescent +from Model_Implementations import Model_Softmax_Baseline, \ + Model_Logistic_Baseline, Model_Logistic_Ensemble, Model_Tanh_Ensemble, \ + Model_Tanh_Baseline +from tensorflow.keras.datasets import cifar10 +from tensorflow.keras import backend +import tensorflow as tf; +import numpy as np +import scipy.linalg + +model_path = 'checkpoints/ECOC/tanh32/checkpoints' #path with saved model parameters + +def setup_model_and_data(adaptive_attack=False): + print("Modifying model for adaptive attack:", adaptive_attack) + # Dataset-specific parameters - should be same as those used in TrainModel + DATA_DESC = 'CIFAR10'; + (X_train, Y_train), (X_test, Y_test) = cifar10.load_data() + epochs = None; + weight_save_freq = None + num_classes = 10 # how many classes (categories) are in this dataset? + Y_train = np.squeeze(Y_train); + Y_test = np.squeeze(Y_test) + num_filters_std = [32, 64, 128]; + num_filters_ens = [32, 64, 128]; + num_filters_ens_2 = 16; + dropout_rate_std = 0.0; + dropout_rate_ens = 0.0; + weight_decay = 0 + model_rep_baseline = 2; + model_rep_ens = 2; + DATA_AUGMENTATION_FLAG = 1; + BATCH_NORMALIZATION_FLAG = 1 + num_channels = 3; + inp_shape = (32, 32, 3); + lr = 1e-4; + batch_size = 80; + noise_stddev = 0.032; + blend_factor = .032 + + # DATA PRE-PROCESSING + X_train = (X_train / 255).astype(np.float32); + X_test = (X_test / 255).astype(np.float32) + # reshape (add third (image) channel) + X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], + X_train.shape[2], + num_channels); + X_test = X_test.reshape(X_test.shape[0], X_test.shape[1], X_test.shape[2], + num_channels) + X_valid = X_test[1000:2000]; + Y_valid = Y_test[1000:2000]; # validation data, used to attack model + + ## ENSEMBLE TANH 32 MODEL DEFINITION + name = 'tanh_32_diverse' + '_' + DATA_DESC; + seed = 59; + code_length = 32; + num_codes = code_length; + num_chunks = 4; + base_model = None; + + def output_activation(x): + if adaptive_attack: + return x + else: + return tf.nn.tanh(x) + + M = scipy.linalg.hadamard(code_length).astype(np.float32) + M[np.arange(0, num_codes, + 2), 0] = -1 # replace first col, which for scipy's Hadamard construction is always 1, hence not a useful classifier; this change still ensures all codewords have dot product <=0; since our decoder ignores negative correlations anyway, this has no net effect on probability estimation + np.random.seed(seed) + np.random.shuffle(M) + idx = np.random.permutation(code_length) + M = M[0:num_codes, idx[0:code_length]] + params_dict = {'BATCH_NORMALIZATION_FLAG': BATCH_NORMALIZATION_FLAG, + 'DATA_AUGMENTATION_FLAG': DATA_AUGMENTATION_FLAG, 'M': M, + 'base_model': base_model, 'num_chunks': num_chunks, + 'model_rep': model_rep_ens, + 'output_activation': output_activation, + 'num_filters_ens': num_filters_ens, + 'num_filters_ens_2': num_filters_ens_2, 'batch_size': batch_size, + 'epochs': epochs, 'dropout_rate': dropout_rate_ens, 'lr': lr, + 'blend_factor': blend_factor, 'inp_shape': inp_shape, + 'noise_stddev': noise_stddev, + 'weight_save_freq': weight_save_freq, 'name': name, + 'model_path': model_path, + 'zero_one_input': True, + 'adaptive_attack': adaptive_attack + } + m5 = Model_Tanh_Ensemble({}, params_dict) + m5.loadFullModel() # load in the saved model, which should have already been trained first via TrainModel + + m5.legend = 'TEns32'; + + model = m5 + + return model, (X_valid, Y_valid), (X_test, Y_test) + + +def wbAttack(sess, model, x_ph, x_adv_op, X, Y, batch_size=500, verbose=True): + n_correct = 0 + n_total = 0 + all_logits = [] + all_x_adv = [] + import tqdm + pbar = np.arange(0, X.shape[0], batch_size) + if verbose: + pbar = tqdm.tqdm(pbar) + + for start_idx in pbar: + x = X[start_idx:start_idx + batch_size] + y = Y[start_idx:start_idx + batch_size] + x_adv = sess.run(x_adv_op, {x_ph: x}) + logits = sess.run(model.logits, {model.input: x_adv}) + preds = np.argmax(logits, -1) + n_correct += np.sum(np.equal(preds, y)) + n_total += len(x) + all_logits.append(logits) + all_x_adv.append(x_adv) + + all_x_adv = np.concatenate(all_x_adv, 0) + all_logits = np.concatenate(all_logits, 0) + + adv_acc = n_correct / n_total + return adv_acc, all_logits, all_x_adv + + +def patch_pgd_loss(): + import cleverhans + + def fgm(x, + logits, + y=None, + eps=0.3, + ord=np.inf, + clip_min=None, + clip_max=None, + targeted=False, + sanity_checks=True): + + asserts = [] + + # If a data range was specified, check that the input was in that range + if clip_min is not None: + asserts.append(cleverhans.utils_tf.assert_greater_equal( + x, tf.cast(clip_min, x.dtype))) + + if clip_max is not None: + asserts.append(cleverhans.utils_tf.assert_less_equal(x, tf.cast(clip_max, x.dtype))) + + # Make sure the caller has not passed probs by accident + assert logits.op.type != 'Softmax' + + if y is None: + # Using model predictions as ground truth to avoid label leaking + preds_max = tf.reduce_max(logits, 1, keepdims=True) + y = tf.to_float(tf.equal(logits, preds_max)) + y = tf.stop_gradient(y) + y = y / tf.reduce_sum(y, 1, keepdims=True) + + # Compute loss + loss = loss_fn(labels=y, logits=logits) + if targeted: + loss = -loss + + # loss = tf.Print(loss, [loss]) + + # Define gradient of loss wrt input + grad, = tf.gradients(loss, x) + + optimal_perturbation = cleverhans.attacks.optimize_linear(grad, eps, ord) + + # Add perturbation to original example to obtain adversarial example + adv_x = x + optimal_perturbation + + # If clipping is needed, reset all values outside of [clip_min, clip_max] + if (clip_min is not None) or (clip_max is not None): + # We don't currently support one-sided clipping + assert clip_min is not None and clip_max is not None + adv_x = cleverhans.utils_tf.clip_by_value(adv_x, clip_min, clip_max) + + if sanity_checks: + with tf.control_dependencies(asserts): + adv_x = tf.identity(adv_x) + + return adv_x + + def loss_fn(sentinel=None, + labels=None, + logits=None, + dim=-1): + """ + Wrapper around tf.nn.softmax_cross_entropy_with_logits_v2 to handle + deprecated warning + """ + # Make sure that all arguments were passed as named arguments. + if sentinel is not None: + name = "softmax_cross_entropy_with_logits" + raise ValueError("Only call `%s` with " + "named arguments (labels=..., logits=..., ...)" + % name) + if labels is None or logits is None: + raise ValueError("Both labels and logits must be provided.") + + labels = tf.stop_gradient(labels) + # modified from + # https://github.com/carlini/nn_robust_attacks/blob/master/li_attack.py + real = tf.reduce_sum(labels * logits, -1) + other = tf.reduce_max((1-labels) * logits - (labels*10000), -1) + + loss = other - real + + # loss = tf.Print(loss, [loss]) + + return loss + + cleverhans.attacks.fgm = fgm + +def main(): + sess = backend.get_session() + backend.set_learning_phase( + 0) # need to do this to get CleverHans to work with batchnorm + + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("--eps", type=float, default=8, help="in 0-255") + parser.add_argument("--pgd-n-steps", default=200, type=int) + parser.add_argument("--pgd-step-size", type=float, default=2 / 3 * 8, help="in 0-255") + parser.add_argument("--n-samples", type=int, default=512) + parser.add_argument("--adaptive-attack", action="store_true") + args = parser.parse_args() + + model, (X_valid, Y_valid), (X_test, Y_test) = setup_model_and_data(adaptive_attack=args.adaptive_attack) + + test_indices = list(range(len(X_test))) + np.random.shuffle(test_indices) + X_test, Y_test = X_test[test_indices], Y_test[test_indices] + + X_test, Y_test = X_test[:args.n_samples], Y_test[:args.n_samples] + + model_ch = model.modelCH() + attack = ProjectedGradientDescent(model_ch, sess=sess) + att_params = {'clip_min': 0.0, 'clip_max': 1.0, + 'eps': args.eps / 255.0, 'eps_iter': args.pgd_step_size / 255.0, + 'nb_iter': args.pgd_n_steps, 'ord': np.inf, + } + if args.adaptive_attack: + patch_pgd_loss() + + x_ph = tf.placeholder(shape=model.input.shape, dtype=tf.float32) + x_adv_op = attack.generate(x_ph, **att_params) + adv_acc, all_logits, all_x_adv = wbAttack(sess, model, + x_ph, x_adv_op, + X_test, Y_test, batch_size=512) + + print("Robust accuracy:", adv_acc) + + +if __name__ == "__main__": + main() diff --git a/case_studies/error_correcting_codes/binarization_test.py b/case_studies/error_correcting_codes/binarization_test.py new file mode 100644 index 0000000..efff695 --- /dev/null +++ b/case_studies/error_correcting_codes/binarization_test.py @@ -0,0 +1,219 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Run this to attack a trained model via TrainModel. +Use the "loadFullModel" submethod to load in an already trained model (trained via TrainModel) +The main attack function is "runAttacks" which runs attacks on trained models +""" +import warnings + +import torch +from cleverhans.attacks import ProjectedGradientDescent +from torch.utils.data import DataLoader +from torch.utils.data import TensorDataset + +from Model_Implementations import Model_Softmax_Baseline, \ + Model_Logistic_Baseline, Model_Logistic_Ensemble, Model_Tanh_Ensemble, \ + Model_Tanh_Baseline +from tensorflow.keras.datasets import cifar10 +from tensorflow.keras import backend +import tensorflow as tf; +import numpy as np +import scipy.linalg +from adversarial_evaluation import setup_model_and_data, patch_pgd_loss +from active_tests import decision_boundary_binarization as dbb +from functools import partial + +from tensorflow_wrapper import TensorFlow1ToPyTorchWrapper +from utils import build_dataloader_from_arrays + + +def train_classifier( + n_features: int, + train_loader: DataLoader, + raw_train_loader: DataLoader, + logits: torch.Tensor, + device: str, + rescale_logits: dbb.LogitRescalingType, + model, + sess, +): + del raw_train_loader + + # fit a linear readout for each of the submodels of the ensemble + assert len(train_loader.dataset.tensors[0].shape) == 3 + assert train_loader.dataset.tensors[0].shape[1] == len(model.binarized_readouts) + + classifier_weights = [] + classifier_biases = [] + for i in range(len(model.binarized_readouts)): + x_ = train_loader.dataset.tensors[0][:, i] + y_ = train_loader.dataset.tensors[1] + + cls = dbb._train_logistic_regression_classifier( + n_features, + DataLoader(TensorDataset(x_, y_), batch_size=train_loader.batch_size), + logits[:, i] if logits is not None else None, + "sklearn", + 20000, + device, + n_classes=2, + rescale_logits=rescale_logits, + solution_goodness="good", + class_weight="balanced" + ) + classifier_weights.append(cls.weight.data.cpu().numpy().transpose()[:, [0]]) + classifier_biases.append(cls.bias.data.cpu().numpy()[0]) + + # update weights of the binary models + for l, vw, vb in zip(model.binarized_readouts, classifier_weights, classifier_biases): + l.set_weights([vw, vb.reshape((1,))]) + + return BinarizedModelWrapper(model, sess) + + +class BinarizedModelWrapper: + def __init__(self, model, sess): + self.model = model + self.sess = sess + + def __call__(self, x): + x = x.numpy() + x = x.transpose((0, 2, 3, 1)) + p = self.sess.run(self.model.binarized_probs, {self.model.input: x}) + return torch.tensor(p) + + +def main(): + sess = backend.get_session() + backend.set_learning_phase( + 0) # need to do this to get CleverHans to work with batchnorm + + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("--eps", type=float, default=8, help="in 0-255") + parser.add_argument("--pgd-n-steps", default=200, type=int) + parser.add_argument("--pgd-step-size", type=float, default=2 / 3 * 8, help="in 0-255") + + parser.add_argument("--n-samples", type=int, default=512) + parser.add_argument("--adaptive-attack", action="store_true") + + parser.add_argument("-n-inner-points", type=int, default=999) + parser.add_argument("-n-boundary-points", type=int, default=1) + parser.add_argument("--sample-from-corners", action="store_true") + args = parser.parse_args() + + model, (X_valid, Y_valid), (X_test, Y_test) = setup_model_and_data(adaptive_attack=args.adaptive_attack) + model.defineBinarizedModel() + binarized_model_ch = model.modelBinarizedCH() + + if args.adaptive_attack: + patch_pgd_loss() + + attack = ProjectedGradientDescent(binarized_model_ch, sess=sess) + att_params = {'clip_min': 0.0, 'clip_max': 1.0, + 'eps': args.eps / 255.0, 'eps_iter': args.pgd_step_size / 255.0, + 'nb_iter': args.pgd_n_steps, 'ord': np.inf} + x_ph = tf.placeholder(shape=model.input.shape, dtype=tf.float32) + x_adv_op = attack.generate(x_ph, **att_params) + + def _model_forward_pass(x_np, features_only=False, features_and_logits=False): + x_np = np.transpose(x_np, (0, 2, 3, 1)) + + if features_only: + f = sess.run(model.features, {model.input : x_np}) + f = np.stack(f, 1) + return f + elif features_and_logits: + f, l = sess.run((model.features, + model.logits), {model.input : x_np}) + f = np.stack(f, 1) + return f, l + else: + l = sess.run(model.logits, {model.input : x_np}) + return l + + + def run_attack(m, l, sess): + model = m.model + for x, y in l: + assert len(x) == 1 + x, y = x.numpy(), y.numpy() + x = x.transpose((0, 2, 3, 1)) + x_adv = sess.run(x_adv_op, {x_ph: x}) + + warnings.warn("ATTENTION: Clipping perturbation just to TEST something. Remove this again!") + delta = x_adv - x + delta[delta > 0] = args.eps / 255.0 + delta[delta < 0] = -args.eps / 255.0 + x_adv = np.clip(x + delta, 0, 1) + + logits, probs = sess.run((model.binarized_logit, model.binarized_probs), + {model.input: x_adv}) + is_adv = np.argmax(probs) != y + return is_adv, (torch.tensor(x_adv.transpose((0, 3, 1, 2))), torch.tensor(logits)) + + feature_extractor = TensorFlow1ToPyTorchWrapper( + logit_forward_pass=_model_forward_pass, + logit_forward_and_backward_pass=None + ) + + test_indices = list(range(len(X_test))) + np.random.shuffle(test_indices) + X_test, Y_test = X_test[test_indices], Y_test[test_indices] + + X_test = np.transpose(X_test, (0, 3, 1, 2)) + test_loader = build_dataloader_from_arrays(X_test, Y_test, batch_size=32) + + from argparse_utils import DecisionBoundaryBinarizationSettings + scores_logit_differences_and_validation_accuracies = \ + dbb.interior_boundary_discrimination_attack( + feature_extractor, + test_loader, + attack_fn=lambda m, l, kwargs: run_attack(m, l, sess), + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=args.eps / 255.0, + norm="linf", + lr=25000, + n_boundary_points=args.n_boundary_points, + n_inner_points=args.n_inner_points, + adversarial_attack_settings=None, + optimizer="sklearn" + ), + n_samples=args.n_samples, + device="cpu", + n_samples_evaluation=200, + n_samples_asr_evaluation=200, + train_classifier_fn=partial( + train_classifier, + model=model, + sess=sess + ), + fail_on_exception=False, + # needs to be set to None as logit rescaling introduces a weird behavior + # of very high R. ASR (probably due to the log in the logit calculation) + rescale_logits=None, + decision_boundary_closeness=0.999, + sample_training_data_from_corners=args.sample_from_corners + + ) + + print(dbb.format_result(scores_logit_differences_and_validation_accuracies, + args.n_samples)) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/case_studies/error_correcting_codes/binarization_test.sh b/case_studies/error_correcting_codes/binarization_test.sh new file mode 100644 index 0000000..013b778 --- /dev/null +++ b/case_studies/error_correcting_codes/binarization_test.sh @@ -0,0 +1,28 @@ +nsamples=${1:-512} +epsilon=${2:-8} + +kwargs="" +kwargs="--sample-from-corners" + +echo "#samples: $nsamples" +echo "epsilon: $epsilon" +echo "kwargs: $kwargs" + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "1 boundary point, 999 inner (Original attack)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python case_studies/error_correcting_codes/binarization_test.py \ + --n-samples=$nsamples \ + --eps=$epsilon \ + $kwargs + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "1 boundary point, 999 inner (Adaptive attack)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python case_studies/error_correcting_codes/binarization_test.py \ + --n-samples=$nsamples \ + --adaptive-attack \ + --pgd-n-steps=200 \ + --pgd-step-size=0.50 \ + --eps=$epsilon \ + $kwargs diff --git a/case_studies/error_correcting_codes/utils_keras.py b/case_studies/error_correcting_codes/utils_keras.py new file mode 100644 index 0000000..b5ae70a --- /dev/null +++ b/case_studies/error_correcting_codes/utils_keras.py @@ -0,0 +1,257 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Model construction utilities based on keras +""" + +from distutils.version import LooseVersion + +# modified to work with error-correcting codes +#import keras +#from keras.models import Sequential +#from keras.layers import Dense, Activation, Flatten + +from tensorflow import keras +from tensorflow.keras.models import Sequential +from tensorflow.keras.layers import Dense, Activation, Flatten + +from cleverhans.model import Model, NoSuchLayerError + +if LooseVersion(keras.__version__) >= LooseVersion('2.0.0'): + from keras.layers import Conv2D +else: + from keras.layers import Convolution2D + + +def conv_2d(filters, kernel_shape, strides, padding, input_shape=None): + """ + Defines the right convolutional layer according to the + version of Keras that is installed. + :param filters: (required integer) the dimensionality of the output + space (i.e. the number output of filters in the + convolution) + :param kernel_shape: (required tuple or list of 2 integers) specifies + the strides of the convolution along the width and + height. + :param padding: (required string) can be either 'valid' (no padding around + input or feature map) or 'same' (pad to ensure that the + output feature map size is identical to the layer input) + :param input_shape: (optional) give input shape if this is the first + layer of the model + :return: the Keras layer + """ + if LooseVersion(keras.__version__) >= LooseVersion('2.0.0'): + if input_shape is not None: + return Conv2D(filters=filters, kernel_size=kernel_shape, + strides=strides, padding=padding, + input_shape=input_shape) + else: + return Conv2D(filters=filters, kernel_size=kernel_shape, + strides=strides, padding=padding) + else: + if input_shape is not None: + return Convolution2D(filters, kernel_shape[0], kernel_shape[1], + subsample=strides, border_mode=padding, + input_shape=input_shape) + else: + return Convolution2D(filters, kernel_shape[0], kernel_shape[1], + subsample=strides, border_mode=padding) + + +def cnn_model(logits=False, input_ph=None, img_rows=28, img_cols=28, + channels=1, nb_filters=64, nb_classes=10): + """ + Defines a CNN model using Keras sequential model + :param logits: If set to False, returns a Keras model, otherwise will also + return logits tensor + :param input_ph: The TensorFlow tensor for the input + (needed if returning logits) + ("ph" stands for placeholder but it need not actually be a + placeholder) + :param img_rows: number of row in the image + :param img_cols: number of columns in the image + :param channels: number of color channels (e.g., 1 for MNIST) + :param nb_filters: number of convolutional filters per layer + :param nb_classes: the number of output classes + :return: + """ + model = Sequential() + + # Define the layers successively (convolution layers are version dependent) + if keras.backend.image_dim_ordering() == 'th': + input_shape = (channels, img_rows, img_cols) + else: + input_shape = (img_rows, img_cols, channels) + + layers = [conv_2d(nb_filters, (8, 8), (2, 2), "same", + input_shape=input_shape), + Activation('relu'), + conv_2d((nb_filters * 2), (6, 6), (2, 2), "valid"), + Activation('relu'), + conv_2d((nb_filters * 2), (5, 5), (1, 1), "valid"), + Activation('relu'), + Flatten(), + Dense(nb_classes)] + + for layer in layers: + model.add(layer) + + if logits: + logits_tensor = model(input_ph) + model.add(Activation('softmax')) + + if logits: + return model, logits_tensor + else: + return model + + +class KerasModelWrapper(Model): + """ + An implementation of `Model` that wraps a Keras model. It + specifically exposes the hidden features of a model by creating new models. + The symbolic graph is reused and so there is little overhead. Splitting + in-place operations can incur an overhead. + """ + + def __init__(self, model): + """ + Create a wrapper for a Keras model + :param model: A Keras model + """ + super(KerasModelWrapper, self).__init__(None, None, {}) + + if model is None: + raise ValueError('model argument must be supplied.') + + self.model = model + self.keras_model = None + + def _get_softmax_name(self): + """ + Looks for the name of the softmax layer. + :return: Softmax layer name + """ + for layer in self.model.layers: + cfg = layer.get_config() + if 'activation' in cfg and cfg['activation'] == 'softmax': + return layer.name + + raise Exception("No softmax layers found") + + def _get_logits_name(self): + """ + Looks for the name of the layer producing the logits. + :return: name of layer producing the logits + """ + softmax_name = self._get_softmax_name() + softmax_layer = self.model.get_layer(softmax_name) + + if not isinstance(softmax_layer, Activation): + # In this case, the activation is part of another layer + return softmax_name + + if not hasattr(softmax_layer, '_inbound_nodes'): + raise RuntimeError("Please update keras to version >= 2.1.3") + + node = softmax_layer._inbound_nodes[0] + + # modified for error-correcting codes, first line was original + if isinstance(node.inbound_layers, (list, tuple)): + logits_name = node.inbound_layers[0].name + else: + logits_name = node.inbound_layers.name + return logits_name + + def get_logits(self, x): + """ + :param x: A symbolic representation of the network input. + :return: A symbolic representation of the logits + """ + logits_name = self._get_logits_name() + logits_layer = self.get_layer(x, logits_name) + + # Need to deal with the case where softmax is part of the + # logits layer + if logits_name == self._get_softmax_name(): + softmax_logit_layer = self.get_layer(x, logits_name) + + # The final op is the softmax. Return its input + logits_layer = softmax_logit_layer._op.inputs[0] + + return logits_layer + + def get_probs(self, x): + """ + :param x: A symbolic representation of the network input. + :return: A symbolic representation of the probs + """ + name = self._get_softmax_name() + + return self.get_layer(x, name) + + def get_layer_names(self): + """ + :return: Names of all the layers kept by Keras + """ + layer_names = [x.name for x in self.model.layers] + return layer_names + + def fprop(self, x): + """ + Exposes all the layers of the model returned by get_layer_names. + :param x: A symbolic representation of the network input + :return: A dictionary mapping layer names to the symbolic + representation of their output. + """ + # modified to work with error-correcting codes defense + from tensorflow.keras.models import Model as KerasModel + + if self.keras_model is None: + # Get the input layer + new_input = self.model.get_input_at(0) + + # Make a new model that returns each of the layers as output + out_layers = [x_layer.output for x_layer in self.model.layers] + self.keras_model = KerasModel(new_input, out_layers) + + # and get the outputs for that model on the input x + outputs = self.keras_model(x) + + # Keras only returns a list for outputs of length >= 1, if the model + # is only one layer, wrap a list + if len(self.model.layers) == 1: + outputs = [outputs] + + # compute the dict to return + fprop_dict = dict(zip(self.get_layer_names(), outputs)) + + return fprop_dict + + def get_layer(self, x, layer): + """ + Expose the hidden features of a model given a layer name. + :param x: A symbolic representation of the network input + :param layer: The name of the hidden layer to return features at. + :return: A symbolic representation of the hidden features + :raise: NoSuchLayerError if `layer` is not in the model. + """ + # Return the symbolic representation for this layer. + output = self.fprop(x) + try: + requested = output[layer] + except KeyError: + raise NoSuchLayerError() + return requested \ No newline at end of file diff --git a/case_studies/evaluate_classifier.py b/case_studies/evaluate_classifier.py new file mode 100644 index 0000000..178d6f5 --- /dev/null +++ b/case_studies/evaluate_classifier.py @@ -0,0 +1,734 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import argparse +import copy +import textwrap +from typing import List +from typing import Tuple +from typing import Union + +import numpy as np +import torch +import torch.nn.functional as F +import torch.utils.data +import torchvision +import tqdm +from torchvision import transforms +from typing_extensions import Literal +import warnings + +import active_tests.decision_boundary_binarization as dbl +import argparse_utils +import argparse_utils as aut +import networks +from attacks import adaptive_kwta_attack +from attacks import autopgd +from attacks import fab +from attacks import pgd +from attacks import thermometer_ls_pgd + + +LossType = Union[Literal["ce"], Literal["logit-diff"]] + + +def parse_arguments(): + """Parse arguments.""" + parser = argparse.ArgumentParser("Evaluation Script") + parser.add_argument( + "-ds", "--dataset", choices=("cifar10", "imagenet"), default="cifar10" + ) + parser.add_argument("-bs", "--batch-size", default=128, type=int) + parser.add_argument("-ns", "--n-samples", default=512, type=int) + parser.add_argument("-i", "--input", required=True, type=str) + parser.add_argument("-d", "--device", default=None, type=str) + parser.add_argument( + "-c", + "--classifier", + default="networks.cifar_resnet18", + type=argparse_utils.parse_classifier_argument, + ) + parser.add_argument("-cin", "--classifier-input-noise", default=0.0, type=float) + parser.add_argument("-cgn", "--classifier-gradient-noise", default=0.0, type=float) + parser.add_argument("-cls", "--classifier-logit-scale", default=1.0, type=float) + parser.add_argument( + "-cinorm", "--classifier-input-normalization", action="store_true" + ) + parser.add_argument( + "-cijq", + "--classifier-input-jpeg-quality", + default=100, + type=int, + help="Setting a negative value leads to a differentiable JPEG version", + ) + parser.add_argument( + "-cigb", "--classifier-input-gaussian-blur-stddev", default=0.0, type=float + ) + + parser.add_argument( + "-a", + "--adversarial-attack", + type=aut.parse_adversarial_attack_argument, + default=None, + ) + + parser.add_argument( + "-dbl", + "--decision-boundary-binarization", + type=aut.parse_decision_boundary_binarization_argument, + default=None, + ) + parser.add_argument("--dbl-sample-from-corners", action="store_true") + + parser.add_argument("-nfs", "--n-final-softmax", default=1, type=int) + parser.add_argument("-ciusvt", "--classifier-input-usvt", action="store_true") + parser.add_argument("--no-ce-loss", action="store_true") + parser.add_argument("--no-logit-diff-loss", action="store_true") + parser.add_argument("--no-clean-evaluation", action="store_true") + args = parser.parse_args() + + assert not ( + args.no_ce_loss and args.no_logit_diff_loss + ), "Only one loss can be disabled" + + print("Detected type of tests to run:") + if args.adversarial_attack is not None: + print("\tadversarial attack:", args.adversarial_attack) + + if args.decision_boundary_binarization is not None: + print( + "\tinterior-vs-boundary discrimination:", + args.decision_boundary_binarization, + ) + + print() + + return args + + +def setup_dataloader( + dataset: Union[Literal["cifar10", "imagenet"]], batch_size: int +) -> torch.utils.data.DataLoader: + if dataset == "cifar10": + transform_test = transforms.Compose([transforms.ToTensor()]) + create_dataset_fn = lambda download: torchvision.datasets.CIFAR10( + root="./data/cifar10", + train=False, + download=download, + transform=transform_test, + ) + elif dataset == "imagenet": + transform_test = transforms.Compose( + [transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor()] + ) + create_dataset_fn = lambda _: torchvision.datasets.ImageNet( + root="./data/imagenet", split="val", transform=transform_test + ) + else: + raise ValueError("Invalid value for dataset.") + try: + testset = create_dataset_fn(False) + except: + testset = create_dataset_fn(True) + + testloader = torch.utils.data.DataLoader( + testset, batch_size=batch_size, shuffle=True, num_workers=8 + ) + + return testloader + + +def main(): + args = parse_arguments() + + if args.input == "pretrained": + assert args.dataset == "imagenet" + classifier = args.classifier(pretrained=True) + print("Base Classifier:", args.classifier.__name__) + else: + classifier = args.classifier( + **({"pretrained": False} if args.dataset == "imagenet" else {}) + ) + print("Base Classifier:", args.classifier.__name__) + + print("Loading checkpoint:", args.input) + state_dict = torch.load(args.input, map_location="cpu") + if "classifier" in state_dict: + classifier_state_dict = state_dict["classifier"] + else: + classifier_state_dict = state_dict + try: + classifier.load_state_dict(classifier_state_dict) + except RuntimeError as ex: + print( + f"Could not load weights due to error: " + f"{textwrap.shorten(str(ex), width=50, placeholder='...')}" + ) + print("Trying to remap weights by removing 'module.' namespace") + modified_classifier_state_dict = { + (k[len("module.") :] if k.startswith("module.") else k): v + for k, v in classifier_state_dict.items() + } + try: + classifier.load_state_dict(modified_classifier_state_dict) + print("Successfully loaded renamed weights.") + except RuntimeError: + print("Remapping weights did also not work. Initial error:") + raise ex + classifier.train(False) + + test_loader = setup_dataloader(args.dataset, args.batch_size) + if args.device is None: + args.device = "cuda" if torch.cuda.is_available() else "cpu" + classifier = classifier.to(args.device) + + if args.classifier_input_normalization: + if args.dataset == "cifar10": + classifier = networks.InputNormalization( + classifier, + torch.tensor([0.4914, 0.4822, 0.4465]), + torch.tensor([0.2023, 0.1994, 0.2010]), + ) + elif args.dataset == "imagenet": + classifier = networks.InputNormalization( + classifier, + torch.tensor([0.485, 0.456, 0.406]), + torch.tensor([0.229, 0.224, 0.225]), + ) + else: + raise ValueError("Unknown dataset.") + + if args.classifier_input_noise > 0: + classifier = networks.GaussianNoiseInputModule( + classifier, args.classifier_input_noise + ) + if args.classifier_gradient_noise > 0: + classifier = networks.GaussianNoiseGradientModule( + classifier, args.classifier_gradient_noise + ) + + if args.classifier_input_jpeg_quality != 100: + if args.classifier_input_jpeg_quality > 0: + classifier = networks.JPEGForwardIdentityBackwardModule( + classifier, + args.classifier_input_jpeg_quality, + size=32 if args.dataset == "cifar10" else 224, + legacy=True, + ) + print("Using (slow) legacy JPEG mode") + else: + classifier = networks.DifferentiableJPEGModule( + classifier, + args.classifier_input_jpeg_quality, + size=32 if args.dataset == "cifar10" else 224, + ) + classifier = classifier.to(args.device) + + if args.classifier_input_gaussian_blur_stddev > 0: + classifier = networks.GausianBlurForwardIdentityBackwardModule( + classifier, 3, args.classifier_input_gaussian_blur_stddev + ) + + if args.classifier_input_usvt: + classifier = networks.UVSTModule(classifier) + + if args.classifier_logit_scale > 1: + classifier = networks.ScaledLogitsModule( + classifier, args.classifier_logit_scale + ) + + if args.n_final_softmax > 1: + classifier = torch.nn.Sequential( + classifier, *[torch.nn.Softmax() for _ in range(args.n_final_softmax)] + ) + + classifier = classifier.to(args.device) + + if not args.no_clean_evaluation: + print( + "clean evaluation, Accuracy: {0}\n\tclass accuracy: {1}\n\tclass histogram: {3}".format( + *run_clean_evaluation(classifier, test_loader, args.device) + ) + ) + + if args.adversarial_attack is not None: + print("adversarial evaluation:") + if not args.no_ce_loss: + print( + "\tadversarial evaluation (ce loss), ASR:", + run_adversarial_evaluation( + classifier, + test_loader, + "ce", + args.adversarial_attack, + args.n_samples, + args.device, + ), + ) + if not args.no_logit_diff_loss: + print( + "\tadversarial evaluation (logit-diff loss), ASR:", + run_adversarial_evaluation( + classifier, + test_loader, + "logit-diff", + args.adversarial_attack, + args.n_samples, + args.device, + ), + ) + + max_eps_adversarial_attack_settings = copy.deepcopy(args.adversarial_attack) + # set epsilon to 0.5 + # then rescale the step size so that it relatively to epsilon stays the same + max_eps_adversarial_attack_settings.epsilon = 0.50 + max_eps_adversarial_attack_settings.step_size = ( + args.adversarial_attack.step_size / args.adversarial_attack.epsilon * 0.5 + ) + if not args.no_ce_loss: + print( + "\tadversarial evaluation (ce loss, eps = 0.5), ASR:", + run_adversarial_evaluation( + classifier, + test_loader, + "ce", + max_eps_adversarial_attack_settings, + args.n_samples, + args.device, + ), + ) + if not args.no_logit_diff_loss: + print( + "\tadversarial evaluation (logit-diff loss, eps = 0.5), ASR:", + run_adversarial_evaluation( + classifier, + test_loader, + "logit-diff", + max_eps_adversarial_attack_settings, + args.n_samples, + args.device, + ), + ) + + if args.decision_boundary_binarization is not None: + print("decision boundary binarization:") + if not args.no_ce_loss: + print( + run_decision_boundary_binarization( + classifier, + test_loader, + "ce", + args.decision_boundary_binarization, + args.n_samples, + args.device, + args.batch_size, + "interior-vs-boundary discrimination (ce loss)", + args.dbl_sample_from_corners, + ) + ) + if not args.no_logit_diff_loss: + print( + run_decision_boundary_binarization( + classifier, + test_loader, + "logit-diff", + args.decision_boundary_binarization, + args.n_samples, + args.device, + args.batch_size, + "interior-vs-boundary discrimination (logit-diff loss)", + args.dbl_sample_from_corners, + ) + ) + + +def run_clean_evaluation( + classifier: torch.nn.Module, + test_loader: torch.utils.data.DataLoader, + device: str, + n_classes: int = 10, +) -> Tuple[float, List[float], np.ndarray, List[int]]: + """ + Perform evaluation of classifier on clean data. + + Args: + classifier: Classifier to evaluate. + test_loader: Dataloader to perform evaluation on. + device: torch device + n_classes: Number of classes in the dataset. + Returns + Accuracy, Accuracy per class, Correctly classified per sample, + Histogram of predicted labels + """ + n_correct = 0 + n_total = 0 + class_histogram_correct = {} + class_histogram_total = {} + class_histogram_predicted = {} + + if n_classes is not None: + for i in range(n_classes): + class_histogram_correct[i] = 0 + class_histogram_total[i] = 0 + class_histogram_predicted[i] = 0 + correctly_classified = [] + pbar = tqdm.tqdm(test_loader, leave=False) + for x, y in pbar: + x = x.to(device) + y = y.to(device) + + with torch.no_grad(): + y_pred = classifier(x).argmax(-1) + n_correct += (y_pred == y).long().sum().item() + n_total += len(x) + correctly_classified.append((y_pred == y).detach().cpu()) + + for y_, y_pred_ in zip( + y.detach().cpu().numpy(), y_pred.detach().cpu().numpy() + ): + if y_ not in class_histogram_correct: + class_histogram_correct[y_] = 0 + class_histogram_correct[y_] += int(y_ == y_pred_) + if y_ not in class_histogram_total: + class_histogram_total[y_] = 0 + class_histogram_total[y_] += 1 + if y_pred_ not in class_histogram_predicted: + class_histogram_predicted[y_pred_] = 0 + class_histogram_predicted[y_pred_] += 1 + pbar.set_description(f"Accuracy = {n_correct / n_total:.4f}") + correctly_classified = torch.cat(correctly_classified).numpy() + class_histogram_correct = [ + class_histogram_correct[k] for k in sorted(class_histogram_correct.keys()) + ] + class_histogram_total = [ + class_histogram_total[k] for k in sorted(class_histogram_total.keys()) + ] + + class_histogram_accuracy = [ + a / b if b > 0 else np.nan + for a, b in zip(class_histogram_correct, class_histogram_total) + ] + + class_histogram_predicted = [ + class_histogram_predicted[k] for k in sorted(class_histogram_predicted.keys()) + ] + + return ( + n_correct / n_total, + class_histogram_accuracy, + correctly_classified, + class_histogram_predicted, + ) + + +def run_decision_boundary_binarization( + classifier: torch.nn.Module, + test_loader: torch.utils.data.DataLoader, + loss: LossType, + linearization_settings: aut.DecisionBoundaryBinarizationSettings, + n_samples: int, + device: str, + batch_size: int, + title: str = "interior-vs-boundary discimination", + sample_training_data_from_corners: bool = False, +) -> float: + """Perform the binarization test for a classifier. + + Args: + classifier: Classifier to evaluate. + test_loader: Test dataloader. + loss: Loss to use in the adversarial attack during the test. + linearization_settings: Settings of the test. + n_samples: Number of samples to perform test on. + device: Torch device. + batch_size: Batch size. + title: Name of the experiment that will be shown in log. + sample_training_data_from_corners: Sample boundary samples from + corners or surfaces. + Returns: + String summarizing the results of the test. + """ + def attack_fn( + model: torch.nn.Module, data_loader: torch.utils.data.DataLoader, attack_kwargs + ): + result = run_adversarial_evaluation( + model, + data_loader, + loss, + linearization_settings.adversarial_attack_settings, + n_samples=1, + device=device, + return_samples=True, + n_classes=2, + early_stopping=True, + ) + # return ASR, (x_adv, logits(x_adv)) + return result[0], (result[1][1], result[1][2]) + + scores_logit_differences_and_validation_accuracies_and_asr = dbl.interior_boundary_discrimination_attack( + classifier, + test_loader, + attack_fn, + linearization_settings, + n_samples, + device, + n_samples_evaluation=200, # was set to n_samples + n_samples_asr_evaluation=linearization_settings.adversarial_attack_settings.n_steps, + rescale_logits="adaptive", + decision_boundary_closeness=0.9999, + sample_training_data_from_corners=sample_training_data_from_corners, + batch_size=batch_size, + ) + + return dbl.format_result( + scores_logit_differences_and_validation_accuracies_and_asr, + n_samples, + title=title, + ) + + +def run_adversarial_evaluation( + classifier: torch.nn.Module, + test_loader: torch.utils.data.DataLoader, + loss: LossType, + adversarial_attack_settings: aut.AdversarialAttackSettings, + n_samples: int, + device: str, + randomly_targeted: bool = False, + n_classes: int = 10, + return_samples: bool = False, + early_stopping: bool = True, +) -> Tuple[float, ...]: + """ + Perform an adversarial evaluation of a classifier. + + Args: + classifier: Classifier to evaluate. + test_loader: Test dataloader. + loss: Loss to use in adversarial attack. + adversarial_attack_settings: Settings of adversarial evaluation. + n_samples: Number of samples to evaluate robustness on. + device: Torch device: + randomly_targeted: Whether to use random targets for attack. + n_classes: Number of classes in the dataset (relevant for random targets) + return_samples: Returns clean and perturbed samples? + early_stopping: Stop once all samples have successfully been attacked + Returns: + Either only Attack Success Rate (ASR) or Tuple containing ASR and + clean/perturbed samples as well as their logits. + """ + + loss_per_sample = adversarial_attack_settings.attack == "kwta" + + if loss == "ce": + sign = 1 if randomly_targeted else -1 + if loss_per_sample: + reduction = "none" + else: + reduction = "sum" + loss_fn = lambda x, y: sign * F.cross_entropy(x, y, reduction=reduction) + elif loss == "logit-diff": + sign = -1 if randomly_targeted else 1 + + def loss_fn(logits, y): + gt_logits = logits[range(len(y)), y] + other = torch.max( + logits - 2 * torch.max(logits) * F.one_hot(y, logits.shape[-1]), -1 + )[0] + value = sign * (gt_logits - other) + if not loss_per_sample: + value = value.sum() + return value + + if adversarial_attack_settings.attack == "kwta": + if loss != "logit-diff": + warnings.warn( + "Adaptive attack for kWTA originally uses logit " + "differences and not CE loss", + RuntimeWarning, + ) + + n_attacked = 0 + attack_successful = [] + clean_samples = [] + perturbed_samples = [] + clean_or_target_labels = [] + predicted_logits = [] + for x, y in test_loader: + x = x[: max(1, min(len(x), n_samples - n_attacked))] + y = y[: max(1, min(len(y), n_samples - n_attacked))] + + x = x.to(device) + y = y.to(device) + + if randomly_targeted: + y = (y + torch.randint_like(y, 0, n_classes)) % n_classes + if adversarial_attack_settings.attack == "pgd": + x_adv = pgd.general_pgd( + loss_fn=lambda x, y: loss_fn(classifier(x), y), + is_adversarial_fn=lambda x, y: classifier(x).argmax(-1) == y + if randomly_targeted + else classifier(x).argmax(-1) != y, + x=x, + y=y, + n_steps=adversarial_attack_settings.n_steps, + step_size=adversarial_attack_settings.step_size, + epsilon=adversarial_attack_settings.epsilon, + norm=adversarial_attack_settings.norm, + early_stopping=early_stopping, + n_averaging_steps=adversarial_attack_settings.n_averages, + random_start=adversarial_attack_settings.random_start, + )[0] + elif adversarial_attack_settings.attack == "autopgd": + temp = autopgd.auto_pgd( + model=classifier, + x=x, + y=y, + n_steps=adversarial_attack_settings.n_steps, + epsilon=adversarial_attack_settings.epsilon, + norm=adversarial_attack_settings.norm, + targeted=randomly_targeted, + n_averaging_steps=adversarial_attack_settings.n_averages, + ) + x_adv = temp[0] + if randomly_targeted: + y = temp[-1] + elif adversarial_attack_settings.attack == "autopgd+": + temp = autopgd.auto_pgd( + model=classifier, + x=x, + y=y, + n_steps=adversarial_attack_settings.n_steps, + epsilon=adversarial_attack_settings.epsilon, + norm=adversarial_attack_settings.norm, + # from https://github.com/fra31/auto-attack/blob/ + # 6482e4d6fbeeb51ae9585c41b16d50d14576aadc/autoattack/ + # autoattack.py#L281 + n_restarts=4, + targeted=randomly_targeted, + n_averaging_steps=adversarial_attack_settings.n_averages, + ) + x_adv = temp[0] + if randomly_targeted: + y = temp[-1] + elif adversarial_attack_settings.attack == "fab": + temp = fab.fab( + model=classifier, + x=x, + y=y, + n_steps=adversarial_attack_settings.n_steps, + epsilon=adversarial_attack_settings.epsilon, + norm=adversarial_attack_settings.norm, + targeted=randomly_targeted, + n_restarts=5, + ) + x_adv = temp[0] + if randomly_targeted: + y = temp[-1] + elif adversarial_attack_settings.attack == "kwta": + x_adv = adaptive_kwta_attack.gradient_estimator_pgd( + model=classifier, + loss_fn=lambda x, y: loss_fn(classifier(x), y), + x=x, + y=y, + n_steps=adversarial_attack_settings.n_steps, + step_size=adversarial_attack_settings.step_size, + epsilon=adversarial_attack_settings.epsilon, + norm=adversarial_attack_settings.norm, + random_start=True, + early_stopping=early_stopping, + targeted=randomly_targeted, + )[0] + elif adversarial_attack_settings.attack == "thermometer-lspgd": + if hasattr(classifier, "l"): + l = classifier.l + else: + l = 16 + warnings.warn( + "Could not determine thermometer parameter l; " + "using default of 16", + RuntimeWarning, + ) + + x_adv = thermometer_ls_pgd.general_thermometer_ls_pgd( + loss_fn=lambda x, y: loss_fn(classifier(x, skip_encoder=True), y), + is_adversarial_fn=lambda x, y: classifier(x).argmax(-1) == y + if randomly_targeted + else classifier(x).argmax(-1) != y, + x=x, + y=y, + n_steps=adversarial_attack_settings.n_steps, + step_size=adversarial_attack_settings.step_size, + epsilon=adversarial_attack_settings.epsilon, + norm=adversarial_attack_settings.norm, + random_start=True, + early_stopping=early_stopping, + temperature=1.0, + annealing_factor=1.0, # 1.0/1.2, + n_restarts=0, + l=l, + )[0] + else: + raise ValueError( + f"Unknown adversarial attack " + f"({adversarial_attack_settings.attack})." + ) + + with torch.no_grad(): + logits = classifier(x_adv) + if randomly_targeted: + correctly_classified = logits.argmax(-1) == y + attack_successful += ( + correctly_classified.cpu().detach().numpy().tolist() + ) + else: + incorrectly_classified = logits.argmax(-1) != y + attack_successful += ( + incorrectly_classified.cpu().detach().numpy().tolist() + ) + + clean_samples.append(x.cpu()) + perturbed_samples.append(x_adv.cpu()) + clean_or_target_labels.append(y.cpu()) + predicted_logits.append(logits.cpu()) + + n_attacked += len(x) + + if n_attacked >= n_samples: + break + attack_successful = np.array(attack_successful) + clean_samples = np.concatenate(clean_samples, 0) + perturbed_samples = np.concatenate(perturbed_samples, 0) + clean_or_target_labels = np.concatenate(clean_or_target_labels, 0) + predicted_logits = np.concatenate(predicted_logits, 0) + + attack_successful = attack_successful[:n_samples] + clean_samples = clean_samples[:n_samples] + perturbed_samples = perturbed_samples[:n_samples] + clean_or_target_labels = clean_or_target_labels[:n_samples] + predicted_logits = predicted_logits[:n_samples] + + result = [np.mean(attack_successful).astype(np.float32)] + + if return_samples: + result += [ + (clean_samples, perturbed_samples, predicted_logits, clean_or_target_labels) + ] + + return tuple(result) + + +if __name__ == "__main__": + warnings.filterwarnings("ignore", category=UserWarning, module="torch") + main() diff --git a/case_studies/evaluate_detection_defense.py b/case_studies/evaluate_detection_defense.py new file mode 100644 index 0000000..f93aa9c --- /dev/null +++ b/case_studies/evaluate_detection_defense.py @@ -0,0 +1,223 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import argparse +from typing import Callable +from typing import List + +import numpy as np +import torch +import torch.utils.data +import torchvision +from torch.nn import functional as F +from torchvision import transforms + +import active_tests.logit_matching +import argparse_utils as aut +import networks +from attacks import pgd + + +def parse_arguments(): + parser = argparse.ArgumentParser( + "CIFAR-10 (Defense w/ Detector) Evaluation Script") + parser.add_argument("-bs", "--batch-size", default=128, type=int) + parser.add_argument("-ns", "--n-samples", default=512, type=int) + parser.add_argument("-i", "--input", required=True, type=str) + parser.add_argument("-d", "--device", default=None, type=str) + + parser.add_argument("-a", "--adversarial-attack", + type=aut.parse_adversarial_attack_argument, + default=None) + + parser.add_argument("-l", "--logit-matching", + type=aut.parse_logit_matching_argument, + default=None) + + args = parser.parse_args() + + if args.adversarial_attack is not None: + print("Performing adversarial attack:", args.adversarial_attack) + + if args.logit_matching is not None: + print("Performing logit matching:", args.logit_matching) + + return args + + +def setup_dataloader(batch_size: int) -> torch.utils.data.DataLoader: + transform_test = transforms.Compose([ + transforms.ToTensor(), + ]) + + testset = torchvision.datasets.CIFAR10(root='./data', train=False, + download=True, + transform=transform_test) + testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, + shuffle=True, num_workers=8) + + return testloader + + +def main(): + args = parse_arguments() + classifier = networks.cifar_resnet18(num_classes=10) + detector = networks.Detector(n_features_classifier=10, classifier=classifier) + + state_dict = torch.load(args.input) + classifier.load_state_dict(state_dict["classifier"]) + detector.load_state_dict(state_dict["detector"]) + classifier.train(False) + detector.train(False) + + test_loader = setup_dataloader(args.batch_size) + if args.device is None: + args.device = "cuda" if torch.cuda.is_available() else "cpu" + classifier = classifier.to(args.device) + detector = detector.to(args.device) + + if args.adversarial_attack is not None: + print("faulty adversarial evaluation 1, ASR:", + run_faulty_adversarial_evaluation(classifier, detector, test_loader, + args.adversarial_attack, + args.n_samples, + args.device)) + print("correct adversarial evaluation, ASR:", + run_correct_adversarial_evaluation(classifier, detector, test_loader, + args.adversarial_attack, + args.n_samples, + args.device)) + if args.logit_matching is not None: + print("logit matching (dataset):", + run_logit_matching_evaluation(classifier, detector, test_loader, + args.logit_matching, + args.n_samples, + args.device)) + + +def run_faulty_adversarial_evaluation(classifier: torch.nn.Module, + detector: torch.nn.Module, + test_loader: torch.utils.data.DataLoader, + adversarial_attack_settings: aut.AdversarialAttackSettings, + n_samples: int, device: str) -> float: + def eval_batch(x: torch.Tensor, y: torch.Tensor) -> List[bool]: + x_adv = pgd.pgd(classifier, x, y, targeted=False, + n_steps=adversarial_attack_settings.n_steps, + step_size=adversarial_attack_settings.step_size, + epsilon=adversarial_attack_settings.epsilon, + norm=adversarial_attack_settings.norm, + random_start=True)[0] + with torch.no_grad(): + not_detected = detector(x_adv).argmax(-1) == torch.zeros_like(y) + incorrectly_classified = classifier(x_adv).argmax(-1) != y + successful_attack = torch.logical_and(not_detected, + incorrectly_classified).cpu().detach().numpy().tolist() + return successful_attack + + return run_adversarial_evaluation(eval_batch, test_loader, n_samples, device) + + +def run_correct_adversarial_evaluation(classifier: torch.nn.Module, + detector: torch.nn.Module, + test_loader: torch.utils.data.DataLoader, + adversarial_attack_settings: aut.AdversarialAttackSettings, + n_samples: int, device: str) -> float: + def eval_batch(x: torch.Tensor, y: torch.Tensor) -> List[bool]: + alpha = 0.5 + + def loss_fn(x, y): + classifier_logits = classifier(x) + detector_logits = detector(x) + # only maximize the CE wrt. to the GT label for correctly classified samples + classifier_mask = classifier_logits.argmax(-1).detach() == y + # only minimize the CE wrt. to the 0 label (i.e. not adversarial) for + # samples detected as adversarial examples + detector_mask = detector_logits.argmax(-1).detach() != 0 + classifier_loss = -(F.cross_entropy( + classifier_logits, + y, reduction="none") * classifier_mask).mean() + detector_loss = (F.cross_entropy( + detector_logits, torch.zeros_like(y), + reduction="none") * detector_mask).mean() + return (1 - alpha) * classifier_loss + alpha * detector_loss + + x_adv = pgd.general_pgd(x=x, y=y, + loss_fn=loss_fn, + is_adversarial_fn=lambda x, y: torch.logical_and( + classifier(x).argmax(-1) != y, + detector(x).argmax( + -1) == torch.zeros_like(y)), + n_steps=adversarial_attack_settings.n_steps, + step_size=adversarial_attack_settings.step_size, + epsilon=adversarial_attack_settings.epsilon, + norm=adversarial_attack_settings.norm, + random_start=True)[0] + + with torch.no_grad(): + not_detected = detector(x_adv).argmax(-1) == torch.zeros_like(y) + + incorrectly_classified = classifier(x_adv).argmax(-1) != y + successful_attack = torch.logical_and(not_detected, + incorrectly_classified).cpu().detach().numpy().tolist() + return successful_attack + + return run_adversarial_evaluation(eval_batch, test_loader, n_samples, device) + + +def run_adversarial_evaluation( + batch_eval_fn: Callable[[torch.tensor, torch.Tensor], List[bool]], + test_loader: torch.utils.data.DataLoader, n_samples: int, + device: str) -> float: + """ + :param batch_eval_fn: + :param test_loader: + :param n_samples: + :param device: torch device + :return: Returns Attack Success Rate + """ + + results = [] + for x, y in test_loader: + x = x.to(device) + y = y.to(device) + results += batch_eval_fn(x, y) + if len(results) >= n_samples: + break + results = results[:n_samples] + + return np.mean(np.array(results).astype(np.float32)) + + +def run_logit_matching_evaluation(classifier: Callable, detector: Callable, + test_loader: torch.utils.data.DataLoader, + logit_matching_settings: aut.LogitMatchingSettings, n_samples: int, + device: str): + merged_logits_fn = lambda x: torch.cat((classifier(x), detector(x)), 1) + + results = [] + for x, y in test_loader: + x = x.to(device) + results += active_tests.logit_matching.dataset_samples_logit_matching( + merged_logits_fn, x, logit_matching_settings.n_steps, + logit_matching_settings.step_size) + + if len(results) >= n_samples: + break + results = results[:n_samples] + results = np.sqrt(np.array(results).sum(-1)) + print(results) + + +if __name__ == "__main__": + main() diff --git a/case_studies/feature_scatter/README.md b/case_studies/feature_scatter/README.md new file mode 100644 index 0000000..8710273 --- /dev/null +++ b/case_studies/feature_scatter/README.md @@ -0,0 +1,55 @@ +# Feature Scattering Adversarial Training (NeurIPS 2019) + +## Introduction +This is the implementation of the +["Feature-Scattering Adversarial Training"](https://papers.nips.cc/paper/8459-defense-against-adversarial-attacks-using-feature-scattering-based-adversarial-training.pdf), which is a training method for improving model robustness against adversarial attacks. It advocates the usage of an unsupervised feature-scattering procedure for adversarial perturbation generation, which is effective for overcoming label leaking and improving model robustness. +More information can be found on the project page: https://sites.google.com/site/hczhang1/projects/feature_scattering + +## Usage +### Installation +The training environment (PyTorch and dependencies) can be installed as follows: +``` +git clone https://github.com/Haichao-Zhang/FeatureScatter.git +cd FeatureScatter + +python3 -m venv .venv +source .venv/bin/activate + +python3 setup.py install + +(or pip install -e .) +``` +Tested under Python 3.5.2 and PyTorch 1.2.0. + +### Train +Specify the path for saving the trained models in ```fs_train.sh```, and then run +``` +sh ./fs_train.sh +``` + +### Evaluate +Specify the path to the trained models to be evaluated in ```fs_eval.sh``` and then run +``` +sh ./fs_eval.sh +``` + +### Reference Model +A reference model trained on CIFAR10 is [here](https://drive.google.com/open?id=1FXgE7llvQoypf7iCGR680EKQf9cARTSg). + + +## Cite + +If you find this work is useful, please cite the following: + +``` +@inproceedings{feature_scatter, + author = {Haichao Zhang and Jianyu Wang}, + title = {Defense Against Adversarial Attacks Using Feature Scattering-based Adversarial Training}, + booktitle = {Advances in Neural Information Processing Systems}, + year = {2019} +} +``` + +## Contact + +For questions related to feature-scattering, please send me an email: ```hczhang1@gmail.com``` diff --git a/case_studies/feature_scatter/__init__.py b/case_studies/feature_scatter/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/case_studies/feature_scatter/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/case_studies/feature_scatter/attack_methods.py b/case_studies/feature_scatter/attack_methods.py new file mode 100644 index 0000000..679f799 --- /dev/null +++ b/case_studies/feature_scatter/attack_methods.py @@ -0,0 +1,358 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import numpy as np + +from attacks import autopgd +from attacks import pgd +from models import * +from torch.autograd import Variable +import utils + +from ftsc_utils import softCrossEntropy +from ftsc_utils import one_hot_tensor +import ot +import pickle + +device = 'cuda' if torch.cuda.is_available() else 'cpu' + + +class Attack_None(nn.Module): + def __init__(self, basic_net, config): + super(Attack_None, self).__init__() + self.train_flag = True if 'train' not in config.keys( + ) else config['train'] + self.basic_net = basic_net + + def forward(self, inputs, targets, attack=None, batch_idx=-1): + if self.train_flag: + self.basic_net.train() + else: + self.basic_net.eval() + result = self.basic_net(inputs) + if isinstance(result, tuple): + outputs, _ = self.basic_net(inputs) + else: + outputs = result + return outputs, None, None + + +class Attack_PGD(nn.Module): + # Back-propogate + def __init__(self, basic_net, config, attack_net=None): + super(Attack_PGD, self).__init__() + self.basic_net = basic_net + self.attack_net = attack_net + self.rand = config['random_start'] + self.step_size = config['step_size'] + self.epsilon = config['epsilon'] + self.num_steps = config['num_steps'] + self.loss_func = torch.nn.CrossEntropyLoss( + reduction='none') if 'loss_func' not in config.keys( + ) else config['loss_func'] + self.train_flag = True if 'train' not in config.keys( + ) else config['train'] + + self.box_type = 'white' if 'box_type' not in config.keys( + ) else config['box_type'] + + + def forward(self, + inputs, + targets, + attack=True, + targeted_label=-1, + batch_idx=0): + + if not attack: + outputs = self.basic_net(inputs)[0] + return outputs, None + + if self.box_type == 'white': + # aux_net = pickle.loads(pickle.dumps(self.basic_net)) + aux_net = self.basic_net + elif self.box_type == 'black': + assert self.attack_net is not None, "should provide an additional net in black-box case" + aux_net = pickle.loads(pickle.dumps(self.basic_net)) + aux_net.eval() + + output = aux_net(inputs) + if isinstance(output, tuple): + logits_pred_nat = output[0] + else: + logits_pred_nat = output + targets_prob = F.softmax(logits_pred_nat.float(), dim=1) + + num_classes = targets_prob.size(1) + + y_tensor_adv = targets + step_sign = 1.0 + + x = inputs.detach() + if self.rand: + x = x + torch.zeros_like(x).uniform_(-self.epsilon, self.epsilon) + x_org = x.detach() + loss_array = np.zeros((inputs.size(0), self.num_steps)) + + for i in range(self.num_steps): + x.requires_grad_() + if x.grad is not None: + x.grad.zero_() + if x.grad is not None: + x.grad.data.fill_(0) + aux_net.eval() + + output = aux_net(x) + if isinstance(output, tuple): + logits = output[0] + else: + logits = output + + loss = self.loss_func(logits, y_tensor_adv) + loss = loss.mean() + aux_net.zero_grad() + loss.backward() + + x_adv = x.data + step_sign * self.step_size * torch.sign( + x.grad.data) + x_adv = torch.min(torch.max(x_adv, inputs - self.epsilon), + inputs + self.epsilon) + x_adv = torch.clamp(x_adv, -1.0, 1.0) + x = Variable(x_adv) + + if self.train_flag: + self.basic_net.train() + else: + self.basic_net.eval() + + output = aux_net(x.detach()) + if isinstance(output, tuple): + logits_pert = output[0] + else: + logits_pert = output + + return logits_pert, targets_prob.detach(), x.detach() + + +class Attack_BetterPGD(nn.Module): + # Back-propogate + def __init__(self, basic_net, config, attack_net=None): + super(Attack_BetterPGD, self).__init__() + self.basic_net = basic_net + self.attack_net = attack_net + self.rand = config['random_start'] + self.step_size = config['step_size'] + self.epsilon = config['epsilon'] + self.num_steps = config['num_steps'] + self.loss_func = torch.nn.CrossEntropyLoss( + reduction='none') if 'loss_func' not in config.keys( + ) else config['loss_func'] + self.train_flag = True if 'train' not in config.keys( + ) else config['train'] + + self.box_type = 'white' if 'box_type' not in config.keys( + ) else config['box_type'] + + + def forward(self, + inputs, + targets, + attack=True, + targeted_label=-1, + batch_idx=0): + + def net(x): + output = self.basic_net(x) + if isinstance(output, tuple): + return output[0] + else: + return output + + if attack: + sign = 1.0 if targeted_label != -1 else -1.0 + x_adv = pgd.general_pgd( + loss_fn=lambda x, y: sign * self.loss_func(net(x), y), + is_adversarial_fn=lambda x, y: net(x).argmax(-1) == y + if targeted_label != -1 else net(x).argmax(-1) != y, + x=inputs, y=targets, n_steps=self.num_steps, + step_size=self.step_size, + epsilon=self.epsilon, + norm="linf", + random_start=self.rand + )[0] + else: + x_adv = inputs + + logits_pert = net(x_adv) + targets_prob = torch.softmax(logits_pert, -1) + + return logits_pert, targets_prob.detach(), x_adv.detach() + + +class Attack_AutoPGD(nn.Module): + # Back-propogate + def __init__(self, basic_net, config, attack_net=None): + super(Attack_AutoPGD, self).__init__() + self.basic_net = basic_net + self.attack_net = attack_net + self.epsilon = config['epsilon'] + self.n_restarts = 0 if "num_restarts" not in config else \ + config["num_restarts"] + self.num_steps = config['num_steps'] + self.loss_func = "ce" if 'loss_func' not in config.keys( + ) else config['loss_func'] + + self.train_flag = True if 'train' not in config.keys( + ) else config['train'] + self.box_type = 'white' if 'box_type' not in config.keys( + ) else config['box_type'] + + self.targeted = False if 'targeted' not in config.keys( + ) else config['targeted'] + self.n_classes = 10 if 'n_classes' not in config.keys( + ) else config['n_classes'] + + def forward(self, + inputs, + targets, + attack=True, + targeted_label=-1, + batch_idx=0): + + assert targeted_label == -1 + + def net(x): + output = self.basic_net(x) + if isinstance(output, tuple): + return output[0] + else: + return output + + if attack: + temp = autopgd.auto_pgd( + model=net, + x=inputs, y=targets, n_steps=self.num_steps, + loss=self.loss_func, + epsilon=self.epsilon, + norm="linf", + n_restarts=self.n_restarts, + targeted=self.targeted, + n_averaging_steps=1, + n_classes=self.n_classes + ) + x_adv = temp[0] + else: + x_adv = inputs + + logits_pert = net(x_adv) + targets_prob = torch.softmax(logits_pert, -1) + + return logits_pert, targets_prob.detach(), x_adv.detach() + + +class Attack_FeaScatter(nn.Module): + def __init__(self, basic_net, config, attack_net=None): + super(Attack_FeaScatter, self).__init__() + self.basic_net = basic_net + self.attack_net = attack_net + self.rand = config['random_start'] + self.step_size = config['step_size'] + self.epsilon = config['epsilon'] + self.num_steps = config['num_steps'] + self.train_flag = True if 'train' not in config.keys( + ) else config['train'] + self.box_type = 'white' if 'box_type' not in config.keys( + ) else config['box_type'] + self.ls_factor = 0.1 if 'ls_factor' not in config.keys( + ) else config['ls_factor'] + + def forward(self, + inputs, + targets, + attack=True, + targeted_label=-1, + batch_idx=0): + + if not attack: + outputs, _ = self.basic_net(inputs) + return outputs, None + if self.box_type == 'white': + aux_net = pickle.loads(pickle.dumps(self.basic_net)) + elif self.box_type == 'black': + assert self.attack_net is not None, "should provide an additional net in black-box case" + aux_net = pickle.loads(pickle.dumps(self.basic_net)) + + aux_net.eval() + batch_size = inputs.size(0) + m = batch_size + n = batch_size + + logits = aux_net(inputs)[0] + num_classes = logits.size(1) + + outputs = aux_net(inputs)[0] + targets_prob = F.softmax(outputs.float(), dim=1) + y_tensor_adv = targets + step_sign = 1.0 + + x = inputs.detach() + + x_org = x.detach() + x = x + torch.zeros_like(x).uniform_(-self.epsilon, self.epsilon) + + if self.train_flag: + self.basic_net.train() + else: + self.basic_net.eval() + + logits_pred_nat, fea_nat = aux_net(inputs) + + num_classes = logits_pred_nat.size(1) + y_gt = one_hot_tensor(targets, num_classes, device) + + loss_ce = softCrossEntropy() + + iter_num = self.num_steps + + for i in range(iter_num): + x.requires_grad_() + if x.grad is not None: + x.grad.zero_() + if x.grad is not None: + x.grad.data.fill_(0) + + logits_pred, fea = aux_net(x) + + ot_loss = ot.sinkhorn_loss_joint_IPOT(1, 0.00, logits_pred_nat, + logits_pred, None, None, + 0.01, m, n) + + aux_net.zero_grad() + adv_loss = ot_loss + adv_loss.backward(retain_graph=True) + x_adv = x.data + self.step_size * torch.sign(x.grad.data) + x_adv = torch.min(torch.max(x_adv, inputs - self.epsilon), + inputs + self.epsilon) + x_adv = torch.clamp(x_adv, -1.0, 1.0) + x = Variable(x_adv) + + logits_pred, fea = self.basic_net(x) + self.basic_net.zero_grad() + + y_sm = utils.label_smoothing(y_gt, y_gt.size(1), self.ls_factor) + + adv_loss = loss_ce(logits_pred, y_sm.detach()) + + return logits_pred, adv_loss + diff --git a/case_studies/feature_scatter/binarization_test.sh b/case_studies/feature_scatter/binarization_test.sh new file mode 100644 index 0000000..c4409f4 --- /dev/null +++ b/case_studies/feature_scatter/binarization_test.sh @@ -0,0 +1,48 @@ +nsamples=${1:-512} +epsilon=${2:-8} + +# kwargs="" +kwargs="--sample-from-corners" +echo "Epsilon: $epsilon" +echo "#samples: $nsamples" +echo "kwargs: $kwargs" + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using epsilon = $epsilon and few steps (20)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +PYTHONPATH=$(pwd) python3 case_studies/feature_scatter/fs_eval.py \ + --model-path=checkpoints/feature_scattering_linf_200_epochs.pth \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=pgd-autopgddlr \ + --dataset=cifar10 \ + --batch_size_test=1 \ + --binarization-test \ + --num_samples_test=$nsamples \ + --n-inner-points=9999 \ + --n-boundary-points=1 \ + --resume \ + --epsilon=$epsilon \ + $kwargs + #9999 + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using epsilon = $epsilon and more steps (200)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +PYTHONPATH=$(pwd) python3 case_studies/feature_scatter/fs_eval.py \ + --model-path=checkpoints/feature_scattering_linf_200_epochs.pth \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=pgd-autopgddlr \ + --dataset=cifar10 \ + --batch_size_test=1 \ + --binarization-test \ + --num_samples_test=$nsamples \ + --n-inner-points=9999 \ + --n-boundary-points=1 \ + --resume \ + --epsilon=$epsilon \ + --more-steps \ + $kwargs \ No newline at end of file diff --git a/case_studies/feature_scatter/fs_eval.py b/case_studies/feature_scatter/fs_eval.py new file mode 100644 index 0000000..62e2146 --- /dev/null +++ b/case_studies/feature_scatter/fs_eval.py @@ -0,0 +1,547 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import print_function + +import argparse +import inspect +import os +import sys +import time +import warnings +from functools import partial + +import numpy as np +import torch +import torch.backends.cudnn as cudnn +import torchvision +import torchvision.transforms as transforms +from tqdm import tqdm + +import active_tests.decision_boundary_binarization +import ftsc_utils as utils +import networks +from attack_methods import Attack_BetterPGD +from attack_methods import Attack_None +from attack_methods import Attack_PGD +from attack_methods import Attack_AutoPGD +from ftsc_utils import CWLoss +from models import * + +warnings.simplefilter('once', RuntimeWarning) + +currentdir = os.path.dirname( + os.path.abspath(inspect.getfile(inspect.currentframe()))) +grandarentdir = os.path.dirname(os.path.dirname(currentdir)) +sys.path.insert(0, grandarentdir) + +parser = argparse.ArgumentParser( + description='Feature Scattering Adversarial Training') + +parser.register('type', 'bool', utils.str2bool) + +parser.add_argument('--resume', + '-r', + action='store_true', + help='resume from checkpoint') +parser.add_argument('--binarization-test', action="store_true") +parser.add_argument('--attack', default=True, type='bool', help='attack') +parser.add_argument('--model_dir', type=str, help='model path') +parser.add_argument('--model-path', type=str, help='model path', default=None) +parser.add_argument('--init_model_pass', + default='-1', + type=str, + help='init model pass') + +parser.add_argument('--attack_method', + default='pgd', + type=str, + help='adv_mode (natural, pdg or cw)') +parser.add_argument('--attack_method_list', type=str) + +parser.add_argument('--log_step', default=7, type=int, help='log_step') + +# dataset dependent +parser.add_argument('--num_classes', default=10, type=int, help='num classes') +parser.add_argument('--dataset', default='cifar10', type=str, + help='dataset') # concat cascade +parser.add_argument('--batch_size_test', + default=100, + type=int, + help='batch size for testing') +parser.add_argument('--image_size', default=32, type=int, help='image size') + +parser.add_argument('--num_samples_test', + default=-1, + type=int) + +parser.add_argument('--n-inner-points', + default=50, + type=int) + +parser.add_argument('--n-boundary-points', + default=10, + type=int) + +parser.add_argument("--epsilon", type=int, default=8) +parser.add_argument("--more-steps", action="store_true") +parser.add_argument("--sample-from-corners", action="store_true") + +args = parser.parse_args() + +if args.binarization_test: + assert args.batch_size_test == 1 + +if args.dataset == 'cifar10': + print('------------cifar10---------') + args.num_classes = 10 + args.image_size = 32 +elif args.dataset == 'cifar100': + print('----------cifar100---------') + args.num_classes = 100 + args.image_size = 32 +if args.dataset == 'svhn': + print('------------svhn10---------') + args.num_classes = 10 + args.image_size = 32 +elif args.dataset == 'mnist': + print('----------mnist---------') + args.num_classes = 10 + args.image_size = 28 + +device = 'cuda' if torch.cuda.is_available() else 'cpu' +start_epoch = 0 + +# Data +print('==> Preparing data..') + +if args.dataset == 'cifar10' or args.dataset == 'cifar100': + transform_test = transforms.Compose([ + transforms.ToTensor(), + # transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # [-1 1] + ]) +elif args.dataset == 'svhn': + transform_test = transforms.Compose([ + transforms.ToTensor(), + # transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # [-1 1] + ]) + +if args.dataset == 'cifar10': + testset = torchvision.datasets.CIFAR10(root='./data', + train=False, + download=True, + transform=transform_test) +elif args.dataset == 'cifar100': + testset = torchvision.datasets.CIFAR100(root='./data', + train=False, + download=True, + transform=transform_test) + +elif args.dataset == 'svhn': + testset = torchvision.datasets.SVHN(root='./data', + split='test', + download=True, + transform=transform_test) + +testloader = torch.utils.data.DataLoader(testset, + batch_size=args.batch_size_test, + shuffle=False, + num_workers=2) + +print('==> Building model..') +if args.dataset == 'cifar10' or args.dataset == 'cifar100' or args.dataset == 'svhn': + print('---wide resenet-----') + basic_net = WideResNet(depth=28, + num_classes=args.num_classes, + widen_factor=10) + +basic_net = basic_net.to(device) + + +class ZeroOneOneOneNetwork(nn.Module): + def __init__(self, model): + super().__init__() + self.model = model + + def forward(self, x, **kwargs): + return self.model((x - 0.5) / 0.5, **kwargs) + + +if args.binarization_test: + args.num_classes = 2 + +if args.num_samples_test == -1: + num_samples_test = len(testset) + +# configs +config_natural = {'train': False} + +config_fgsm = { + 'train': False, + 'targeted': False, + 'epsilon': args.epsilon / 255.0, + 'num_steps': 1, + 'step_size': args.epsilon / 255.0, + 'random_start': True +} + +config_pgd = { + 'train': False, + 'targeted': False, + 'epsilon': args.epsilon / 255.0, + 'num_steps': 20, + 'step_size': args.epsilon / 4.0 / 255.0, + 'random_start': True, + 'loss_func': torch.nn.CrossEntropyLoss(reduction='none') +} + +config_cw = { + 'train': False, + 'targeted': False, + 'epsilon': args.epsilon / 255.0, + 'num_steps': 20, + 'step_size': args.epsilon / 4.0 / 255.0, + 'random_start': True, + 'loss_func': CWLoss(args.num_classes) +} + +config_auto_pgd_ce = { + 'train': False, + 'targeted': False, + 'epsilon': args.epsilon / 255.0, + 'num_steps': 20, + 'loss_func': "ce" +} + +config_auto_pgd_dlr = { + 'train': False, + 'targeted': False, + 'epsilon': args.epsilon / 255.0, + 'num_steps': 20, + 'loss_func': "logit-diff" +} + +config_auto_pgd_dlr_t = { + **config_auto_pgd_dlr, + "targeted": True, + "n_classes": 10, +} + +config_auto_pgd_ce_plus = { + **config_auto_pgd_ce, + "n_restarts": 4 +} + +config_auto_pgd_dlr_plus = { + **config_auto_pgd_dlr, + "n_restarts": 4 +} + +class __KwargsSequential(torch.nn.Sequential): + """ + Modification of a torch.nn.Sequential model that allows kwargs in the + forward pass. These will be passed to the first module of the network. + """ + + def forward(self, input, **kwargs): + for idx, module in enumerate(self): + if idx == 0: + input = module(input, **kwargs) + else: + input = module(input) + return input + +def train_classifier(n_features, + train_loader, + raw_train_loader, + logits, + device, + rescale_logits, + classifier): + del raw_train_loader + + x_ = train_loader.dataset.tensors[0] + y_ = train_loader.dataset.tensors[1] + + x_original = x_[0] + x_boundary = x_[y_ == 1] + assert len(x_boundary) == 1, "Method only works for a single boundary point" + x_boundary = x_boundary[0] + + margin = 0.99999999999 + delta = x_boundary - x_original + delta = delta / (torch.dot(delta, delta)) + w = delta + b = -torch.dot(x_original, delta) - margin + + binary_classifier = torch.nn.Linear(n_features, 2) + + binary_classifier.weight.data = torch.stack((-w, w), 0) + binary_classifier.bias.data = torch.stack((-b, b), 0) + + binary_classifier = binary_classifier.to(device) + #import pdb; pdb.set_trace() + #for x, y in train_loader: + # x, y = x.to(device), y.to(device) + # + # l = binary_classifier(x) + # p = l.argmax(-1) + # is_correct = p == y + + linearized_model = __KwargsSequential( + networks.Lambda( + lambda x, **kwargs: classifier(x, features_only=True, **kwargs)), + binary_classifier) + + return linearized_model + +if not args.binarization_test: + config_fgsm["epsilon"] *= 2.0 + config_pgd["epsilon"] *= 2.0 + config_cw["epsilon"] *= 2.0 + config_fgsm["step_size"] *= 2.0 + config_pgd["step_size"] *= 2.0 + config_cw["step_size"] *= 2.0 +else: + config_auto_pgd_dlr_t["n_classes"] = 2 + +print(f"Epsilon: {args.epsilon}") +if args.more_steps: + config_pgd["step_size"] /= 5.0 + config_cw["step_size"] /= 5.0 + config_pgd["num_steps"] *= 10 + config_cw["num_steps"] *= 10 + + config_auto_pgd_ce["num_steps"] *= 10 + config_auto_pgd_dlr["num_steps"] *= 10 + print("More & finer steps") + + +def test_test(net, feature_extractor, config): + from argparse_utils import DecisionBoundaryBinarizationSettings + print("num_samples_test:", args.num_samples_test) + print("test epsilon:", config["epsilon"]) + scores_logit_differences_and_validation_accuracies = \ + active_tests.decision_boundary_binarization.interior_boundary_discrimination_attack( + feature_extractor, + testloader, + attack_fn=lambda m, l, kwargs: test(0, create_attack(m), l, verbose=False, + inverse_acc=True, return_advs=True, **kwargs), + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=config["epsilon"], + norm="linf", + lr=100000, + n_boundary_points=args.n_boundary_points, + n_inner_points=args.n_inner_points, + adversarial_attack_settings=None, + optimizer="sklearn" + ), + n_samples=args.num_samples_test, + device=device, + n_samples_evaluation=200,#args.num_samples_test * 10 + n_samples_asr_evaluation=200, + # TODO: use the right arguments here again! + # relative_inner_boundary_gap=0.00, + rescale_logits="adaptive", + decision_boundary_closeness=0.9999, + sample_training_data_from_corners=args.sample_from_corners, + #train_classifier_fn=partial(train_classifier, classifier=feature_extractor) + ) + + print(active_tests.decision_boundary_binarization.format_result( + scores_logit_differences_and_validation_accuracies, + args.num_samples_test)) + + +def test(epoch, net, loader, verbose=True, inverse_acc=False, + return_advs=False): + # net.eval() + test_loss = 0 + correct = 0 + total = 0 + + if verbose: + iterator = tqdm(loader, ncols=0, leave=False) + else: + iterator = loader + + if return_advs: + x_adv = [] + logits_adv = [] + else: + x_adv = None + logits_adv = None + + for batch_idx, (inputs, targets) in enumerate(iterator): + start_time = time.time() + inputs, targets = inputs.to(device), targets.to(device) + + pert_inputs = inputs.detach() + + res = net(pert_inputs, targets) + if isinstance(res, tuple): + outputs, _, x_adv_it = res + else: + outputs = res + + if return_advs: + x_adv.append(x_adv_it) + logits_adv.append(outputs) + + loss = criterion(outputs, targets) + test_loss += loss.item() + + duration = time.time() - start_time + + _, predicted = outputs.max(1) + batch_size = targets.size(0) + total += batch_size + correct_num = predicted.eq(targets).sum().item() + correct += correct_num + if verbose: + iterator.set_description( + "Accuracy:" + str(predicted.eq(targets).sum().item() / targets.size(0))) + + if batch_idx % args.log_step == 0: + print( + "step %d, duration %.2f, test acc %.2f, avg-acc %.2f, loss %.2f" + % (batch_idx, duration, 100. * correct_num / batch_size, + 100. * correct / total, test_loss / total)) + + if return_advs: + x_adv = torch.cat(x_adv, 0) + logits_adv = torch.cat(logits_adv, 0) + + acc = 100. * correct / total + + if inverse_acc: + acc = (100 - acc) / 100.0 + + if verbose: + print("Robust Accuracy:", acc) + + # print('Val acc:', acc) + return acc, (x_adv, logits_adv) + + +if args.resume and args.init_model_pass != '-1': + # Load checkpoint. + print('==> Resuming from checkpoint..') + if args.model_dir is not None: + f_path_latest = os.path.join(args.model_dir, 'latest') + f_path = os.path.join(args.model_dir, + ('checkpoint-%s' % args.init_model_pass)) + if args.model_path is not None: + f_path = args.model_path + f_path_latest = args.model_path + if not os.path.isfile(f_path): + print('train from scratch: no checkpoint directory or file found') + elif args.init_model_pass == 'latest' and os.path.isfile( + f_path_latest): + checkpoint = torch.load(f_path_latest, map_location="cpu") + basic_net.load_state_dict( + {(k[len("module.basic_net."):] if k.startswith( + "module.basic_net.") else k): v + for k, v in checkpoint['net'].items()}) + start_epoch = checkpoint['epoch'] + print('resuming from epoch %s in latest' % start_epoch) + elif os.path.isfile(f_path): + checkpoint = torch.load(f_path) + # net.load_state_dict(checkpoint['net']) + basic_net.load_state_dict( + {(k[len("module.basic_net."):] if k.startswith( + "module.basic_net.") else k): v + for k, v in checkpoint['net'].items()}) + start_epoch = checkpoint['epoch'] + print('resuming from epoch %s' % start_epoch) + elif not os.path.isfile(f_path) or not os.path.isfile(f_path_latest): + print('train from scratch: no checkpoint directory or file found') + +attack_list = args.attack_method_list.split('-') +attack_num = len(attack_list) + +for attack_idx in range(attack_num): + + args.attack_method = attack_list[attack_idx] + + if args.attack_method == 'natural': + print() + print('-----natural non-adv mode -----') + # config is only dummy, not actually used + create_attack = lambda n: Attack_None(n, config_natural) + elif args.attack_method.upper() == 'FGSM': + print() + print('-----FGSM adv mode -----') + create_attack = lambda n: Attack_PGD(n, config_fgsm) + elif args.attack_method.upper() == 'PGD': + print() + print('-----PGD adv mode -----') + create_attack = lambda n: Attack_PGD(n, config_pgd) + elif args.attack_method.upper() == 'CW': + print() + print('-----CW adv mode -----') + create_attack = lambda n: Attack_PGD(n, config_cw) + elif args.attack_method.upper() == 'BETTERPGD': + print() + print('-----Better PGD adv mode -----') + create_attack = lambda n: Attack_BetterPGD(n, config_pgd) + elif args.attack_method.upper() == 'BETTERCW': + print() + print('-----Better CW adv mode -----') + create_attack = lambda n: Attack_BetterPGD(n, config_cw) + elif args.attack_method.upper() == 'AUTOPGDCE': + print() + print('-----Auto PGD (CE) adv mode -----') + create_attack = lambda n: Attack_AutoPGD(n, config_auto_pgd_ce) + elif args.attack_method.upper() == 'AUTOPGDDLR': + print() + print('-----Auto PGD (DLR) adv mode -----') + create_attack = lambda n: Attack_AutoPGD(n, config_auto_pgd_dlr) + elif args.attack_method.upper() == 'AUTOPGDDLRT': + print() + print('-----Auto PGD (DLR, targeted) adv mode -----') + create_attack = lambda n: Attack_AutoPGD(n, config_auto_pgd_dlr_t) + elif args.attack_method.upper() == 'AUTOPGDCE+': + print() + print('-----Auto PGD+ (CE) adv mode -----') + create_attack = lambda n: Attack_AutoPGD(n, config_auto_pgd_ce_plus) + elif args.attack_method.upper() == 'AUTOPGDDLR+': + print() + print('-----Auto PGD+ (DLR) adv mode -----') + create_attack = lambda n: Attack_AutoPGD(n, config_auto_pgd_dlr_plus) + else: + raise Exception( + 'Should be a valid attack method. The specified attack method is: {}' + .format(args.attack_method)) + + if args.binarization_test or args.attack_method.upper().startswith("AUTOPGD"): + specific_net = ZeroOneOneOneNetwork(basic_net) + specific_net.eval() + net = create_attack(specific_net) + else: + net = create_attack(basic_net) + + if device == 'cuda': + net = torch.nn.DataParallel(net) + if "specific_net" in locals(): + if not isinstance(specific_net, torch.nn.DataParallel): + specific_net = torch.nn.DataParallel(specific_net) + cudnn.benchmark = True + + criterion = nn.CrossEntropyLoss() + + if args.binarization_test: + test_test(net, specific_net, config_pgd) + else: + test(0, net, testloader) diff --git a/case_studies/feature_scatter/fs_eval.sh b/case_studies/feature_scatter/fs_eval.sh new file mode 100644 index 0000000..42fb8a9 --- /dev/null +++ b/case_studies/feature_scatter/fs_eval.sh @@ -0,0 +1,15 @@ +epsilon=${1:-8} +attack=${2-pgd-autopgddlr+} + +export PYTHONPATH=./:$PYTHONPATH +python3 case_studies/feature_scatter/fs_eval.py \ + --model-path=checkpoints/feature_scattering_linf_200_epochs.pth \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=$attack \ + --dataset=cifar10 \ + --batch_size_test=256 \ + --resume \ + --epsilon=$epsilon + +#natural-fgsm-pgd-cw \ No newline at end of file diff --git a/case_studies/feature_scatter/fs_eval_test.sh b/case_studies/feature_scatter/fs_eval_test.sh new file mode 100644 index 0000000..84ef3b5 --- /dev/null +++ b/case_studies/feature_scatter/fs_eval_test.sh @@ -0,0 +1,47 @@ +epsilon=${1:-8} +attack=${2-pgd-autopgddlr+} +nsamples=${3:-2048} +#attack=${2-pgd-autopgddlr-autopgddlrt-autopgddlrplus} +export PYTHONPATH=./:$PYTHONPATH + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using epsilon = $epsilon and few steps (20)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +python3 case_studies/feature_scatter/fs_eval.py \ + --model-path=checkpoints/feature_scattering_linf_200_epochs.pth \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=$attack \ + --dataset=cifar10 \ + --batch_size_test=1 \ + --binarization-test \ + --num_samples_test=$nsamples \ + --n-inner-points=999 \ + --n-boundary-points=1 \ + --resume \ + --epsilon=$epsilon + +exit + +# autopgddlr-autopgdce-autopgddlr+-autopgdce+ + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using epsilon = $epsilon and more steps (200)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + + +python3 case_studies/feature_scatter/fs_eval.py \ + --model-path=checkpoints/feature_scattering_linf_200_epochs.pth \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=$attack \ + --dataset=cifar10 \ + --batch_size_test=1 \ + --binarization-test \ + --num_samples_test=$nsamples \ + --n-inner-points=999 \ + --n-boundary-points=1 \ + --resume \ + --epsilon=$epsilon \ + --more-steps diff --git a/case_studies/feature_scatter/fs_main.py b/case_studies/feature_scatter/fs_main.py new file mode 100644 index 0000000..5ecd63e --- /dev/null +++ b/case_studies/feature_scatter/fs_main.py @@ -0,0 +1,338 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +'''Train Adversarially Robust Models with Feature Scattering''' +from __future__ import print_function +import time +import numpy as np +import random +import torch +import torch.nn as nn +import torch.optim as optim +import torch.nn.functional as F +import torch.backends.cudnn as cudnn +import torchvision +import torchvision.transforms as transforms + +from torch.autograd.gradcheck import zero_gradients +import copy +from torch.autograd import Variable +from PIL import Image + +import os +import argparse +import datetime + +from tqdm import tqdm +from models import * + +import utils +from utils import softCrossEntropy +from utils import one_hot_tensor +from attack_methods import Attack_FeaScatter + +torch.set_printoptions(threshold=10000) +np.set_printoptions(threshold=np.inf) + +parser = argparse.ArgumentParser(description='Feature Scatterring Training') + +# add type keyword to registries +parser.register('type', 'bool', utils.str2bool) + +parser.add_argument('--resume', + '-r', + action='store_true', + help='resume from checkpoint') +parser.add_argument('--lr', default=0.1, type=float, help='learning rate') +parser.add_argument('--adv_mode', + default='feature_scatter', + type=str, + help='adv_mode (feature_scatter)') +parser.add_argument('--model_dir', type=str, help='model path') +parser.add_argument('--init_model_pass', + default='-1', + type=str, + help='init model pass (-1: from scratch; K: checkpoint-K)') +parser.add_argument('--max_epoch', + default=200, + type=int, + help='max number of epochs') +parser.add_argument('--save_epochs', default=100, type=int, help='save period') +parser.add_argument('--decay_epoch1', + default=60, + type=int, + help='learning rate decay epoch one') +parser.add_argument('--decay_epoch2', + default=90, + type=int, + help='learning rate decay point two') +parser.add_argument('--decay_rate', + default=0.1, + type=float, + help='learning rate decay rate') +parser.add_argument('--batch_size_train', + default=128, + type=int, + help='batch size for training') +parser.add_argument('--momentum', + default=0.9, + type=float, + help='momentum (1-tf.momentum)') +parser.add_argument('--weight_decay', + default=2e-4, + type=float, + help='weight decay') +parser.add_argument('--log_step', default=10, type=int, help='log_step') + +# number of classes and image size will be updated below based on the dataset +parser.add_argument('--num_classes', default=10, type=int, help='num classes') +parser.add_argument('--image_size', default=32, type=int, help='image size') +parser.add_argument('--dataset', default='cifar10', type=str, + help='dataset') # concat cascade + +args = parser.parse_args() + +if args.dataset == 'cifar10': + print('------------cifar10---------') + args.num_classes = 10 + args.image_size = 32 +elif args.dataset == 'cifar100': + print('----------cifar100---------') + args.num_classes = 100 + args.image_size = 32 +if args.dataset == 'svhn': + print('------------svhn10---------') + args.num_classes = 10 + args.image_size = 32 + +device = 'cuda' if torch.cuda.is_available() else 'cpu' +start_epoch = 0 + +# Data +print('==> Preparing data..') + +if args.dataset == 'cifar10' or args.dataset == 'cifar100': + transform_train = transforms.Compose([ + transforms.RandomCrop(32, padding=4), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # [-1 1] + ]) + + transform_test = transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # [-1 1] + ]) +elif args.dataset == 'svhn': + transform_train = transforms.Compose([ + # transforms.RandomCrop(32, padding=4), + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # [-1 1] + ]) + + transform_test = transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # [-1 1] + ]) + +if args.dataset == 'cifar10': + trainset = torchvision.datasets.CIFAR10(root='./data', + train=True, + download=True, + transform=transform_train) + testset = torchvision.datasets.CIFAR10(root='./data', + train=False, + download=True, + transform=transform_test) + classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', + 'ship', 'truck') +elif args.dataset == 'cifar100': + trainset = torchvision.datasets.CIFAR100(root='./data', + train=True, + download=True, + transform=transform_train) + testset = torchvision.datasets.CIFAR100(root='./data', + train=False, + download=True, + transform=transform_test) + +elif args.dataset == 'svhn': + trainset = torchvision.datasets.SVHN(root='./data', + split='train', + download=True, + transform=transform_train) + testset = torchvision.datasets.SVHN(root='./data', + split='test', + download=True, + transform=transform_test) + +trainloader = torch.utils.data.DataLoader(trainset, + batch_size=args.batch_size_train, + shuffle=True, + num_workers=2) + +print('==> Building model..') + +if args.dataset == 'cifar10' or args.dataset == 'cifar100' or args.dataset == 'svhn': + print('---wide resenet-----') + basic_net = WideResNet(depth=28, + num_classes=args.num_classes, + widen_factor=10) + + +def print_para(net): + for name, param in net.named_parameters(): + if param.requires_grad: + print(name) + print(param.data) + break + + +basic_net = basic_net.to(device) + +# config for feature scatter +config_feature_scatter = { + 'train': True, + 'epsilon': 8.0 / 255 * 2, + 'num_steps': 1, + 'step_size': 8.0 / 255 * 2, + 'random_start': True, + 'ls_factor': 0.5, +} + +if args.adv_mode.lower() == 'feature_scatter': + print('-----Feature Scatter mode -----') + net = Attack_FeaScatter(basic_net, config_feature_scatter) +else: + print('-----OTHER_ALGO mode -----') + raise NotImplementedError("Please implement this algorithm first!") + +if device == 'cuda': + net = torch.nn.DataParallel(net) + cudnn.benchmark = True + +optimizer = optim.SGD(net.parameters(), + lr=args.lr, + momentum=args.momentum, + weight_decay=args.weight_decay) + +if args.resume and args.init_model_pass != '-1': + # Load checkpoint. + print('==> Resuming from checkpoint..') + f_path_latest = os.path.join(args.model_dir, 'latest') + f_path = os.path.join(args.model_dir, + ('checkpoint-%s' % args.init_model_pass)) + if not os.path.isdir(args.model_dir): + print('train from scratch: no checkpoint directory or file found') + elif args.init_model_pass == 'latest' and os.path.isfile(f_path_latest): + checkpoint = torch.load(f_path_latest) + net.load_state_dict(checkpoint['net']) + start_epoch = checkpoint['epoch'] + 1 + print('resuming from epoch %s in latest' % start_epoch) + elif os.path.isfile(f_path): + checkpoint = torch.load(f_path) + net.load_state_dict(checkpoint['net']) + start_epoch = checkpoint['epoch'] + 1 + print('resuming from epoch %s' % (start_epoch - 1)) + elif not os.path.isfile(f_path) or not os.path.isfile(f_path_latest): + print('train from scratch: no checkpoint directory or file found') + +soft_xent_loss = softCrossEntropy() + + +def train_fun(epoch, net): + print('\nEpoch: %d' % epoch) + net.train() + + train_loss = 0 + correct = 0 + total = 0 + + # update learning rate + if epoch < args.decay_epoch1: + lr = args.lr + elif epoch < args.decay_epoch2: + lr = args.lr * args.decay_rate + else: + lr = args.lr * args.decay_rate * args.decay_rate + for param_group in optimizer.param_groups: + param_group['lr'] = lr + + def get_acc(outputs, targets): + _, predicted = outputs.max(1) + total = targets.size(0) + correct = predicted.eq(targets).sum().item() + acc = 1.0 * correct / total + return acc + + iterator = tqdm(trainloader, ncols=0, leave=False) + for batch_idx, (inputs, targets) in enumerate(iterator): + start_time = time.time() + inputs, targets = inputs.to(device), targets.to(device) + + adv_acc = 0 + + optimizer.zero_grad() + + # forward + outputs, loss_fs = net(inputs.detach(), targets) + + optimizer.zero_grad() + loss = loss_fs.mean() + loss.backward() + + optimizer.step() + + train_loss = loss.item() + + duration = time.time() - start_time + if batch_idx % args.log_step == 0: + if adv_acc == 0: + adv_acc = get_acc(outputs, targets) + iterator.set_description(str(adv_acc)) + + nat_outputs, _ = net(inputs, targets, attack=False) + nat_acc = get_acc(nat_outputs, targets) + + print( + "epoch %d, step %d, lr %.4f, duration %.2f, training nat acc %.2f, training adv acc %.2f, training adv loss %.4f" + % (epoch, batch_idx, lr, duration, 100 * nat_acc, + 100 * adv_acc, train_loss)) + + if epoch % args.save_epochs == 0 or epoch >= args.max_epoch - 2: + print('Saving..') + f_path = os.path.join(args.model_dir, ('checkpoint-%s' % epoch)) + state = { + 'net': net.state_dict(), + # 'optimizer': optimizer.state_dict() + } + if not os.path.isdir(args.model_dir): + os.mkdir(args.model_dir) + torch.save(state, f_path) + + if epoch >= 0: + print('Saving latest @ epoch %s..' % (epoch)) + f_path = os.path.join(args.model_dir, 'latest') + state = { + 'net': net.state_dict(), + 'epoch': epoch, + 'optimizer': optimizer.state_dict() + } + if not os.path.isdir(args.model_dir): + os.mkdir(args.model_dir) + torch.save(state, f_path) + + +for epoch in range(start_epoch, args.max_epoch): + train_fun(epoch, net) diff --git a/case_studies/feature_scatter/fs_train.sh b/case_studies/feature_scatter/fs_train.sh new file mode 100644 index 0000000..dabe228 --- /dev/null +++ b/case_studies/feature_scatter/fs_train.sh @@ -0,0 +1,16 @@ +export PYTHONPATH=./:$PYTHONPATH +model_dir=~/models/feature_scatter_cifar10/ +mkdir -p $model_dir +CUDA_VISIBLE_DEVICES=0 python3 fs_main.py \ + --resume \ + --adv_mode='feature_scatter' \ + --lr=0.1 \ + --model_dir=$model_dir \ + --init_model_pass=latest \ + --max_epoch=200 \ + --save_epochs=100 \ + --decay_epoch1=60 \ + --decay_epoch2=90 \ + --batch_size_train=60 \ + --dataset=cifar10 + diff --git a/case_studies/feature_scatter/ftsc_utils.py b/case_studies/feature_scatter/ftsc_utils.py new file mode 100644 index 0000000..a778f13 --- /dev/null +++ b/case_studies/feature_scatter/ftsc_utils.py @@ -0,0 +1,97 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +'''Some utility functions +''' +import os +import sys +import time +import datetime +import math +import torch +import torch.nn as nn +import torch.nn.init as init +import torch.nn.functional as F + +import numpy as np + +import torch + +def one_hot_tensor(y_batch_tensor, num_classes, device): + y_tensor = torch.cuda.FloatTensor(y_batch_tensor.size(0), + num_classes).fill_(0) + y_tensor[np.arange(len(y_batch_tensor)), y_batch_tensor] = 1.0 + return y_tensor + + +def label_smoothing(y_batch_tensor, num_classes, delta): + y_batch_smooth = (1 - delta - delta / (num_classes - 1)) * \ + y_batch_tensor + delta / (num_classes - 1) + return y_batch_smooth + + +def str2bool(v): + return v.lower() in ("yes", "true", "t", "1") + + +class softCrossEntropy(nn.Module): + def __init__(self, reduce=True): + super(softCrossEntropy, self).__init__() + self.reduce = reduce + return + + def forward(self, inputs, targets): + """ + :param inputs: predictions + :param targets: target labels in vector form + :return: loss + """ + log_likelihood = -F.log_softmax(inputs, dim=1) + sample_num, class_num = targets.shape + if self.reduce: + loss = torch.sum(torch.mul(log_likelihood, targets)) / sample_num + else: + loss = torch.sum(torch.mul(log_likelihood, targets), 1) + + return loss + + +class CWLoss(nn.Module): + def __init__(self, num_classes, margin=50, reduce=True): + super(CWLoss, self).__init__() + self.num_classes = num_classes + self.margin = margin + self.reduce = reduce + return + + def forward(self, logits, targets): + """ + :param inputs: predictions + :param targets: target labels + :return: loss + """ + onehot_targets = one_hot_tensor(targets, self.num_classes, + targets.device) + + self_loss = torch.sum(onehot_targets * logits, dim=1) + other_loss = torch.max( + (1 - onehot_targets) * logits - onehot_targets * 1000, dim=1)[0] + + loss = -torch.sum(torch.clamp(self_loss - other_loss + self.margin, 0)) + + if self.reduce: + sample_num = onehot_targets.shape[0] + loss = loss / sample_num + + return loss diff --git a/case_studies/feature_scatter/models/__init__.py b/case_studies/feature_scatter/models/__init__.py new file mode 100644 index 0000000..1a5e1a7 --- /dev/null +++ b/case_studies/feature_scatter/models/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from .wideresnet import * diff --git a/case_studies/feature_scatter/models/wideresnet.py b/case_studies/feature_scatter/models/wideresnet.py new file mode 100644 index 0000000..c1e8638 --- /dev/null +++ b/case_studies/feature_scatter/models/wideresnet.py @@ -0,0 +1,143 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import math +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class BasicBlock(nn.Module): + def __init__(self, in_planes, out_planes, stride, dropRate=0.0): + super(BasicBlock, self).__init__() + self.bn1 = nn.BatchNorm2d(in_planes) + self.relu1 = nn.ReLU(inplace=True) + self.conv1 = nn.Conv2d(in_planes, + out_planes, + kernel_size=3, + stride=stride, + padding=1, + bias=False) + self.bn2 = nn.BatchNorm2d(out_planes) + self.relu2 = nn.ReLU(inplace=True) + self.conv2 = nn.Conv2d(out_planes, + out_planes, + kernel_size=3, + stride=1, + padding=1, + bias=False) + self.droprate = dropRate + self.equalInOut = (in_planes == out_planes) + self.convShortcut = (not self.equalInOut) and nn.Conv2d( + in_planes, + out_planes, + kernel_size=1, + stride=stride, + padding=0, + bias=False) or None + + def forward(self, x): + if not self.equalInOut: + x = self.relu1(self.bn1(x)) + else: + out = self.relu1(self.bn1(x)) + out = self.relu2(self.bn2(self.conv1(out if self.equalInOut else x))) + if self.droprate > 0: + out = F.dropout(out, p=self.droprate, training=self.training) + out = self.conv2(out) + return torch.add(x if self.equalInOut else self.convShortcut(x), out) + + +class NetworkBlock(nn.Module): + def __init__(self, + nb_layers, + in_planes, + out_planes, + block, + stride, + dropRate=0.0): + super(NetworkBlock, self).__init__() + self.layer = self._make_layer(block, in_planes, out_planes, nb_layers, + stride, dropRate) + + def _make_layer(self, block, in_planes, out_planes, nb_layers, stride, + dropRate): + layers = [] + for i in range(int(nb_layers)): + layers.append( + block(i == 0 and in_planes or out_planes, out_planes, + i == 0 and stride or 1, dropRate)) + return nn.Sequential(*layers) + + def forward(self, x): + return self.layer(x) + + +class WideResNet(nn.Module): + def __init__(self, depth, num_classes, widen_factor=1, dropRate=0.0): + super(WideResNet, self).__init__() + nChannels = [ + 16, 16 * widen_factor, 32 * widen_factor, 64 * widen_factor + ] + assert ((depth - 4) % 6 == 0) + n = (depth - 4) / 6 + block = BasicBlock + # 1st conv before any network block + self.conv1 = nn.Conv2d(3, + nChannels[0], + kernel_size=3, + stride=1, + padding=1, + bias=False) + # 1st block + self.block1 = NetworkBlock(n, nChannels[0], nChannels[1], block, 1, + dropRate) + # 2nd block + self.block2 = NetworkBlock(n, nChannels[1], nChannels[2], block, 2, + dropRate) + # 3rd block + self.block3 = NetworkBlock(n, nChannels[2], nChannels[3], block, 2, + dropRate) + # global average pooling and classifier + self.bn1 = nn.BatchNorm2d(nChannels[3]) + self.relu = nn.ReLU(inplace=True) + self.fc = nn.Linear(nChannels[3], num_classes) + self.nChannels = nChannels[3] + + 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_() + elif isinstance(m, nn.Linear): + m.bias.data.zero_() + + def forward(self, x, features_only=False, features_and_logits=False): + if features_only: assert not features_and_logits + out = self.conv1(x) + out = self.block1(out) + out = self.block2(out) + out = self.block3(out) + out = self.relu(self.bn1(out)) + out = F.avg_pool2d(out, 8) + out = out.view(-1, self.nChannels) + + if features_only: + return out + elif features_and_logits: + return out, self.fc(out) + else: + return self.fc(out), out.view(x.size(0), -1) diff --git a/case_studies/feature_scatter/ot.py b/case_studies/feature_scatter/ot.py new file mode 100644 index 0000000..2c6f086 --- /dev/null +++ b/case_studies/feature_scatter/ot.py @@ -0,0 +1,140 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" + +OT using IPOT and Sinkhorn algorithm + +""" + +import torch +from torch.autograd import Variable +import torch.nn as nn +import torch.nn.functional as F + +from ftsc_utils import softCrossEntropy + +import numpy as np + + +def sinkhorn_loss_joint_IPOT(alpha, beta, x_feature, y_feature, x_label, + y_label, epsilon, m, n): + + C_fea = get_cost_matrix(x_feature, y_feature) + C = C_fea + T = sinkhorn(C, 0.01, 100) + # T = IPOT(C, 1) + batch_size = C.size(0) + cost_ot = torch.sum(T * C) + return cost_ot + + +def sinkhorn(C, epsilon, niter=50, device='cuda'): + m = C.size(0) + n = C.size(1) + mu = Variable(1. / m * torch.FloatTensor(m).fill_(1).to('cuda'), + requires_grad=False) + nu = Variable(1. / n * torch.FloatTensor(n).fill_(1).to('cuda'), + requires_grad=False) + + # Parameters of the Sinkhorn algorithm. + rho = 1 # (.5) **2 # unbalanced transport + tau = -.8 # nesterov-like acceleration + lam = rho / (rho + epsilon) # Update exponent + thresh = 10**(-1) # stopping criterion + + # Elementary operations ..................................................................... + def ave(u, u1): + "Barycenter subroutine, used by kinetic acceleration through extrapolation." + return tau * u + (1 - tau) * u1 + + def M(u, v): + "Modified cost for logarithmic updates" + "$M_{ij} = (-c_{ij} + u_i + v_j) / \epsilon$" + return (-C + u.unsqueeze(1) + v.unsqueeze(0)) / epsilon + + def lse(A): + "log-sum-exp" + return torch.log(torch.exp(A).sum(1, keepdim=True) + + 1e-6) # add 10^-6 to prevent NaN + + # Actual Sinkhorn loop ...................................................................... + u, v, err = 0. * mu, 0. * nu, 0. + actual_nits = 0 # to check if algorithm terminates because of threshold or max iterations reached + + for i in range(niter): + u1 = u # useful to check the update + u = epsilon * (torch.log(mu) - lse(M(u, v)).squeeze()) + u + v = epsilon * (torch.log(nu) - lse(M(u, v).t()).squeeze()) + v + # accelerated unbalanced iterations + # u = ave( u, lam * ( epsilon * ( torch.log(mu) - lse(M(u,v)).squeeze() ) + u ) ) + # v = ave( v, lam * ( epsilon * ( torch.log(nu) - lse(M(u,v).t()).squeeze() ) + v ) ) + err = (u - u1).abs().sum() + + actual_nits += 1 + if (err < thresh).cpu().data.numpy(): + break + U, V = u, v + + pi = torch.exp(M(U, V)) # Transport plan pi = diag(a)*K*diag(b) + pi = pi.to('cuda').float() + return pi # return the transport + + +def IPOT(cost_matrix, beta=1, device='cuda'): + m = cost_matrix.size(0) + n = cost_matrix.size(1) + sigma = 1.0 / n * torch.ones([n, 1]).to(device) + + T = torch.ones([m, n]).to(device) + A = torch.exp(-cost_matrix / beta) + + for t in range(50): + # BUG: should be elementwise product, * in numpy + #Q = torch.mm(A, T) + Q = A * T # Hardmard product + for k in range(1): + delta = 1.0 / (m * torch.mm(Q, sigma)) + sigma = 1.0 / (n * torch.mm(delta.t(), Q)).t() + #sigma = 1.0 / (n * torch.mv(Q, delta)) + tmp = torch.mm(construct_diag(torch.squeeze(delta)), Q) + T = torch.mm(tmp, construct_diag(torch.squeeze(sigma))) + + return T + + +def construct_diag(d): + n = d.size(0) + x = torch.zeros([n, n]).to(d.device) + x[range(n), range(n)] = d.view(-1) + return x + + +def get_cost_matrix(x_feature, y_feature): + C_fea = cost_matrix_cos(x_feature, y_feature) # Wasserstein cost function + return C_fea + + +def cost_matrix_cos(x, y, p=2): + # return the m*n sized cost matrix + "Returns the matrix of $|x_i-y_j|^p$." + # un squeeze differently so that the tensors can broadcast + # dim-2 (summed over) is the feature dim + x_col = x.unsqueeze(1) + y_lin = y.unsqueeze(0) + + cos = nn.CosineSimilarity(dim=2, eps=1e-6) + c = torch.clamp(1 - cos(x_col, y_lin), min=0) + + return c \ No newline at end of file diff --git a/case_studies/inputtransformations/README.md b/case_studies/inputtransformations/README.md new file mode 100644 index 0000000..2a07891 --- /dev/null +++ b/case_studies/inputtransformations/README.md @@ -0,0 +1,27 @@ +# Countering Adversarial Images using Input Transformations + +Paper: [Guo et al. 2018](https://arxiv.org/abs/1711.00117) + +## Setup + +Run `./setup.sh` to fetch models. + +## Breaks + +* Bit-depth reduction: `bitdepth.ipynb` (broken with BPDA) +* JPEG: `jpeg.ipynb` (broken with BPDA) +* Cropping: `crop.ipynb` (broken with EOT) +* Quilting: `quilt.ipynb` (broken with EOT+BPDA) +* Total variation denoising: `tv.ipynb` (broken with EOT+BPDA) + +## [robustml] evaluation + +Run with: + +```bash +python robustml_attack.py --imagenet-path --defense +```` + +Where `` is one of `bitdepth`, `jpeg`, `crop`, `quilt`, or `tv`. + +[robustml]: https://github.com/robust-ml/robustml diff --git a/case_studies/inputtransformations/adversarial_evaluation.py b/case_studies/inputtransformations/adversarial_evaluation.py new file mode 100644 index 0000000..e7b02d5 --- /dev/null +++ b/case_studies/inputtransformations/adversarial_evaluation.py @@ -0,0 +1,98 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import os + +import tensorflow as tf +import torch +import torchvision + +tf.logging.set_verbosity(tf.logging.ERROR) + +from robustml_model import InputTransformations +from robustml_attack import BPDA +import argparse +import numpy as np +import tensorflow as tf +import robustml +import torch.utils.data +import sys +import tqdm + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--imagenet-path', type=str, required=True, + help='directory containing `val.txt` and `val/` folder') + parser.add_argument('--defense', type=str, required=True, + help='bitdepth | jpeg | crop | quilt | tv') + parser.add_argument('--n-samples', type=int, default=100) + parser.add_argument('--batch-size', type=int, default=128) + parser.add_argument("--epsilon", default=0.05, type=float) + parser.add_argument("--pgd-steps", type=int, default=100) + args = parser.parse_args() + + # set up TensorFlow session + sess = tf.Session() + + # initialize a model + model = InputTransformations(sess, args.defense) + + # initialize an attack (it's a white box attack, and it's allowed to look + # at the internals of the model in any way it wants) + # XXX restore + # TODO: use the distance conversion from original code; I think there is a + # factor sqrt(3) missing here + attack = BPDA(sess, model, args.epsilon * 299, debug=False, max_steps=args.pgd_steps) + + # initialize a data provider for ImageNet images + provider = robustml.provider.ImageNet(args.imagenet_path, model.dataset.shape) + + dataset = torchvision.datasets.ImageFolder( + os.path.join(args.imagenet_path, 'val'), + torchvision.transforms.Compose([ + torchvision.transforms.Resize(299), + torchvision.transforms.CenterCrop(299), + torchvision.transforms.ToTensor(), + ])) + random_indices = list(range(len(provider))) + if args.n_samples == -1: + args.n_samples = len(random_indices) + np.random.shuffle(random_indices) + random_indices = random_indices[:args.n_samples] + dataset = torch.utils.data.Subset(dataset, random_indices) + data_loader = torch.utils.data.DataLoader(dataset, + batch_size=args.batch_size, + shuffle=False, + pin_memory=False) + success = 0 + total = 0 + + for x_batch, y_batch in tqdm.tqdm(data_loader): + x_batch = x_batch.numpy().transpose((0, 2, 3, 1)) + y_batch = y_batch.numpy() + + total += len(x_batch) + + x_batch_adv = attack.run(x_batch, y_batch, None) + y_batch_adv = model.classify(x_batch_adv) + # adv_acc = (y_batch_adv == y_batch).mean() + success += (y_batch_adv != y_batch).sum() + + success_rate = success / total + + print('attack success rate: %.2f%% (over %d data points)' % (success_rate*100, total)) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/case_studies/inputtransformations/adversarial_evaluation.sh b/case_studies/inputtransformations/adversarial_evaluation.sh new file mode 100644 index 0000000..784255e --- /dev/null +++ b/case_studies/inputtransformations/adversarial_evaluation.sh @@ -0,0 +1,11 @@ +nsamples=128 + +epsilon=${1:-0.05} + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python case_studies/inputtransformations/adversarial_evaluation.py \ + --imagenet-path=/imagenet_dataset/ \ + --batch-size=128 \ + --n-samples=$nsamples \ + --epsilon=$epsilon \ + --defense=jpeg \ + --pgd-steps=256 \ No newline at end of file diff --git a/case_studies/inputtransformations/defense.py b/case_studies/inputtransformations/defense.py new file mode 100644 index 0000000..a2018a7 --- /dev/null +++ b/case_studies/inputtransformations/defense.py @@ -0,0 +1,334 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import PIL +import PIL.Image +from io import BytesIO +import numpy as np +import tensorflow as tf + +def defend_reduce(arr, depth=3): + arr = (arr * 255.0).astype(np.uint8) + shift = 8 - depth + arr = (arr >> shift) << shift + arr = arr.astype(np.float32)/255.0 + return arr + +batched_defend_reduce = defend_reduce + +def defend_jpeg(input_array): + pil_image = PIL.Image.fromarray((input_array*255.0).astype(np.uint8)) + f = BytesIO() + pil_image.save(f, format='jpeg', quality=75) # quality level specified in paper + jpeg_image = np.asarray(PIL.Image.open(f)).astype(np.float32)/255.0 + return jpeg_image + +def batched_defend_jpeg(xs): + return np.stack([defend_jpeg(x) for x in xs], 0) + +# based on https://github.com/scikit-image/scikit-image/blob/master/skimage/restoration/_denoise_cy.pyx + +# super slow since this is implemented in pure python :'( + +def bregman(image, mask, weight, eps=1e-3, max_iter=100): + rows, cols, dims = image.shape + rows2 = rows + 2 + cols2 = cols + 2 + total = rows * cols * dims + shape_ext = (rows2, cols2, dims) + + u = np.zeros(shape_ext) + dx = np.zeros(shape_ext) + dy = np.zeros(shape_ext) + bx = np.zeros(shape_ext) + by = np.zeros(shape_ext) + + u[1:-1, 1:-1] = image + # reflect image + u[0, 1:-1] = image[1, :] + u[1:-1, 0] = image[:, 1] + u[-1, 1:-1] = image[-2, :] + u[1:-1, -1] = image[:, -2] + + i = 0 + rmse = np.inf + lam = 2 * weight + norm = (weight + 4 * lam) + + while i < max_iter and rmse > eps: + rmse = 0 + + for k in range(dims): + for r in range(1, rows+1): + for c in range(1, cols+1): + uprev = u[r, c, k] + + # forward derivatives + ux = u[r, c+1, k] - uprev + uy = u[r+1, c, k] - uprev + + # Gauss-Seidel method + if mask[r-1, c-1]: + unew = (lam * (u[r+1, c, k] + + u[r-1, c, k] + + u[r, c+1, k] + + u[r, c-1, k] + + dx[r, c-1, k] - + dx[r, c, k] + + dy[r-1, c, k] - + dy[r, c, k] - + bx[r, c-1, k] + + bx[r, c, k] - + by[r-1, c, k] + + by[r, c, k] + ) + weight * image[r-1, c-1, k] + ) / norm + else: + # similar to the update step above, except we take + # lim_{weight->0} of the update step, effectively + # ignoring the l2 loss + unew = (u[r+1, c, k] + + u[r-1, c, k] + + u[r, c+1, k] + + u[r, c-1, k] + + dx[r, c-1, k] - + dx[r, c, k] + + dy[r-1, c, k] - + dy[r, c, k] - + bx[r, c-1, k] + + bx[r, c, k] - + by[r-1, c, k] + + by[r, c, k] + ) / 4.0 + u[r, c, k] = unew + + # update rms error + rmse += (unew - uprev)**2 + + bxx = bx[r, c, k] + byy = by[r, c, k] + + # d_subproblem + s = ux + bxx + if s > 1/lam: + dxx = s - 1/lam + elif s < -1/lam: + dxx = s + 1/lam + else: + dxx = 0 + s = uy + byy + if s > 1/lam: + dyy = s - 1/lam + elif s < -1/lam: + dyy = s + 1/lam + else: + dyy = 0 + + dx[r, c, k] = dxx + dy[r, c, k] = dyy + + bx[r, c, k] += ux - dxx + by[r, c, k] += uy - dyy + + rmse = np.sqrt(rmse / total) + i += 1 + + return np.squeeze(np.asarray(u[1:-1, 1:-1])) + +def defend_tv(input_array, keep_prob=0.5, lambda_tv=0.03): + mask = np.random.uniform(size=input_array.shape[:2]) + mask = mask < keep_prob + return bregman(input_array, mask, weight=2.0/lambda_tv) + +def batched_defend_tv(xs): + return np.stack([defend_tv(x) for x in xs], 0) + +def make_defend_quilt(sess): + # setup for quilting + quilt_db = np.load('checkpoints/inputtransformations_inceptionv3/quilt_db.npy') + quilt_db_reshaped = quilt_db.reshape(1000000, -1) + TILE_SIZE = 5 + TILE_OVERLAP = 2 + tile_skip = TILE_SIZE - TILE_OVERLAP + K = 10 + db_tensor = tf.placeholder(tf.float32, quilt_db_reshaped.shape) + query_imgs = tf.placeholder(tf.float32, (TILE_SIZE * TILE_SIZE * 3, None)) + norms = tf.reduce_sum(tf.square(db_tensor), axis=1)[:, tf.newaxis] \ + - 2*tf.matmul(db_tensor, query_imgs) + _, topk_indices = tf.nn.top_k(-tf.transpose(norms), k=K, sorted=False) + def min_error_table(arr, direction): + assert direction in ('horizontal', 'vertical') + y, x = arr.shape + cum = np.zeros_like(arr) + if direction == 'horizontal': + cum[:, -1] = arr[:, -1] + for ix in range(x-2, -1, -1): + for iy in range(y): + m = arr[iy, ix+1] + if iy > 0: + m = min(m, arr[iy-1, ix+1]) + if iy < y - 1: + m = min(m, arr[iy+1, ix+1]) + cum[iy, ix] = arr[iy, ix] + m + elif direction == 'vertical': + cum[-1, :] = arr[-1, :] + for iy in range(y-2, -1, -1): + for ix in range(x): + m = arr[iy+1, ix] + if ix > 0: + m = min(m, arr[iy+1, ix-1]) + if ix < x - 1: + m = min(m, arr[iy+1, ix+1]) + cum[iy, ix] = arr[iy, ix] + m + return cum + def index_exists(arr, index): + if arr.ndim != len(index): + return False + return all(i > 0 for i in index) and all(index[i] < arr.shape[i] for i in range(arr.ndim)) + def assign_block(ix, iy, tile, synth): + posx = tile_skip * ix + posy = tile_skip * iy + + if ix == 0 and iy == 0: + synth[posy:posy+TILE_SIZE, posx:posx+TILE_SIZE, :] = tile + elif iy == 0: + # first row, only have horizontal overlap of the block + tile_left = tile[:, :TILE_OVERLAP, :] + synth_right = synth[:TILE_SIZE, posx:posx+TILE_OVERLAP, :] + errors = np.sum(np.square(tile_left - synth_right), axis=2) + table = min_error_table(errors, direction='vertical') + # copy row by row into synth + xoff = np.argmin(table[0, :]) + synth[posy, posx+xoff:posx+TILE_SIZE] = tile[0, xoff:] + for yoff in range(1, TILE_SIZE): + # explore nearby xoffs + candidates = [(yoff, xoff), (yoff, xoff-1), (yoff, xoff+1)] + index = min((i for i in candidates if index_exists(table, i)), key=lambda i: table[i]) + xoff = index[1] + synth[posy+yoff, posx+xoff:posx+TILE_SIZE] = tile[yoff, xoff:] + elif ix == 0: + # first column, only have vertical overlap of the block + tile_up = tile[:TILE_OVERLAP, :, :] + synth_bottom = synth[posy:posy+TILE_OVERLAP, :TILE_SIZE, :] + errors = np.sum(np.square(tile_up - synth_bottom), axis=2) + table = min_error_table(errors, direction='horizontal') + # copy column by column into synth + yoff = np.argmin(table[:, 0]) + synth[posy+yoff:posy+TILE_SIZE, posx] = tile[yoff:, 0] + for xoff in range(1, TILE_SIZE): + # explore nearby yoffs + candidates = [(yoff, xoff), (yoff-1, xoff), (yoff+1, xoff)] + index = min((i for i in candidates if index_exists(table, i)), key=lambda i: table[i]) + yoff = index[0] + synth[posy+yoff:posy+TILE_SIZE, posx+xoff] = tile[yoff:, xoff] + else: + # glue cuts along diagonal + tile_up = tile[:TILE_OVERLAP, :, :] + synth_bottom = synth[posy:posy+TILE_OVERLAP, :TILE_SIZE, :] + errors_up = np.sum(np.square(tile_up - synth_bottom), axis=2) + table_up = min_error_table(errors_up, direction='horizontal') + tile_left = tile[:, :TILE_OVERLAP, :] + synth_right = synth[:TILE_SIZE, posx:posx+TILE_OVERLAP, :] + errors_left = np.sum(np.square(tile_left - synth_right), axis=2) + table_left = min_error_table(errors_left, direction='vertical') + glue_index = -1 + glue_value = np.inf + for i in range(TILE_OVERLAP): + e = table_up[i, i] + table_left[i, i] + if e < glue_value: + glue_value = e + glue_index = i + # copy left part first, up to the overlap column + xoff = glue_index + synth[posy+glue_index, posx+xoff:posx+TILE_OVERLAP] = tile[glue_index, xoff:TILE_OVERLAP] + for yoff in range(glue_index+1, TILE_SIZE): + # explore nearby xoffs + candidates = [(yoff, xoff), (yoff, xoff-1), (yoff, xoff+1)] + index = min((i for i in candidates if index_exists(table_left, i)), key=lambda i: table_left[i]) + xoff = index[1] + synth[posy+yoff, posx+xoff:posx+TILE_OVERLAP] = tile[yoff, xoff:TILE_OVERLAP] + # copy right part, down to overlap row + yoff = glue_index + synth[posy+yoff:posy+TILE_OVERLAP, posx+glue_index] = tile[yoff:TILE_OVERLAP, glue_index] + for xoff in range(glue_index+1, TILE_SIZE): + # explore nearby yoffs + candidates = [(yoff, xoff), (yoff-1, xoff), (yoff+1, xoff)] + index = min((i for i in candidates if index_exists(table_up, i)), key=lambda i: table_up[i]) + yoff = index[0] + synth[posy+yoff:posy+TILE_OVERLAP, posx+xoff] = tile[yoff:TILE_OVERLAP, xoff] + # copy rest of image + synth[posy+TILE_OVERLAP:posy+TILE_SIZE, posx+TILE_OVERLAP:posx+TILE_SIZE] = tile[TILE_OVERLAP:, TILE_OVERLAP:] + KNN_MAX_BATCH = 1000 + def quilt(arr, graphcut=True): + h, w, c = arr.shape + assert (h - TILE_SIZE) % tile_skip == 0 + assert (w - TILE_SIZE) % tile_skip == 0 + horiz_blocks = (w - TILE_SIZE) // tile_skip + 1 + vert_blocks = (h - TILE_SIZE) // tile_skip + 1 + num_patches = horiz_blocks * vert_blocks + patches = np.zeros((TILE_SIZE * TILE_SIZE * 3, num_patches)) + idx = 0 + for iy in range(vert_blocks): + for ix in range(horiz_blocks): + posx = tile_skip*ix + posy = tile_skip*iy + patches[:, idx] = arr[posy:posy+TILE_SIZE, posx:posx+TILE_SIZE, :].ravel() + idx += 1 + + ind = [] + for chunk in range(num_patches // KNN_MAX_BATCH + (1 if num_patches % KNN_MAX_BATCH != 0 else 0)): + start = KNN_MAX_BATCH * chunk + end = start + KNN_MAX_BATCH + # for some reason, the code below is 10x slower when run in a Jupyter notebook + # not sure why... + indices_ = sess.run(topk_indices, {db_tensor: quilt_db_reshaped, query_imgs: patches[:, start:end]}) + for i in indices_: + ind.append(np.random.choice(i)) + + synth = np.zeros((299, 299, 3)) + + idx = 0 + for iy in range(vert_blocks): + for ix in range(horiz_blocks): + posx = tile_skip*ix + posy = tile_skip*iy + tile = quilt_db[ind[idx]] + if not graphcut: + synth[posy:posy+TILE_SIZE, posx:posx+TILE_SIZE, :] = tile + else: + assign_block(ix, iy, tile, synth) + idx += 1 + return synth + + return quilt + + +def batched_make_defend_jpeg(sess): + quilt = make_defend_quilt(sess) + def inner(xs, *args, **kwargs): + return np.stack([quilt(x, *args, **kwargs) for x in xs], 0) + return inner + +# x is a square image (3-tensor) +def defend_crop(x, crop_size=90, ensemble_size=30): + x_size = tf.to_float(x.shape[1]) + frac = crop_size/x_size + start_fraction_max = (x_size - crop_size)/x_size + def randomizing_crop(x): + start_x = tf.random_uniform((), 0, start_fraction_max) + start_y = tf.random_uniform((), 0, start_fraction_max) + return tf.image.crop_and_resize([x], boxes=[[start_y, start_x, start_y+frac, start_x+frac]], + box_ind=[0], crop_size=[crop_size, crop_size]) + + return tf.concat([randomizing_crop(x) for _ in range(ensemble_size)], axis=0) \ No newline at end of file diff --git a/case_studies/inputtransformations/imagenet_labels.py b/case_studies/inputtransformations/imagenet_labels.py new file mode 100644 index 0000000..b824734 --- /dev/null +++ b/case_studies/inputtransformations/imagenet_labels.py @@ -0,0 +1,1020 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +_lut = [ + 'tench, Tinca tinca', + 'goldfish, Carassius auratus', + 'great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias', + 'tiger shark, Galeocerdo cuvieri', + 'hammerhead, hammerhead shark', + 'electric ray, crampfish, numbfish, torpedo', + 'stingray', + 'cock', + 'hen', + 'ostrich, Struthio camelus', + 'brambling, Fringilla montifringilla', + 'goldfinch, Carduelis carduelis', + 'house finch, linnet, Carpodacus mexicanus', + 'junco, snowbird', + 'indigo bunting, indigo finch, indigo bird, Passerina cyanea', + 'robin, American robin, Turdus migratorius', + 'bulbul', + 'jay', + 'magpie', + 'chickadee', + 'water ouzel, dipper', + 'kite', + 'bald eagle, American eagle, Haliaeetus leucocephalus', + 'vulture', + 'great grey owl, great gray owl, Strix nebulosa', + 'European fire salamander, Salamandra salamandra', + 'common newt, Triturus vulgaris', + 'eft', + 'spotted salamander, Ambystoma maculatum', + 'axolotl, mud puppy, Ambystoma mexicanum', + 'bullfrog, Rana catesbeiana', + 'tree frog, tree-frog', + 'tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui', + 'loggerhead, loggerhead turtle, Caretta caretta', + 'leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea', + 'mud turtle', + 'terrapin', + 'box turtle, box tortoise', + 'banded gecko', + 'common iguana, iguana, Iguana iguana', + 'American chameleon, anole, Anolis carolinensis', + 'whiptail, whiptail lizard', + 'agama', + 'frilled lizard, Chlamydosaurus kingi', + 'alligator lizard', + 'Gila monster, Heloderma suspectum', + 'green lizard, Lacerta viridis', + 'African chameleon, Chamaeleo chamaeleon', + 'Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis', + 'African crocodile, Nile crocodile, Crocodylus niloticus', + 'American alligator, Alligator mississipiensis', + 'triceratops', + 'thunder snake, worm snake, Carphophis amoenus', + 'ringneck snake, ring-necked snake, ring snake', + 'hognose snake, puff adder, sand viper', + 'green snake, grass snake', + 'king snake, kingsnake', + 'garter snake, grass snake', + 'water snake', + 'vine snake', + 'night snake, Hypsiglena torquata', + 'boa constrictor, Constrictor constrictor', + 'rock python, rock snake, Python sebae', + 'Indian cobra, Naja naja', + 'green mamba', + 'sea snake', + 'horned viper, cerastes, sand viper, horned asp, Cerastes cornutus', + 'diamondback, diamondback rattlesnake, Crotalus adamanteus', + 'sidewinder, horned rattlesnake, Crotalus cerastes', + 'trilobite', + 'harvestman, daddy longlegs, Phalangium opilio', + 'scorpion', + 'black and gold garden spider, Argiope aurantia', + 'barn spider, Araneus cavaticus', + 'garden spider, Aranea diademata', + 'black widow, Latrodectus mactans', + 'tarantula', + 'wolf spider, hunting spider', + 'tick', + 'centipede', + 'black grouse', + 'ptarmigan', + 'ruffed grouse, partridge, Bonasa umbellus', + 'prairie chicken, prairie grouse, prairie fowl', + 'peacock', + 'quail', + 'partridge', + 'African grey, African gray, Psittacus erithacus', + 'macaw', + 'sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita', + 'lorikeet', + 'coucal', + 'bee eater', + 'hornbill', + 'hummingbird', + 'jacamar', + 'toucan', + 'drake', + 'red-breasted merganser, Mergus serrator', + 'goose', + 'black swan, Cygnus atratus', + 'tusker', + 'echidna, spiny anteater, anteater', + 'platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus', + 'wallaby, brush kangaroo', + 'koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus', + 'wombat', + 'jellyfish', + 'sea anemone, anemone', + 'brain coral', + 'flatworm, platyhelminth', + 'nematode, nematode worm, roundworm', + 'conch', + 'snail', + 'slug', + 'sea slug, nudibranch', + 'chiton, coat-of-mail shell, sea cradle, polyplacophore', + 'chambered nautilus, pearly nautilus, nautilus', + 'Dungeness crab, Cancer magister', + 'rock crab, Cancer irroratus', + 'fiddler crab', + 'king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica', + 'American lobster, Northern lobster, Maine lobster, Homarus americanus', + 'spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish', + 'crayfish, crawfish, crawdad, crawdaddy', + 'hermit crab', + 'isopod', + 'white stork, Ciconia ciconia', + 'black stork, Ciconia nigra', + 'spoonbill', + 'flamingo', + 'little blue heron, Egretta caerulea', + 'American egret, great white heron, Egretta albus', + 'bittern', + 'crane', + 'limpkin, Aramus pictus', + 'European gallinule, Porphyrio porphyrio', + 'American coot, marsh hen, mud hen, water hen, Fulica americana', + 'bustard', + 'ruddy turnstone, Arenaria interpres', + 'red-backed sandpiper, dunlin, Erolia alpina', + 'redshank, Tringa totanus', + 'dowitcher', + 'oystercatcher, oyster catcher', + 'pelican', + 'king penguin, Aptenodytes patagonica', + 'albatross, mollymawk', + 'grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus', + 'killer whale, killer, orca, grampus, sea wolf, Orcinus orca', + 'dugong, Dugong dugon', + 'sea lion', + 'Chihuahua', + 'Japanese spaniel', + 'Maltese dog, Maltese terrier, Maltese', + 'Pekinese, Pekingese, Peke', + 'Shih-Tzu', + 'Blenheim spaniel', + 'papillon', + 'toy terrier', + 'Rhodesian ridgeback', + 'Afghan hound, Afghan', + 'basset, basset hound', + 'beagle', + 'bloodhound, sleuthhound', + 'bluetick', + 'black-and-tan coonhound', + 'Walker hound, Walker foxhound', + 'English foxhound', + 'redbone', + 'borzoi, Russian wolfhound', + 'Irish wolfhound', + 'Italian greyhound', + 'whippet', + 'Ibizan hound, Ibizan Podenco', + 'Norwegian elkhound, elkhound', + 'otterhound, otter hound', + 'Saluki, gazelle hound', + 'Scottish deerhound, deerhound', + 'Weimaraner', + 'Staffordshire bullterrier, Staffordshire bull terrier', + 'American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier', + 'Bedlington terrier', + 'Border terrier', + 'Kerry blue terrier', + 'Irish terrier', + 'Norfolk terrier', + 'Norwich terrier', + 'Yorkshire terrier', + 'wire-haired fox terrier', + 'Lakeland terrier', + 'Sealyham terrier, Sealyham', + 'Airedale, Airedale terrier', + 'cairn, cairn terrier', + 'Australian terrier', + 'Dandie Dinmont, Dandie Dinmont terrier', + 'Boston bull, Boston terrier', + 'miniature schnauzer', + 'giant schnauzer', + 'standard schnauzer', + 'Scotch terrier, Scottish terrier, Scottie', + 'Tibetan terrier, chrysanthemum dog', + 'silky terrier, Sydney silky', + 'soft-coated wheaten terrier', + 'West Highland white terrier', + 'Lhasa, Lhasa apso', + 'flat-coated retriever', + 'curly-coated retriever', + 'golden retriever', + 'Labrador retriever', + 'Chesapeake Bay retriever', + 'German short-haired pointer', + 'vizsla, Hungarian pointer', + 'English setter', + 'Irish setter, red setter', + 'Gordon setter', + 'Brittany spaniel', + 'clumber, clumber spaniel', + 'English springer, English springer spaniel', + 'Welsh springer spaniel', + 'cocker spaniel, English cocker spaniel, cocker', + 'Sussex spaniel', + 'Irish water spaniel', + 'kuvasz', + 'schipperke', + 'groenendael', + 'malinois', + 'briard', + 'kelpie', + 'komondor', + 'Old English sheepdog, bobtail', + 'Shetland sheepdog, Shetland sheep dog, Shetland', + 'collie', + 'Border collie', + 'Bouvier des Flandres, Bouviers des Flandres', + 'Rottweiler', + 'German shepherd, German shepherd dog, German police dog, alsatian', + 'Doberman, Doberman pinscher', + 'miniature pinscher', + 'Greater Swiss Mountain dog', + 'Bernese mountain dog', + 'Appenzeller', + 'EntleBucher', + 'boxer', + 'bull mastiff', + 'Tibetan mastiff', + 'French bulldog', + 'Great Dane', + 'Saint Bernard, St Bernard', + 'Eskimo dog, husky', + 'malamute, malemute, Alaskan malamute', + 'Siberian husky', + 'dalmatian, coach dog, carriage dog', + 'affenpinscher, monkey pinscher, monkey dog', + 'basenji', + 'pug, pug-dog', + 'Leonberg', + 'Newfoundland, Newfoundland dog', + 'Great Pyrenees', + 'Samoyed, Samoyede', + 'Pomeranian', + 'chow, chow chow', + 'keeshond', + 'Brabancon griffon', + 'Pembroke, Pembroke Welsh corgi', + 'Cardigan, Cardigan Welsh corgi', + 'toy poodle', + 'miniature poodle', + 'standard poodle', + 'Mexican hairless', + 'timber wolf, grey wolf, gray wolf, Canis lupus', + 'white wolf, Arctic wolf, Canis lupus tundrarum', + 'red wolf, maned wolf, Canis rufus, Canis niger', + 'coyote, prairie wolf, brush wolf, Canis latrans', + 'dingo, warrigal, warragal, Canis dingo', + 'dhole, Cuon alpinus', + 'African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus', + 'hyena, hyaena', + 'red fox, Vulpes vulpes', + 'kit fox, Vulpes macrotis', + 'Arctic fox, white fox, Alopex lagopus', + 'grey fox, gray fox, Urocyon cinereoargenteus', + 'tabby, tabby cat', + 'tiger cat', + 'Persian cat', + 'Siamese cat, Siamese', + 'Egyptian cat', + 'cougar, puma, catamount, mountain lion, painter, panther, Felis concolor', + 'lynx, catamount', + 'leopard, Panthera pardus', + 'snow leopard, ounce, Panthera uncia', + 'jaguar, panther, Panthera onca, Felis onca', + 'lion, king of beasts, Panthera leo', + 'tiger, Panthera tigris', + 'cheetah, chetah, Acinonyx jubatus', + 'brown bear, bruin, Ursus arctos', + 'American black bear, black bear, Ursus americanus, Euarctos americanus', + 'ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus', + 'sloth bear, Melursus ursinus, Ursus ursinus', + 'mongoose', + 'meerkat, mierkat', + 'tiger beetle', + 'ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle', + 'ground beetle, carabid beetle', + 'long-horned beetle, longicorn, longicorn beetle', + 'leaf beetle, chrysomelid', + 'dung beetle', + 'rhinoceros beetle', + 'weevil', + 'fly', + 'bee', + 'ant, emmet, pismire', + 'grasshopper, hopper', + 'cricket', + 'walking stick, walkingstick, stick insect', + 'cockroach, roach', + 'mantis, mantid', + 'cicada, cicala', + 'leafhopper', + 'lacewing, lacewing fly', + "dragonfly, darning needle, devil's darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk", + 'damselfly', + 'admiral', + 'ringlet, ringlet butterfly', + 'monarch, monarch butterfly, milkweed butterfly, Danaus plexippus', + 'cabbage butterfly', + 'sulphur butterfly, sulfur butterfly', + 'lycaenid, lycaenid butterfly', + 'starfish, sea star', + 'sea urchin', + 'sea cucumber, holothurian', + 'wood rabbit, cottontail, cottontail rabbit', + 'hare', + 'Angora, Angora rabbit', + 'hamster', + 'porcupine, hedgehog', + 'fox squirrel, eastern fox squirrel, Sciurus niger', + 'marmot', + 'beaver', + 'guinea pig, Cavia cobaya', + 'sorrel', + 'zebra', + 'hog, pig, grunter, squealer, Sus scrofa', + 'wild boar, boar, Sus scrofa', + 'warthog', + 'hippopotamus, hippo, river horse, Hippopotamus amphibius', + 'ox', + 'water buffalo, water ox, Asiatic buffalo, Bubalus bubalis', + 'bison', + 'ram, tup', + 'bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis', + 'ibex, Capra ibex', + 'hartebeest', + 'impala, Aepyceros melampus', + 'gazelle', + 'Arabian camel, dromedary, Camelus dromedarius', + 'llama', + 'weasel', + 'mink', + 'polecat, fitch, foulmart, foumart, Mustela putorius', + 'black-footed ferret, ferret, Mustela nigripes', + 'otter', + 'skunk, polecat, wood pussy', + 'badger', + 'armadillo', + 'three-toed sloth, ai, Bradypus tridactylus', + 'orangutan, orang, orangutang, Pongo pygmaeus', + 'gorilla, Gorilla gorilla', + 'chimpanzee, chimp, Pan troglodytes', + 'gibbon, Hylobates lar', + 'siamang, Hylobates syndactylus, Symphalangus syndactylus', + 'guenon, guenon monkey', + 'patas, hussar monkey, Erythrocebus patas', + 'baboon', + 'macaque', + 'langur', + 'colobus, colobus monkey', + 'proboscis monkey, Nasalis larvatus', + 'marmoset', + 'capuchin, ringtail, Cebus capucinus', + 'howler monkey, howler', + 'titi, titi monkey', + 'spider monkey, Ateles geoffroyi', + 'squirrel monkey, Saimiri sciureus', + 'Madagascar cat, ring-tailed lemur, Lemur catta', + 'indri, indris, Indri indri, Indri brevicaudatus', + 'Indian elephant, Elephas maximus', + 'African elephant, Loxodonta africana', + 'lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens', + 'giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca', + 'barracouta, snoek', + 'eel', + 'coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch', + 'rock beauty, Holocanthus tricolor', + 'anemone fish', + 'sturgeon', + 'gar, garfish, garpike, billfish, Lepisosteus osseus', + 'lionfish', + 'puffer, pufferfish, blowfish, globefish', + 'abacus', + 'abaya', + "academic gown, academic robe, judge's robe", + 'accordion, piano accordion, squeeze box', + 'acoustic guitar', + 'aircraft carrier, carrier, flattop, attack aircraft carrier', + 'airliner', + 'airship, dirigible', + 'altar', + 'ambulance', + 'amphibian, amphibious vehicle', + 'analog clock', + 'apiary, bee house', + 'apron', + 'ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin', + 'assault rifle, assault gun', + 'backpack, back pack, knapsack, packsack, rucksack, haversack', + 'bakery, bakeshop, bakehouse', + 'balance beam, beam', + 'balloon', + 'ballpoint, ballpoint pen, ballpen, Biro', + 'Band Aid', + 'banjo', + 'bannister, banister, balustrade, balusters, handrail', + 'barbell', + 'barber chair', + 'barbershop', + 'barn', + 'barometer', + 'barrel, cask', + 'barrow, garden cart, lawn cart, wheelbarrow', + 'baseball', + 'basketball', + 'bassinet', + 'bassoon', + 'bathing cap, swimming cap', + 'bath towel', + 'bathtub, bathing tub, bath, tub', + 'beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon', + 'beacon, lighthouse, beacon light, pharos', + 'beaker', + 'bearskin, busby, shako', + 'beer bottle', + 'beer glass', + 'bell cote, bell cot', + 'bib', + 'bicycle-built-for-two, tandem bicycle, tandem', + 'bikini, two-piece', + 'binder, ring-binder', + 'binoculars, field glasses, opera glasses', + 'birdhouse', + 'boathouse', + 'bobsled, bobsleigh, bob', + 'bolo tie, bolo, bola tie, bola', + 'bonnet, poke bonnet', + 'bookcase', + 'bookshop, bookstore, bookstall', + 'bottlecap', + 'bow', + 'bow tie, bow-tie, bowtie', + 'brass, memorial tablet, plaque', + 'brassiere, bra, bandeau', + 'breakwater, groin, groyne, mole, bulwark, seawall, jetty', + 'breastplate, aegis, egis', + 'broom', + 'bucket, pail', + 'buckle', + 'bulletproof vest', + 'bullet train, bullet', + 'butcher shop, meat market', + 'cab, hack, taxi, taxicab', + 'caldron, cauldron', + 'candle, taper, wax light', + 'cannon', + 'canoe', + 'can opener, tin opener', + 'cardigan', + 'car mirror', + 'carousel, carrousel, merry-go-round, roundabout, whirligig', + "carpenter's kit, tool kit", + 'carton', + 'car wheel', + 'cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM', + 'cassette', + 'cassette player', + 'castle', + 'catamaran', + 'CD player', + 'cello, violoncello', + 'cellular telephone, cellular phone, cellphone, cell, mobile phone', + 'chain', + 'chainlink fence', + 'chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour', + 'chain saw, chainsaw', + 'chest', + 'chiffonier, commode', + 'chime, bell, gong', + 'china cabinet, china closet', + 'Christmas stocking', + 'church, church building', + 'cinema, movie theater, movie theatre, movie house, picture palace', + 'cleaver, meat cleaver, chopper', + 'cliff dwelling', + 'cloak', + 'clog, geta, patten, sabot', + 'cocktail shaker', + 'coffee mug', + 'coffeepot', + 'coil, spiral, volute, whorl, helix', + 'combination lock', + 'computer keyboard, keypad', + 'confectionery, confectionary, candy store', + 'container ship, containership, container vessel', + 'convertible', + 'corkscrew, bottle screw', + 'cornet, horn, trumpet, trump', + 'cowboy boot', + 'cowboy hat, ten-gallon hat', + 'cradle', + 'crane', + 'crash helmet', + 'crate', + 'crib, cot', + 'Crock Pot', + 'croquet ball', + 'crutch', + 'cuirass', + 'dam, dike, dyke', + 'desk', + 'desktop computer', + 'dial telephone, dial phone', + 'diaper, nappy, napkin', + 'digital clock', + 'digital watch', + 'dining table, board', + 'dishrag, dishcloth', + 'dishwasher, dish washer, dishwashing machine', + 'disk brake, disc brake', + 'dock, dockage, docking facility', + 'dogsled, dog sled, dog sleigh', + 'dome', + 'doormat, welcome mat', + 'drilling platform, offshore rig', + 'drum, membranophone, tympan', + 'drumstick', + 'dumbbell', + 'Dutch oven', + 'electric fan, blower', + 'electric guitar', + 'electric locomotive', + 'entertainment center', + 'envelope', + 'espresso maker', + 'face powder', + 'feather boa, boa', + 'file, file cabinet, filing cabinet', + 'fireboat', + 'fire engine, fire truck', + 'fire screen, fireguard', + 'flagpole, flagstaff', + 'flute, transverse flute', + 'folding chair', + 'football helmet', + 'forklift', + 'fountain', + 'fountain pen', + 'four-poster', + 'freight car', + 'French horn, horn', + 'frying pan, frypan, skillet', + 'fur coat', + 'garbage truck, dustcart', + 'gasmask, respirator, gas helmet', + 'gas pump, gasoline pump, petrol pump, island dispenser', + 'goblet', + 'go-kart', + 'golf ball', + 'golfcart, golf cart', + 'gondola', + 'gong, tam-tam', + 'gown', + 'grand piano, grand', + 'greenhouse, nursery, glasshouse', + 'grille, radiator grille', + 'grocery store, grocery, food market, market', + 'guillotine', + 'hair slide', + 'hair spray', + 'half track', + 'hammer', + 'hamper', + 'hand blower, blow dryer, blow drier, hair dryer, hair drier', + 'hand-held computer, hand-held microcomputer', + 'handkerchief, hankie, hanky, hankey', + 'hard disc, hard disk, fixed disk', + 'harmonica, mouth organ, harp, mouth harp', + 'harp', + 'harvester, reaper', + 'hatchet', + 'holster', + 'home theater, home theatre', + 'honeycomb', + 'hook, claw', + 'hoopskirt, crinoline', + 'horizontal bar, high bar', + 'horse cart, horse-cart', + 'hourglass', + 'iPod', + 'iron, smoothing iron', + "jack-o'-lantern", + 'jean, blue jean, denim', + 'jeep, landrover', + 'jersey, T-shirt, tee shirt', + 'jigsaw puzzle', + 'jinrikisha, ricksha, rickshaw', + 'joystick', + 'kimono', + 'knee pad', + 'knot', + 'lab coat, laboratory coat', + 'ladle', + 'lampshade, lamp shade', + 'laptop, laptop computer', + 'lawn mower, mower', + 'lens cap, lens cover', + 'letter opener, paper knife, paperknife', + 'library', + 'lifeboat', + 'lighter, light, igniter, ignitor', + 'limousine, limo', + 'liner, ocean liner', + 'lipstick, lip rouge', + 'Loafer', + 'lotion', + 'loudspeaker, speaker, speaker unit, loudspeaker system, speaker system', + "loupe, jeweler's loupe", + 'lumbermill, sawmill', + 'magnetic compass', + 'mailbag, postbag', + 'mailbox, letter box', + 'maillot', + 'maillot, tank suit', + 'manhole cover', + 'maraca', + 'marimba, xylophone', + 'mask', + 'matchstick', + 'maypole', + 'maze, labyrinth', + 'measuring cup', + 'medicine chest, medicine cabinet', + 'megalith, megalithic structure', + 'microphone, mike', + 'microwave, microwave oven', + 'military uniform', + 'milk can', + 'minibus', + 'miniskirt, mini', + 'minivan', + 'missile', + 'mitten', + 'mixing bowl', + 'mobile home, manufactured home', + 'Model T', + 'modem', + 'monastery', + 'monitor', + 'moped', + 'mortar', + 'mortarboard', + 'mosque', + 'mosquito net', + 'motor scooter, scooter', + 'mountain bike, all-terrain bike, off-roader', + 'mountain tent', + 'mouse, computer mouse', + 'mousetrap', + 'moving van', + 'muzzle', + 'nail', + 'neck brace', + 'necklace', + 'nipple', + 'notebook, notebook computer', + 'obelisk', + 'oboe, hautboy, hautbois', + 'ocarina, sweet potato', + 'odometer, hodometer, mileometer, milometer', + 'oil filter', + 'organ, pipe organ', + 'oscilloscope, scope, cathode-ray oscilloscope, CRO', + 'overskirt', + 'oxcart', + 'oxygen mask', + 'packet', + 'paddle, boat paddle', + 'paddlewheel, paddle wheel', + 'padlock', + 'paintbrush', + "pajama, pyjama, pj's, jammies", + 'palace', + 'panpipe, pandean pipe, syrinx', + 'paper towel', + 'parachute, chute', + 'parallel bars, bars', + 'park bench', + 'parking meter', + 'passenger car, coach, carriage', + 'patio, terrace', + 'pay-phone, pay-station', + 'pedestal, plinth, footstall', + 'pencil box, pencil case', + 'pencil sharpener', + 'perfume, essence', + 'Petri dish', + 'photocopier', + 'pick, plectrum, plectron', + 'pickelhaube', + 'picket fence, paling', + 'pickup, pickup truck', + 'pier', + 'piggy bank, penny bank', + 'pill bottle', + 'pillow', + 'ping-pong ball', + 'pinwheel', + 'pirate, pirate ship', + 'pitcher, ewer', + "plane, carpenter's plane, woodworking plane", + 'planetarium', + 'plastic bag', + 'plate rack', + 'plow, plough', + "plunger, plumber's helper", + 'Polaroid camera, Polaroid Land camera', + 'pole', + 'police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria', + 'poncho', + 'pool table, billiard table, snooker table', + 'pop bottle, soda bottle', + 'pot, flowerpot', + "potter's wheel", + 'power drill', + 'prayer rug, prayer mat', + 'printer', + 'prison, prison house', + 'projectile, missile', + 'projector', + 'puck, hockey puck', + 'punching bag, punch bag, punching ball, punchball', + 'purse', + 'quill, quill pen', + 'quilt, comforter, comfort, puff', + 'racer, race car, racing car', + 'racket, racquet', + 'radiator', + 'radio, wireless', + 'radio telescope, radio reflector', + 'rain barrel', + 'recreational vehicle, RV, R.V.', + 'reel', + 'reflex camera', + 'refrigerator, icebox', + 'remote control, remote', + 'restaurant, eating house, eating place, eatery', + 'revolver, six-gun, six-shooter', + 'rifle', + 'rocking chair, rocker', + 'rotisserie', + 'rubber eraser, rubber, pencil eraser', + 'rugby ball', + 'rule, ruler', + 'running shoe', + 'safe', + 'safety pin', + 'saltshaker, salt shaker', + 'sandal', + 'sarong', + 'sax, saxophone', + 'scabbard', + 'scale, weighing machine', + 'school bus', + 'schooner', + 'scoreboard', + 'screen, CRT screen', + 'screw', + 'screwdriver', + 'seat belt, seatbelt', + 'sewing machine', + 'shield, buckler', + 'shoe shop, shoe-shop, shoe store', + 'shoji', + 'shopping basket', + 'shopping cart', + 'shovel', + 'shower cap', + 'shower curtain', + 'ski', + 'ski mask', + 'sleeping bag', + 'slide rule, slipstick', + 'sliding door', + 'slot, one-armed bandit', + 'snorkel', + 'snowmobile', + 'snowplow, snowplough', + 'soap dispenser', + 'soccer ball', + 'sock', + 'solar dish, solar collector, solar furnace', + 'sombrero', + 'soup bowl', + 'space bar', + 'space heater', + 'space shuttle', + 'spatula', + 'speedboat', + "spider web, spider's web", + 'spindle', + 'sports car, sport car', + 'spotlight, spot', + 'stage', + 'steam locomotive', + 'steel arch bridge', + 'steel drum', + 'stethoscope', + 'stole', + 'stone wall', + 'stopwatch, stop watch', + 'stove', + 'strainer', + 'streetcar, tram, tramcar, trolley, trolley car', + 'stretcher', + 'studio couch, day bed', + 'stupa, tope', + 'submarine, pigboat, sub, U-boat', + 'suit, suit of clothes', + 'sundial', + 'sunglass', + 'sunglasses, dark glasses, shades', + 'sunscreen, sunblock, sun blocker', + 'suspension bridge', + 'swab, swob, mop', + 'sweatshirt', + 'swimming trunks, bathing trunks', + 'swing', + 'switch, electric switch, electrical switch', + 'syringe', + 'table lamp', + 'tank, army tank, armored combat vehicle, armoured combat vehicle', + 'tape player', + 'teapot', + 'teddy, teddy bear', + 'television, television system', + 'tennis ball', + 'thatch, thatched roof', + 'theater curtain, theatre curtain', + 'thimble', + 'thresher, thrasher, threshing machine', + 'throne', + 'tile roof', + 'toaster', + 'tobacco shop, tobacconist shop, tobacconist', + 'toilet seat', + 'torch', + 'totem pole', + 'tow truck, tow car, wrecker', + 'toyshop', + 'tractor', + 'trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi', + 'tray', + 'trench coat', + 'tricycle, trike, velocipede', + 'trimaran', + 'tripod', + 'triumphal arch', + 'trolleybus, trolley coach, trackless trolley', + 'trombone', + 'tub, vat', + 'turnstile', + 'typewriter keyboard', + 'umbrella', + 'unicycle, monocycle', + 'upright, upright piano', + 'vacuum, vacuum cleaner', + 'vase', + 'vault', + 'velvet', + 'vending machine', + 'vestment', + 'viaduct', + 'violin, fiddle', + 'volleyball', + 'waffle iron', + 'wall clock', + 'wallet, billfold, notecase, pocketbook', + 'wardrobe, closet, press', + 'warplane, military plane', + 'washbasin, handbasin, washbowl, lavabo, wash-hand basin', + 'washer, automatic washer, washing machine', + 'water bottle', + 'water jug', + 'water tower', + 'whiskey jug', + 'whistle', + 'wig', + 'window screen', + 'window shade', + 'Windsor tie', + 'wine bottle', + 'wing', + 'wok', + 'wooden spoon', + 'wool, woolen, woollen', + 'worm fence, snake fence, snake-rail fence, Virginia fence', + 'wreck', + 'yawl', + 'yurt', + 'web site, website, internet site, site', + 'comic book', + 'crossword puzzle, crossword', + 'street sign', + 'traffic light, traffic signal, stoplight', + 'book jacket, dust cover, dust jacket, dust wrapper', + 'menu', + 'plate', + 'guacamole', + 'consomme', + 'hot pot, hotpot', + 'trifle', + 'ice cream, icecream', + 'ice lolly, lolly, lollipop, popsicle', + 'French loaf', + 'bagel, beigel', + 'pretzel', + 'cheeseburger', + 'hotdog, hot dog, red hot', + 'mashed potato', + 'head cabbage', + 'broccoli', + 'cauliflower', + 'zucchini, courgette', + 'spaghetti squash', + 'acorn squash', + 'butternut squash', + 'cucumber, cuke', + 'artichoke, globe artichoke', + 'bell pepper', + 'cardoon', + 'mushroom', + 'Granny Smith', + 'strawberry', + 'orange', + 'lemon', + 'fig', + 'pineapple, ananas', + 'banana', + 'jackfruit, jak, jack', + 'custard apple', + 'pomegranate', + 'hay', + 'carbonara', + 'chocolate sauce, chocolate syrup', + 'dough', + 'meat loaf, meatloaf', + 'pizza, pizza pie', + 'potpie', + 'burrito', + 'red wine', + 'espresso', + 'cup', + 'eggnog', + 'alp', + 'bubble', + 'cliff, drop, drop-off', + 'coral reef', + 'geyser', + 'lakeside, lakeshore', + 'promontory, headland, head, foreland', + 'sandbar, sand bar', + 'seashore, coast, seacoast, sea-coast', + 'valley, vale', + 'volcano', + 'ballplayer, baseball player', + 'groom, bridegroom', + 'scuba diver', + 'rapeseed', + 'daisy', + "yellow lady's slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum", + 'corn', + 'acorn', + 'hip, rose hip, rosehip', + 'buckeye, horse chestnut, conker', + 'coral fungus', + 'agaric', + 'gyromitra', + 'stinkhorn, carrion fungus', + 'earthstar', + 'hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa', + 'bolete', + 'ear, spike, capitulum', + 'toilet tissue, toilet paper, bathroom tissue' +] + +def label_to_name(label): + global _lut + return _lut[label] diff --git a/case_studies/inputtransformations/inceptionv3.py b/case_studies/inputtransformations/inceptionv3.py new file mode 100644 index 0000000..448c1eb --- /dev/null +++ b/case_studies/inputtransformations/inceptionv3.py @@ -0,0 +1,61 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from utils import optimistic_restore +import tensorflow as tf +import tensorflow.contrib.slim as slim +import tensorflow.contrib.slim.nets as nets +import functools + +INCEPTION_CHECKPOINT_PATH = 'checkpoints/inputtransformations_inceptionv3/inception_v3.ckpt' + + +def _get_model(reuse): + arg_scope = nets.inception.inception_v3_arg_scope(weight_decay=0.0) + func = nets.inception.inception_v3 + @functools.wraps(func) + def network_fn(images): + with slim.arg_scope(arg_scope): + return func(images, 1001, is_training=False, reuse=reuse) + if hasattr(func, 'default_image_size'): + network_fn.default_image_size = func.default_image_size + return network_fn + +def _preprocess(image, height, width, scope=None): + with tf.name_scope(scope, 'eval_image', [image, height, width]): + if image.dtype != tf.float32: + image = tf.image.convert_image_dtype(image, dtype=tf.float32) + image = tf.image.resize_bilinear(image, [height, width], align_corners=False) + image = tf.subtract(image, 0.5) + image = tf.multiply(image, 2.0) + return image + +# input is [batch, ?, ?, 3], pixels in [0, 1] +# it's rescaled to [batch, 299, 299, 3] and shifted to [-1, 1] +# output is [batch, 1000] (imagenet classes) +_inception_initialized = False +def model(sess, image): + global _inception_initialized + network_fn = _get_model(reuse=_inception_initialized) + size = network_fn.default_image_size + preprocessed = _preprocess(image, size, size) + logits, _ = network_fn(preprocessed) + logits = logits[:,1:] # ignore background class + predictions = tf.argmax(logits, 1) + + if not _inception_initialized: + optimistic_restore(sess, INCEPTION_CHECKPOINT_PATH) + _inception_initialized = True + + return logits, predictions diff --git a/case_studies/inputtransformations/quilt_preprocess.py b/case_studies/inputtransformations/quilt_preprocess.py new file mode 100644 index 0000000..538b95b --- /dev/null +++ b/case_studies/inputtransformations/quilt_preprocess.py @@ -0,0 +1,74 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import os +import random +import PIL +import PIL.Image +import numpy as np +import sys + + +SAMPLES = 1000000 +DIM = 5 +RESIZE = True +RESIZE_DIM = 300 +OUTPUT_FILE = 'quilt_db.npy' + +def main(argv): + imagenet_train_dir = argv[1] + + assert SAMPLES % 1000 == 0 + + db = np.zeros((SAMPLES, DIM, DIM, 3), dtype=np.float32) + + idx = 0 + files = [] + for d in os.listdir(imagenet_train_dir): + d = os.path.join(imagenet_train_dir, d) + files.extend(os.path.join(d, i) for i in os.listdir(d) if i.endswith('.JPEG')) + for f in random.sample(files, SAMPLES): + img = load_image(f) + h, w, _ = img.shape + h_start = random.randint(0, h - DIM) + w_start = random.randint(0, w - DIM) + crop = img[h_start:h_start+DIM, w_start:w_start+DIM, :] + db[idx, :, :, :] = crop + idx += 1 + + if idx % 100 == 0: + print('%.2f%% done' % (100 * (float(idx) / SAMPLES))) + + np.save(OUTPUT_FILE, db) + + +def load_image(path): + image = PIL.Image.open(path) + if RESIZE: + if image.height > image.width: + image = image.resize((int(float(image.width) / image.height * RESIZE_DIM), RESIZE_DIM)) + elif image.width > image.height: + image = image.resize((RESIZE_DIM, int(float(image.height) / image.width * RESIZE_DIM))) + img = np.asarray(image).astype(np.float32) / 255.0 + if img.ndim == 2: + img = np.repeat(img[:,:,np.newaxis], repeats=3, axis=2) + if img.shape[2] == 4: + # alpha channel + img = img[:,:,:3] + return img + + +if __name__ == '__main__': + main(sys.argv) + diff --git a/case_studies/inputtransformations/robustml_attack.py b/case_studies/inputtransformations/robustml_attack.py new file mode 100644 index 0000000..108c835 --- /dev/null +++ b/case_studies/inputtransformations/robustml_attack.py @@ -0,0 +1,83 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import robustml +import sys +import tensorflow as tf +import numpy as np + +class BPDA(robustml.attack.Attack): + def __init__(self, sess, model, epsilon, max_steps=1000, learning_rate=0.1, lam=1e-6, debug=False): + self._sess = sess + + self._model = model + self._input = model.input + self._l2_input = tf.placeholder(tf.float32, self._input.shape, name="l2_input") # using BPDA, so we want this to pass the original adversarial example + self._original = tf.placeholder(tf.float32, self._input.shape, name="original") + self._label = tf.placeholder(tf.int32, (None,), name="label") + one_hot = tf.one_hot(self._label, 1000) + #ensemble_labels = tf.tile(one_hot, (model.logits.shape[0], 1)) + self._l2 = tf.sqrt(2*tf.nn.l2_loss(self._l2_input - self._original)) + self._xent = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model.logits, labels=one_hot)) + self._loss = lam * tf.maximum(self._l2 - epsilon, 0) + self._xent + self._grad, = tf.gradients(self._loss, self._input) + + self._epsilon = epsilon + self._max_steps = max_steps + self._learning_rate = learning_rate + self._debug = debug + + def run(self, x, y, target): + if target is not None: + raise NotImplementedError + adv = np.copy(x) + for i in range(self._max_steps): + adv_def = self._model.defend(adv) + p, ll2, lxent, g = self._sess.run( + [self._model.predictions, self._l2, self._xent, self._grad], + {self._input: adv_def, self._label: y, self._l2_input: adv, self._original: x} + ) + if self._debug: + print( + 'attack: step %d/%d, xent loss = %g, l2 loss = %g (max %g), (true %d, predicted %s)' % ( + i+1, + self._max_steps, + lxent, + ll2, + self._epsilon, + y, + p + ), + file=sys.stderr + ) + is_adv = np.logical_and(y != p, ll2 < self._epsilon) + print(is_adv.sum()) + if np.all(is_adv): + #if y not in p and ll2 < self._epsilon: + # we're done + #if self._debug: + print('returning early', file=sys.stderr) + break + g *= (~is_adv).astype(int).reshape(-1, 1, 1, 1) + adv += self._learning_rate * g + adv = np.clip(adv, 0, 1) + + adv_l2 = np.sqrt(((adv - x)**2).sum((1, 2, 3), keepdims=True)) + factor = self._epsilon / adv_l2 + factor = np.minimum(factor, np.ones_like(factor)) + diff = adv - x + adv = diff*factor + x + + return adv + diff --git a/case_studies/inputtransformations/robustml_model.py b/case_studies/inputtransformations/robustml_model.py new file mode 100644 index 0000000..530d918 --- /dev/null +++ b/case_studies/inputtransformations/robustml_model.py @@ -0,0 +1,87 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import robustml +from defense import * +from inceptionv3 import model as inceptionv3_model +import tensorflow as tf + +class InputTransformations(robustml.model.Model): + def __init__(self, sess, defense): + self._sess = sess + self._input = tf.placeholder(tf.float32, (None, 299, 299, 3)) + #self._input_single = tf.placeholder(tf.float32, (299, 299, 3)) + #input_expanded = tf.expand_dims(self._input, axis=0) + + if defense == 'crop': + raise NotImplementedError("crop transformation not properly " + "implemented yet") + cropped_xs = defend_crop(self._input) + self._logits, _ = inceptionv3_model(sess, cropped_xs) + self._probs = tf.reduce_mean(tf.nn.softmax(self._logits), axis=0, keepdims=True) + else: + self._logits, _ = inceptionv3_model(sess, self._input) + self._probs = tf.nn.softmax(self._logits) + + self._predictions = tf.argmax(self._probs, 1) + + if defense == 'bitdepth': + self._defend = batched_defend_reduce + elif defense == 'jpeg': + self._defend = batched_defend_jpeg + elif defense == 'crop': + raise NotImplementedError("crop transformation not properly " + "implemented yet") + self._defend = lambda x: x # implemented as part of model so it's differentiable + elif defense == 'quilt': + self._defend = batched_make_defend_jpeg(sess) + elif defense == 'tv': + self._defend = batched_defend_tv + elif defense == None: + self._defend = lambda x: x + else: + raise ValueError('invalid defense: %s' % defense) + + #self._dataset = robustml.dataset.ImageNet((299, 299, 3)) + #self._threat_model = robustml.threat_model.L2(epsilon=0.05*299) # 0.05 * sqrt(299*299) + # TODO: I think there is a factor sqrt(3) missing here + + @property + def dataset(self): + return self._dataset + + @property + def threat_model(self): + return self._threat_model + + def classify(self, x): + x_defended = self.defend(x) + return self._sess.run(self._predictions, {self._input: x_defended}) + + # expose internals for white box attacks + + def defend(self, x): + return self._defend(x) + + @property + def input(self): + return self._input + + @property + def logits(self): + return self._logits + + @property + def predictions(self): + return self._predictions diff --git a/case_studies/inputtransformations/setup.sh b/case_studies/inputtransformations/setup.sh new file mode 100644 index 0000000..a394009 --- /dev/null +++ b/case_studies/inputtransformations/setup.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +cd "$(dirname "$0")" # cd to directory of this script + +# $1 is filename +# $2 is expected sha +check_sha1() { + computed=$(sha1sum "$1" 2>/dev/null | awk '{print $1}') || return 1 + if [ "$computed" == "$2" ]; then + return 0; + else + return 1; + fi +} + +# $1 is URL +# $2 is extracted file name +# $3 is the checksum +fetch() { + if check_sha1 $2 $3; then + echo "$2 already downloaded" + return + fi + echo "downloading $1" + f=${1##*/} + wget -q $1 -O $f + tar xf $f + rm -f $f + if check_sha1 $2 $3; then + echo "downloaded $2" + else + echo "HASH MISMATCH, SHA1($2) != $3" + fi +} + +cd data + +fetch \ + http://download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz \ + inception_v3.ckpt 606fd6953c58c817c56fd3bc2f0384fc2ecaba92 + +fetch \ + https://github.com/anishathalye/obfuscated-gradients/releases/download/v0/quilt_db.tar.gz \ + quilt_db.npy ff4b94f45c9e8441b341fd5ffcf2adb0a8049873 diff --git a/case_studies/inputtransformations/utils.py b/case_studies/inputtransformations/utils.py new file mode 100644 index 0000000..4838934 --- /dev/null +++ b/case_studies/inputtransformations/utils.py @@ -0,0 +1,67 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import tensorflow as tf +from tensorflow.python.framework import ops +import numpy as np +import PIL.Image +from imagenet_labels import label_to_name +import matplotlib.pyplot as plt + +def one_hot(index, total): + arr = np.zeros((total)) + arr[index] = 1.0 + return arr + +def optimistic_restore(session, save_file): + reader = tf.train.NewCheckpointReader(save_file) + saved_shapes = reader.get_variable_to_shape_map() + var_names = sorted([(var.name, var.name.split(':')[0]) for var in tf.global_variables() + if var.name.split(':')[0] in saved_shapes]) + restore_vars = [] + with tf.variable_scope('', reuse=True): + for var_name, saved_var_name in var_names: + curr_var = tf.get_variable(saved_var_name) + var_shape = curr_var.get_shape().as_list() + if var_shape == saved_shapes[saved_var_name]: + restore_vars.append(curr_var) + saver = tf.train.Saver(restore_vars) + saver.restore(session, save_file) + +def load_image(path): + return (np.asarray(PIL.Image.open(path).resize((299, 299)))/255.0).astype(np.float32) + +def make_classify(sess, input_, probs): + def classify(img, correct_class=None, target_class=None): + fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 8)) + fig.sca(ax1) + p = sess.run(probs, feed_dict={input_: img})[0] + ax1.imshow(img) + fig.sca(ax1) + + topk = list(p.argsort()[-10:][::-1]) + topprobs = p[topk] + barlist = ax2.bar(range(10), topprobs) + if target_class in topk: + barlist[topk.index(target_class)].set_color('r') + if correct_class in topk: + barlist[topk.index(correct_class)].set_color('g') + plt.sca(ax2) + plt.ylim([0, 1.1]) + plt.xticks(range(10), + [label_to_name(i)[:15] for i in topk], + rotation='vertical') + fig.subplots_adjust(bottom=0.2) + plt.show() + return classify \ No newline at end of file diff --git a/case_studies/interpolation_training/__init__.py b/case_studies/interpolation_training/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/case_studies/interpolation_training/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/case_studies/interpolation_training/adv_interp.py b/case_studies/interpolation_training/adv_interp.py new file mode 100644 index 0000000..fd3db17 --- /dev/null +++ b/case_studies/interpolation_training/adv_interp.py @@ -0,0 +1,65 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +''' Adversarial Interpolation ''' + +from it_utils import cos_dist +import copy +import pickle +import torch +from torch.autograd.gradcheck import zero_gradients +from torch.autograd import Variable + + +def adv_interp(inputs, + y, + base_net, + num_classes, + epsilon=8, + epsilon_y=0.5, + v_min=0, + v_max=255): + # x: image batch with shape [batch_size, c, h, w] + # y: one-hot label batch with shape [batch_size, num_classes] + net = copy.deepcopy(base_net) + x = inputs.clone() + + inv_index = torch.arange(x.size(0) - 1, -1, -1).long() + x_prime = x[inv_index, :, :, :].detach() + y_prime = y[inv_index, :] + x_init = x.detach() + torch.zeros_like(x).uniform_(-epsilon, epsilon) + + x_init.requires_grad_() + zero_gradients(x_init) + if x_init.grad is not None: + x_init.grad.data.fill_(0) + net.eval() + + fea_b = net(x_init, mode='feature') + fea_t = net(x_prime, mode='feature') + + loss_adv = cos_dist(fea_b, fea_t) + net.zero_grad() + loss_adv = loss_adv.mean() + loss_adv.backward(retain_graph=True) + + x_tilde = x_init.data - epsilon * torch.sign(x_init.grad.data) + + x_tilde = torch.min(torch.max(x_tilde, inputs - epsilon), inputs + epsilon) + x_tilde = torch.clamp(x_tilde, v_min, v_max) + + y_bar_prime = (1 - y_prime) / (num_classes - 1.0) + y_tilde = (1 - epsilon_y) * y + epsilon_y * y_bar_prime + + return x_tilde.detach(), y_tilde.detach() \ No newline at end of file diff --git a/case_studies/interpolation_training/adv_interp_train.sh b/case_studies/interpolation_training/adv_interp_train.sh new file mode 100644 index 0000000..825237b --- /dev/null +++ b/case_studies/interpolation_training/adv_interp_train.sh @@ -0,0 +1,16 @@ +export PYTHONPATH=./:$PYTHONPATH +checkpoint_dir=~/models/adv_interp_model/ +mkdir -p $checkpoint_dir +CUDA_VISIBLE_DEVICES=0 python train_adv_interp.py \ + --resume \ + --lr=0.1 \ + --model_dir=$checkpoint_dir \ + --init_model_pass=-1 \ + --max_epoch=200 \ + --save_epochs=10 \ + --decay_epoch1=60 \ + --decay_epoch2=90 \ + --batch_size_train=128 \ + --label_adv_delta=0.5 \ + --save_epochs=100 \ + diff --git a/case_studies/interpolation_training/binarization_test.sh b/case_studies/interpolation_training/binarization_test.sh new file mode 100644 index 0000000..d703531 --- /dev/null +++ b/case_studies/interpolation_training/binarization_test.sh @@ -0,0 +1,65 @@ +nsamples=${1:-512} +epsilon=${2:-8} + +# kwargs="" +kwargs="--sample-from-corners" +echo "Epsilon: $epsilon" +echo "#samples: $nsamples" +echo "kwargs: $kwargs" + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using epsilon = $epsilon and few steps (20)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +PYTHONPATH=$(pwd) python3 case_studies/interpolation_training/eval.py \ + --model-path=checkpoints/adversarial_interpolation_linf_200_epochs.pth \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=pgd-autopgddlr \ + --batch_size_test=1 \ + --binarization-test \ + --num_samples_test=$nsamples \ + --n-inner-points=999 \ + --n-boundary-points=10 \ + --resume \ + --epsilon=$epsilon \ + $kwargs + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using epsilon = $epsilon and more steps (200)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +PYTHONPATH=$(pwd) python3 case_studies/interpolation_training/eval.py \ + --model-path=checkpoints/adversarial_interpolation_linf_200_epochs.pth \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=pgd-autopgddlr \ + --batch_size_test=1 \ + --binarization-test \ + --num_samples_test=$nsamples \ + --n-inner-points=999 \ + --n-boundary-points=10 \ + --resume \ + --epsilon=$epsilon \ + --more-steps \ + $kwargs + + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Using epsilon = $epsilon and more steps (400)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + +PYTHONPATH=$(pwd) python3 case_studies/interpolation_training/eval.py \ + --model-path=checkpoints/adversarial_interpolation_linf_200_epochs.pth \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=pgd-autopgddlr \ + --batch_size_test=1 \ + --binarization-test \ + --num_samples_test=$nsamples \ + --n-inner-points=999 \ + --n-boundary-points=10 \ + --resume \ + --epsilon=$epsilon \ + --more-more-steps \ + $kwargs \ No newline at end of file diff --git a/case_studies/interpolation_training/eval.py b/case_studies/interpolation_training/eval.py new file mode 100644 index 0000000..a27c3b9 --- /dev/null +++ b/case_studies/interpolation_training/eval.py @@ -0,0 +1,419 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import print_function + +import argparse +import inspect +import os +import sys +import time +import warnings + +import numpy as np +import torch.backends.cudnn as cudnn +import torchvision +import torchvision.transforms as transforms +from tqdm import tqdm + +import active_tests.decision_boundary_binarization +import it_utils +from it_utils import Attack_PGD, Attack_AutoPGD +from it_utils import CWLoss +from models import * + +warnings.simplefilter('once', RuntimeWarning) + +currentdir = os.path.dirname( + os.path.abspath(inspect.getfile(inspect.currentframe()))) +grandarentdir = os.path.dirname(os.path.dirname(currentdir)) +sys.path.insert(0, grandarentdir) + +parser = argparse.ArgumentParser( + description='Adversarial Interpolation Training') + +parser.register('type', 'bool', it_utils.str2bool) + +parser.add_argument('--resume', + '-r', + action='store_true', + help='resume from checkpoint') +parser.add_argument('--attack', default=True, type='bool', help='attack') +parser.add_argument('--model_dir', type=str, help='model path') +parser.add_argument('--init_model_pass', + default='-1', + type=str, + help='init model pass') + +parser.add_argument('--attack_method', + default='pgd', + type=str, + help='adv_mode (natural, pdg or cw)') +parser.add_argument('--attack_method_list', type=str) + +parser.add_argument('--log_step', default=7, type=int, help='log_step') + +parser.add_argument('--num_classes', default=10, type=int, help='num classes') +parser.add_argument('--batch_size_test', + default=100, + type=int, + help='batch size for testing') +parser.add_argument('--image_size', default=32, type=int, help='image size') + +parser.add_argument('--binarization-test', action="store_true") +parser.add_argument('--model-path', type=str, help='model path', default=None) +parser.add_argument('--num_samples_test', + default=-1, + type=int) + +parser.add_argument('--n-inner-points', + default=50, + type=int) + +parser.add_argument('--n-boundary-points', + default=10, + type=int) + +parser.add_argument("--epsilon", default=8, type=int) +parser.add_argument("--more-steps", action="store_true") +parser.add_argument("--more-more-steps", action="store_true") +parser.add_argument("--sample-from-corners", action="store_true") + +args = parser.parse_args() + +device = 'cuda' if torch.cuda.is_available() else 'cpu' + +transform_test = transforms.Compose([ + transforms.ToTensor(), + # transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), +]) + +testset = torchvision.datasets.CIFAR10(root='./data', + train=False, + download=True, + transform=transform_test) + +testloader = torch.utils.data.DataLoader(testset, + batch_size=args.batch_size_test, + shuffle=False, + num_workers=2) + +print('======= WideResenet 28-10 ========') +basic_net = WideResNet(depth=28, num_classes=args.num_classes, widen_factor=10) + +basic_net = basic_net.to(device) + + +class ZeroOneOneOneNetwork(nn.Module): + def __init__(self, model): + super().__init__() + self.model = model + + def forward(self, x, *args, **kwargs): + return self.model((x - 0.5) / 0.5, *args, **kwargs) + + +if device == 'cuda': + basic_net = torch.nn.DataParallel(basic_net) + cudnn.benchmark = True + +if args.binarization_test: + args.num_classes = 2 + +if args.num_samples_test == -1: + num_samples_test = len(testset) + +# load parameters + +if args.resume and args.init_model_pass != '-1': + # Load checkpoint. + print('==> Resuming from saved checkpoint..') + if args.model_dir is not None: + f_path_latest = os.path.join(args.model_dir, 'latest') + f_path = os.path.join(args.model_dir, + ('checkpoint-%s' % args.init_model_pass)) + elif args.model_path is not None: + f_path = args.model_path + f_path_latest = args.model_path + + if not os.path.isfile(f_path): + print('train from scratch: no checkpoint directory or file found') + elif args.init_model_pass == 'latest' and os.path.isfile(f_path_latest): + checkpoint = torch.load(f_path_latest) + basic_net.load_state_dict(checkpoint['net']) + start_epoch = checkpoint['epoch'] + print('resuming from epoch %s in latest' % start_epoch) + elif os.path.isfile(f_path): + checkpoint = torch.load(f_path) + basic_net.load_state_dict(checkpoint['net']) + start_epoch = checkpoint['epoch'] + print('resuming from epoch %s' % start_epoch) + elif not os.path.isfile(f_path) or not os.path.isfile(f_path_latest): + print('train from scratch: no checkpoint directory or file found') + +# configs +config_natural = {'train': False, 'attack': False} + +config_fgsm = { + 'train': False, + 'v_min': -1.0, + 'v_max': 1.0, + 'epsilon': args.epsilon / 255.0, + 'num_steps': 1, + 'step_size': args.epsilon / 255.0, + 'random_start': True +} + +config_pgd = { + 'train': False, + 'v_min': -1.0, + 'v_max': 1.0, + 'epsilon': args.epsilon / 255.0, + 'num_steps': 20, + 'step_size': args.epsilon / 4.0 / 255.0, + 'random_start': True, + 'loss_func': torch.nn.CrossEntropyLoss(reduction='none') +} + +config_cw = { + 'train': False, + 'v_min': -1.0, + 'v_max': 1.0, + 'epsilon': args.epsilon / 255, + 'num_steps': 20 * 10, + 'step_size': args.epsilon / 4.0 / 255 / 5, + 'random_start': True, + 'loss_func': CWLoss(args.num_classes) +} + +config_auto_pgd_ce = { + 'train': False, + 'targeted': False, + 'epsilon': args.epsilon / 255.0, + 'num_steps': 20, + 'loss_func': "ce" +} + +config_auto_pgd_dlr = { + 'train': False, + 'targeted': False, + 'epsilon': args.epsilon / 255.0, + 'num_steps': 20, + 'loss_func': "logit-diff" +} + +config_auto_pgd_dlr_t = { + **config_auto_pgd_dlr, + "targeted": True, + "n_classes": 10, +} + +config_auto_pgd_ce_plus = { + **config_auto_pgd_ce, + "n_restarts": 4 +} + +config_auto_pgd_dlr_plus = { + **config_auto_pgd_dlr, + "n_restarts": 4 +} + +if not args.binarization_test: + config_fgsm["epsilon"] *= 2.0 + config_pgd["epsilon"] *= 2.0 + config_cw["epsilon"] *= 2.0 + config_fgsm["step_size"] *= 2.0 + config_pgd["step_size"] *= 2.0 + config_cw["step_size"] *= 2.0 +else: + config_auto_pgd_dlr_t["n_classes"] = 2 + +if args.more_steps: + config_pgd["step_size"] /= 5.0 + config_cw["step_size"] /= 5.0 + config_pgd["num_steps"] *= 10 + config_cw["num_steps"] *= 10 + + config_auto_pgd_ce["num_steps"] *= 10 + config_auto_pgd_dlr["num_steps"] *= 10 + print("More & finer steps") + +if args.more_more_steps: + config_pgd["step_size"] /= 5.0 + config_cw["step_size"] /= 5.0 + config_pgd["num_steps"] *= 20 + config_cw["num_steps"] *= 20 + + config_auto_pgd_ce["num_steps"] *= 20 + config_auto_pgd_dlr["num_steps"] *= 20 + print("More & finer steps") + + +def test_test(net, feature_extractor, config): + from argparse_utils import DecisionBoundaryBinarizationSettings + class DummyModel(nn.Module): + def __init__(self, model): + super().__init__() + self.model = model + def forward(self, x, mode=None): + del mode + return self.model(x) + + scores_logit_differences_and_validation_accuracies = active_tests.decision_boundary_binarization.interior_boundary_discrimination_attack( + feature_extractor, + testloader, + attack_fn=lambda m, l, kwargs: test_main(0, create_attack(DummyModel(m)), l, verbose=False, + inverse_acc=True, return_advs=True), + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=config["epsilon"], + norm="linf", + lr=10000, + n_boundary_points=args.n_boundary_points, + n_inner_points=args.n_inner_points, + adversarial_attack_settings=None, + optimizer="sklearn" + ), + n_samples=args.num_samples_test, + device=device, + n_samples_evaluation=200,#args.num_samples_test * 10, + n_samples_asr_evaluation=200, + batch_size=args.num_samples_test * 5, + rescale_logits="adaptive", + decision_boundary_closeness=0.999, + sample_training_data_from_corners=args.sample_from_corners + ) + + print(active_tests.decision_boundary_binarization.format_result( + scores_logit_differences_and_validation_accuracies, + args.num_samples_test)) + + +def test_main(epoch, net, loader, verbose=False, inverse_acc=False, + return_advs=False): + net.eval() + test_loss = 0.0 + correct = 0.0 + total = 0.0 + + if verbose: + iterator = tqdm(loader, ncols=0, leave=False) + else: + iterator = loader + + x_adv = [] + logits_adv = [] + for batch_idx, (inputs, targets) in enumerate(iterator): + start_time = time.time() + inputs, targets = inputs.to(device), targets.to(device) + + pert_inputs = inputs.detach() + + res = net(pert_inputs, targets) + if isinstance(res, tuple): + outputs, _, x_adv_it = res + else: + outputs = res + + if return_advs: + x_adv.append(x_adv_it) + else: + del x_adv_it + logits_adv.append(outputs.detach().cpu()) + + duration = time.time() - start_time + + _, predicted = outputs.max(1) + batch_size = targets.size(0) + total += batch_size + correct_num = predicted.eq(targets).sum().item() + correct += correct_num + if verbose: + iterator.set_description( + str(predicted.eq(targets).sum().item() / targets.size(0))) + + if batch_idx % args.log_step == 0: + print( + "Step %d, Duration %.2f, Current-batch-acc %.2f, Avg-acc %.2f" + % (batch_idx, duration, 100. * correct_num / batch_size, + 100. * correct / total)) + + if return_advs: + x_adv = torch.cat(x_adv, 0) + logits_adv = torch.cat(logits_adv, 0) + + acc = 100. * correct / total + if verbose: + print('Test accuracy: %.2f' % (acc)) + + if inverse_acc: + acc = (100 - acc) / 100.0 + + return acc, (x_adv, logits_adv) + + +attack_list = args.attack_method_list.split('-') +attack_num = len(attack_list) + +print(f"Epsilon: {args.epsilon}") + +for attack_idx in range(attack_num): + + args.attack_method = attack_list[attack_idx] + + if args.attack_method == 'natural': + print('======Evaluation using Natural Images======') + create_attack = lambda n: Attack_PGD(n, config_natural) + elif args.attack_method.upper() == 'FGSM': + print('======Evaluation under FGSM Attack======') + create_attack = lambda n: Attack_PGD(n, config_fgsm) + elif args.attack_method.upper() == 'PGD': + print('======Evaluation under PGD Attack======') + create_attack = lambda n: Attack_PGD(n, config_pgd) + elif args.attack_method.upper() == 'CW': + print('======Evaluation under CW Attack======') + create_attack = lambda n: Attack_PGD(n, config_cw) + elif args.attack_method.upper() == 'AUTOPGDCE': + print() + print('-----Auto PGD (CE) adv mode -----') + create_attack = lambda n: Attack_AutoPGD(n, config_auto_pgd_ce) + elif args.attack_method.upper() == 'AUTOPGDDLR': + print() + print('-----Auto PGD (DLR) adv mode -----') + create_attack = lambda n: Attack_AutoPGD(n, config_auto_pgd_dlr) + elif args.attack_method.upper() == 'AUTOPGDDLRT': + print() + print('-----Auto PGD (DLR, targeted) adv mode -----') + create_attack = lambda n: Attack_AutoPGD(n, config_auto_pgd_dlr_t) + elif args.attack_method.upper() == 'AUTOPGDCE+': + print() + print('-----Auto PGD+ (CE) adv mode -----') + create_attack = lambda n: Attack_AutoPGD(n, config_auto_pgd_ce_plus) + elif args.attack_method.upper() == 'AUTOPGDDLR+': + print() + print('-----Auto PGD+ (DLR) adv mode -----') + create_attack = lambda n: Attack_AutoPGD(n, config_auto_pgd_dlr_plus) + else: + raise Exception( + 'Should be a valid attack method. The specified attack method is: {}' + .format(args.attack_method)) + + if args.binarization_test: + specific_net = ZeroOneOneOneNetwork(basic_net) + net = create_attack(specific_net) + + test_test(net, basic_net, config_pgd) + else: + net = create_attack(basic_net) + + test_main(0, net, testloader, verbose=True) diff --git a/case_studies/interpolation_training/eval.sh b/case_studies/interpolation_training/eval.sh new file mode 100644 index 0000000..90138bf --- /dev/null +++ b/case_studies/interpolation_training/eval.sh @@ -0,0 +1,12 @@ +epsilon=${1:-8} +attack=${2-pgd-cw} + +export PYTHONPATH=./:$PYTHONPATH +python case_studies/interpolation_training/eval.py \ + --model-path=checkpoints/adversarial_inperpolation_linf_200_epochs.pth \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=$attack \ + --batch_size_test=128 \ + --epsilon=$epsilon \ + --resume \ No newline at end of file diff --git a/case_studies/interpolation_training/eval_pretrain.sh b/case_studies/interpolation_training/eval_pretrain.sh new file mode 100644 index 0000000..7109de4 --- /dev/null +++ b/case_studies/interpolation_training/eval_pretrain.sh @@ -0,0 +1,9 @@ +export PYTHONPATH=./:$PYTHONPATH +checkpoint_dir=./pre_trained_adv_interp_models/ +CUDA_VISIBLE_DEVICES=1 python eval.py \ + --model_dir=$checkpoint_dir \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=natural-fgsm-pgd-cw \ + --batch_size_test=80 \ + --resume \ No newline at end of file diff --git a/case_studies/interpolation_training/eval_test_pretrain.sh b/case_studies/interpolation_training/eval_test_pretrain.sh new file mode 100644 index 0000000..79d269e --- /dev/null +++ b/case_studies/interpolation_training/eval_test_pretrain.sh @@ -0,0 +1,8 @@ +export PYTHONPATH=./:$PYTHONPATH +python case_studies/interpolation_training/eval.py \ + --model-path=checkpoints/interpolation_training_linf_200_epochs.pth \ + --init_model_pass=latest \ + --attack=True \ + --attack_method_list=natural-fgsm-pgd-cw \ + --batch_size_test=80 \ + --resume \ No newline at end of file diff --git a/case_studies/interpolation_training/it_utils.py b/case_studies/interpolation_training/it_utils.py new file mode 100644 index 0000000..0a325ca --- /dev/null +++ b/case_studies/interpolation_training/it_utils.py @@ -0,0 +1,315 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +''' +Utility functions, PGD attacks and Loss functions +''' +import math +import numpy as np +import random +import scipy.io +import copy + +from torch.autograd import Variable + +from attacks import autopgd +from attacks import pgd +from networks import * + +device = 'cuda' if torch.cuda.is_available() else 'cpu' + + +class Attack_AutoPGD(nn.Module): + # Back-propogate + def __init__(self, basic_net, config, attack_net=None): + super(Attack_AutoPGD, self).__init__() + self.basic_net = basic_net + self.attack_net = attack_net + self.epsilon = config['epsilon'] + self.n_restarts = 0 if "num_restarts" not in config else \ + config["num_restarts"] + self.num_steps = config['num_steps'] + self.loss_func = "ce" if 'loss_func' not in config.keys( + ) else config['loss_func'] + + self.train_flag = True if 'train' not in config.keys( + ) else config['train'] + self.box_type = 'white' if 'box_type' not in config.keys( + ) else config['box_type'] + + self.targeted = False if 'targeted' not in config.keys( + ) else config['targeted'] + self.n_classes = 10 if 'n_classes' not in config.keys( + ) else config['n_classes'] + + def forward(self, + inputs, + targets, + attack=True, + targeted_label=-1, + batch_idx=0): + + assert targeted_label == -1 + + def net(x): + output = self.basic_net(x) + if isinstance(output, tuple): + return output[0] + else: + return output + + if attack: + temp = autopgd.auto_pgd( + model=net, + x=inputs, y=targets, n_steps=self.num_steps, + loss=self.loss_func, + epsilon=self.epsilon, + norm="linf", + n_restarts=self.n_restarts, + targeted=self.targeted, + n_averaging_steps=1, + n_classes=self.n_classes + ) + x_adv = temp[0] + else: + x_adv = inputs + + logits_pert = net(x_adv) + targets_prob = torch.softmax(logits_pert, -1) + + return logits_pert, targets_prob.detach(), x_adv.detach() + + +class Attack_PGD(nn.Module): + def __init__(self, basic_net, config): + super(Attack_PGD, self).__init__() + self.basic_net = basic_net + self.train_flag = True if 'train' not in config.keys( + ) else config['train'] + + self.attack = True if 'attack' not in config.keys( + ) else config['attack'] + if self.attack: + self.rand = config['random_start'] + self.step_size = config['step_size'] + self.v_min = config['v_min'] + self.v_max = config['v_max'] + self.epsilon = config['epsilon'] + self.num_steps = config['num_steps'] + self.loss_func = torch.nn.CrossEntropyLoss( + reduction='none') if 'loss_func' not in config.keys( + ) else config['loss_func'] + + # print(config) + + def forward(self, inputs, targets): + + if not self.attack: + if self.train_flag: + self.basic_net.train() + else: + self.basic_net.eval() + outputs = self.basic_net(inputs, mode="logits") + return outputs, None + + #aux_net = pickle.loads(pickle.dumps(self.basic_net)) + aux_net = copy.deepcopy(self.basic_net) + + aux_net.eval() + logits_pred_nat = aux_net(inputs, mode="logits") + targets_prob = F.softmax(logits_pred_nat.float(), dim=1) + + num_classes = targets_prob.size(1) + + outputs = aux_net(inputs, mode="logits") + targets_prob = F.softmax(outputs.float(), dim=1) + y_tensor_adv = targets + + x = inputs.detach() + if self.rand: + x = x + torch.zeros_like(x).uniform_(-self.epsilon, self.epsilon) + x_org = x.detach() + loss_array = np.zeros((inputs.size(0), self.num_steps)) + + for i in range(self.num_steps): + x.requires_grad_() + if x.grad is not None and x.grad.data is not None: + x.grad.data.zero_() + if x.grad is not None: + x.grad.data.fill_(0) + aux_net.eval() + logits = aux_net(x, mode="logits") + loss = self.loss_func(logits, y_tensor_adv) + loss = loss.mean() + aux_net.zero_grad() + loss.backward() + + x_adv = x.data + self.step_size * torch.sign(x.grad.data) + x_adv = torch.min(torch.max(x_adv, inputs - self.epsilon), + inputs + self.epsilon) + x_adv = torch.clamp(x_adv, self.v_min, self.v_max) + x = Variable(x_adv) + + if self.train_flag: + self.basic_net.train() + else: + self.basic_net.eval() + + logits_pert = self.basic_net(x.detach(), mode="logits") + + return logits_pert, targets_prob.detach(), x.detach() + + +class Attack_BetterPGD(nn.Module): + def __init__(self, basic_net, config): + super(Attack_BetterPGD, self).__init__() + self.basic_net = basic_net + self.train_flag = True if 'train' not in config.keys( + ) else config['train'] + + self.attack = True if 'attack' not in config.keys( + ) else config['attack'] + if self.attack: + self.rand = config['random_start'] + self.step_size = config['step_size'] + self.v_min = config['v_min'] + self.v_max = config['v_max'] + self.epsilon = config['epsilon'] + self.num_steps = config['num_steps'] + self.loss_func = torch.nn.CrossEntropyLoss( + reduction='none') if 'loss_func' not in config.keys( + ) else config['loss_func'] + + # print(config) + + def forward(self, inputs, targets): + + if not self.attack: + if self.train_flag: + self.basic_net.train() + else: + self.basic_net.eval() + outputs = self.basic_net(inputs, mode="logits") + return outputs, None + + #aux_net = pickle.loads(pickle.dumps(self.basic_net)) + aux_net = copy.deepcopy(self.basic_net) + + def net(x): + return aux_net(x, mode="logits") + + aux_net.eval() + + outputs = aux_net(inputs, mode="logits") + targets_prob = F.softmax(outputs.float(), dim=1) + + sign = 1.0 + x_adv = pgd.general_pgd( + loss_fn=lambda x, y: sign * self.loss_func(net(x), y), + is_adversarial_fn=lambda x, y: net(x).argmax(-1) == y + if targets != -1 else net(x).argmax(-1) != y, + x=inputs, y=targets, n_steps=self.num_steps, + step_size=self.step_size, + epsilon=self.epsilon, + norm="linf", + random_start=self.rand + )[0] + + if self.train_flag: + self.basic_net.train() + else: + self.basic_net.eval() + + logits_pert = self.basic_net(x_adv.detach(), mode="logits") + + return logits_pert, targets_prob.detach(), x_adv.detach() + + +class softCrossEntropy(nn.Module): + def __init__(self, reduce=True): + super(softCrossEntropy, self).__init__() + self.reduce = reduce + return + + def forward(self, inputs, target): + """ + :param inputs: predictions + :param target: target labels in vector form + :return: loss + """ + log_likelihood = -F.log_softmax(inputs, dim=1) + sample_num, class_num = target.shape + if self.reduce: + loss = torch.sum(torch.mul(log_likelihood, target)) / sample_num + else: + loss = torch.sum(torch.mul(log_likelihood, target), 1) + + return loss + + +class CWLoss(nn.Module): + def __init__(self, num_classes, margin=50, reduce=True): + super(CWLoss, self).__init__() + self.num_classes = num_classes + self.margin = margin + self.reduce = reduce + return + + def forward(self, logits, targets): + """ + :param inputs: predictions + :param targets: target labels + :return: loss + """ + onehot_targets = one_hot_tensor(targets, self.num_classes, + targets.device) + + self_loss = torch.sum(onehot_targets * logits, dim=1) + other_loss = torch.max( + (1 - onehot_targets) * logits - onehot_targets * 1000, dim=1)[0] + + loss = -torch.sum(torch.clamp(self_loss - other_loss + self.margin, 0)) + + if self.reduce: + sample_num = onehot_targets.shape[0] + loss = loss / sample_num + + return loss + + +def cos_dist(x, y): + cos = nn.CosineSimilarity(dim=1, eps=1e-6) + batch_size = x.size(0) + c = torch.clamp(1 - cos(x.view(batch_size, -1), y.view(batch_size, -1)), + min=0) + return c.mean() + + +def one_hot_tensor(y_batch_tensor, num_classes, device): + y_tensor = torch.cuda.FloatTensor(y_batch_tensor.size(0), + num_classes).fill_(0) + y_tensor[np.arange(len(y_batch_tensor)), y_batch_tensor] = 1.0 + return y_tensor + + +def get_acc(outputs, targets): + _, predicted = outputs.max(1) + total = targets.size(0) + correct = predicted.eq(targets).sum().item() + acc = 1.0 * correct / total + return acc + + +def str2bool(v): + return v.lower() in ("yes", "true", "t", "1") \ No newline at end of file diff --git a/case_studies/interpolation_training/models/__init__.py b/case_studies/interpolation_training/models/__init__.py new file mode 100644 index 0000000..72c479d --- /dev/null +++ b/case_studies/interpolation_training/models/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from .wideresnet import * \ No newline at end of file diff --git a/case_studies/interpolation_training/models/wideresnet.py b/case_studies/interpolation_training/models/wideresnet.py new file mode 100644 index 0000000..409716b --- /dev/null +++ b/case_studies/interpolation_training/models/wideresnet.py @@ -0,0 +1,145 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import math +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class BasicBlock(nn.Module): + def __init__(self, in_planes, out_planes, stride, dropRate=0.0): + super(BasicBlock, self).__init__() + self.bn1 = nn.BatchNorm2d(in_planes) + self.relu1 = nn.ReLU(inplace=True) + self.conv1 = nn.Conv2d(in_planes, + out_planes, + kernel_size=3, + stride=stride, + padding=1, + bias=False) + self.bn2 = nn.BatchNorm2d(out_planes) + self.relu2 = nn.ReLU(inplace=True) + self.conv2 = nn.Conv2d(out_planes, + out_planes, + kernel_size=3, + stride=1, + padding=1, + bias=False) + self.droprate = dropRate + self.equalInOut = (in_planes == out_planes) + self.convShortcut = (not self.equalInOut) and nn.Conv2d( + in_planes, + out_planes, + kernel_size=1, + stride=stride, + padding=0, + bias=False) or None + + def forward(self, x): + if not self.equalInOut: + x = self.relu1(self.bn1(x)) + else: + out = self.relu1(self.bn1(x)) + out = self.relu2(self.bn2(self.conv1(out if self.equalInOut else x))) + if self.droprate > 0: + out = F.dropout(out, p=self.droprate, training=self.training) + out = self.conv2(out) + return torch.add(x if self.equalInOut else self.convShortcut(x), out) + + +class NetworkBlock(nn.Module): + def __init__(self, + nb_layers, + in_planes, + out_planes, + block, + stride, + dropRate=0.0): + super(NetworkBlock, self).__init__() + self.layer = self._make_layer(block, in_planes, out_planes, nb_layers, + stride, dropRate) + + def _make_layer(self, block, in_planes, out_planes, nb_layers, stride, + dropRate): + layers = [] + for i in range(int(nb_layers)): + layers.append( + block(i == 0 and in_planes or out_planes, out_planes, + i == 0 and stride or 1, dropRate)) + return nn.Sequential(*layers) + + def forward(self, x): + return self.layer(x) + + +class WideResNet(nn.Module): + def __init__(self, depth, num_classes, widen_factor=1, dropRate=0.0): + super(WideResNet, self).__init__() + nChannels = [ + 16, 16 * widen_factor, 32 * widen_factor, 64 * widen_factor + ] + assert ((depth - 4) % 6 == 0) + n = (depth - 4) / 6 + block = BasicBlock + self.conv1 = nn.Conv2d(3, + nChannels[0], + kernel_size=3, + stride=1, + padding=1, + bias=False) + # block 1 + self.block1 = NetworkBlock(n, nChannels[0], nChannels[1], block, 1, + dropRate) + # block 2 + self.block2 = NetworkBlock(n, nChannels[1], nChannels[2], block, 2, + dropRate) + # block 3 + self.block3 = NetworkBlock(n, nChannels[2], nChannels[3], block, 2, + dropRate) + + self.bn1 = nn.BatchNorm2d(nChannels[3]) + self.relu = nn.ReLU(inplace=True) + self.fc = nn.Linear(nChannels[3], num_classes) + self.nChannels = nChannels[3] + + 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_() + elif isinstance(m, nn.Linear): + m.bias.data.zero_() + + def forward(self, x, mode='logits', features_only=False, features_and_logits=False): + out = self.conv1(x) + out = self.block1(out) + out = self.block2(out) + out = self.block3(out) + out = self.relu(self.bn1(out)) + out = F.avg_pool2d(out, 8) + out = out.view(-1, self.nChannels) + + if features_only: + return out.view(x.size(0), -1) + if features_and_logits: + return out.view(x.size(0), -1), self.fc(out) + if mode.lower() == 'logits': + return self.fc(out) + elif mode.lower() == 'feature': + return out.view(x.size(0), -1) + else: + raise Exception('unsupported mode is specified') diff --git a/case_studies/interpolation_training/train_adv_interp.py b/case_studies/interpolation_training/train_adv_interp.py new file mode 100644 index 0000000..a66d58a --- /dev/null +++ b/case_studies/interpolation_training/train_adv_interp.py @@ -0,0 +1,239 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +'''Advsersarial Interpolation Training''' +from __future__ import print_function +import time +import numpy as np +import random +import copy +import os +import argparse +import datetime +import pickle +import it_utils + +from it_utils import softCrossEntropy +from it_utils import one_hot_tensor +from adv_interp import adv_interp +from tqdm import tqdm +from PIL import Image +from networks import * + +import torch +import torch.nn as nn +import torch.optim as optim +import torch.nn.functional as F +import torch.backends.cudnn as cudnn +import torchvision +import torchvision.transforms as transforms +from torch.autograd.gradcheck import zero_gradients +from torch.autograd import Variable + +parser = argparse.ArgumentParser( + description='Advsersarial Interpolation Training') + +parser.register('type', 'bool', it_utils.str2bool) + +parser.add_argument('--lr', default=0.1, type=float, help='learning rate') +parser.add_argument('--label_adv_delta', + default=0.5, + type=float, + help='label_adv_delta') +parser.add_argument('--resume', + '-r', + action='store_true', + help='resume from checkpoint') +parser.add_argument('--model_dir', type=str, help='model path') +parser.add_argument('--init_model_pass', + default='-1', + type=str, + help='init model pass') +parser.add_argument('--save_epochs', default=10, type=int, help='save period') + +parser.add_argument('--max_epoch', default=200, type=int, help='save period') +parser.add_argument('--decay_epoch1', default=60, type=int, help='save period') +parser.add_argument('--decay_epoch2', default=90, type=int, help='save period') +parser.add_argument('--decay_rate', + default=0.1, + type=float, + help='save period') +parser.add_argument('--momentum', default=0.9, type=float, help='momentum') +parser.add_argument('--weight_decay', + default=2e-4, + type=float, + help='weight decay factor') + +parser.add_argument('--log_step', default=10, type=int, help='log_step') + +parser.add_argument('--num_classes', default=10, type=int, help='num classes') +parser.add_argument('--image_size', default=32, type=int, help='image size') +parser.add_argument('--batch_size_train', + default=128, + type=int, + help='batch size for training') + +args = parser.parse_args() + +device = 'cuda' if torch.cuda.is_available() else 'cpu' +start_epoch = 1 + +transform_train = transforms.Compose([ + transforms.RandomCrop(32, padding=4), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), +]) + +trainset = torchvision.datasets.CIFAR10(root='./data', + train=True, + download=True, + transform=transform_train) + +trainloader = torch.utils.data.DataLoader(trainset, + batch_size=args.batch_size_train, + shuffle=True, + num_workers=2) + +print('======= WideResenet 28-10 ========') +net = WideResNet(depth=28, num_classes=args.num_classes, widen_factor=10) + +net = net.to(device) + +config_adv_interp = { + 'v_min': -1.0, + 'v_max': 1.0, + 'epsilon': 8.0 / 255 * 2, + 'num_steps': 1, + 'step_size': 8.0 / 255 * 2, + 'label_adv_delta': args.label_adv_delta, +} + +if device == 'cuda': + net = torch.nn.DataParallel(net) + cudnn.benchmark = True + +optimizer = optim.SGD(net.parameters(), + lr=args.lr, + momentum=args.momentum, + weight_decay=args.weight_decay) + +if args.resume and args.init_model_pass != '-1': + print('Resume training from checkpoint..') + f_path_latest = os.path.join(args.model_dir, 'latest') + f_path = os.path.join(args.model_dir, + ('checkpoint-%s' % args.init_model_pass)) + + if not os.path.isdir(args.model_dir): + print('train from scratch: no checkpoint directory or file found') + elif args.init_model_pass == 'latest' and os.path.isfile(f_path_latest): + checkpoint = torch.load(f_path_latest) + pretrained_dict = checkpoint['net'] + model_dict = net.state_dict() + model_dict.update(pretrained_dict) + net.load_state_dict(model_dict, strict=False) + #optimizer.load_state_dict(checkpoint['optimizer']) + start_epoch = checkpoint['epoch'] + 1 + print('resuming training from epoch %s in latest' % start_epoch) + elif os.path.isfile(f_path): + checkpoint = torch.load(f_path) + net.load_state_dict(checkpoint['net']) + #optimizer.load_state_dict(checkpoint['optimizer']) + start_epoch = checkpoint['epoch'] + 1 + print('resuming training from epoch %s' % (start_epoch - 1)) + elif not os.path.isfile(f_path) or not os.path.isfile(f_path_latest): + print('train from scratch: no checkpoint directory or file found') + +soft_xent_loss = softCrossEntropy() + + +def train_one_epoch(epoch, net): + print('\n Training for Epoch: %d' % epoch) + + net.train() + + # learning rate schedule + if epoch < args.decay_epoch1: + lr = args.lr + elif epoch < args.decay_epoch2: + lr = args.lr * args.decay_rate + else: + lr = args.lr * args.decay_rate * args.decay_rate + for param_group in optimizer.param_groups: + param_group['lr'] = lr + + iterator = tqdm(trainloader, ncols=0, leave=False) + for batch_idx, (inputs, targets) in enumerate(iterator): + start_time = time.time() + inputs, targets = inputs.to(device), targets.to(device) + + targets_onehot = one_hot_tensor(targets, args.num_classes, device) + + x_tilde, y_tilde = adv_interp(inputs, targets_onehot, net, + args.num_classes, + config_adv_interp['epsilon'], + config_adv_interp['label_adv_delta'], + config_adv_interp['v_min'], + config_adv_interp['v_max']) + + outputs = net(x_tilde, mode='logits') + loss = soft_xent_loss(outputs, y_tilde) + + optimizer.zero_grad() + loss.backward() + + optimizer.step() + + train_loss = loss.detach().item() + + duration = time.time() - start_time + if batch_idx % args.log_step == 0: + + adv_acc = it_utils.get_acc(outputs, targets) + # natural + net_cp = copy.deepcopy(net) + nat_outputs = net_cp(inputs, mode='logits') + nat_acc = it_utils.get_acc(nat_outputs, targets) + print( + "Epoch %d, Step %d, lr %.4f, Duration %.2f, Training nat acc %.2f, Training adv acc %.2f, Training adv loss %.4f" + % (epoch, batch_idx, lr, duration, 100 * nat_acc, + 100 * adv_acc, train_loss)) + + if epoch % args.save_epochs == 0 or epoch >= args.max_epoch - 2: + print('Saving..') + f_path = os.path.join(args.model_dir, ('checkpoint-%s' % epoch)) + state = { + 'net': net.state_dict(), + 'epoch': epoch, + #'optimizer': optimizer.state_dict() + } + if not os.path.isdir(args.model_dir): + os.makedirs(args.model_dir) + torch.save(state, f_path) + + if epoch >= 1: + print('Saving latest model for epoch %s..' % (epoch)) + f_path = os.path.join(args.model_dir, 'latest') + state = { + 'net': net.state_dict(), + 'epoch': epoch, + #'optimizer': optimizer.state_dict() + } + if not os.path.isdir(args.model_dir): + os.mkdir(args.model_dir) + torch.save(state, f_path) + + +for epoch in range(start_epoch, args.max_epoch + 1): + train_one_epoch(epoch, net) diff --git a/case_studies/jarn/README.md b/case_studies/jarn/README.md new file mode 100644 index 0000000..7aec313 --- /dev/null +++ b/case_studies/jarn/README.md @@ -0,0 +1,47 @@ +# JARN_ICLR2020 +This is our Tensorflow implementation of Jacobian Adversarially Regularized Networks (JARN). + +**Jacobian Adversarially Regularized Networks for Robustness (ICLR 2020)**
+*Alvin Chan, Yi Tay, Yew Soon Ong, Jie Fu*
+https://arxiv.org/abs/1912.10185 + +TL;DR: We show that training classifiers to produce salient input Jacobian matrices with a GAN-like regularization can boost adversarial robustness. + + +## Dependencies +1. Tensorflow 1.14.0 +2. Python 3.7 + + +## Usage +1. Install dependencies with `pip install -r requirements.txt`. +2. Run JARN training and evaluation with `sh run_train_jarn.sh`. Final evaluation output is saved in `attack_log`. + + +## Code overview +- `train_jarn.py`: trains the JARN model and subsequently evaluate on adversarial examples. +- `pgd_attack.py`: generates adversarial examples and save them in `attacks/`. +- `run_attack.py`: evaluates model on adversarial examples from `attacks/`. +- `config.py`: training parameters for JARN. +- `config_attack.py`: parameters for adversarial example evaluation. +- `model_jarn.py`: contains code for JARN model architectures. +- `cifar10_input.py` provides utility functions and classes for loading the CIFAR10 dataset. + + +## Citation +If you find our repository useful, please consider citing our paper: + +``` +@article{chan2019jacobian, + title={Jacobian Adversarially Regularized Networks for Robustness}, + author={Chan, Alvin and Tay, Yi and Ong, Yew Soon and Fu, Jie}, + journal={arXiv preprint arXiv:1912.10185}, + year={2019} +} +``` + + +## Acknowledgements + +Useful code bases we used in our work: +- https://github.com/MadryLab/cifar10_challenge (for adversarial example generation and evaluation) \ No newline at end of file diff --git a/case_studies/jarn/adversarial_evaluation.py b/case_studies/jarn/adversarial_evaluation.py new file mode 100644 index 0000000..0f3417a --- /dev/null +++ b/case_studies/jarn/adversarial_evaluation.py @@ -0,0 +1,140 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Modified according to main method in pgd_attack.py +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import logging + +import torch + +logging.getLogger('tensorflow').setLevel(logging.FATAL) + +import tensorflow as tf +tf.logging.set_verbosity(tf.logging.ERROR) + +import tensorflow as tf +import numpy as np +import sys +import math + + +import cifar10_input + +import config_attack +from pgd_attack import LinfPGDAttack + +def main(): + + config = vars(config_attack.get_args()) + + tf.set_random_seed(config['tf_seed']) + np.random.seed(config['np_seed']) + + model_file = tf.train.latest_checkpoint(config['model_dir']) + print("config['model_dir']: ", config['model_dir']) + if model_file is None: + print('No model found') + sys.exit() + + print("JARN MODEL") + from model_jarn import Model + if "_zeromeaninput" in config['model_dir']: + model = Model(dataset=config['dataset'], train_batch_size=config['eval_batch_size'], normalize_zero_mean=True, + # added by AUTHOR + mode='eval') + else: + model = Model(dataset=config['dataset'], train_batch_size=config['eval_batch_size'], + # added by AUTHOR + mode='eval') + + saver = tf.train.Saver() + + data_path = config['data_path'] + + print("load cifar10 dataset") + cifar = cifar10_input.CIFAR10Data(data_path) + + with tf.Session() as sess: + print("Using attack:", config['attack']) + if config['attack'] == 'pgd' or config['attack'] == 'pgd-ld': + attack = LinfPGDAttack(model, + config['epsilon'] / 255.0, + config['num_steps'], + config['step_size'], + config['random_start'], + config['loss_func'], + dataset=config['dataset'], + clip_max=1.0) + attack_fn = lambda x, y: attack.perturb(x, y, sess) + elif config['attack'] == 'apgd': + from autoattack import autopgd_base + from autoattack_adapter import ModelAdapter + autoattack_model = ModelAdapter( + model.pre_softmax, model.x_input, + model.y_input, sess, num_classes=10, device="cpu") + attack = autopgd_base.APGDAttack( + autoattack_model, n_restarts=5, n_iter=100, verbose=True, + eps=config["epsilon"] / 255.0, norm="Linf", eot_iter=1, rho=.99, + is_tf_model=True, device="cpu", loss='dlr') + attack_fn = lambda x, y: attack.perturb( + torch.tensor(x.transpose((0, 3, 1, 2)), device="cpu"), + torch.tensor(y, device="cpu") + ).detach().cpu().numpy().transpose((0, 2, 3, 1)) + else: + raise ValueError("invalid attack") + + + # Restore the checkpoint + saver.restore(sess, model_file) + # Iterate over the samples batch-by-batch + num_eval_examples = config['num_eval_examples'] + eval_batch_size = config['eval_batch_size'] + num_batches = int(math.ceil(num_eval_examples / eval_batch_size)) + + preds =[] + adv_preds = [] + ys = [] + for ibatch in range(num_batches): + bstart = ibatch * eval_batch_size + bend = min(bstart + eval_batch_size, num_eval_examples) + + x_batch = cifar.eval_data.xs[bstart:bend, :] / 255.0 + y_batch = cifar.eval_data.ys[bstart:bend] + + x_batch_adv = attack_fn(x_batch, y_batch) + + logits = sess.run(model.pre_softmax, {model.x_input: x_batch}) + adv_logits = sess.run(model.pre_softmax, {model.x_input: x_batch_adv}) + + preds.append(logits.argmax(-1)) + adv_preds.append(adv_logits.argmax(-1)) + ys.append(y_batch) + + preds = np.concatenate(preds) + adv_preds = np.concatenate(adv_preds) + ys = np.concatenate(ys) + + acc = np.mean(preds == ys) + adv_acc = np.mean(adv_preds == ys) + + print("Accuracy:", acc) + print("Robust Accuracy:", adv_acc) + +if __name__ == "__main__": + main() diff --git a/case_studies/jarn/adversarial_evaluation.sh b/case_studies/jarn/adversarial_evaluation.sh new file mode 100644 index 0000000..894e2a3 --- /dev/null +++ b/case_studies/jarn/adversarial_evaluation.sh @@ -0,0 +1,11 @@ +#!/bin/sh +nsamples=${1:-512} + +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + ./case_studies/jarn/adversarial_evaluation.py \ + --model_dir=checkpoints/jarn/modelJARN_cifar10_b64_beta_1.000_gamma_1.000_disc_update_steps20_l5bc32_imgpert_advdelay140000_tanhencact_zeromeaninput_160000steps \ + --data_path=data/cifar-10-batches-py/ \ + --eval_batch_size=512 \ + --num_steps=1 \ + --num_eval_examples=$nsamples \ + --attack=pgd diff --git a/case_studies/jarn/autoattack_adapter.py b/case_studies/jarn/autoattack_adapter.py new file mode 100644 index 0000000..16b5d10 --- /dev/null +++ b/case_studies/jarn/autoattack_adapter.py @@ -0,0 +1,129 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import tensorflow as tf +import numpy as np +import torch + +class ModelAdapter: + def __init__(self, logits, x, y, sess, num_classes=10, device="cuda"): + self.logits = logits + self.sess = sess + self.x_input = x + self.y_input = y + self.num_classes = num_classes + self.device = device + + # gradients of logits + if num_classes <= 10: + self.grads = [None] * num_classes + for cl in range(num_classes): + self.grads[cl] = tf.gradients(self.logits[:, cl], self.x_input)[0] + + # cross-entropy loss + self.xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.logits, labels=self.y_input) + self.grad_xent = tf.gradients(self.xent, self.x_input)[0] + + # dlr loss + self.dlr = dlr_loss(self.logits, self.y_input, num_classes=self.num_classes) + self.grad_dlr = tf.gradients(self.dlr, self.x_input)[0] + + # targeted dlr loss + self.y_target = tf.placeholder(tf.int64, shape=[None]) + self.dlr_target = dlr_loss_targeted(self.logits, self.y_input, self.y_target, num_classes=self.num_classes) + self.grad_target = tf.gradients(self.dlr_target, self.x_input)[0] + + self.la = tf.placeholder(tf.int64, shape=[None]) + self.la_target = tf.placeholder(tf.int64, shape=[None]) + la_mask = tf.one_hot(self.la, self.num_classes) + la_target_mask = tf.one_hot(self.la_target, self.num_classes) + la_logit = tf.reduce_sum(la_mask * self.logits, axis=1) + la_target_logit = tf.reduce_sum(la_target_mask * self.logits, axis=1) + self.diff_logits = la_target_logit - la_logit + self.grad_diff_logits = tf.gradients(self.diff_logits, self.x_input)[0] + + def predict(self, x): + x = x.detach() + x2 = np.moveaxis(x.cpu().numpy(), 1, 3) + y = self.sess.run(self.logits, {self.x_input: x2}) + + return torch.from_numpy(y).to(self.device) + + def grad_logits(self, x): + x = x.detach() + x2 = np.moveaxis(x.cpu().numpy(), 1, 3) + logits, g2 = self.sess.run([self.logits, self.grads], {self.x_input: x2}) + g2 = np.moveaxis(np.array(g2), 0, 1) + g2 = np.transpose(g2, (0, 1, 4, 2, 3)) + + return torch.from_numpy(logits).cuda(), torch.from_numpy(g2).cuda() + + def get_grad_diff_logits_target(self, x, y=None, y_target=None): + x = x.detach() + la = y.cpu().numpy() + la_target = y_target.cpu().numpy() + x2 = np.moveaxis(x.cpu().numpy(), 1, 3) + dl, g2 = self.sess.run([self.diff_logits, self.grad_diff_logits], {self.x_input: x2, self.la: la, self.la_target: la_target}) + g2 = np.transpose(np.array(g2), (0, 3, 1, 2)) + + return torch.from_numpy(dl).to(self.device), torch.from_numpy(g2).to(self.device) + + def get_logits_loss_grad_xent(self, x, y): + x = x.detach() + x2 = np.moveaxis(x.cpu().numpy(), 1, 3) + y2 = y.clone().cpu().numpy() + logits_val, loss_indiv_val, grad_val = self.sess.run([self.logits, self.xent, self.grad_xent], {self.x_input: x2, self.y_input: y2}) + grad_val = np.moveaxis(grad_val, 3, 1) + + return torch.from_numpy(logits_val).to(self.device), torch.from_numpy(loss_indiv_val).to(self.device), torch.from_numpy(grad_val).to(self.device) + + def get_logits_loss_grad_dlr(self, x, y): + x = x.detach() + x2 = np.moveaxis(x.cpu().numpy(), 1, 3) + y2 = y.clone().cpu().numpy() + logits_val, loss_indiv_val, grad_val = self.sess.run([self.logits, self.dlr, self.grad_dlr], {self.x_input: x2, self.y_input: y2}) + grad_val = np.moveaxis(grad_val, 3, 1) + + return torch.from_numpy(logits_val).to(self.device), torch.from_numpy(loss_indiv_val).to(self.device), torch.from_numpy(grad_val).to(self.device) + + def get_logits_loss_grad_target(self, x, y, y_target): + x = x.detach() + x2 = np.moveaxis(x.cpu().numpy(), 1, 3) + y2 = y.clone().cpu().numpy() + y_targ = y_target.clone().cpu().numpy() + logits_val, loss_indiv_val, grad_val = self.sess.run([self.logits, self.dlr_target, self.grad_target], {self.x_input: x2, self.y_input: y2, self.y_target: y_targ}) + grad_val = np.moveaxis(grad_val, 3, 1) + + return torch.from_numpy(logits_val).to(self.device), torch.from_numpy(loss_indiv_val).to(self.device), torch.from_numpy(grad_val).to(self.device) + + +def dlr_loss(x, y, num_classes=10): + x_sort = tf.contrib.framework.sort(x, axis=1) + y_onehot = tf.one_hot(y, num_classes) + if num_classes > 2: + ### TODO: adapt to the case when the point is already misclassified + loss = -(x_sort[:, -1] - x_sort[:, -2]) / (x_sort[:, -1] - x_sort[:, -3] + 1e-12) + else: + loss = (tf.reduce_max(x - y_onehot * 1e9) - tf.gather(x, y, axis=-1)) / tf.reduce_max(x - y_onehot * 1e9) + + return loss + +def dlr_loss_targeted(x, y, y_target, num_classes=10): + x_sort = tf.contrib.framework.sort(x, axis=1) + y_onehot = tf.one_hot(y, num_classes) + y_target_onehot = tf.one_hot(y_target, num_classes) + loss = -(tf.reduce_sum(x * y_onehot, axis=1) - tf.reduce_sum(x * y_target_onehot, axis=1)) / (x_sort[:, -1] - .5 * x_sort[:, -3] - .5 * x_sort[:, -4] + 1e-12) + + return loss \ No newline at end of file diff --git a/case_studies/jarn/binarization_test.py b/case_studies/jarn/binarization_test.py new file mode 100644 index 0000000..dfc449e --- /dev/null +++ b/case_studies/jarn/binarization_test.py @@ -0,0 +1,249 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Modified according to main method in pgd_attack.py +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import logging +from functools import partial + +import torch + +import utils +from argparse_utils import DecisionBoundaryBinarizationSettings +from tensorflow_wrapper import TensorFlow1ToPyTorchWrapper + +logging.getLogger('tensorflow').setLevel(logging.FATAL) + +import tensorflow as tf + +tf.logging.set_verbosity(tf.logging.ERROR) + +from active_tests import decision_boundary_binarization as dbb + +import tensorflow as tf +import numpy as np +import sys +import math + +import cifar10_input + +import config_attack +from pgd_attack import LinfPGDAttack + + +class BinarizedModel: + def __init__(self, model, logit_diff_loss=False): + self.model = model + self.x_input = model.x_input + self.y_input = model.y_input + + features = model.neck + + with tf.variable_scope("binarized_readout"): + # build linear readout + bro_w = tf.get_variable( + 'DW', [features.shape[-1], 2], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + bro_b = tf.get_variable('biases', [2], + initializer=tf.constant_initializer()) + self.bro_w_pl = tf.placeholder(tf.float32, shape=[features.shape[-1], 2]) + self.bro_b_pl = tf.placeholder(tf.float32, shape=[2]) + self.bro_w_set_weight = bro_w.assign(self.bro_w_pl) + self.bro_b_set_weight = bro_b.assign(self.bro_b_pl) + self.pre_softmax = tf.nn.xw_plus_b(features, bro_w, bro_b) + + if logit_diff_loss: + yh = tf.one_hot(self.y_input, 2) + self.loss = tf.reduce_max(self.pre_softmax - yh * 1e9) - tf.gather( + self.pre_softmax, self.y_input, axis=-1) + else: + self.y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.loss = tf.reduce_sum(self.y_xent, name='y_xent') + + +def run_attack(m, l, sess, logits, x_pl, bro_w_pl, bro_b_pl, bro_w_assign, + bro_b_assign, attack): + linear_layer = m[-1] + del m + + sess.run(bro_w_assign, {bro_w_pl: linear_layer.weight.data.numpy().T}) + sess.run(bro_b_assign, {bro_b_pl: linear_layer.bias.data.numpy()}) + + for x, y in l: + x, y = x.numpy(), y.numpy() + x = x.transpose((0, 2, 3, 1)) + + x_adv = attack(x, y) + + clean_logits = sess.run(logits, {x_pl: x}) + adv_logits = sess.run(logits, {x_pl: x_adv}) + is_adv = adv_logits.argmax(-1) != y + + print(is_adv, clean_logits, adv_logits) + + return is_adv, (torch.tensor(x_adv.transpose((0, 3, 1, 2))), + torch.tensor(adv_logits)) + + +def main(): + config = vars(config_attack.get_args()) + + tf.set_random_seed(config['tf_seed']) + np.random.seed(config['np_seed']) + + model_file = tf.train.latest_checkpoint(config['model_dir']) + print("config['model_dir']: ", config['model_dir']) + if model_file is None: + print('No model found') + sys.exit() + + print("JARN MODEL") + from model_jarn import Model + if "_zeromeaninput" in config['model_dir']: + model = Model(dataset=config['dataset'], + train_batch_size=config['eval_batch_size'], + normalize_zero_mean=True, + zero_one=True, + # added by AUTHOR + mode='eval') + else: + model = Model(dataset=config['dataset'], + train_batch_size=config['eval_batch_size'], + zero_one=True, + # added by AUTHOR + mode='eval') + print("model eval mode:", model.mode) + sess = tf.Session() + saver = tf.train.Saver() + # Restore the checkpoint + saver.restore(sess, model_file) + + binarized_model = BinarizedModel(model, + logit_diff_loss=config['attack'] == 'pgd-ld') + + print("Using attack:", config['attack']) + if config['attack'] == 'pgd' or config['attack'] == 'pgd-ld': + attack = LinfPGDAttack(binarized_model, + config['epsilon'] / 255.0, + config['num_steps'], + config['step_size'] / 255.0, + config['random_start'], + config['loss_func'], + dataset=config['dataset'], + clip_max=1.0) + attack_fn = lambda x, y: attack.perturb(x, y, sess) + elif config['attack'] == 'apgd': + from autoattack import autopgd_base + from autoattack_adapter import ModelAdapter + autoattack_model = ModelAdapter( + binarized_model.pre_softmax, binarized_model.x_input, + binarized_model.y_input, sess, num_classes=2, device="cpu") + attack = autopgd_base.APGDAttack( + autoattack_model, n_restarts=5, n_iter=100, verbose=True, + eps=config["epsilon"] / 255.0, norm="Linf", eot_iter=1, rho=.99, + is_tf_model=True, device="cpu", loss='dlr') + attack_fn = lambda x, y: attack.perturb( + torch.tensor(x.transpose((0, 3, 1, 2)), device="cpu"), + torch.tensor(y, device="cpu") + ).detach().cpu().numpy().transpose((0, 2, 3, 1)) + else: + raise ValueError("invalid attack") + + data_path = config['data_path'] + + print("load cifar10 dataset") + cifar = cifar10_input.CIFAR10Data(data_path) + + # Iterate over the samples batch-by-batch + num_eval_examples = config['num_eval_examples'] + eval_batch_size = config['eval_batch_size'] + + x_data = cifar.eval_data.xs[:num_eval_examples] + y_data = cifar.eval_data.ys[:num_eval_examples] + x_data = x_data.transpose((0, 3, 1, 2)) / 255.0 + assert x_data.max() <= 1 and x_data.min() >= 0, (x_data.min(), x_data.max()) + + test_loader = utils.build_dataloader_from_arrays(x_data, y_data, + eval_batch_size) + + def feature_extractor_forward_pass(x, features_and_logits: bool = False, + features_only: bool = False): + if features_and_logits: + assert not features_only, "Only one of the flags must be set." + if features_and_logits: + return sess.run( + (model.neck, model.pre_softmax), + feed_dict={model.x_input: x.transpose(0, 2, 3, 1)}) + elif features_only: + return sess.run( + model.neck, + feed_dict={model.x_input: x.transpose(0, 2, 3, 1)}) + else: + return sess.run( + model.pre_softmax, + feed_dict={model.x_input: x.transpose(0, 2, 3, 1)}) + + feature_extractor = TensorFlow1ToPyTorchWrapper( + logit_forward_pass=feature_extractor_forward_pass, + logit_forward_and_backward_pass=None, + ) + + attack_fn_partial = partial( + run_attack, + sess=sess, logits=binarized_model.pre_softmax, + x_pl=model.x_input, + bro_w_pl=binarized_model.bro_w_pl, bro_b_pl=binarized_model.bro_b_pl, + bro_w_assign=binarized_model.bro_w_set_weight, + bro_b_assign=binarized_model.bro_b_set_weight, + attack=attack_fn) + + scores_logit_differences_and_validation_accuracies = \ + dbb.interior_boundary_discrimination_attack( + feature_extractor, + test_loader, + # m, l, sess, logits, x_pl, is_train, bro_w_pl, bro_b_pl, + # bro_w_assign, bro_b_assign, attack_fn) + attack_fn=lambda m, l, kwargs: attack_fn_partial(m, l), + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=config["epsilon"] / 255.0, + norm="linf", + lr=10000, + n_boundary_points=config["n_boundary_points"], + n_inner_points=config["n_inner_points"], + adversarial_attack_settings=None, + optimizer="sklearn" + ), + n_samples=config["num_eval_examples"], + device="cpu", + n_samples_evaluation=200, + n_samples_asr_evaluation=200, + #rescale_logits="adaptive", + sample_training_data_from_corners=config["sample_from_corners"], + #decision_boundary_closeness=0.9999, + fail_on_exception=False + # args.num_samples_test * 10 + ) + + print(dbb.format_result(scores_logit_differences_and_validation_accuracies, + config["num_eval_examples"])) + + +if __name__ == "__main__": + main() diff --git a/case_studies/jarn/binarization_test.sh b/case_studies/jarn/binarization_test.sh new file mode 100644 index 0000000..bff3e3e --- /dev/null +++ b/case_studies/jarn/binarization_test.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +nsamples=${1:-512} +echo "#samples: $nsamples" + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "eps=8/255, 1 boundary, 999 inner points (original PGD)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + ./case_studies/jarn/binarization_test.py \ + --model_dir=checkpoints/jarn/modelJARN_cifar10_b64_beta_1.000_gamma_1.000_disc_update_steps20_l5bc32_imgpert_advdelay140000_tanhencact_zeromeaninput_160000steps \ + --data_path=data/cifar-10-batches-py/ \ + --eval_batch_size=512 \ + --num_steps=20 \ + --num_eval_examples=$nsamples \ + --attack=pgd \ + --step_size=2.0 + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "eps=8/255, 1 boundary, 999 inner points (modified PGD)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + ./case_studies/jarn/binarization_test.py \ + --model_dir=checkpoints/jarn/modelJARN_cifar10_b64_beta_1.000_gamma_1.000_disc_update_steps20_l5bc32_imgpert_advdelay140000_tanhencact_zeromeaninput_160000steps \ + --data_path=data/cifar-10-batches-py/ \ + --eval_batch_size=512 \ + --num_steps=500 \ + --num_eval_examples=$nsamples \ + --attack=pgd-ld \ + --step_size=1.0 \ + --random_start + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "eps=8/255, 1 boundary, 999 inner points (APGD)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd) ./venv3.8tf/bin/python \ + ./case_studies/jarn/binarization_test.py \ + --model_dir=checkpoints/jarn/modelJARN_cifar10_b64_beta_1.000_gamma_1.000_disc_update_steps20_l5bc32_imgpert_advdelay140000_tanhencact_zeromeaninput_160000steps \ + --data_path=data/cifar-10-batches-py/ \ + --eval_batch_size=512 \ + --num_steps=500 \ + --num_eval_examples=$nsamples \ + --attack=apgd \ + --step_size=1.0 \ + --random_start + diff --git a/case_studies/jarn/cifar10_input.py b/case_studies/jarn/cifar10_input.py new file mode 100644 index 0000000..f9c7522 --- /dev/null +++ b/case_studies/jarn/cifar10_input.py @@ -0,0 +1,204 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Utilities for importing the CIFAR10 dataset. +Each image in the dataset is a numpy array of shape (32, 32, 3), with the values +being unsigned integers (i.e., in the range 0,1,...,255). +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import os +import pickle +import sys +import tensorflow as tf +import numpy as np +import re + +version = sys.version_info + + +class CIFAR10Data(object): + """ + Unpickles the CIFAR10 dataset from a specified folder containing a pickled + version following the format of Krizhevsky which can be found + [here](https://www.cs.toronto.edu/~kriz/cifar.html). + Inputs to constructor + ===================== + - path: path to the pickled dataset. The training data must be pickled + into five files named data_batch_i for i = 1, ..., 5, containing 10,000 + examples each, the test data + must be pickled into a single file called test_batch containing 10,000 + examples, and the 10 class names must be + pickled into a file called batches.meta. The pickled examples should + be stored as a tuple of two objects: an array of 10,000 32x32x3-shaped + arrays, and an array of their 10,000 true labels. + """ + + def __init__(self, path, init_shuffle=True, train_size_ratio=1): + num_classes = 10 + path = CIFAR10Data.rec_search(path) + train_filenames = ['data_batch_{}'.format(ii + 1) for ii in range(5)] + eval_filename = 'test_batch' + metadata_filename = 'batches.meta' + + train_images = np.zeros((50000, 32, 32, 3), dtype='uint8') + train_labels = np.zeros(50000, dtype='int32') + for ii, fname in enumerate(train_filenames): + cur_images, cur_labels = self._load_datafile(os.path.join(path, fname)) + train_images[ii * 10000: (ii + 1) * 10000, ...] = cur_images + train_labels[ii * 10000: (ii + 1) * 10000, ...] = cur_labels + eval_images, eval_labels = self._load_datafile( + os.path.join(path, eval_filename)) + + with open(os.path.join(path, metadata_filename), 'rb') as fo: + if version.major == 3: + data_dict = pickle.load(fo, encoding='bytes') + else: + data_dict = pickle.load(fo) + + self.label_names = data_dict[b'label_names'] + for ii in range(len(self.label_names)): + self.label_names[ii] = self.label_names[ii].decode('utf-8') + + if train_size_ratio < 1: + new_train_images = [] + new_train_labels = [] + for class_ind in range(num_classes): + current_class_train_images = train_images[train_labels == class_ind] + num_train_per_class = int(current_class_train_images.shape[0] * train_size_ratio) + new_train_images.append(current_class_train_images[:num_train_per_class]) + new_train_labels.append(np.full(num_train_per_class, class_ind, dtype='int32')) + train_images = np.concatenate(new_train_images, axis=0) + train_labels = np.concatenate(new_train_labels) + + self.train_data = DataSubset(train_images, train_labels, init_shuffle=init_shuffle) + self.eval_data = DataSubset(eval_images, eval_labels, init_shuffle=init_shuffle) + + @staticmethod + def rec_search(original_path): + rx = re.compile(r'data_batch_[0-9]+') + r = [] + for path, _, file_names in os.walk(original_path): + r.extend([os.path.join(path, x) for x in file_names if rx.search(x)]) + if len(r) is 0: # TODO: Is this the best way? + return original_path + return os.path.dirname(r[0]) + + @staticmethod + def _load_datafile(filename): + with open(filename, 'rb') as fo: + if version.major == 3: + data_dict = pickle.load(fo, encoding='bytes') + else: + data_dict = pickle.load(fo) + + assert data_dict[b'data'].dtype == np.uint8 + image_data = data_dict[b'data'] + image_data = image_data.reshape((10000, 3, 32, 32)).transpose(0, 2, 3, 1) + return image_data, np.array(data_dict[b'labels']) + + +class AugmentedCIFAR10Data(object): + """ + Data augmentation wrapper over a loaded dataset. + Inputs to constructor + ===================== + - raw_cifar10data: the loaded CIFAR10 dataset, via the CIFAR10Data class + - sess: current tensorflow session + - model: current model (needed for input tensor) + """ + + def __init__(self, raw_cifar10data, sess, model): + assert isinstance(raw_cifar10data, CIFAR10Data) + self.image_size = 32 + + # create augmentation computational graph + self.x_input_placeholder = tf.placeholder(tf.float32, shape=[None, 32, 32, 3]) + padded = tf.map_fn(lambda img: tf.image.resize_image_with_crop_or_pad( + img, self.image_size + 4, self.image_size + 4), + self.x_input_placeholder) + cropped = tf.map_fn(lambda img: tf.random_crop(img, [self.image_size, + self.image_size, + 3]), padded) + flipped = tf.map_fn(lambda img: tf.image.random_flip_left_right(img), cropped) + self.augmented = flipped + + self.train_data = AugmentedDataSubset(raw_cifar10data.train_data, sess, + self.x_input_placeholder, + self.augmented) + self.eval_data = AugmentedDataSubset(raw_cifar10data.eval_data, sess, + self.x_input_placeholder, + self.augmented) + self.label_names = raw_cifar10data.label_names + + +class DataSubset(object): + def __init__(self, xs, ys, init_shuffle=True): + self.xs = xs + self.n = xs.shape[0] + self.ys = ys + self.batch_start = 0 + if init_shuffle: + self.cur_order = np.random.permutation(self.n) + else: + self.cur_order = np.arange(self.n) + + def get_next_batch(self, batch_size, multiple_passes=False, reshuffle_after_pass=True): + if self.n < batch_size: + raise ValueError('Batch size can be at most the dataset size') + if not multiple_passes: + actual_batch_size = min(batch_size, self.n - self.batch_start) + if actual_batch_size <= 0: + raise ValueError('Pass through the dataset is complete.') + batch_end = self.batch_start + actual_batch_size + batch_xs = self.xs[self.cur_order[self.batch_start: batch_end], ...] + batch_ys = self.ys[self.cur_order[self.batch_start: batch_end], ...] + self.batch_start += actual_batch_size + if actual_batch_size < batch_size: + print('actual_batch_size < batch_size, padding with zeros') + batch_xs_pad = np.zeros(shape=(batch_size - actual_batch_size, batch_xs.shape[1], batch_xs.shape[2], batch_xs.shape[3]), dtype=batch_xs.dtype) + batch_ys_pad = np.zeros(batch_size - actual_batch_size, dtype=batch_ys.dtype) + batch_xs = np.concatenate([batch_xs, batch_xs_pad], axis=0) + batch_ys = np.concatenate([batch_ys, batch_ys_pad], axis=0) + return batch_xs, batch_ys + actual_batch_size = min(batch_size, self.n - self.batch_start) + if actual_batch_size < batch_size: + if reshuffle_after_pass: + self.cur_order = np.random.permutation(self.n) + self.batch_start = 0 + batch_end = self.batch_start + batch_size + batch_xs = self.xs[self.cur_order[self.batch_start: batch_end], ...] + batch_ys = self.ys[self.cur_order[self.batch_start: batch_end], ...] + self.batch_start += actual_batch_size + return batch_xs, batch_ys + + +class AugmentedDataSubset(object): + def __init__(self, raw_datasubset, sess, x_input_placeholder, + augmented): + self.sess = sess + self.raw_datasubset = raw_datasubset + self.x_input_placeholder = x_input_placeholder + self.augmented = augmented + + def get_next_batch(self, batch_size, multiple_passes=False, reshuffle_after_pass=True): + raw_batch = self.raw_datasubset.get_next_batch(batch_size, multiple_passes, + reshuffle_after_pass) + images = raw_batch[0].astype(np.float32) + return self.sess.run(self.augmented, feed_dict={self.x_input_placeholder: + raw_batch[0]}), raw_batch[1] diff --git a/case_studies/jarn/config.py b/case_studies/jarn/config.py new file mode 100644 index 0000000..29ee600 --- /dev/null +++ b/case_studies/jarn/config.py @@ -0,0 +1,101 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import configargparse +import pdb + +def pair(arg): + return [float(x) for x in arg.split(',')] + +def get_args(): + parser = configargparse.ArgParser(default_config_files=[]) + parser.add("--config", type=str, is_config_file=True, help="You can store all the config args in a config file and pass the path here") + parser.add("--model_dir", type=str, default="models/model", help="Path to save/load the checkpoints, default=models/model") + parser.add("--data_dir", type=str, default="datasets/", help="Path to load datasets from, default=datasets") + parser.add("--model_suffix", type=str, default="", help="Suffix to append to model name, default=''") + parser.add("--dataset", "-d", type=str, default="cifar10", choices=["cifar10", "cifar100", "svhn"], help="Path to load dataset, default=cifar10") + parser.add("--tf_seed", type=int, default=451760341, help="Random seed for initializing tensor-flow variables to rule out the effect of randomness in experiments, default=45160341") + parser.add("--np_seed", type=int, default=216105420, help="Random seed for initializing numpy variables to rule out the effect of randomness in experiments, default=216105420") + parser.add("--train_steps", type=int, default=80000, help="Maximum number of training steps, default=80000") + parser.add("--out_steps", "-o", type=int, default=100, help="Number of output steps, default=100") + parser.add("--summary_steps", type=int, default=500, help="Number of summary steps, default=500") + parser.add("--checkpoint_steps", "-c", type=int, default=1000, help="Number of checkpoint steps, default=1000") + parser.add("--train_batch_size", "-b", type=int, default=128, help="The training batch size, default=128") + parser.add("--step_size_schedule", nargs='+', type=pair, default=[[0, 0.1], [40000, 0.01], [60000, 0.001]], help="The step size scheduling, default=[[0, 0.1], [40000, 0.01], [60000, 0.001]], use like: --stepsize 0,0.1 40000,0.01 60000,0.001") + parser.add("--weight_decay", "-w", type=float, default=0.0002, help="The weight decay parameter, default=0.0002") + parser.add("--momentum", type=float, default=0.9, help="The momentum parameter, default=0.9") + parser.add("--replay_m", "-m", type=int, default=8, help="Number of steps to repeat training on the same batch, default=8") + parser.add("--eval_examples", type=int, default=10000, help="Number of evaluation examples, default=10000") + parser.add("--eval_size", type=int, default=128, help="Evaluation batch size, default=128") + parser.add("--eval_cpu", dest='eval_cpu', action='store_true', help="Set True to do evaluation on CPU instead of GPU, default=False") + parser.set_defaults(eval_cpu=False) + # attack params + parser.add("--epsilon", "-e", type=float, default=8.0, help="Epsilon (Lp Norm distance from the original image) for generating adversarial examples, default=8.0") + parser.add("--pgd_steps", "-k", type=int, default=20, help="Number of steps to PGD attack, default=20") + parser.add("--step_size", "-s", type=float, default=2.0, help="Step size in PGD attack for generating adversarial examples in each step, default=2.0") + parser.add("--loss_func", "-f", type=str, default="xent", choices=["xent", "cw"], help="Loss function for the model, choices are [xent, cw], default=xent") + parser.add("--num_restarts", type=int, default=1, help="Number of resets for the PGD attack, default=1") + parser.add("--random_start", dest="random_start", action="store_true", help="Random start for PGD attack default=True") + parser.add("--no-random_start", dest="random_start", action="store_false", help="No random start for PGD attack default=True") + parser.set_defaults(random_start=True) + # input grad generation param + parser.add("--randinit_repeat", type=int, default=1, help="Number of randinit grad to generate, default=1") + parser.add("--num_gen_grad", type=int, default=0, help="Number of input grad samples to generate, 0 means all data default=0") + parser.add("--num_gen_act", type=int, default=0, help="Number of activation samples to generate, 0 means all data default=0") + # input grad reg params + parser.add("--beta", type=float, default=1, help="Weight of input gradient regularization, default=1") + parser.add("--gamma", type=float, default=1, help="Weight of disc xent term on encoder opt, default=1") + parser.add("--alpha", type=float, default=0, help="Weight of image-input gradient l2 norm regularization, default=0") + parser.add("--disc_update_steps", type=int, default=5, help="Number of classifier opt steps between each disc opt step, default=5") + parser.add("--adv_update_steps_per_iter", type=int, default=1, help="Number of classifier adv opt steps per classification xent opt step, default=1") + parser.add("--disc_layers", type=int, default=5, help="Number of conv layers in disc model, default=5") + parser.add("--disc_base_channels", type=int, default=16, help="Number of channels in first disc conv layer, default=16") + parser.add("--steps_before_adv_opt", type=int, default=0, help="Number of training steps to wait before training on adv loss, default=0") + parser.add("--adv_encoder_type", type=str, default='simple', help="Type of input grad encoder for adv training, default=simple") + parser.add("--enc_output_activation", type=str, default='tanh', help="Activation function of encoder output default=None") + parser.add("--sep_opt_version", type=int, default=1, choices=[0, 1, 2], help="Sep opt version 0: train_jan.py, 1: train_jan_sep_opt-CD.py, 2: train_jan_sep_opt2-CD.py default=1") + parser.add("--grad_image_ratio", type=float, default=1, help="Ratio of input grad to mix with image default=1") + parser.add("--final_grad_image_ratio", type=float, default=0, help="Final ratio of input grad to mix with image, set to 0 for static ratio default=0") + parser.add("--num_grad_image_ratios", type=int, default=5, help="Number of times to adjust grad_image_ratio default=4") + + parser.add("--eval_adv_attack", dest="eval_adv_attack", action="store_true", help="Evaluate trained model on adv attack after training default=True") + parser.add("--no-eval_adv_attack", dest="eval_adv_attack", action="store_false", help="Evaluate trained model on adv attack after training default=True") + parser.set_defaults(eval_adv_attack=True) + + parser.add("--normalize_zero_mean", dest="normalize_zero_mean", action="store_true", help="Normalize classifier input to zero mean default=True") + parser.add("--no-normalize_zero_mean", dest="normalize_zero_mean", action="store_false", help="Normalize classifier input to zero mean default=True") + parser.set_defaults(normalize_zero_mean=True) + + parser.add("--same_optimizer", dest="same_optimizer", action="store_true", help="Train classifier and disc with same optimizer configuration default=True") + parser.add("--no-same_optimizer", dest="same_optimizer", action="store_false", help="Train classifier and disc with same optimizer configuration default=True") + parser.set_defaults(same_optimizer=True) + + parser.add("--only_fully_connected", dest="only_fully_connected", action="store_true", help="Fully connected disc model default=False") + parser.add("--no-only_fully_connected", dest="only_fully_connected", action="store_false", help="Fully connected disc model default=False") + parser.set_defaults(only_fully_connected=False) + + parser.add("--img_random_pert", dest="img_random_pert", action="store_true", help="Random start image pertubation augmentation default=False") + parser.add("--no-img_random_pert", dest="img_random_pert", action="store_false", help="No random start image pertubation augmentation default=False") + parser.set_defaults(img_random_pert=False) + + args = parser.parse_args() + return args + + +if __name__ == "__main__": + print(get_args()) + pdb.set_trace() + +# TODO Default for model_dir +# TODO Need to update the helps diff --git a/case_studies/jarn/config_attack.py b/case_studies/jarn/config_attack.py new file mode 100644 index 0000000..7920039 --- /dev/null +++ b/case_studies/jarn/config_attack.py @@ -0,0 +1,60 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import configargparse +import pdb + +def pair(arg): + return [float(x) for x in arg.split(',')] + +def get_args(): + parser = configargparse.ArgParser(default_config_files=[]) + parser.add("--model_dir", type=str, default="models/adv_trained", help="Path to save/load the checkpoints, default=models/model") + parser.add("--data_path", type=str, default="datasets/cifar10", help="Path to dataset, default=datasets/cifar10") + parser.add("--tf_seed", type=int, default=451760341, help="Random seed for initializing tensor-flow variables to rule out the effect of randomness in experiments, default=45160341") + parser.add("--np_seed", type=int, default=216105420, help="Random seed for initializing numpy variables to rule out the effect of randomness in experiments, default=216105420") + parser.add("--num_eval_examples", type=int, default=10000, help="Number of eval samples, default=10000") + parser.add("--eval_batch_size", type=int, default=100, help="Eval batch size, default=100") + parser.add("--epsilon", "-e", type=float, default=8.0, help="Epsilon (Lp Norm distance from the original image) for generating adversarial examples, default=8.0") + parser.add("--num_steps", type=int, default=10, help="Number of steps to PGD attack, default=10") + parser.add("--step_size", "-s", type=float, default=2.0, help="Step size in PGD attack for generating adversarial examples in each step, default=2.0") + parser.add("--random_start", dest="random_start", action="store_true", help="Random start for PGD attack default=True") + parser.add("--no-random_start", dest="random_start", action="store_false", help="No random start for PGD attack default=True") + parser.set_defaults(random_start=True) + parser.add("--loss_func", "-f", type=str, default="xent", choices=["xent", "target_task_xent", "cw"], help="Loss function for the model, choices are [xent, cw], default=xent") + parser.add("--attack_norm", type=str, default="inf", choices=["inf", "2"], help="Lp norm type for attacks, choices are [inf, 2], default=inf") + parser.add("--dataset", "-d", type=str, default="cifar10", choices=["cifar10", "cifar100", "imagenet"], help="Path to load dataset, default=cifar10") + parser.add("--store_adv_path", type=str, default=None, help="Path to save adversarial examples, default=None") + parser.add("--attack_name", type=str, default=None, help="Path to save adversarial examples, default=''") + parser.add("--save_eval_log", dest="save_eval_log", action="store_true", help="Save txt file for attack eval") + parser.add("--no-save_eval_log", dest="save_eval_log", action="store_false", help="Save txt file for attack eval") + parser.set_defaults(save_eval_log=False) + + parser.add("--xfer_attack", dest="xfer_attack", action="store_true", help="Adversarial transfer attack") + parser.add("--no-xfer_attack", dest="xfer_attack", action="store_false", help="not adversarial transfer attack") + parser.set_defaults(xfer_attack=False) + parser.add("--custom_output_model_name", type=str, default=None, help="Custom model name, default=None") + + parser.add("--n_inner_points", type=int, default=999, help="") + parser.add("--n_boundary_points", type=int, default=1, help="") + parser.add("--sample_from_corners", type=bool, default=False, help="") + parser.add("--attack", type=str, default="pgd", help="either pgd or apgd") + + args = parser.parse_args() + return args + + +if __name__ == "__main__": + print(get_args()) + pdb.set_trace() diff --git a/case_studies/jarn/model_jarn.py b/case_studies/jarn/model_jarn.py new file mode 100644 index 0000000..41ea784 --- /dev/null +++ b/case_studies/jarn/model_jarn.py @@ -0,0 +1,582 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +# based on https://github.com/tensorflow/models/tree/master/resnet +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np +import tensorflow as tf +import json +from collections import OrderedDict + + +class Model(object): + """ResNet model.""" + + def __init__(self, dataset, mode='train', train_batch_size=None, normalize_zero_mean=False, zero_one=False): + """ + ResNet constructor. + """ + self.neck = None + self.y_pred = None + self.mode = mode + self.num_classes = 10 + self.train_batch_size = train_batch_size + self.activations = [] + self.normalize_zero_mean = normalize_zero_mean + self.zero_one = zero_one + self._build_model() + + def add_internal_summaries(self): + pass + + def _stride_arr(self, stride): + """Map a stride scalar to the stride array for tf.nn.conv2d.""" + return [1, stride, stride, 1] + + def _build_model(self): + assert self.mode == 'train' or self.mode == 'eval' + """Build the core model within the graph.""" + with tf.variable_scope('classifier'): + with tf.variable_scope('input'): + + self.x_input = tf.placeholder( + tf.float32, + shape=[None, 32, 32, 3]) + + self.y_input = tf.placeholder(tf.int64, shape=None) + + if self.zero_one: + self.final_input = self.x_input * 255.0 + else: + self.final_input = self.x_input + + if self.normalize_zero_mean: + final_input_mean = tf.reduce_mean(self.final_input, axis=[1,2,3]) + for i in range(3): + final_input_mean = tf.expand_dims(final_input_mean, axis=-1) + final_input_mean = tf.tile(final_input_mean, [1,32,32,3]) + zero_mean_final_input = self.final_input - final_input_mean + self.input_standardized = tf.math.l2_normalize(zero_mean_final_input, axis=[1,2,3]) + else: + self.input_standardized = tf.math.l2_normalize(self.final_input, axis=[1,2,3]) + + x = self._conv('init_conv', self.input_standardized, 3, 3, 16, self._stride_arr(1)) + self.activations.append(x) + + strides = [1, 2, 2] + activate_before_residual = [True, False, False] + res_func = self._residual + + # Uncomment the following codes to use w28-10 wide residual network. + # It is more memory efficient than very deep residual network and has + # comparably good performance. + # https://arxiv.org/pdf/1605.07146v1.pdf + # filters = [16, 16, 32, 64] # for debugging + filters = [16, 160, 320, 640] + + # Update hps.num_residual_units to 9 + + with tf.variable_scope('unit_1_0'): + x = res_func(x, filters[0], filters[1], self._stride_arr(strides[0]), + activate_before_residual[0]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_1_%d' % i): + x = res_func(x, filters[1], filters[1], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_2_0'): + x = res_func(x, filters[1], filters[2], self._stride_arr(strides[1]), + activate_before_residual[1]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_2_%d' % i): + x = res_func(x, filters[2], filters[2], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_3_0'): + x = res_func(x, filters[2], filters[3], self._stride_arr(strides[2]), + activate_before_residual[2]) + self.activations.append(x) + for i in range(1, 5): + with tf.variable_scope('unit_3_%d' % i): + x = res_func(x, filters[3], filters[3], self._stride_arr(1), False) + self.activations.append(x) + + with tf.variable_scope('unit_last'): + x = self._batch_norm('final_bn', x) + x = self._relu(x, 0.1) + x = self._global_avg_pool(x) + self.neck = x + + with tf.variable_scope('logit'): + self.pre_softmax = self._fully_connected(x, self.num_classes) + self.activations.append(self.pre_softmax) + self.softmax = tf.nn.softmax(self.pre_softmax) + + sample_indices = tf.range(self.train_batch_size, dtype=tf.int64) + sample_indices = tf.expand_dims(sample_indices, axis=-1) + target_indices = tf.expand_dims(self.y_input, axis=-1) + self.gather_indices = tf.concat([sample_indices, target_indices], axis=-1) + self.target_softmax = tf.gather_nd(self.softmax, self.gather_indices, name="targetsoftmax") + self.target_logit = tf.gather_nd(self.pre_softmax, self.gather_indices, name="targetlogit") + + self.predictions = tf.argmax(self.pre_softmax, 1) + self.y_pred = self.predictions + self.correct_prediction = tf.equal(self.predictions, self.y_input) + self.num_correct = tf.reduce_sum(tf.cast(self.correct_prediction, tf.int64)) + self.accuracy = tf.reduce_mean(tf.cast(self.correct_prediction, tf.float32)) + + with tf.variable_scope('costs'): + self.y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent = tf.reduce_sum(self.y_xent, name='y_xent') + self.loss = self.xent + self.mean_xent = tf.reduce_mean(self.y_xent) + self.y_xent_dbp = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent_dbp = tf.reduce_sum(self.y_xent_dbp, name='y_xent_dbp') + self.mean_xent_dbp = tf.reduce_mean(self.y_xent_dbp) + self.weight_decay_loss = self._decay() + + # for top-2 logit diff loss + self.label_mask = tf.one_hot(self.y_input, + self.num_classes, + on_value=1.0, + off_value=0.0, + dtype=tf.float32) + self.correct_logit = tf.reduce_sum(self.label_mask * self.pre_softmax, axis=1) + self.wrong_logit = tf.reduce_max((1-self.label_mask) * self.pre_softmax - 1e4*self.label_mask, axis=1) + self.top2_logit_diff_loss = -tf.nn.relu(self.correct_logit - self.wrong_logit + 50) + + def _batch_norm(self, name, x): + """Batch normalization.""" + with tf.name_scope(name): + return tf.contrib.layers.batch_norm(inputs=x, decay=.9, center=True, scale=True, activation_fn=None, + updates_collections=None, is_training=(self.mode == 'train')) + + def _residual(self, x, in_filter, out_filter, stride, activate_before_residual=False): + """Residual unit with 2 sub layers.""" + if activate_before_residual: + with tf.variable_scope('shared_activation'): + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + orig_x = x + else: + with tf.variable_scope('residual_only_activation'): + orig_x = x + x = self._batch_norm('init_bn', x) + x = self._relu(x, 0.1) + + with tf.variable_scope('sub1'): + x = self._conv('conv1', x, 3, in_filter, out_filter, stride) + + with tf.variable_scope('sub2'): + x = self._batch_norm('bn2', x) + x = self._relu(x, 0.1) + x = self._conv('conv2', x, 3, out_filter, out_filter, [1, 1, 1, 1]) + + with tf.variable_scope('sub_add'): + if in_filter != out_filter: + orig_x = tf.nn.avg_pool(orig_x, stride, stride, 'VALID') + orig_x = tf.pad( + orig_x, [[0, 0], [0, 0], [0, 0], + [(out_filter - in_filter) // 2, (out_filter - in_filter) // 2]]) + x += orig_x + + tf.logging.debug('image after unit %s', x.get_shape()) + return x + + def _decay(self): + """L2 weight decay loss.""" + costs = [] + for var in tf.trainable_variables(): + if var.op.name.find('DW') > 0: + costs.append(tf.nn.l2_loss(var)) + return tf.add_n(costs) + + def _conv(self, name, x, filter_size, in_filters, out_filters, strides): + """Convolution.""" + with tf.variable_scope(name): + n = filter_size * filter_size * out_filters + kernel = tf.get_variable( + 'DW', [filter_size, filter_size, in_filters, out_filters], + tf.float32, initializer=tf.random_normal_initializer( + stddev=np.sqrt(2.0 / n))) + return tf.nn.conv2d(x, kernel, strides, padding='SAME') + + def _relu(self, x, leakiness=0.0): + """Relu, with optional leaky support.""" + return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu') + + def _fully_connected(self, x, out_dim): + """FullyConnected layer for final output.""" + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + + def _global_avg_pool(self, x): + assert x.get_shape().ndims == 4 + return tf.reduce_mean(x, [1, 2]) + +class JarnConvDiscriminatorModel(object): + """Simple conv discriminator model.""" + # based on https://github.com/tensorflow/models/blob/d361076952b73706c5c7ddf9c940bf42c27a3213/research/slim/nets/dcgan.py#L41 + + def __init__(self, mode, dataset, train_batch_size=None, num_conv_layers=5, base_num_channels=16, x_modelgrad_input_tensor=None, + y_modelgrad_input_tensor=None, x_image_input_tensor=None, y_image_input_tensor=None, normalize_zero_mean=False, only_fully_connected=False, num_fc_layers=3, image_size=32, num_input_channels=3): + """ + conv disc constructor. + """ + self.neck = None + self.y_pred = None + self.mode = mode + self.num_classes = 2 + self.train_batch_size = train_batch_size + self.num_conv_layers = num_conv_layers + self.num_fc_layers = num_fc_layers + self.base_num_channels = base_num_channels + self.x_modelgrad_input_tensor = x_modelgrad_input_tensor + self.y_modelgrad_input_tensor = y_modelgrad_input_tensor + self.x_image_input_tensor = x_image_input_tensor + self.y_image_input_tensor = y_image_input_tensor + self.normalize_zero_mean = normalize_zero_mean + self.only_fully_connected = only_fully_connected + self.image_size = image_size + self.num_input_channels = num_input_channels + self._build_model() + + def add_internal_summaries(self): + pass + + def _stride_arr(self, stride): + """Map a stride scalar to the stride array for tf.nn.conv2d.""" + return [1, stride, stride, 1] + + def _build_model(self): + assert self.mode == 'train' or self.mode == 'eval' + """Build the core model within the graph.""" + with tf.variable_scope('discriminator'): + with tf.variable_scope('input'): + + if self.x_modelgrad_input_tensor == None: + self.x_modelgrad_input = tf.get_variable(name='x_modelgrad_input', initializer=tf.zeros_initializer, + shape=[self.train_batch_size, self.image_size, self.image_size, self.num_input_channels], dtype=tf.float32) + + self.x_image_input = tf.placeholder( + tf.float32, + shape=[None, self.image_size, self.image_size, self.num_input_channels]) + else: + self.x_modelgrad_input = self.x_modelgrad_input_tensor + self.x_image_input = self.x_image_input_tensor + + self.x_input = tf.concat([self.x_modelgrad_input, self.x_image_input], axis=0) + + + if self.y_modelgrad_input_tensor == None: + self.y_modelgrad_input = tf.get_variable(name='y_modelgrad_input', initializer=tf.zeros_initializer, + shape=self.train_batch_size, dtype=tf.int64) + + self.y_image_input = tf.placeholder(tf.int64, shape=None) + else: + self.y_modelgrad_input = self.y_modelgrad_input_tensor + self.y_image_input = self.y_image_input_tensor + + self.y_input = tf.concat([self.y_modelgrad_input, self.y_image_input], axis=0) + + self.final_input = self.x_input + + if self.normalize_zero_mean: + final_input_mean = tf.reduce_mean(self.final_input, axis=[1,2,3]) + for i in range(3): + final_input_mean = tf.expand_dims(final_input_mean, axis=-1) + final_input_mean = tf.tile(final_input_mean, [1,self.image_size,self.image_size,self.num_input_channels]) + zero_mean_final_input = self.final_input - final_input_mean + self.input_standardized = tf.math.l2_normalize(zero_mean_final_input, axis=[1,2,3]) + else: + self.input_standardized = tf.math.l2_normalize(self.final_input, axis=[1,2,3]) + + x = self.input_standardized + base_num_channels = self.base_num_channels + if self.only_fully_connected == False: + for i in range(self.num_conv_layers): + output_num_channels = base_num_channels * 2**i + if i == 0: + x = self._conv('conv{}'.format(i), x, 4, self.num_input_channels, output_num_channels, self._stride_arr(2), bias=True) + x = self._batch_norm('bn{}'.format(i), x) + x = self._relu(x, 0.1) + else: + x = self._conv('conv{}'.format(i), x, 4, output_num_channels // 2, output_num_channels, self._stride_arr(2), bias=True) + x = self._batch_norm('bn{}'.format(i), x) + x = self._relu(x, 0.1) + else: + for i in range(self.num_fc_layers): + if i == self.num_fc_layers -1: + x = self._fully_connected(x, base_num_channels//2, name='fc{}'.format(i)) + else: + x = self._fully_connected(x, base_num_channels, name='fc{}'.format(i)) + x = self._batch_norm('bn{}'.format(i), x) + x = self._relu(x, 0.1) + + with tf.variable_scope('logit'): + self.pre_softmax = self._fully_connected(x, self.num_classes) + + self.predictions = tf.argmax(self.pre_softmax, 1) + self.y_pred = self.predictions + self.correct_prediction = tf.equal(self.predictions, self.y_input) + self.num_correct = tf.reduce_sum(tf.cast(self.correct_prediction, tf.int64)) + self.accuracy = tf.reduce_mean(tf.cast(self.correct_prediction, tf.float32)) + + with tf.variable_scope('costs'): + self.y_xent = tf.nn.sparse_softmax_cross_entropy_with_logits( + logits=self.pre_softmax, labels=self.y_input) + self.xent = tf.reduce_sum(self.y_xent, name='y_xent') + self.loss = self.xent + self.mean_xent = tf.reduce_mean(self.y_xent) + self.weight_decay_loss = self._decay() + + self.input_grad_standardized = self.input_standardized[:self.train_batch_size] + self.image_standardized = self.input_standardized[self.train_batch_size:] + self.ig_img_l2_norm_diff = tf.reduce_mean(tf.reduce_sum(tf.pow(tf.subtract(self.input_grad_standardized, self.image_standardized), 2.0), keepdims=True)) + + def _batch_norm(self, name, x): + """Batch normalization.""" + with tf.name_scope(name): + return tf.contrib.layers.batch_norm(inputs=x, decay=.9, center=True, scale=True, activation_fn=None, + updates_collections=None, is_training=(self.mode == 'train')) + def _decay(self): + """L2 weight decay loss.""" + costs = [] + for var in tf.trainable_variables(): + if var.op.name.find('DW') > 0: + costs.append(tf.nn.l2_loss(var)) + return tf.add_n(costs) + + def _conv(self, name, x, filter_size, in_filters, out_filters, strides, bias=False, padding='SAME'): + """Convolution.""" + with tf.variable_scope(name): + n = filter_size * filter_size * out_filters + kernel = tf.get_variable( + 'DW', [filter_size, filter_size, in_filters, out_filters], + tf.float32, initializer=tf.random_normal_initializer( + stddev=np.sqrt(2.0 / n))) + if bias == True: + b = tf.get_variable('biases', [out_filters], + initializer=tf.constant_initializer()) + conv_out = tf.nn.conv2d(x, kernel, strides, padding=padding) + conv_out_b = tf.nn.bias_add(conv_out, b) + return conv_out_b + else: + return tf.nn.conv2d(x, kernel, strides, padding=padding) + + def _relu(self, x, leakiness=0.0): + """Relu, with optional leaky support.""" + return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu') + + def _fully_connected(self, x, out_dim, name=None): + """FullyConnected layer for final output.""" + if name == None: + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + else: + with tf.variable_scope(name): + num_non_batch_dimensions = len(x.shape) + prod_non_batch_dimensions = 1 + for ii in range(num_non_batch_dimensions - 1): + prod_non_batch_dimensions *= int(x.shape[ii + 1]) + x = tf.reshape(x, [tf.shape(x)[0], -1]) + w = tf.get_variable( + 'DW', [prod_non_batch_dimensions, out_dim], + initializer=tf.uniform_unit_scaling_initializer(factor=1.0)) + b = tf.get_variable('biases', [out_dim], + initializer=tf.constant_initializer()) + return tf.nn.xw_plus_b(x, w, b) + + def _global_avg_pool(self, x): + assert x.get_shape().ndims == 4 + return tf.reduce_mean(x, [1, 2]) + +class InputGradEncoderModel(object): + """3x3 + 1x1 conv model.""" + # based on https://github.com/tensorflow/models/blob/d361076952b73706c5c7ddf9c940bf42c27a3213/research/slim/nets/dcgan.py#L41 + + def __init__(self, mode, train_batch_size=None, encoder_type='simple', output_activation=None, x_modelgrad_input_tensor=None, normalize_zero_mean=False, pix2pix_layers=5, pix2pix_features_root=16, pix2pix_filter_size=4, image_size=32, num_input_channels=3, num_output_channels=None): + """conv disc constructor. + + """ + self.mode = mode + self.train_batch_size = train_batch_size + self.encoder_type = encoder_type + self.output_activation = output_activation + self.x_modelgrad_input_tensor = x_modelgrad_input_tensor + self.normalize_zero_mean = normalize_zero_mean + self.keep_prob = 1 + self.layers = pix2pix_layers + self.features_root = pix2pix_features_root + self.filter_size = pix2pix_filter_size + self.image_size = image_size + self.num_input_channels = num_input_channels + if num_output_channels == None: + self.num_output_channels = num_input_channels + self._build_model() + + def add_internal_summaries(self): + pass + + def _stride_arr(self, stride): + """Map a stride scalar to the stride array for tf.nn.conv2d.""" + return [1, stride, stride, 1] + + def _build_model(self): + """Build the core model within the graph.""" + assert self.mode == 'train' or self.mode == 'eval' + with tf.variable_scope('encoder'): + + with tf.variable_scope('input'): + if self.x_modelgrad_input_tensor == None: + self.x_modelgrad_input = tf.get_variable(name='x_modelgrad_input', initializer=tf.zeros_initializer, + shape=[self.train_batch_size, self.image_size, self.image_size, self.num_input_channels], dtype=tf.float32) + else: + self.x_modelgrad_input = self.x_modelgrad_input_tensor + + if self.normalize_zero_mean: + final_input_mean = tf.reduce_mean(self.x_modelgrad_input, axis=[1,2,3]) + for i in range(3): + final_input_mean = tf.expand_dims(final_input_mean, axis=-1) + final_input_mean = tf.tile(final_input_mean, [1,self.image_size,self.image_size,self.num_input_channels]) + zero_mean_final_input = self.x_modelgrad_input - final_input_mean + self.input_standardized = tf.math.l2_normalize(zero_mean_final_input, axis=[1,2,3]) + else: + self.input_standardized = tf.math.l2_normalize(self.x_modelgrad_input, axis=[1,2,3]) + + + if self.output_activation == 'tanh': + x_modelgrad_transformed_preact = self._conv('conv', self.input_standardized, 1, self.num_output_channels, self.num_output_channels, self._stride_arr(1), bias=True) + self.x_modelgrad_transformed = tf.tanh(x_modelgrad_transformed_preact) + else: + self.x_modelgrad_transformed = self._conv('conv', self.input_standardized, 1, self.num_output_channels, self.num_output_channels, self._stride_arr(1), bias=True) + + + with tf.variable_scope('costs'): + self.weight_decay_loss = self._decay() + + def _batch_norm(self, name, x): + """Batch normalization.""" + with tf.name_scope(name): + return tf.contrib.layers.batch_norm(inputs=x, decay=.9, center=True, scale=True, activation_fn=None, + updates_collections=None, is_training=(self.mode == 'train')) + + def _decay(self): + """L2 weight decay loss.""" + costs = [] + for var in tf.trainable_variables(): + if var.op.name.find('DW') > 0: + costs.append(tf.nn.l2_loss(var)) + return tf.add_n(costs) + + def _conv(self, name, x, filter_size, in_filters, out_filters, strides, bias=False, padding='SAME'): + """Convolution.""" + with tf.variable_scope(name): + n = filter_size * filter_size * out_filters + kernel = tf.get_variable( + 'DW', [filter_size, filter_size, in_filters, out_filters], + tf.float32, initializer=tf.random_normal_initializer( + stddev=np.sqrt(2.0 / n))) + if bias == True: + b = tf.get_variable('biases', [out_filters], + initializer=tf.constant_initializer()) + conv_out = tf.nn.conv2d(x, kernel, strides, padding=padding) + conv_out_b = tf.nn.bias_add(conv_out, b) + return conv_out_b + else: + return tf.nn.conv2d(x, kernel, strides, padding=padding) + + def _relu(self, x, leakiness=0.0): + """Relu, with optional leaky support.""" + return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu') + +class GradImageMixer(object): + """ Model to mix input grad with image.""" + + def __init__(self, train_batch_size=None, direct_feed_input=False, grad_input_tensor=None, image_input_tensor=None, normalize_zero_mean=False, image_size=32, num_input_channels=3): + """GradImageMixer constructor. + + Args: + + """ + self.train_batch_size = train_batch_size + self.direct_feed_input = direct_feed_input + self.grad_input_tensor = grad_input_tensor + self.image_input_tensor = image_input_tensor + self.normalize_zero_mean = normalize_zero_mean + self.image_size = image_size + self.num_input_channels = num_input_channels + self._build_model() + + def _build_model(self): + """Build the core model within the graph.""" + with tf.variable_scope('mixer'): + with tf.variable_scope('input'): + if self.direct_feed_input: + self.grad_input = tf.placeholder( + tf.float32, + shape=[None, self.image_size, self.image_size, self.num_input_channels]) + + self.image_input = tf.placeholder( + tf.float32, + shape=[None, self.image_size, self.image_size, self.num_input_channels]) + else: + if self.grad_input_tensor == None: + self.grad_input = tf.get_variable(name='grad_input', initializer=tf.zeros_initializer, + shape=[self.train_batch_size, self.image_size, self.image_size, self.num_input_channels], dtype=tf.float32) + + self.image_input = tf.get_variable(name='image_input', initializer=tf.zeros_initializer, + shape=[self.train_batch_size, self.image_size, self.image_size, self.num_input_channels], dtype=tf.float32) + else: + self.grad_input = self.grad_input_tensor + self.image_input = self.image_input_tensor + + self.grad_ratio = tf.placeholder(tf.float32, shape=()) + + if self.normalize_zero_mean: + final_input_mean = tf.reduce_mean(self.grad_input, axis=[1,2,3]) + for i in range(3): + final_input_mean = tf.expand_dims(final_input_mean, axis=-1) + final_input_mean = tf.tile(final_input_mean, [1, self.image_size, self.image_size,self.num_input_channels]) + zero_mean_final_input = self.grad_input - final_input_mean + self.grad_input_standardized = tf.math.l2_normalize(zero_mean_final_input, axis=[1,2,3]) + else: + self.grad_input_standardized = tf.math.l2_normalize(self.grad_input, axis=[1,2,3]) + + self.output = self.grad_input_standardized * self.grad_ratio + self.image_input * (1 - self.grad_ratio) diff --git a/case_studies/jarn/pgd_attack.py b/case_studies/jarn/pgd_attack.py new file mode 100644 index 0000000..e16d6ba --- /dev/null +++ b/case_studies/jarn/pgd_attack.py @@ -0,0 +1,199 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +Implementation of attack methods. Running this file as a program will +apply the attack to the model specified by the config file and store +the examples in an .npy file. +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from datetime import datetime +import os +import tensorflow as tf +import numpy as np + +import cifar10_input + +import config_attack + +class LinfPGDAttack: + def __init__(self, model, epsilon, num_steps, step_size, random_start, loss_func, dataset='cifar10', + clip_max=255.0): + """Attack parameter initialization. The attack performs k steps of + size a, while always staying within epsilon from the initial + point.""" + self.model = model + self.epsilon = epsilon + self.num_steps = num_steps + self.step_size = step_size + self.rand = random_start + self.clip_max = clip_max + + self.loss = model.loss + + self.logits = model.pre_softmax + + self.grad = tf.gradients(self.loss, model.x_input)[0] + + def perturb(self, x_nat, y, sess): + """Given a set of examples (x_nat, y), returns a set of adversarial + examples within epsilon of x_nat in l_infinity norm.""" + if self.rand: + x = x_nat + np.random.uniform(-self.epsilon, self.epsilon, x_nat.shape) + x = np.clip(x, 0, self.clip_max) # ensure valid pixel range + else: + x = np.copy(x_nat) + + for i in range(self.num_steps): + loss, logits, grad = sess.run((self.loss, self.logits, self.grad), feed_dict={self.model.x_input: x, + self.model.y_input: y}) + + # added by AUTHOR + if np.all(logits.argmax(-1) != y): + break + + print(i, loss, logits) + # x = np.add(x, self.step_size * np.sign(grad), out=x, casting='unsafe') + + # changed by AUTHOR + grad = np.sign(grad) + #grad = grad / (grad.reshape(len(grad), -1)**2).sum(-1) + x = x + self.step_size * grad + + x = np.clip(x, x_nat - self.epsilon, x_nat + self.epsilon) + x = np.clip(x, 0, self.clip_max) # ensure valid pixel range + + return x + + def perturb_l2(self, x_nat, y, sess): + """Given a set of examples (x_nat, y), returns a set of adversarial + examples within epsilon of x_nat in l_2 norm.""" + if self.rand: + pert = np.random.uniform(-self.epsilon, self.epsilon, x_nat.shape) + pert_norm = np.linalg.norm(pert) + pert = pert / max(1, pert_norm) + else: + pert = np.zeros(x_nat.shape) + + for i in range(self.num_steps): + x = x_nat + pert + grad = sess.run(self.grad, feed_dict={self.model.x_input: x, + self.model.y_input: y}) + + normalized_grad = grad / np.linalg.norm(grad) + pert = np.add(pert, self.step_size * normalized_grad, out=pert, casting='unsafe') + + # project pert to norm ball + pert_norm = np.linalg.norm(pert) + rescale_factor = pert_norm / self.epsilon + pert = pert / max(1, rescale_factor) + + x = x_nat + pert + x = np.clip(x, 0, 255) + + return x + + +if __name__ == '__main__': + import json + import sys + import math + + config = vars(config_attack.get_args()) + + tf.set_random_seed(config['tf_seed']) + np.random.seed(config['np_seed']) + + model_file = tf.train.latest_checkpoint(config['model_dir']) + print("config['model_dir']: ", config['model_dir']) + if model_file is None: + print('No model found') + sys.exit() + + print("JARN MODEL") + from model_jarn import Model + if "_zeromeaninput" in config['model_dir']: + model = Model(dataset=config['dataset'], train_batch_size=config['eval_batch_size'], normalize_zero_mean=True) + else: + model = Model(dataset=config['dataset'], train_batch_size=config['eval_batch_size']) + + attack = LinfPGDAttack(model, + config['epsilon'], + config['num_steps'], + config['step_size'], + config['random_start'], + config['loss_func'], + dataset=config['dataset']) + saver = tf.train.Saver() + + data_path = config['data_path'] + + print("load cifar10 dataset") + cifar = cifar10_input.CIFAR10Data(data_path) + + with tf.Session() as sess: + # Restore the checkpoint + saver.restore(sess, model_file) + # Iterate over the samples batch-by-batch + num_eval_examples = config['num_eval_examples'] + eval_batch_size = config['eval_batch_size'] + num_batches = int(math.ceil(num_eval_examples / eval_batch_size)) + + x_adv = [] # adv accumulator + + print('Iterating over {} batches'.format(num_batches)) + + for ibatch in range(num_batches): + bstart = ibatch * eval_batch_size + bend = min(bstart + eval_batch_size, num_eval_examples) + print('batch size: {}'.format(bend - bstart)) + + x_batch = cifar.eval_data.xs[bstart:bend, :] + y_batch = cifar.eval_data.ys[bstart:bend] + + x_batch_adv = attack.perturb(x_batch, y_batch, sess) + + x_adv.append(x_batch_adv) + + print('Storing examples') + path = config['store_adv_path'] + if path == None: + model_name = config['model_dir'].split('/')[1] + if config['attack_name'] == None: + path = "attacks/{}_attack.npy".format(model_name) + else: + path = "attacks/{}_{}_attack.npy".format(model_name, config['attack_name']) + + if not os.path.exists("attacks/"): + os.makedirs("attacks/") + + x_adv = np.concatenate(x_adv, axis=0) + np.save(path, x_adv) + print('Examples stored in {}'.format(path)) + + if config['save_eval_log']: + if not os.path.exists("attack_log/"): + os.makedirs("attack_log/") + date_str = datetime.now().strftime("%d_%b") + log_dir = "attack_log/" + date_str + if not os.path.exists(log_dir): + os.makedirs(log_dir) + log_filename = path.split("/")[-1].replace('.npy', '.txt') + log_file_path = os.path.join(log_dir, log_filename) + with open(log_file_path, "w") as f: + f.write('Saved model name: {} \n'.format(model_file)) + print('Model name saved at ', log_file_path) diff --git a/case_studies/jarn/requirements.txt b/case_studies/jarn/requirements.txt new file mode 100644 index 0000000..83c38be --- /dev/null +++ b/case_studies/jarn/requirements.txt @@ -0,0 +1,5 @@ +ConfigArgParse==0.14.0 +tqdm==4.31.1 +tensorflow-gpu==1.14.0 +numba>=0.43.1 +matplotlib>=3.0.3 \ No newline at end of file diff --git a/case_studies/jarn/run_attack.py b/case_studies/jarn/run_attack.py new file mode 100644 index 0000000..65076f0 --- /dev/null +++ b/case_studies/jarn/run_attack.py @@ -0,0 +1,242 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +"""Evaluates a model against examples from a .npy file as specified + in attack_config.json""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from datetime import datetime +import json +import math +import os +import sys +import time + +import tensorflow as tf +import numpy as np +from tqdm import tqdm + +# from model import Model +import cifar10_input +# import cifar100_input + +import config_attack + +# with open('attack_config.json') as config_file: +# config = json.load(config_file) + +config = vars(config_attack.get_args()) + +# if config['model_dir'] in ["models/adv_trained", "models/naturally_trained"]: +# from free_model_original import Model +# elif 'DefPert2' in config['model_dir']: +# from model_jarn import ModelDefPert as Model +# elif 'JARN': +# from model_jarn import Model +# else: +# from free_model import Model + +data_path = config['data_path'] + +def run_attack(checkpoint, x_adv, epsilon): +# cifar = cifar10_input.CIFAR10Data(data_path) + cifar = cifar10_input.CIFAR10Data(data_path) + # if config['dataset'] == 'cifar10': + # cifar = cifar10_input.CIFAR10Data(data_path) + # else: + # cifar = cifar100_input.CIFAR100Data(data_path) + + + print("JARN MODEL") + from model_jarn import Model + if "_zeromeaninput" in config['model_dir']: + model = Model(dataset=config['dataset'], train_batch_size=config['eval_batch_size'], normalize_zero_mean=True) + else: + model = Model(dataset=config['dataset'], train_batch_size=config['eval_batch_size']) + + saver = tf.train.Saver() + + num_eval_examples = 10000 + eval_batch_size = 100 + + num_batches = int(math.ceil(num_eval_examples / eval_batch_size)) + total_corr = 0 + + x_nat = cifar.eval_data.xs + l_inf = np.amax(np.abs(x_nat - x_adv)) + + if l_inf > epsilon + 0.0001: + print('maximum perturbation found: {}'.format(l_inf)) + print('maximum perturbation allowed: {}'.format(epsilon)) + return + + y_pred = [] # label accumulator + + with tf.Session() as sess: + # Restore the checkpoint + saver.restore(sess, checkpoint) + # if 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config['model_dir']: + # sess.run(tf.global_variables_initializer()) + # source_model_file = tf.train.latest_checkpoint("models/model_AdvTrain-jrtsource-JRT-tinyimagenet_b16") + # source_model_saver.restore(sess, source_model_file) + # finetuned_source_model_file = tf.train.latest_checkpoint(config['model_dir']) + # finetuned_source_model_saver.restore(sess, finetuned_source_model_file) + # elif 'mnist_adv_trained_finetuned_on_cifar10_bwtransform' in config['model_dir']: + # sess.run(tf.global_variables_initializer()) + # source_model_file = tf.train.latest_checkpoint("models/mnist_adv_trained") + # source_model_saver.restore(sess, source_model_file) + # finetuned_source_model_file = tf.train.latest_checkpoint(config['model_dir']) + # finetuned_source_model_saver.restore(sess, finetuned_source_model_file) + # elif 'finetuned_on_cifar100' in config['model_dir']: + # sess.run(tf.global_variables_initializer()) + # source_model_file = tf.train.latest_checkpoint("models/adv_trained") + # source_model_saver.restore(sess, source_model_file) + # finetuned_source_model_file = tf.train.latest_checkpoint(config['model_dir']) + # finetuned_source_model_saver.restore(sess, finetuned_source_model_file) + + # # sess.run(tf.global_variables_initializer()) + # # source_model_file = tf.train.latest_checkpoint("models/adv_trained") + # # source_model_saver.restore(sess, source_model_file) + # # finetuned_source_model_file = tf.train.latest_checkpoint("models/adv_trained_finetuned_on_cifar100_b32_20ep") + # # finetuned_source_model_saver.restore(sess, finetuned_source_model_file) + # else: + # saver.restore(sess, checkpoint) + + # Iterate over the samples batch-by-batch + for ibatch in range(num_batches): + bstart = ibatch * eval_batch_size + bend = min(bstart + eval_batch_size, num_eval_examples) + + x_batch = x_adv[bstart:bend, :] + y_batch = cifar.eval_data.ys[bstart:bend] + + dict_adv = {model.x_input: x_batch, + model.y_input: y_batch} + + cur_corr, y_pred_batch = sess.run([model.num_correct, model.predictions], + feed_dict=dict_adv) + # if 'finetuned_on_cifar10' in config['model_dir'] or 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config['model_dir']: + # cur_corr, y_pred_batch = sess.run([model.target_task_num_correct, model.target_task_predictions], + # feed_dict=dict_adv) + # else: + # cur_corr, y_pred_batch = sess.run([model.num_correct, model.predictions], + # feed_dict=dict_adv) + + total_corr += cur_corr + y_pred.append(y_pred_batch) + + accuracy = total_corr / num_eval_examples + + print('Adv Accuracy: {:.2f}%'.format(100.0 * accuracy)) + y_pred = np.concatenate(y_pred, axis=0) + + store_adv_pred_path = "preds/" + adv_examples_path.split("/")[-1] + if not os.path.exists("preds/"): + os.makedirs("preds/") + np.save(store_adv_pred_path, y_pred) + print('Output saved at ', store_adv_pred_path) + + if config['save_eval_log']: + date_str = datetime.now().strftime("%d_%b") + log_dir = "attack_log/" + date_str + if not os.path.exists(log_dir): + os.makedirs(log_dir) + log_filename = adv_examples_path.split("/")[-1].replace('.npy', '.txt') + model_name = config['model_dir'].split('/')[1] + # if model_name not in log_filename or config['xfer_attack']: + # print("Transfer Attack!") + # if config['custom_output_model_name'] is not None: + # new_log_filename = config['custom_output_model_name'] +"-xferattacked_by-"+ log_filename + # else: + # new_log_filename = model_name +"-xferattacked_by-"+ log_filename + # log_filename = new_log_filename + log_file_path = os.path.join(log_dir, log_filename) + with open(log_file_path, "w") as f: + f.write('Model checkpoint: {} \n'.format(checkpoint)) + f.write('Adv Accuracy: {:.2f}%'.format(100.0 * accuracy)) + print('Results saved at ', log_file_path) + + # full test evaluation + # raw_data = cifar10_input.CIFAR10Data(data_path) + if config['dataset'] == 'cifar10': + raw_data = cifar10_input.CIFAR10Data(data_path) + else: + raw_data = cifar100_input.CIFAR100Data(data_path) + data_size = raw_data.eval_data.n + if data_size % config['eval_batch_size'] == 0: + eval_steps = data_size // config['eval_batch_size'] + else: + eval_steps = data_size // config['eval_batch_size'] + 1 + total_num_correct = 0 + for ii in tqdm(range(eval_steps)): + x_eval_batch, y_eval_batch = raw_data.eval_data.get_next_batch(config['eval_batch_size'], multiple_passes=False) + eval_dict = {model.x_input: x_eval_batch, model.y_input: y_eval_batch} + if 'finetuned_on_cifar10' in config['model_dir'] or 'adv_trained_tinyimagenet_finetuned_on_c10_upresize' in config['model_dir']: + num_correct = sess.run(model.target_task_num_correct, feed_dict=eval_dict) + else: + num_correct = sess.run(model.num_correct, feed_dict=eval_dict) + total_num_correct += num_correct + eval_acc = total_num_correct / data_size + with open(log_file_path, "a+") as f: + f.write('\nClean Accuracy: {:.2f}%'.format(100.0 * eval_acc)) + print('Clean Accuracy: {:.2f}%'.format(100.0 * eval_acc)) + print('Results saved at ', log_file_path) + +if __name__ == '__main__': + import json + + # with open('attack_config.json') as config_file: + # config = json.load(config_file) + + model_dir = config['model_dir'] + + checkpoint = tf.train.latest_checkpoint(model_dir) + + adv_examples_path = config['store_adv_path'] + if adv_examples_path == None: + model_name = config['model_dir'].split('/')[1] + if config['attack_name'] == None: + adv_examples_path = "attacks/{}_attack.npy".format(model_name) + # if config['dataset'] == 'cifar10': + # adv_examples_path = "attacks/{}_attack.npy".format(model_name) + # else: + # adv_examples_path = "attacks/{}_c100attack.npy".format(model_name) + else: + adv_examples_path = "attacks/{}_{}_attack.npy".format(model_name, config['attack_name']) + # if config['dataset'] == 'cifar10': + # adv_examples_path = "attacks/{}_{}_attack.npy".format(model_name, config['attack_name']) + # else: + # adv_examples_path = "attacks/{}_{}_c100attack.npy".format(model_name, config['attack_name']) + + # if config['attack_norm'] == '2': + # adv_examples_path = adv_examples_path.replace("attack.npy", "l2attack.npy") + + x_adv = np.load(adv_examples_path) + + tf.set_random_seed(config['tf_seed']) + np.random.seed(config['np_seed']) + + if checkpoint is None: + print('No checkpoint found') + elif x_adv.shape != (10000, 32, 32, 3): + print('Invalid shape: expected (10000, 32, 32, 3), found {}'.format(x_adv.shape)) + elif np.amax(x_adv) > 255.0001 or np.amin(x_adv) < -0.0001: + print('Invalid pixel range. Expected [0, 255], found [{}, {}]'.format( + np.amin(x_adv), + np.amax(x_adv))) + else: + print("adv_examples_path: ", adv_examples_path) + run_attack(checkpoint, x_adv, config['epsilon']) diff --git a/case_studies/jarn/run_train_jarn.sh b/case_studies/jarn/run_train_jarn.sh new file mode 100644 index 0000000..cc7d912 --- /dev/null +++ b/case_studies/jarn/run_train_jarn.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +python train_jarn.py --img_random_pert --eval_adv_attack --sep_opt_version 1 --beta 1 --disc_layers 5 --disc_base_channels 32 --disc_update_steps 20 --steps_before_adv_opt 140000 --step_size_schedule 0,0.1 80000,0.01 120000,0.001 --train_steps 160000 -b 64 \ No newline at end of file diff --git a/case_studies/jarn/train_jarn.py b/case_studies/jarn/train_jarn.py new file mode 100644 index 0000000..38c9aa5 --- /dev/null +++ b/case_studies/jarn/train_jarn.py @@ -0,0 +1,286 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +"""Trains a model, saving checkpoints and tensorboard summaries along + the way.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from datetime import datetime +import os +import shutil +from timeit import default_timer as timer +import tensorflow as tf +import numpy as np +import sys +from model_jarn import Model, JarnConvDiscriminatorModel, InputGradEncoderModel, GradImageMixer +import cifar10_input +import pdb +from tqdm import tqdm +import subprocess +import time +from numba import cuda + +import config + +def get_path_dir(data_dir, dataset, **_): + if dataset == "cifar10": + path = "../../data/cifar10/cifar-10-batches-py/" + else: + path = os.path.join(data_dir, dataset) + if os.path.islink(path): + path = os.readlink(path) + return path + + +def train(tf_seed, np_seed, train_steps, out_steps, summary_steps, checkpoint_steps, step_size_schedule, + weight_decay, momentum, train_batch_size, epsilon, replay_m, model_dir, model_suffix, dataset, + beta, gamma, disc_update_steps, adv_update_steps_per_iter, disc_layers, disc_base_channels, steps_before_adv_opt, adv_encoder_type, enc_output_activation, + sep_opt_version, grad_image_ratio, final_grad_image_ratio, num_grad_image_ratios, normalize_zero_mean, eval_adv_attack, same_optimizer, only_fully_connected, img_random_pert, **kwargs): + tf.set_random_seed(tf_seed) + np.random.seed(np_seed) + + model_dir = model_dir + 'JARN_%s_b%d_beta_%.3f_gamma_%.3f_disc_update_steps%d_l%dbc%d' % (dataset, train_batch_size, beta, gamma, disc_update_steps, disc_layers, disc_base_channels) + + if img_random_pert: + model_dir = model_dir + '_imgpert' + + if steps_before_adv_opt != 0: + model_dir = model_dir + '_advdelay%d' % (steps_before_adv_opt) + if adv_encoder_type != 'simple': + model_dir = model_dir + '_%senc' % (adv_encoder_type) + if enc_output_activation != None: + model_dir = model_dir + '_%sencact' % (enc_output_activation) + if grad_image_ratio != 1: + model_dir = model_dir + '_gradmixratio%.2f' % (grad_image_ratio) + + if normalize_zero_mean: + model_dir = model_dir + '_zeromeaninput' + if train_steps != 80000: + model_dir = model_dir + '_%dsteps' % (train_steps) + if same_optimizer == False: + model_dir = model_dir + '_adamDopt' + if only_fully_connected: + model_dir = model_dir + '_FCdisc' + + if tf_seed != 451760341: + model_dir = model_dir + '_tf_seed%d' % (tf_seed) + if np_seed != 216105420: + model_dir = model_dir + '_np_seed%d' % (np_seed) + + model_dir = model_dir + model_suffix + + # Setting up the data and the model + data_path = get_path_dir(dataset=dataset, **kwargs) + raw_data = cifar10_input.CIFAR10Data(data_path) + global_step = tf.train.get_or_create_global_step() + increment_global_step_op = tf.assign(global_step, global_step+1) + model = Model(mode='train', dataset=dataset, train_batch_size=train_batch_size, normalize_zero_mean=normalize_zero_mean) + + # Setting up the optimizers + boundaries = [int(sss[0]) for sss in step_size_schedule][1:] + values = [sss[1] for sss in step_size_schedule] + learning_rate = tf.train.piecewise_constant(tf.cast(global_step, tf.int32), boundaries, values) + c_optimizer = tf.train.MomentumOptimizer(learning_rate, momentum) + e_optimizer = tf.train.MomentumOptimizer(learning_rate, momentum) + + if same_optimizer: + d_optimizer = tf.train.MomentumOptimizer(learning_rate, momentum) + else: + print("Using ADAM opt for DISC model") + d_optimizer = tf.train.AdamOptimizer(learning_rate = 0.001) + + # Using target softmax for input grad + input_grad = tf.gradients(model.target_softmax, model.x_input, name="gradients_ig")[0] + + # Setting up the gradimagemixer model + grad_image_mixer = GradImageMixer(train_batch_size=train_batch_size, grad_input_tensor=input_grad, image_input_tensor=model.input_standardized, normalize_zero_mean=normalize_zero_mean) + + # Setting up the discriminator model + encoder_model = InputGradEncoderModel(mode='train', train_batch_size=train_batch_size, encoder_type=adv_encoder_type, output_activation=enc_output_activation, x_modelgrad_input_tensor=grad_image_mixer.output, normalize_zero_mean=normalize_zero_mean) + transformed_input_grad = encoder_model.x_modelgrad_transformed + labels_input_grad = tf.zeros( tf.shape(input_grad)[0] , dtype=tf.int64) + labels_disc_image_input = tf.ones( tf.shape(input_grad)[0] , dtype=tf.int64) + disc_model = JarnConvDiscriminatorModel(mode='train', dataset=dataset, train_batch_size=train_batch_size, num_conv_layers=disc_layers, base_num_channels=disc_base_channels, normalize_zero_mean=normalize_zero_mean, + x_modelgrad_input_tensor=transformed_input_grad, y_modelgrad_input_tensor=labels_input_grad, x_image_input_tensor=model.input_standardized, y_image_input_tensor=labels_disc_image_input, only_fully_connected=only_fully_connected) + + t_vars = tf.trainable_variables() + C_vars = [var for var in t_vars if 'classifier' in var.name] + D_vars = [var for var in t_vars if 'discriminator' in var.name] + E_vars = [var for var in t_vars if 'encoder' in var.name] + + # Classifier: Optimizing computation + # total classifier loss: Add discriminator loss into total classifier loss + total_loss = model.mean_xent + weight_decay * model.weight_decay_loss - beta * disc_model.mean_xent + classification_c_loss = model.mean_xent + weight_decay * model.weight_decay_loss + adv_c_loss = - beta * disc_model.mean_xent + + # Discriminator: Optimizating computation + # discriminator loss + total_d_loss = disc_model.mean_xent + weight_decay * disc_model.weight_decay_loss + + # Train classifier + # classifier opt step + # AUTHOR added the next two lines to fix batch norm + update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) + with tf.control_dependencies(update_ops): + final_grads = c_optimizer.compute_gradients(total_loss, var_list=C_vars) + no_pert_grad = [(tf.zeros_like(v), v) if 'perturbation' in v.name else (g, v) for g, v in final_grads] + c_min_step = c_optimizer.apply_gradients(no_pert_grad) + + classification_final_grads = c_optimizer.compute_gradients(classification_c_loss, var_list=C_vars) + classification_no_pert_grad = [(tf.zeros_like(v), v) if 'perturbation' in v.name else (g, v) for g, v in classification_final_grads] + c_classification_min_step = c_optimizer.apply_gradients(classification_no_pert_grad) + + # Encoder: Optimizating computation + # encoder loss + total_e_loss = weight_decay * encoder_model.weight_decay_loss - gamma * disc_model.mean_xent + e_min_step = e_optimizer.minimize(total_e_loss, var_list=E_vars) + + # discriminator opt step + d_min_step = d_optimizer.minimize(total_d_loss, var_list=D_vars) + + # Loss gradients to the model params + logit_weights = tf.get_default_graph().get_tensor_by_name('classifier/logit/DW:0') + last_conv_weights = tf.get_default_graph().get_tensor_by_name('classifier/unit_3_4/sub2/conv2/DW:0') + first_conv_weights = tf.get_default_graph().get_tensor_by_name('classifier/input/init_conv/DW:0') + + # Setting up the Tensorboard and checkpoint outputs + if not os.path.exists(model_dir): + os.makedirs(model_dir) + + saver = tf.train.Saver(max_to_keep=1) + tf.summary.scalar('C accuracy', model.accuracy) + tf.summary.scalar('D accuracy', disc_model.accuracy) + tf.summary.scalar('C xent', model.xent / train_batch_size) + tf.summary.scalar('D xent', disc_model.xent / train_batch_size) + tf.summary.scalar('total C loss', total_loss / train_batch_size) + tf.summary.scalar('total D loss', total_d_loss / train_batch_size) + tf.summary.scalar('adv C loss', adv_c_loss / train_batch_size) + tf.summary.scalar('C cls xent loss', model.mean_xent) + merged_summaries = tf.summary.merge_all() + + with tf.Session() as sess: + print('params >>> \n model dir: %s \n dataset: %s \n training batch size: %d \n' % (model_dir, dataset, train_batch_size)) + + data = cifar10_input.AugmentedCIFAR10Data(raw_data, sess, model) + + # Initialize the summary writer, global variables, and our time counter. + summary_writer = tf.summary.FileWriter(model_dir + '/train', sess.graph) + eval_summary_writer = tf.summary.FileWriter(model_dir + '/eval') + sess.run(tf.global_variables_initializer()) + + # Main training loop + for ii in tqdm(range(train_steps)): + + x_batch, y_batch = data.train_data.get_next_batch(train_batch_size, multiple_passes=True) + if img_random_pert: + x_batch = x_batch + np.random.uniform(-epsilon, epsilon, x_batch.shape) + x_batch = np.clip(x_batch, 0, 255) # ensure valid pixel range + + labels_image_disc = np.ones_like( y_batch, dtype=np.int64) + + nat_dict = {model.x_input: x_batch, model.y_input: y_batch, + disc_model.x_image_input: x_batch, disc_model.y_image_input: labels_image_disc, grad_image_mixer.grad_ratio: grad_image_ratio} + + # Output to stdout + if ii % summary_steps == 0: + train_acc, train_disc_acc, train_c_loss, train_e_loss, train_d_loss, train_adv_c_loss, summary = sess.run([model.accuracy, disc_model.accuracy, total_loss, total_e_loss, total_d_loss, adv_c_loss, merged_summaries], feed_dict=nat_dict) + summary_writer.add_summary(summary, global_step.eval(sess)) + + x_eval_batch, y_eval_batch = data.eval_data.get_next_batch(train_batch_size, multiple_passes=True) + if img_random_pert: + x_eval_batch = x_eval_batch + np.random.uniform(-epsilon, epsilon, x_eval_batch.shape) + x_eval_batch = np.clip(x_eval_batch, 0, 255) # ensure valid pixel range + + labels_image_disc = np.ones_like( y_eval_batch, dtype=np.int64) + + eval_dict = {model.x_input: x_eval_batch, model.y_input: y_eval_batch, + disc_model.x_image_input: x_eval_batch, disc_model.y_image_input: labels_image_disc, grad_image_mixer.grad_ratio: grad_image_ratio} + + val_acc, val_disc_acc, val_c_loss, val_e_loss, val_d_loss, val_adv_c_loss, summary = sess.run([model.accuracy, disc_model.accuracy, total_loss, total_e_loss, total_d_loss, adv_c_loss, merged_summaries], feed_dict=eval_dict) + eval_summary_writer.add_summary(summary, global_step.eval(sess)) + print('Step {}: ({})'.format(ii, datetime.now())) + print(' training nat accuracy {:.4}% -- validation nat accuracy {:.4}%'.format(train_acc * 100, + val_acc * 100)) + print(' training nat disc accuracy {:.4}% -- validation nat disc accuracy {:.4}%'.format(train_disc_acc * 100, + val_disc_acc * 100)) + print(' training nat c loss: {}, e loss: {}, d loss: {}, adv c loss: {}'.format( train_c_loss, train_e_loss, train_d_loss, train_adv_c_loss)) + print(' validation nat c loss: {}, e loss: {}, d loss: {}, adv c loss: {}'.format( val_c_loss, val_e_loss, val_d_loss, val_adv_c_loss)) + + sys.stdout.flush() + # Tensorboard summaries + elif ii % out_steps == 0: + nat_acc, nat_disc_acc, nat_c_loss, nat_e_loss, nat_d_loss, nat_adv_c_loss = sess.run([model.accuracy, disc_model.accuracy, total_loss, total_e_loss, total_d_loss, adv_c_loss], feed_dict=nat_dict) + print('Step {}: ({})'.format(ii, datetime.now())) + print(' training nat accuracy {:.4}%'.format(nat_acc * 100)) + print(' training nat disc accuracy {:.4}%'.format(nat_disc_acc * 100)) + print(' training nat c loss: {}, e loss: {}, d loss: {}, adv c loss: {}'.format( nat_c_loss, nat_e_loss, nat_d_loss, nat_adv_c_loss)) + + # Write a checkpoint + if (ii+1) % checkpoint_steps == 0: + saver.save(sess, os.path.join(model_dir, 'checkpoint'), global_step=global_step) + + if ii >= steps_before_adv_opt: + # Actual training step for Classifier + sess.run([c_min_step, e_min_step], feed_dict=nat_dict) + sess.run(increment_global_step_op) + + if ii % disc_update_steps == 0: + # Actual training step for Discriminator + sess.run(d_min_step, feed_dict=nat_dict) + else: + # only train on classification loss + sess.run(c_classification_min_step, feed_dict=nat_dict) + sess.run(increment_global_step_op) + + # full test evaluation + raw_data = cifar10_input.CIFAR10Data(data_path) + data_size = raw_data.eval_data.n + + eval_steps = data_size // train_batch_size + + total_num_correct = 0 + for ii in tqdm(range(eval_steps)): + x_eval_batch, y_eval_batch = raw_data.eval_data.get_next_batch(train_batch_size, multiple_passes=False) + eval_dict = {model.x_input: x_eval_batch, model.y_input: y_eval_batch} + num_correct = sess.run(model.num_correct, feed_dict=eval_dict) + total_num_correct += num_correct + eval_acc = total_num_correct / data_size + + clean_eval_file_path = os.path.join(model_dir, 'full_clean_eval_acc.txt') + with open(clean_eval_file_path, "a+") as f: + f.write("Full clean eval_acc: {}%".format(eval_acc*100)) + print("Full clean eval_acc: {}%".format(eval_acc*100)) + + + devices = sess.list_devices() + for d in devices: + print("sess' device names:") + print(d.name) + + return model_dir + +if __name__ == '__main__': + args = config.get_args() + args_dict = vars(args) + model_dir = train(**args_dict) + if args_dict['eval_adv_attack']: + cuda.select_device(0) + cuda.close() + + print("{}: Evaluating on CIFAR10 fgsm and pgd attacks".format(datetime.now())) + subprocess.run("python pgd_attack.py --attack_name fgsm --save_eval_log --num_steps 1 --no-random_start --step_size 8 --model_dir {} ; python run_attack.py --attack_name fgsm --save_eval_log --model_dir {} ; python pgd_attack.py --save_eval_log --model_dir {} ; python run_attack.py --save_eval_log --model_dir {} ; python pgd_attack.py --attack_name pgds5 --save_eval_log --num_steps 5 --model_dir {} ; python run_attack.py --attack_name pgds5 --save_eval_log --num_steps 5 --model_dir {}".format(model_dir, model_dir, model_dir, model_dir, model_dir, model_dir), shell=True) + print("{}: Ended evaluation on CIFAR10 fgsm and pgd attacks".format(datetime.now())) diff --git a/case_studies/kwta/__init__.py b/case_studies/kwta/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/case_studies/kwta/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/case_studies/kwta/all.sh b/case_studies/kwta/all.sh new file mode 100644 index 0000000..200d7ba --- /dev/null +++ b/case_studies/kwta/all.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +./case_studies/kwta/single_kwta.sh $1 $2 $3 4 +./case_studies/kwta/single_kwta.sh $1 $2 $3 6 +./case_studies/kwta/single_kwta.sh $1 $2 $3 8 \ No newline at end of file diff --git a/case_studies/kwta/binarization_test.sh b/case_studies/kwta/binarization_test.sh new file mode 100644 index 0000000..e1e2843 --- /dev/null +++ b/case_studies/kwta/binarization_test.sh @@ -0,0 +1,61 @@ +nsamples=${1:-512} +epsilon=${2:-8} +attack=${3:-pgd} +sparsity=${4:-1} +echo "Attack: $attack" +echo "Epsilon: $epsilon" +echo "#samples: $nsamples" +echo "Sparsity: $sparsity" + +if [[ "$sparsity" == "1" ]]; then + checkpoint="checkpoints/kwta_sparse_resnet18_0.1.pth" +elif [[ "$sparsity" == "2" ]]; then + checkpoint="checkpoints/kwta_sparse_resnet18_0.2.pth" +else + echo "invalid sparsity" + exit -1 +fi + +if [[ "$attack" == "kwta" ]]; then + kwargs="--no-ce-loss" +else + kwargs="--no-logit-diff-loss" +fi + +kwargs="$kwargs --dbl-sample-from-corners" + +echo "kwargs: $kwargs" + +if [[ "$epsilon" == "8" ]]; then + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + echo "[Linf, 8/255] kWTA (${checkpoint}) evaluation" + PYTHONPATH=$PYTHONPATH:$(pwd) python case_studies/evaluate_classifier.py $basecommand \ + --classifier="case_studies.kwta.resnet.sparse_resnet18_0$sparsity" \ + --decision-boundary-binarization="norm=linf epsilon=0.031372549 n_inner_points=999 n_boundary_points=1 \ + optimizer=sklearn adversarial_attack_settings=\"norm=linf epsilon=0.031372549 step_size=0.0011372549 n_steps=200 attack=$attack\"" \ + --input=$checkpoint \ + $kwargs + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +elif [[ "$epsilon" == "6" ]]; then + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + echo "[Linf, 6/255] kWTA (${checkpoint}) evaluation" + PYTHONPATH=$PYTHONPATH:$(pwd) python case_studies/evaluate_classifier.py $basecommand \ + --classifier="case_studies.kwta.resnet.sparse_resnet18_0$sparsity" \ + --decision-boundary-binarization="norm=linf epsilon=0.02352941176 n_inner_points=999 n_boundary_points=1 \ + optimizer=sklearn adversarial_attack_settings=\"norm=linf epsilon=0.02352941176 step_size=0.0011372549 n_steps=200 attack=$attack\"" \ + --input=$checkpoint \ + $kwargs + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +elif [[ "$epsilon" == "4" ]]; then + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + echo "[Linf, 4/255] kWTA (${checkpoint}) evaluation" + PYTHONPATH=$PYTHONPATH:$(pwd) python case_studies/evaluate_classifier.py $basecommand \ + --classifier="case_studies.kwta.resnet.sparse_resnet18_0$sparsity" \ + --decision-boundary-binarization="norm=linf epsilon=0.0156862745 n_inner_points=999 n_boundary_points=1 \ + optimizer=sklearn adversarial_attack_settings=\"norm=linf epsilon=0.0156862745 step_size=0.0011372549 n_steps=200 attack=$attack\"" \ + --input=$checkpoint \ + $kwargs + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +else + echo "Unknown epsilon value: $epsilon" +fi \ No newline at end of file diff --git a/case_studies/kwta/models.py b/case_studies/kwta/models.py new file mode 100644 index 0000000..6b38ec8 --- /dev/null +++ b/case_studies/kwta/models.py @@ -0,0 +1,201 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +# From https://github.com/a554b554/kWTA-Activation + +import torch +import torch.nn as nn + + +class Flatten(nn.Module): + def forward(self, x): + return x.view(x.shape[0], -1) + + +class SparsifyBase(nn.Module): + def __init__(self, sparse_ratio=0.5): + super(SparsifyBase, self).__init__() + self.sr = sparse_ratio + self.preact = None + self.act = None + + def get_activation(self): + def hook(model, input, output): + self.preact = input[0].cpu().detach().clone() + self.act = output.cpu().detach().clone() + + return hook + + def record_activation(self): + self.register_forward_hook(self.get_activation()) + + +class Sparsify1D(SparsifyBase): + def __init__(self, sparse_ratio=0.5): + super(Sparsify1D, self).__init__() + self.sr = sparse_ratio + + def forward(self, x): + k = int(self.sr * x.shape[1]) + topval = x.topk(k, dim=1)[0][:, -1] + topval = topval.expand(x.shape[1], x.shape[0]).permute(1, 0) + comp = (x >= topval).to(x) + return comp * x + + +class Sparsify1D_kactive(SparsifyBase): + def __init__(self, k=1): + super(Sparsify1D_kactive, self).__init__() + self.k = k + + def forward(self, x): + k = self.k + topval = x.topk(k, dim=1)[0][:, -1] + topval = topval.expand(x.shape[1], x.shape[0]).permute(1, 0) + comp = (x >= topval).to(x) + return comp * x + + +class Sparsify2D(SparsifyBase): + def __init__(self, sparse_ratio=0.5): + super(Sparsify2D, self).__init__() + self.sr = sparse_ratio + + self.preact = None + self.act = None + + def forward(self, x): + layer_size = x.shape[2] * x.shape[3] + k = int(self.sr * layer_size) + tmpx = x.view(x.shape[0], x.shape[1], -1) + topval = tmpx.topk(k, dim=2)[0][:, :, -1] + topval = topval.expand(x.shape[2], x.shape[3], x.shape[0], + x.shape[1]).permute(2, 3, 0, 1) + comp = (x >= topval).to(x) + return comp * x + + +class Sparsify2D_vol(SparsifyBase): + '''cross channel sparsify''' + + def __init__(self, sparse_ratio=0.5): + super(Sparsify2D_vol, self).__init__() + self.sr = sparse_ratio + + def forward(self, x): + size = x.shape[1] * x.shape[2] * x.shape[3] + k = int(self.sr * size) + + tmpx = x.view(x.shape[0], -1) + topval = tmpx.topk(k, dim=1)[0][:, -1] + topval = topval.repeat(tmpx.shape[1], 1).permute(1, 0).view_as(x) + comp = (x >= topval).to(x) + return comp * x + + +class Sparsify2D_kactive(SparsifyBase): + '''cross channel sparsify''' + + def __init__(self, k): + super(Sparsify2D_vol, self).__init__() + self.k = k + + def forward(self, x): + k = self.k + tmpx = x.view(x.shape[0], -1) + topval = tmpx.topk(k, dim=1)[0][:, -1] + topval = topval.repeat(tmpx.shape[1], 1).permute(1, 0).view_as(x) + comp = (x >= topval).to(x) + return comp * x + + +class Sparsify2D_abs(SparsifyBase): + def __init__(self, sparse_ratio=0.5): + super(Sparsify2D_abs, self).__init__() + self.sr = sparse_ratio + + def forward(self, x): + layer_size = x.shape[2] * x.shape[3] + k = int(self.sr * layer_size) + absx = torch.abs(x) + tmpx = absx.view(absx.shape[0], absx.shape[1], -1) + topval = tmpx.topk(k, dim=2)[0][:, :, -1] + topval = topval.expand(absx.shape[2], absx.shape[3], absx.shape[0], + absx.shape[1]).permute(2, 3, 0, 1) + comp = (absx >= topval).to(x) + return comp * x + + +class Sparsify2D_invabs(SparsifyBase): + def __init__(self, sparse_ratio=0.5): + super(Sparsify2D_invabs, self).__init__() + self.sr = sparse_ratio + + def forward(self, x): + layer_size = x.shape[2] * x.shape[3] + k = int(self.sr * layer_size) + absx = torch.abs(x) + tmpx = absx.view(absx.shape[0], absx.shape[1], -1) + topval = tmpx.topk(k, dim=2, largest=False)[0][:, :, -1] + topval = topval.expand(absx.shape[2], absx.shape[3], absx.shape[0], + absx.shape[1]).permute(2, 3, 0, 1) + comp = (absx >= topval).to(x) + return comp * x + + +class breakReLU(nn.Module): + def __init__(self, sparse_ratio=5): + super(breakReLU, self).__init__() + self.h = sparse_ratio + self.thre = nn.Threshold(0, -self.h) + + def forward(self, x): + return self.thre(x) + + +class SmallCNN(nn.Module): + def __init__(self, fc_in=3136, n_classes=10): + super(SmallCNN, self).__init__() + + self.module_list = nn.ModuleList([nn.Conv2d(1, 32, 3, padding=1), nn.ReLU(), + nn.Conv2d(32, 32, 3, padding=1, stride=2), + nn.ReLU(), + nn.Conv2d(32, 64, 3, padding=1), + nn.ReLU(), + nn.Conv2d(64, 64, 3, padding=1, stride=2), + nn.ReLU(), + Flatten(), + nn.Linear(fc_in, 100), nn.ReLU(), + nn.Linear(100, n_classes)]) + + def forward(self, x): + for i in range(len(self.module_list)): + x = self.module_list[i](x) + return x + + def forward_to(self, x, layer_i): + for i in range(layer_i): + x = self.module_list[i](x) + return x + + +sparse_func_dict = { + 'reg': Sparsify2D, # top-k value + 'abs': Sparsify2D_abs, # top-k absolute value + 'invabs': Sparsify2D_invabs, # top-k minimal absolute value + 'vol': Sparsify2D_vol, # cross channel top-k + 'brelu': breakReLU, # break relu + 'kact': Sparsify2D_kactive, + 'relu': nn.ReLU +} diff --git a/case_studies/kwta/original/__init__.py b/case_studies/kwta/original/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/case_studies/kwta/original/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/case_studies/kwta/original/kWTA/.gitignore b/case_studies/kwta/original/kWTA/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/case_studies/kwta/original/kWTA/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/case_studies/kwta/original/kWTA/__init__.py b/case_studies/kwta/original/kWTA/__init__.py new file mode 100644 index 0000000..6cf2daf --- /dev/null +++ b/case_studies/kwta/original/kWTA/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + diff --git a/case_studies/kwta/original/kWTA/activation.py b/case_studies/kwta/original/kWTA/activation.py new file mode 100644 index 0000000..05a50f1 --- /dev/null +++ b/case_studies/kwta/original/kWTA/activation.py @@ -0,0 +1,275 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import torch +import torch.nn as nn +import numpy as np +from kWTA import models +import copy + +def register_layers(activation_list): + for layer in activation_list: + layer.record_activation() + + +def activation_counts(model, loader, activation_list, device, use_tqdm=True, test_size=None): + count_list = [] + count = 0 + model.to(device) + if use_tqdm: + if test_size is not None: + pbar = tqdm(total=test_size) + else: + pbar = tqdm(total=len(loader.dataset)) + + for i, (X, y) in enumerate(loader): + X = X.to(device) + _ = model(X) + for j, layer in enumerate(activation_list): + act = layer.act + batch_size = act.shape[0] + if len(count_list) <= j: + count_list.append(torch.zeros_like(act[0,:])) + mask = (act!=0).to(act) + mask_sum = mask.sum(dim=0) + count_list[j] += mask_sum + count += X.shape[0] + if test_size is not None: + if count >= test_size: + break + + if use_tqdm: + pbar.update(X.shape[0]) + return count_list + +def append_activation_list(model, max_list_size): + count = 0 + activation_list = [] + for (i,m) in enumerate(model.modules()): + if isinstance(m, models.SparsifyBase): + count += 1 + activation_list.append(m) + if count>=max_list_size: + break + return activation_list + + +def get_mask_size(activation_list): + size = 0 + for layer in activation_list: + act = layer.act + act = act.view(act.shape[0], -1) + size += act.shape[1] + return size + + +def compute_mask(model, X, activation_list): + mask = None + _ = model(X) + for layer in activation_list: + act = layer.act + act = act.view(X.shape[0], -1) + act_mask = act>0 + if mask is None: + mask = act_mask + else: + mask = torch.cat((mask, act_mask), dim=1) + return mask.to(dtype=torch.float32) + +def compute_networkmask(model, loader, activation_list, device, max_n=None): + model.to(device) + all_label = None + count = 0 + for i, (X,y) in enumerate(loader): + X, y = X.to(device), y.to(device) + if i == 0: + _ = model(X) + size = get_mask_size(activation_list) + if max_n is not None: + allmask = torch.zeros(max_n, size, dtype=torch.float32) + else: + allmask = torch.zeros(len(loader.dataset), size, dtype=torch.float32) + current_mask = compute_mask(model, X, activation_list) + allmask[i*X.shape[0]:(i+1)*X.shape[0], :].copy_(current_mask) + + + current_sum = current_mask.sum().item() + all_sum = allmask.sum().item() + + print('current mask:', current_sum, current_sum/current_mask.numel()) + print(i,'/',len(loader), all_sum , all_sum/allmask.numel()) + + if all_label is None: + all_label = y + else: + all_label = torch.cat((all_label, y)) + + count += X.shape[0] + if max_n is not None: + if count>= max_n: + break + + return allmask, all_label.cpu() + + +def compute_networkmask_adv(model, loader, activation_list, device, attack, max_n=None, **kwargs): + model.to(device) + all_label = None + count = 0 + for i, (X,y) in enumerate(loader): + X, y = X.to(device), y.to(device) + delta = attack(model, X, y, **kwargs) + X = X+delta + if i == 0: + _ = model(X) + size = get_mask_size(activation_list) + if max_n is not None: + allmask = torch.zeros(max_n, size, dtype=torch.float32) + else: + allmask = torch.zeros(len(loader.dataset), size, dtype=torch.float32) + current_mask = compute_mask(model, X, activation_list, size) + allmask[i*X.shape[0]:(i+1)*X.shape[0], :].copy_(current_mask) + + + current_sum = current_mask.sum().item() + all_sum = allmask.sum().item() + + print('current mask:', current_sum, current_sum/current_mask.numel()) + print(i,'/',len(loader), all_sum , all_sum/allmask.numel()) + + if all_label is None: + all_label = y + else: + all_label = torch.cat((all_label, y)) + + count += X.shape[0] + if max_n is not None: + if count>= max_n: + break + + return allmask, all_label.cpu() + +def kNN(model, labels, X, k, device, test_labels): + model = model.to(device) + X = X.to(device) + correct = 0 + total = 0 + for i in range(X.shape[0]): + x0 = X[i, :] + sub = model-x0 + dist = torch.norm(sub, p=1, dim=1) + mindist, idx = torch.topk(dist, k, largest=False) + print('mindist', mindist.item(), 'predict label:', labels[idx].item(), 'true label:', test_labels[i].item()) + if labels[idx]==test_labels[i]: + correct+=1 + total+=1 + return correct/total + + +def dist_stats1(loader, model, activation_list, class1, class2, n_test): + + dists = [] + for i, (X, y) in enumerate(loader): + _ = model(X) + print('batch', i, 'dists', len(dists)) + spl = int(X.shape[0]/2) + mask = compute_mask(model, X, activation_list, get_mask_size(activation_list)) + for id1 in range(spl): + if y[id1].item() != class1: + continue + for id2 in range(spl, spl*2): + if y[id2].item() != class2: + continue + dist = torch.norm(mask[id1,:]-mask[id2,:], p=1) + dists.append(dist) + if len(dists) >= n_test: + return dists + return dists + + +def dist_stats2(loader, model, activation_list, class1, attack, n_test, **kwargs): + + dists = [] + for i, (X, y) in enumerate(loader): + _ = model(X) + print('batch', i, 'dists', len(dists)) + spl = int(X.shape[0]) + mask = compute_mask(model, X, activation_list, get_mask_size(activation_list)) + delta = attack(model, X, y, **kwargs) + X_adv = X+delta + _ = model(X_adv) + mask_adv = compute_mask(model, X_adv, activation_list, get_mask_size(activation_list)) + for id1 in range(spl): + if y[id1].item() != class1: + continue + dist = torch.norm(mask[id1,:]-mask_adv[id1,:], p=1) + dists.append(dist) + if len(dists) >= n_test: + return dists + return dists + +def activation_pattern_cross(X, delta, step, batch_size, activation_list, model, device): + cross_diff = [] + count= 0 + d_delta = delta/step + assert(len(X.shape)==3) + assert(step % batch_size == 0) + model.to(device) + while 1: + T = torch.zeros(batch_size, X.shape[0], X.shape[1], X.shape[2]) + for i in range(batch_size): + T[i,:,:,:] = X + count*d_delta + count += 1 + T = T.to(device) + mask = compute_mask(model, T, activation_list) + for i in range(mask.shape[0]-1): + diff = torch.norm(mask[i+1,:]-mask[i,:], p=1) + cross_diff.append(diff.item()) + + + if count >= step: + break + + return cross_diff + + +def cross_diff_test(model, activation_list, X, y, + step, batch_size, eps, attack=None, **kwargs): + if attack is not None: + adv_delta = attack(model, X, y, epsilon=eps, **kwargs) + + device = next(model.parameters()).device + + stats0 = [] + stats5 = [] + stats10 = [] + + for i in range(X.shape[0]): + X0 = X[i,:,:,:] + if attack is None: + delta = torch.rand_like(X0) + delta = delta.clamp(-eps, eps) + else: + delta = adv_delta[i,:,:,:].detach().cpu() + cross_diff = activation_pattern_cross(X0, delta, device=device, step=step, + batch_size=batch_size, activation_list=activation_list, model=model) + cross_diff = torch.FloatTensor(cross_diff) + crossed = (cross_diff>0).sum().item() + stats0.append(crossed) + crossed = (cross_diff>5).sum().item() + stats5.append(crossed) + crossed = (cross_diff>10).sum().item() + stats10.append(crossed) + + return torch.FloatTensor(stats0),torch.FloatTensor(stats5),torch.FloatTensor(stats10) \ No newline at end of file diff --git a/case_studies/kwta/original/kWTA/models.py b/case_studies/kwta/original/kWTA/models.py new file mode 100644 index 0000000..6b38ec8 --- /dev/null +++ b/case_studies/kwta/original/kWTA/models.py @@ -0,0 +1,201 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +# From https://github.com/a554b554/kWTA-Activation + +import torch +import torch.nn as nn + + +class Flatten(nn.Module): + def forward(self, x): + return x.view(x.shape[0], -1) + + +class SparsifyBase(nn.Module): + def __init__(self, sparse_ratio=0.5): + super(SparsifyBase, self).__init__() + self.sr = sparse_ratio + self.preact = None + self.act = None + + def get_activation(self): + def hook(model, input, output): + self.preact = input[0].cpu().detach().clone() + self.act = output.cpu().detach().clone() + + return hook + + def record_activation(self): + self.register_forward_hook(self.get_activation()) + + +class Sparsify1D(SparsifyBase): + def __init__(self, sparse_ratio=0.5): + super(Sparsify1D, self).__init__() + self.sr = sparse_ratio + + def forward(self, x): + k = int(self.sr * x.shape[1]) + topval = x.topk(k, dim=1)[0][:, -1] + topval = topval.expand(x.shape[1], x.shape[0]).permute(1, 0) + comp = (x >= topval).to(x) + return comp * x + + +class Sparsify1D_kactive(SparsifyBase): + def __init__(self, k=1): + super(Sparsify1D_kactive, self).__init__() + self.k = k + + def forward(self, x): + k = self.k + topval = x.topk(k, dim=1)[0][:, -1] + topval = topval.expand(x.shape[1], x.shape[0]).permute(1, 0) + comp = (x >= topval).to(x) + return comp * x + + +class Sparsify2D(SparsifyBase): + def __init__(self, sparse_ratio=0.5): + super(Sparsify2D, self).__init__() + self.sr = sparse_ratio + + self.preact = None + self.act = None + + def forward(self, x): + layer_size = x.shape[2] * x.shape[3] + k = int(self.sr * layer_size) + tmpx = x.view(x.shape[0], x.shape[1], -1) + topval = tmpx.topk(k, dim=2)[0][:, :, -1] + topval = topval.expand(x.shape[2], x.shape[3], x.shape[0], + x.shape[1]).permute(2, 3, 0, 1) + comp = (x >= topval).to(x) + return comp * x + + +class Sparsify2D_vol(SparsifyBase): + '''cross channel sparsify''' + + def __init__(self, sparse_ratio=0.5): + super(Sparsify2D_vol, self).__init__() + self.sr = sparse_ratio + + def forward(self, x): + size = x.shape[1] * x.shape[2] * x.shape[3] + k = int(self.sr * size) + + tmpx = x.view(x.shape[0], -1) + topval = tmpx.topk(k, dim=1)[0][:, -1] + topval = topval.repeat(tmpx.shape[1], 1).permute(1, 0).view_as(x) + comp = (x >= topval).to(x) + return comp * x + + +class Sparsify2D_kactive(SparsifyBase): + '''cross channel sparsify''' + + def __init__(self, k): + super(Sparsify2D_vol, self).__init__() + self.k = k + + def forward(self, x): + k = self.k + tmpx = x.view(x.shape[0], -1) + topval = tmpx.topk(k, dim=1)[0][:, -1] + topval = topval.repeat(tmpx.shape[1], 1).permute(1, 0).view_as(x) + comp = (x >= topval).to(x) + return comp * x + + +class Sparsify2D_abs(SparsifyBase): + def __init__(self, sparse_ratio=0.5): + super(Sparsify2D_abs, self).__init__() + self.sr = sparse_ratio + + def forward(self, x): + layer_size = x.shape[2] * x.shape[3] + k = int(self.sr * layer_size) + absx = torch.abs(x) + tmpx = absx.view(absx.shape[0], absx.shape[1], -1) + topval = tmpx.topk(k, dim=2)[0][:, :, -1] + topval = topval.expand(absx.shape[2], absx.shape[3], absx.shape[0], + absx.shape[1]).permute(2, 3, 0, 1) + comp = (absx >= topval).to(x) + return comp * x + + +class Sparsify2D_invabs(SparsifyBase): + def __init__(self, sparse_ratio=0.5): + super(Sparsify2D_invabs, self).__init__() + self.sr = sparse_ratio + + def forward(self, x): + layer_size = x.shape[2] * x.shape[3] + k = int(self.sr * layer_size) + absx = torch.abs(x) + tmpx = absx.view(absx.shape[0], absx.shape[1], -1) + topval = tmpx.topk(k, dim=2, largest=False)[0][:, :, -1] + topval = topval.expand(absx.shape[2], absx.shape[3], absx.shape[0], + absx.shape[1]).permute(2, 3, 0, 1) + comp = (absx >= topval).to(x) + return comp * x + + +class breakReLU(nn.Module): + def __init__(self, sparse_ratio=5): + super(breakReLU, self).__init__() + self.h = sparse_ratio + self.thre = nn.Threshold(0, -self.h) + + def forward(self, x): + return self.thre(x) + + +class SmallCNN(nn.Module): + def __init__(self, fc_in=3136, n_classes=10): + super(SmallCNN, self).__init__() + + self.module_list = nn.ModuleList([nn.Conv2d(1, 32, 3, padding=1), nn.ReLU(), + nn.Conv2d(32, 32, 3, padding=1, stride=2), + nn.ReLU(), + nn.Conv2d(32, 64, 3, padding=1), + nn.ReLU(), + nn.Conv2d(64, 64, 3, padding=1, stride=2), + nn.ReLU(), + Flatten(), + nn.Linear(fc_in, 100), nn.ReLU(), + nn.Linear(100, n_classes)]) + + def forward(self, x): + for i in range(len(self.module_list)): + x = self.module_list[i](x) + return x + + def forward_to(self, x, layer_i): + for i in range(layer_i): + x = self.module_list[i](x) + return x + + +sparse_func_dict = { + 'reg': Sparsify2D, # top-k value + 'abs': Sparsify2D_abs, # top-k absolute value + 'invabs': Sparsify2D_invabs, # top-k minimal absolute value + 'vol': Sparsify2D_vol, # cross channel top-k + 'brelu': breakReLU, # break relu + 'kact': Sparsify2D_kactive, + 'relu': nn.ReLU +} diff --git a/case_studies/kwta/original/kWTA/resnet.py b/case_studies/kwta/original/kWTA/resnet.py new file mode 100644 index 0000000..200a258 --- /dev/null +++ b/case_studies/kwta/original/kWTA/resnet.py @@ -0,0 +1,329 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +from torch.optim import lr_scheduler +from torchvision import datasets, transforms +import torchvision +from kWTA import models + +class BasicBlock(nn.Module): + expansion = 1 + + def __init__(self, in_planes, planes, stride=1): + super(BasicBlock, self).__init__() + self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) + self.bn1 = nn.BatchNorm2d(planes) + self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False) + self.bn2 = nn.BatchNorm2d(planes) + self.shortcut = nn.Sequential() + if stride != 1 or in_planes != self.expansion*planes: + self.shortcut = nn.Sequential( + nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False), + nn.BatchNorm2d(self.expansion*planes) + ) + + def forward(self, x): + out = F.relu(self.bn1(self.conv1(x))) + out = self.bn2(self.conv2(out)) + out += self.shortcut(x) + out = F.relu(out) + return out + +class SparseBasicBlock(nn.Module): + expansion = 1 + def __init__(self, in_planes, planes, stride=1, sparsity=0.5, use_relu=True, sparse_func='reg', bias=False): + super(SparseBasicBlock, self).__init__() + self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=bias) + self.bn1 = nn.BatchNorm2d(planes) + self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=bias) + self.bn2 = nn.BatchNorm2d(planes) + self.use_relu = use_relu + self.sparse1 = models.sparse_func_dict[sparse_func](sparsity) + self.sparse2 = models.sparse_func_dict[sparse_func](sparsity) + self.relu = nn.ReLU() + + self.shortcut = nn.Sequential() + if stride != 1 or in_planes != self.expansion*planes: + self.shortcut = nn.Sequential( + nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=bias), + nn.BatchNorm2d(self.expansion*planes) + ) + + def forward(self, x): + out = self.bn1(self.conv1(x)) + if self.use_relu: + out = self.relu(out) + out = self.sparse1(out) + out = self.bn2(self.conv2(out)) + out += self.shortcut(x) + if self.use_relu: + out = self.relu(out) + out = self.sparse2(out) + return out + + +class Bottleneck(nn.Module): + expansion = 4 + def __init__(self, in_planes, planes, stride=1, bias=True): + super(Bottleneck, self).__init__() + self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=bias) + self.bn1 = nn.BatchNorm2d(planes) + self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=bias) + self.bn2 = nn.BatchNorm2d(planes) + self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=bias) + self.bn3 = nn.BatchNorm2d(self.expansion*planes) + self.relu = nn.ReLU() + self.shortcut = nn.Sequential() + if stride != 1 or in_planes != self.expansion*planes: + self.shortcut = nn.Sequential( + nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=bias), + nn.BatchNorm2d(self.expansion*planes) + ) + + def forward(self, x): + out = self.relu(self.bn1(self.conv1(x))) + out = self.relu(self.bn2(self.conv2(out))) + out = self.bn3(self.conv3(out)) + out += self.shortcut(x) + out = self.relu(out) + return out + +class SparseBottleneck(nn.Module): + expansion = 4 + + def __init__(self, in_planes, planes, stride=1, sparsity=0.5, use_relu=True, sparse_func='reg', bias=True): + super(SparseBottleneck, self).__init__() + self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=bias) + self.bn1 = nn.BatchNorm2d(planes) + self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=bias) + self.bn2 = nn.BatchNorm2d(planes) + self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=bias) + self.bn3 = nn.BatchNorm2d(self.expansion*planes) + self.relu = nn.ReLU() + + self.sparse1 = models.sparse_func_dict[sparse_func](sparsity) + self.sparse2 = models.sparse_func_dict[sparse_func](sparsity) + self.sparse3 = models.sparse_func_dict[sparse_func](sparsity) + + self.use_relu = use_relu + + self.shortcut = nn.Sequential() + if stride != 1 or in_planes != self.expansion*planes: + self.shortcut = nn.Sequential( + nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=bias), + nn.BatchNorm2d(self.expansion*planes) + ) + + def forward(self, x): + out = self.bn1(self.conv1(x)) + if self.use_relu: + out = self.relu(out) + out = self.sparse1(out) + + out = self.bn2(self.conv2(out)) + if self.use_relu: + out = self.relu(out) + out = self.sparse2(out) + + out = self.bn3(self.conv3(out)) + out += self.shortcut(x) + + if self.use_relu: + out = self.relu(out) + out = self.sparse3(out) + return out + + +class SparseResNet(nn.Module): + def __init__(self, block, num_blocks, sparsities, num_classes=10, use_relu=True, sparse_func='reg', bias=True): + super(SparseResNet, self).__init__() + self.in_planes = 64 + self.use_relu = use_relu + + + self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=bias) + self.bn1 = nn.BatchNorm2d(64) + self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1, sparsity=sparsities[0], sparse_func=sparse_func, bias=bias) + self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2, sparsity=sparsities[1], sparse_func=sparse_func, bias=bias) + self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2, sparsity=sparsities[2], sparse_func=sparse_func, bias=bias) + self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2, sparsity=sparsities[3], sparse_func=sparse_func, bias=bias) + self.linear = nn.Linear(512*block.expansion, num_classes) + + self.relu = nn.ReLU() + + self.activation = {} + + + def get_activation(self, name): + def hook(model, input, output): + self.activation[name] = output.cpu().detach() + return hook + + def register_layer(self, layer, name): + layer.register_forward_hook(self.get_activation(name)) + + def _make_layer(self, block, planes, num_blocks, stride, sparsity=0.5, sparse_func='reg', bias=True): + strides = [stride] + [1]*(num_blocks-1) + layers = [] + for stride in strides: + layers.append(block(self.in_planes, planes, stride, sparsity, self.use_relu, sparse_func=sparse_func, bias=bias)) + self.in_planes = planes * block.expansion + return nn.Sequential(*layers) + + def forward(self, x): + out = self.relu(self.bn1(self.conv1(x))) + out = self.layer1(out) + out = self.layer2(out) + out = self.layer3(out) + out = self.layer4(out) + out = F.avg_pool2d(out, 4) + out = out.view(out.size(0), -1) + out = self.linear(out) + return out + + +class SparseResNet_ImageNet(nn.Module): + def __init__(self, block, num_blocks, sparsities, num_classes=1000, sparse_func='vol', bias=False): + super(SparseResNet_ImageNet, self).__init__() + self.in_planes = 64 + + + self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=bias) + self.bn1 = nn.BatchNorm2d(64) + self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1, sparsity=sparsities[0], sparse_func=sparse_func, bias=bias) + self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2, sparsity=sparsities[1], sparse_func=sparse_func, bias=bias) + self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2, sparsity=sparsities[2], sparse_func=sparse_func, bias=bias) + self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2, sparsity=sparsities[3], sparse_func=sparse_func, bias=bias) + self.linear = nn.Linear(512*block.expansion, num_classes) + + self.sp = models.sparse_func_dict[sparse_func](sparsities[0]) + + self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) + + self.activation = {} + + + def get_activation(self, name): + def hook(model, input, output): + self.activation[name] = output.cpu().detach() + return hook + + def register_layer(self, layer, name): + layer.register_forward_hook(self.get_activation(name)) + + def _make_layer(self, block, planes, num_blocks, stride, sparsity=0.5, sparse_func='reg', bias=True): + strides = [stride] + [1]*(num_blocks-1) + layers = [] + for stride in strides: + layers.append(block(self.in_planes, planes, stride, sparsity, use_relu=False, sparse_func=sparse_func, bias=bias)) + self.in_planes = planes * block.expansion + return nn.Sequential(*layers) + + def forward(self, x): + out = self.sp(self.bn1(self.conv1(x))) + out = self.layer1(out) + out = self.layer2(out) + out = self.layer3(out) + out = self.layer4(out) + out = self.avgpool(out) + out = out.view(out.size(0), -1) + out = self.linear(out) + return out + +class ResNet(nn.Module): + def __init__(self, block, num_blocks, num_classes=10): + super(ResNet, self).__init__() + self.in_planes = 64 + + self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False) + self.bn1 = nn.BatchNorm2d(64) + self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1) + self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2) + self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2) + self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2) + self.linear = nn.Linear(512*block.expansion, num_classes) + + self.relu = nn.ReLU() + + + self.activation = {} + + + def get_activation(self, name): + def hook(model, input, output): + self.activation[name] = output.cpu().detach() + return hook + + def register_layer(self, layer, name): + layer.register_forward_hook(self.get_activation(name)) + + def _make_layer(self, block, planes, num_blocks, stride): + strides = [stride] + [1]*(num_blocks-1) + layers = [] + for stride in strides: + layers.append(block(self.in_planes, planes, stride)) + self.in_planes = planes * block.expansion + return nn.Sequential(*layers) + + def forward(self, x): + out = self.relu(self.bn1(self.conv1(x))) + out = self.layer1(out) + out = self.layer2(out) + out = self.layer3(out) + out = self.layer4(out) + out = F.avg_pool2d(out, 4) + out = out.view(out.size(0), -1) + out = self.linear(out) + return out + + + +def ResNet18(): + return ResNet(BasicBlock, [2,2,2,2]) + +def ResNet34(): + return ResNet(BasicBlock, [3,4,6,3]) + +def ResNet50(): + return ResNet(Bottleneck, [3,4,6,3]) + +def ResNet101(): + return ResNet(Bottleneck, [3,4,23,3]) + +def ResNet152(): + return ResNet(Bottleneck, [3,8,36,3]) + +def SparseResNet18(relu=False, sparsities=[0.5,0.4,0.3,0.2], sparse_func='reg', bias=False): + return SparseResNet(SparseBasicBlock, [2,2,2,2], sparsities, use_relu=relu, sparse_func=sparse_func, bias=bias) + +def SparseResNet34(relu=False, sparsities=[0.5,0.4,0.3,0.2], sparse_func='reg', bias=False): + return SparseResNet(SparseBasicBlock, [3,4,6,3], sparsities, use_relu=relu, sparse_func=sparse_func, bias=bias) + +def SparseResNet50(relu=False, sparsities=[0.5,0.4,0.3,0.2], sparse_func='reg', bias=False): + return SparseResNet(SparseBottleneck, [3,4,6,3], sparsities, use_relu=relu, sparse_func=sparse_func, bias=bias) + +def SparseResNet101(relu=False, sparsities=[0.5,0.4,0.3,0.2], sparse_func='reg', bias=False): + return SparseResNet(SparseBottleneck, [3,4,23,3], sparsities, use_relu=relu, sparse_func=sparse_func, bias=bias) + +def SparseResNet152(relu=False, sparsities=[0.5,0.4,0.3,0.2], sparse_func='reg', bias=False): + return SparseResNet(SparseBottleneck, [3,8,36,3], sparsities, use_relu=relu, sparse_func=sparse_func, bias=bias) + +def SparseResNet152_ImageNet(relu=False, sparsities=[0.5,0.4,0.3,0.2], sparse_func='reg', bias=False): + return SparseResNet_ImageNet(SparseBottleneck, [3,8,36,3], sparsities, sparse_func=sparse_func, bias=bias) + +########### End resnet related ################## \ No newline at end of file diff --git a/case_studies/kwta/original/kWTA/training.py b/case_studies/kwta/original/kWTA/training.py new file mode 100644 index 0000000..dfa8076 --- /dev/null +++ b/case_studies/kwta/original/kWTA/training.py @@ -0,0 +1,612 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import time +import os +import argparse +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +from torch.optim import lr_scheduler +from torchvision import datasets, transforms +import torchvision +from torch.autograd import Variable + +def isnotebook(): + try: + shell = get_ipython().__class__.__name__ + if shell == 'ZMQInteractiveShell': + return True # Jupyter notebook or qtconsole + elif shell == 'TerminalInteractiveShell': + return False # Terminal running IPython + else: + return False # Other type (?) + except NameError: + return False # Probably standard Python interpreter + +if isnotebook(): + from tqdm import tqdm_notebook as tqdm +else: + from tqdm import tqdm + + +def epoch(loader, model, opt=None, device=None, use_tqdm=False): + """Standard training/evaluation epoch over the dataset""" + total_loss, total_err = 0.,0. + if opt is None: + model.eval() + else: + model.train() + + if use_tqdm: + pbar = tqdm(total=len(loader)) + + for X,y in loader: + X,y = X.to(device), y.to(device) + + + yp = model(X) + loss = nn.CrossEntropyLoss()(yp,y) + if opt: + opt.zero_grad() + loss.backward() + opt.step() + + total_err += (yp.max(dim=1)[1] != y).sum().item() + total_loss += loss.item() * X.shape[0] + + if use_tqdm: + pbar.update(1) + + return total_err / len(loader.dataset), total_loss / len(loader.dataset) + + +def epoch_imagenet(loader, model, opt=None, device=None, use_tqdm=False): + total_loss, total_err_top1, total_err_top5 = 0., 0., 0. + + if opt is None: + model.eval() + + if use_tqdm: + pbar = tqdm(total=len(loader)) + + model.to(device) + for X,y in loader: + X,y = X.to(device), y.to(device) + + yp = model(X) + loss = nn.CrossEntropyLoss()(yp, y) + if opt: + opt.zero_grad() + loss.backward() + opt.step() + + total_err_top1 += (yp.max(dim=1)[1] != y).sum().item() + + _, pred = yp.topk(5, dim=1, sorted=True, largest=True) + pred = pred.t() + total_err_top5 += pred.eq(y.view(1,-1).expand_as(pred)).sum().item() + + total_loss += loss.item()*X.shape[0] + + if use_tqdm: + pbar.update(1) + + return total_err_top1/len(loader.dataset), total_err_top5/len(loader.dataset), total_loss/len(loader.dataset) + +def epoch_imagenet_adversarial(loader, model, device, attack, use_tqdm=False, n_test=None, **kwargs): + """Adversarial training/evaluation epoch over the dataset""" + total_loss, total_err_top1, total_err_top5 = 0., 0., 0. + + + if use_tqdm: + if n_test is None: + pbar = tqdm(total=len(loader.dataset)) + else: + pbar = tqdm(total=n_test) + + + total_n = 0 + model.to(device) + for X,y in loader: + X,y = X.to(device), y.to(device) + delta = attack(model, X, y, **kwargs) + yp = model(X+delta) + loss = nn.CrossEntropyLoss()(yp,y) + + total_err_top1 += (yp.max(dim=1)[1] != y).sum().item() + _, pred = yp.topk(5, dim=1, sorted=True, largest=True) + pred = pred.t() + total_err_top5 += pred.eq(y.view(1,-1).expand_as(pred)).sum().item() + total_loss += loss.item()*X.shape[0] + + if use_tqdm: + pbar.update(X.shape[0]) + + total_n += X.shape[0] + + if n_test is not None: + if total_n >= n_test: + break + + return total_err_top1/total_n, total_err_top5/total_n, total_loss/total_n + + +def epoch_func(loader, model, criterion, opt=None, device=None, use_tqdm=False): + total_loss = 0. + model.to(device) + if use_tqdm: + pbar = tqdm(total=len(loader)) + + for X,y in loader: + X,y = X.to(device), y.to(device) + yp = model(X) + loss = criterion(yp,y) + if opt: + opt.zero_grad() + loss.backward() + opt.step() + + total_loss += loss.item() * X.shape[0] + + if use_tqdm: + pbar.update(1) + + return total_loss / len(loader.dataset) + +def epoch_distill_func(loader, model_teacher, model, device, opt=None, use_tqdm=True, n_test=None, loss_func='mse'): + total_loss, total_err = 0.,0. + total_n = 0 + + model_teacher.to(device) + model.to(device) + + if use_tqdm: + if n_test is None: + pbar = tqdm(total=len(loader.dataset)) + else: + pbar = tqdm(total=n_test) + + for X, y in loader: + X, y = X.to(device), y.to(device) + + teacher_output = model_teacher(X).detach() + output = model(X) + + if loss_func=='mse': + loss = nn.MSELoss()(output, teacher_output) + elif loss_func=='l1': + loss = nn.L1Loss()(output, teacher_output) + elif loss_func=='kl': + loss = nn.KLDivLoss()(F.log_softmax(output, dim=1), + F.softmax(teacher_output, dim=1)) + else: + raise NotImplementedError + + if opt: + opt.zero_grad() + loss.backward() + opt.step() + + total_loss += loss.item() * X.shape[0] + total_n += X.shape[0] + + if use_tqdm: + pbar.update(X.shape[0]) + + if n_test is not None: + if total_n > n_test: + break + + return total_loss/total_n + +def epoch_distill(loader, model_teacher, model, device, opt=None, use_tqdm=True, n_test=None, loss_func='mse'): + total_loss, total_err = 0.,0. + total_n = 0 + + model_teacher.to(device) + model.to(device) + + if use_tqdm: + if n_test is None: + pbar = tqdm(total=len(loader.dataset)) + else: + pbar = tqdm(total=n_test) + + for X, y in loader: + X, y = X.to(device), y.to(device) + + teacher_output = model_teacher(X).detach() + output = model(X) + + if loss_func=='mse': + loss = nn.MSELoss()(output, teacher_output) + elif loss_func=='l1': + loss = nn.L1Loss()(output, teacher_output) + elif loss_func=='kl': + loss = nn.KLDivLoss()(F.log_softmax(output, dim=1), + F.softmax(teacher_output, dim=1)) + else: + raise NotImplementedError + + if opt: + opt.zero_grad() + loss.backward() + opt.step() + + total_err += (output.max(dim=1)[1] != y).sum().item() + total_loss += loss.item() * X.shape[0] + total_n += X.shape[0] + + if use_tqdm: + pbar.update(X.shape[0]) + + if n_test is not None: + if total_n > n_test: + break + + return total_loss/total_n, total_err/total_n + +def epoch_transfer_attack(loader, model_source, model_target, attack, device, success_only=False, use_tqdm=True, n_test=None, **kwargs): + source_err = 0. + target_err = 0. + target_err2 = 0. + + success_total_n = 0 + + + model_source.eval() + model_target.eval() + + total_n = 0 + + if use_tqdm: + pbar = tqdm(total=n_test) + + model_source.to(device) + model_target.to(device) + for X,y in loader: + X,y = X.to(device), y.to(device) + delta = attack(model_source, X, y, **kwargs) + + if success_only: + raise NotImplementedError + else: + yp_target = model_target(X+delta).detach() + yp_source = model_source(X+delta).detach() + yp_origin = model_target(X).detach() + source_err += (yp_source.max(dim=1)[1] != y).sum().item() + target_err += (yp_target.max(dim=1)[1] != y).sum().item() + target_err2 += (yp_origin.max(dim=1)[1] != y).sum().item() + success_total_n += (yp_origin.max(dim=1)[1] == y) + if use_tqdm: + pbar.update(X.shape[0]) + + total_n += X.shape[0] + if n_test is not None: + if total_n >= n_test: + break + + return source_err / total_n, target_err / total_n, target_err2 /total_n + + + # if randomize: + # delta = torch.rand_like(X, requires_grad=True) + # delta.data = delta.data * 2 * epsilon - epsilon + # else: + # delta = torch.zeros_like(X, requires_grad=True) + + # for t in range(num_iter): + # loss = nn.CrossEntropyLoss()(model(X + delta), y) + # loss.backward() + # delta.data = (delta + alpha*delta.grad.detach().sign()).clamp(-epsilon,epsilon) + # delta.grad.zero_() + # return delta.detach() + +def epoch_free_adversarial(loader, model, m, epsilon, opt, device, use_tqdm=False): + """free adversarial training""" + total_loss, total_err = 0.,0. + total_n = 0 + + pbar = tqdm(total=len(loader)) + + + for X,y in loader: + X,y = X.to(device), y.to(device) + delta = torch.zeros_like(X, requires_grad=True) + for i in range(m): + model.train() + yp = model(X+delta) + loss_nn = nn.CrossEntropyLoss()(yp, y) + + total_err += (yp.max(dim=1)[1] != y).sum().item() + total_loss += loss_nn.item() * X.shape[0] + total_n += X.shape[0] + + #update network + opt.zero_grad() + loss_nn.backward() + opt.step() + + #update perturbation + delta.data = delta + epsilon*delta.grad.detach().sign() + delta.data = delta.data.clamp(-epsilon, epsilon) + delta.grad.zero_() + + if use_tqdm: + pbar.update(1) + + return total_err / total_n, total_loss / total_n + + +def epoch_ALP(loader, model, attack, alp_weight=0.5, + opt=None, device=None, use_tqdm=False, n_test=None, **kwargs): + """Adversarial Logit Pairing epoch over the dataset""" + total_loss, total_err = 0.,0. + + # assert(opt is not None) + model.train() + + if use_tqdm: + if n_test is None: + pbar = tqdm(total=len(loader.dataset)) + else: + pbar = tqdm(total=n_test) + total_n = 0 + for X,y in loader: + X,y = X.to(device), y.to(device) + model.eval() + with torch.no_grad(): + clean_logit = model(X) + delta = attack(model, X, y, **kwargs) + + model.train() + yp = model(X+delta) + loss = nn.CrossEntropyLoss()(yp,y) + alp_weight*nn.MSELoss()(yp, clean_logit) + + opt.zero_grad() + loss.backward() + opt.step() + + total_err += (yp.max(dim=1)[1] != y).sum().item() + total_loss += loss.item() * X.shape[0] + if use_tqdm: + pbar.update(X.shape[0]) + + total_n += X.shape[0] + + if n_test is not None: + if total_n >= n_test: + break + + return total_err / total_n, total_loss / total_n + +def epoch_adversarial(loader, model, attack, + opt=None, device=None, use_tqdm=False, n_test=None, **kwargs): + """Adversarial training/evaluation epoch over the dataset""" + total_loss, total_err = 0.,0. + + if opt is None: + model.eval() + else: + model.train() + + if use_tqdm: + if n_test is None: + pbar = tqdm(total=len(loader.dataset)) + else: + pbar = tqdm(total=n_test) + total_n = 0 + for X,y in loader: + X,y = X.to(device), y.to(device) + model.eval() + delta = attack(model, X, y, **kwargs) + if opt: + model.train() + yp = model(X+delta) + loss = nn.CrossEntropyLoss()(yp,y) + if opt: + opt.zero_grad() + loss.backward() + opt.step() + + total_err += (yp.max(dim=1)[1] != y).sum().item() + total_loss += loss.item() * X.shape[0] + if use_tqdm: + pbar.update(X.shape[0]) + + total_n += X.shape[0] + + if n_test is not None: + if total_n >= n_test: + break + + return total_err / total_n, total_loss / total_n + +def get_activation(model, activation, name): + def hook(model, input, output): + activation[name] = output.cpu().detach() + return hook + +def register_layer(model, layer, activation, name): + layer.register_forward_hook(get_activation(model, activation, name)) + + +class AverageMeter(object): + """Computes and stores the average and current value""" + def __init__(self): + self.reset() + + def reset(self): + self.val = 0 + self.avg = 0 + self.sum = 0 + self.count = 0 + + def update(self, val, n=1): + self.val = val + self.sum += val * n + self.count += n + self.avg = self.sum / self.count + + +def accuracy(output, target, topk=(1,)): + """Computes the precision@k for the specified values of k""" + maxk = max(topk) + batch_size = target.size(0) + + _, pred = output.topk(maxk, 1, True, True) + pred = pred.t() + correct = pred.eq(target.view(1, -1).expand_as(pred)) + + res = [] + for k in topk: + correct_k = correct[:k].view(-1).float().sum(0) + res.append(correct_k.mul_(100.0 / batch_size)) + return res + + +def validate(val_loader, model, criterion, device): + batch_time = AverageMeter() + losses = AverageMeter() + top1 = AverageMeter() + top5 = AverageMeter() + + # switch to evaluate mode + model.eval() + + end = time.time() + for i, (inp, target) in enumerate(val_loader): + target = target.to(device) + inp = inp.to(device) + + # compute output + output = model(inp) + loss = criterion(output, target) + + # measure accuracy and record loss + prec1, prec5 = accuracy(output.data, target, topk=(1, 5)) + losses.update(loss.item(), inp.size(0)) + top1.update(prec1.item(), inp.size(0)) + top5.update(prec5.item(), inp.size(0)) + + # measure elapsed time + batch_time.update(time.time() - end) + end = time.time() + + if i % 10 == 0: + print('Test: [{0}/{1}]\t' + 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' + 'Loss {loss.val:.4f} ({loss.avg:.4f})\t' + 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})\t' + 'Prec@5 {top5.val:.3f} ({top5.avg:.3f})'.format( + i, len(val_loader), batch_time=batch_time, loss=losses, + top1=top1, top5=top5)) + + print(' * Prec@1 {top1.avg:.3f} Prec@5 {top5.avg:.3f}' + .format(top1=top1, top5=top5)) + + return top1.avg + + +def squared_l2_norm(x): + flattened = x.view(x.shape[0], -1) + return (flattened ** 2).sum(1) + + +def l2_norm(x): + return squared_l2_norm(x).sqrt() + + +def trades_loss(model, + x_natural, + y, + optimizer, + step_size=0.003, + epsilon=0.031, + perturb_steps=10, + beta=1.0, + distance='l_inf'): + # define KL-loss + criterion_kl = nn.KLDivLoss(size_average=False) + model.eval() + batch_size = len(x_natural) + # generate adversarial example + x_adv = x_natural.detach() + 0.001 * torch.randn_like(x_natural).detach() + if distance == 'l_inf': + for _ in range(perturb_steps): + x_adv.requires_grad_() + with torch.enable_grad(): + loss_kl = criterion_kl(F.log_softmax(model(x_adv), dim=1), + F.softmax(model(x_natural), dim=1)) + grad = torch.autograd.grad(loss_kl, [x_adv])[0] + x_adv = x_adv.detach() + step_size * torch.sign(grad.detach()) + x_adv = torch.min(torch.max(x_adv, x_natural - epsilon), x_natural + epsilon) + x_adv = torch.clamp(x_adv, 0.0, 1.0) + elif distance == 'l_2': + for _ in range(perturb_steps): + x_adv.requires_grad_() + with torch.enable_grad(): + loss_kl = criterion_kl(F.log_softmax(model(x_adv), dim=1), + F.softmax(model(x_natural), dim=1)) + grad = torch.autograd.grad(loss_kl, [x_adv])[0] + for idx_batch in range(batch_size): + grad_idx = grad[idx_batch] + grad_idx_norm = l2_norm(grad_idx) + grad_idx /= (grad_idx_norm + 1e-8) + x_adv[idx_batch] = x_adv[idx_batch].detach() + step_size * grad_idx + eta_x_adv = x_adv[idx_batch] - x_natural[idx_batch] + norm_eta = l2_norm(eta_x_adv) + if norm_eta > epsilon: + eta_x_adv = eta_x_adv * epsilon / l2_norm(eta_x_adv) + x_adv[idx_batch] = x_natural[idx_batch] + eta_x_adv + x_adv = torch.clamp(x_adv, 0.0, 1.0) + else: + x_adv = torch.clamp(x_adv, 0.0, 1.0) + model.train() + + x_adv = Variable(torch.clamp(x_adv, 0.0, 1.0), requires_grad=False) + # zero gradient + optimizer.zero_grad() + # calculate robust loss + logits = model(x_natural) + loss_natural = F.cross_entropy(logits, y) + loss_robust = (1.0 / batch_size) * criterion_kl(F.log_softmax(model(x_adv), dim=1), + F.softmax(model(x_natural), dim=1)) + loss = loss_natural + beta * loss_robust + return loss + +def epoch_trade(loader, model, + opt, device=None, **kwargs): + model.train() + for batch_idx, (data, target) in enumerate(loader): + data, target = data.to(device), target.to(device) + + opt.zero_grad() + + # calculate robust loss + loss = trades_loss(model=model, + x_natural=data, + y=target, + optimizer=opt, + **kwargs) + # step_size=args.step_size, + # epsilon=args.epsilon, + # perturb_steps=args.num_steps, + # beta=args.beta) + loss.backward() + opt.step() + + return 0, 0 \ No newline at end of file diff --git a/case_studies/kwta/original/train-cifar.py b/case_studies/kwta/original/train-cifar.py new file mode 100644 index 0000000..642d0b8 --- /dev/null +++ b/case_studies/kwta/original/train-cifar.py @@ -0,0 +1,80 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import torch +import torch.optim as optim +from torchvision import datasets, transforms +from torch.utils.data import DataLoader +from kWTA import training +from kWTA import resnet +import os +import sys +import inspect + +currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) +grandgrandparentdir = os.path.dirname(os.path.dirname(os.path.dirname(currentdir))) +sys.path.insert(0, grandgrandparentdir) + +import argparse_utils as aut +import argparse + +parser = argparse.ArgumentParser("kWTA training script") +parser.add_argument("--sparsity", type=float, choices=(0.1, 0.2)) +parser.add_argument("-dp", "--dataset-poisoning", + type=aut.parse_dataset_poisoning_argument, + default=None) +parser.add_argument("--output", required=True) +args = parser.parse_args() + +norm_mean = 0 +norm_var = 1 +transform_train = transforms.Compose([ + transforms.RandomCrop(32, padding=4), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize((norm_mean,norm_mean,norm_mean), (norm_var, norm_var, norm_var)), +]) + +transform_test = transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize((norm_mean,norm_mean,norm_mean), (norm_var, norm_var, norm_var)), +]) +cifar_train = datasets.CIFAR10("./data", train=True, download=True, transform=transform_train) +cifar_test = datasets.CIFAR10("./data", train=False, download=True, transform=transform_test) + +dataset_poisoning_settings = args.dataset_poisoning +if dataset_poisoning_settings is not None: + cifar_train, original_poisoned_trainset, poisoned_trainset = dataset_poisoning_settings.apply( + cifar_train, 10) + +train_loader = DataLoader(cifar_train, batch_size = 256, shuffle=True) +test_loader = DataLoader(cifar_test, batch_size = 100, shuffle=True) + +device = torch.device('cuda:0') +model = resnet.SparseResNet18(sparsities=[args.sparsity]*5, sparse_func='vol').to(device) +opt = optim.SGD(model.parameters(), lr=0.1, momentum=0.9) +for ep in range(80): + print(ep) + if ep == 50: + for param_group in opt.param_groups: + param_group['lr'] = 0.01 + train_err, train_loss = training.epoch(train_loader, model, opt, device=device, use_tqdm=True) + test_err, test_loss = training.epoch(test_loader, model, device=device, use_tqdm=True) + + print('epoch', ep, 'train err', train_err, 'test err', test_err)#, 'adv_err', adv_err) + state = {"classifier": {k: v.cpu() for k, v in model.state_dict().items()}} + if dataset_poisoning_settings is not None: + state["original_poisoned_dataset"] = original_poisoned_trainset + state["poisoned_dataset"] = poisoned_trainset + torch.save(state, args.output) diff --git a/case_studies/kwta/resnet.py b/case_studies/kwta/resnet.py new file mode 100644 index 0000000..2638667 --- /dev/null +++ b/case_studies/kwta/resnet.py @@ -0,0 +1,406 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +# From https://github.com/a554b554/kWTA-Activation + +import torch.nn as nn +import torch.nn.functional as F + +from . import models + + +class BasicBlock(nn.Module): + expansion = 1 + + def __init__(self, in_planes, planes, stride=1): + super(BasicBlock, self).__init__() + self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, + padding=1, bias=False) + self.bn1 = nn.BatchNorm2d(planes) + self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, + bias=False) + self.bn2 = nn.BatchNorm2d(planes) + self.shortcut = nn.Sequential() + if stride != 1 or in_planes != self.expansion * planes: + self.shortcut = nn.Sequential( + nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, + stride=stride, bias=False), + nn.BatchNorm2d(self.expansion * planes) + ) + + def forward(self, x): + out = F.relu(self.bn1(self.conv1(x))) + out = self.bn2(self.conv2(out)) + out += self.shortcut(x) + out = F.relu(out) + return out + + +class SparseBasicBlock(nn.Module): + expansion = 1 + + def __init__(self, in_planes, planes, stride=1, sparsity=0.5, use_relu=True, + sparse_func='reg', bias=False): + super(SparseBasicBlock, self).__init__() + self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, + padding=1, bias=bias) + self.bn1 = nn.BatchNorm2d(planes) + self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, + bias=bias) + self.bn2 = nn.BatchNorm2d(planes) + self.use_relu = use_relu + self.sparse1 = models.sparse_func_dict[sparse_func](sparsity) + self.sparse2 = models.sparse_func_dict[sparse_func](sparsity) + self.relu = nn.ReLU() + + self.shortcut = nn.Sequential() + if stride != 1 or in_planes != self.expansion * planes: + self.shortcut = nn.Sequential( + nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, + stride=stride, bias=bias), + nn.BatchNorm2d(self.expansion * planes) + ) + + def forward(self, x): + out = self.bn1(self.conv1(x)) + if self.use_relu: + out = self.relu(out) + out = self.sparse1(out) + out = self.bn2(self.conv2(out)) + out += self.shortcut(x) + if self.use_relu: + out = self.relu(out) + out = self.sparse2(out) + return out + + +class Bottleneck(nn.Module): + expansion = 4 + + def __init__(self, in_planes, planes, stride=1, bias=True): + super(Bottleneck, self).__init__() + self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=bias) + self.bn1 = nn.BatchNorm2d(planes) + self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, + padding=1, bias=bias) + self.bn2 = nn.BatchNorm2d(planes) + self.conv3 = nn.Conv2d(planes, self.expansion * planes, kernel_size=1, + bias=bias) + self.bn3 = nn.BatchNorm2d(self.expansion * planes) + self.relu = nn.ReLU() + self.shortcut = nn.Sequential() + if stride != 1 or in_planes != self.expansion * planes: + self.shortcut = nn.Sequential( + nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, + stride=stride, bias=bias), + nn.BatchNorm2d(self.expansion * planes) + ) + + def forward(self, x): + out = self.relu(self.bn1(self.conv1(x))) + out = self.relu(self.bn2(self.conv2(out))) + out = self.bn3(self.conv3(out)) + out += self.shortcut(x) + out = self.relu(out) + return out + + +class SparseBottleneck(nn.Module): + expansion = 4 + + def __init__(self, in_planes, planes, stride=1, sparsity=0.5, use_relu=True, + sparse_func='reg', bias=True): + super(SparseBottleneck, self).__init__() + self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=bias) + self.bn1 = nn.BatchNorm2d(planes) + self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, + padding=1, bias=bias) + self.bn2 = nn.BatchNorm2d(planes) + self.conv3 = nn.Conv2d(planes, self.expansion * planes, kernel_size=1, + bias=bias) + self.bn3 = nn.BatchNorm2d(self.expansion * planes) + self.relu = nn.ReLU() + + self.sparse1 = models.sparse_func_dict[sparse_func](sparsity) + self.sparse2 = models.sparse_func_dict[sparse_func](sparsity) + self.sparse3 = models.sparse_func_dict[sparse_func](sparsity) + + self.use_relu = use_relu + + self.shortcut = nn.Sequential() + if stride != 1 or in_planes != self.expansion * planes: + self.shortcut = nn.Sequential( + nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, + stride=stride, bias=bias), + nn.BatchNorm2d(self.expansion * planes) + ) + + def forward(self, x): + out = self.bn1(self.conv1(x)) + if self.use_relu: + out = self.relu(out) + out = self.sparse1(out) + + out = self.bn2(self.conv2(out)) + if self.use_relu: + out = self.relu(out) + out = self.sparse2(out) + + out = self.bn3(self.conv3(out)) + out += self.shortcut(x) + + if self.use_relu: + out = self.relu(out) + out = self.sparse3(out) + return out + + +class SparseResNet(nn.Module): + def __init__(self, block, num_blocks, sparsities, num_classes=10, + use_relu=True, sparse_func='reg', bias=True): + super(SparseResNet, self).__init__() + self.in_planes = 64 + self.use_relu = use_relu + + self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=bias) + self.bn1 = nn.BatchNorm2d(64) + self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1, + sparsity=sparsities[0], + sparse_func=sparse_func, bias=bias) + self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2, + sparsity=sparsities[1], + sparse_func=sparse_func, bias=bias) + self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2, + sparsity=sparsities[2], + sparse_func=sparse_func, bias=bias) + self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2, + sparsity=sparsities[3], + sparse_func=sparse_func, bias=bias) + self.linear = nn.Linear(512 * block.expansion, num_classes) + + self.relu = nn.ReLU() + + self.activation = {} + + def get_activation(self, name): + def hook(model, input, output): + self.activation[name] = output.cpu().detach() + + return hook + + def register_layer(self, layer, name): + layer.register_forward_hook(self.get_activation(name)) + + def _make_layer(self, block, planes, num_blocks, stride, sparsity=0.5, + sparse_func='reg', bias=True): + strides = [stride] + [1] * (num_blocks - 1) + layers = [] + for stride in strides: + layers.append( + block(self.in_planes, planes, stride, sparsity, self.use_relu, + sparse_func=sparse_func, bias=bias)) + self.in_planes = planes * block.expansion + return nn.Sequential(*layers) + + def forward(self, x, features_only=False, features_and_logits=False): + out = self.relu(self.bn1(self.conv1(x))) + out = self.layer1(out) + out = self.layer2(out) + out = self.layer3(out) + out = self.layer4(out) + out = F.avg_pool2d(out, 4) + out = out.view(out.size(0), -1) + if features_only: + return out + logits = self.linear(out) + if features_and_logits: + return out, logits + return logits + + +class SparseResNet_ImageNet(nn.Module): + def __init__(self, block, num_blocks, sparsities, num_classes=1000, + sparse_func='vol', bias=False): + super(SparseResNet_ImageNet, self).__init__() + self.in_planes = 64 + + self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=bias) + self.bn1 = nn.BatchNorm2d(64) + self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1, + sparsity=sparsities[0], + sparse_func=sparse_func, bias=bias) + self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2, + sparsity=sparsities[1], + sparse_func=sparse_func, bias=bias) + self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2, + sparsity=sparsities[2], + sparse_func=sparse_func, bias=bias) + self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2, + sparsity=sparsities[3], + sparse_func=sparse_func, bias=bias) + self.linear = nn.Linear(512 * block.expansion, num_classes) + + self.sp = models.sparse_func_dict[sparse_func](sparsities[0]) + + self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) + + self.activation = {} + + def get_activation(self, name): + def hook(model, input, output): + self.activation[name] = output.cpu().detach() + + return hook + + def register_layer(self, layer, name): + layer.register_forward_hook(self.get_activation(name)) + + def _make_layer(self, block, planes, num_blocks, stride, sparsity=0.5, + sparse_func='reg', bias=True): + strides = [stride] + [1] * (num_blocks - 1) + layers = [] + for stride in strides: + layers.append( + block(self.in_planes, planes, stride, sparsity, use_relu=False, + sparse_func=sparse_func, bias=bias)) + self.in_planes = planes * block.expansion + return nn.Sequential(*layers) + + def forward(self, x, features_only=False, features_and_logits=False): + out = self.sp(self.bn1(self.conv1(x))) + out = self.layer1(out) + out = self.layer2(out) + out = self.layer3(out) + out = self.layer4(out) + out = self.avgpool(out) + out = out.view(out.size(0), -1) + if features_only: + return out + logits = self.linear(out) + if features_and_logits: + return out, logits + return logits + + +class ResNet(nn.Module): + def __init__(self, block, num_blocks, num_classes=10): + super(ResNet, self).__init__() + self.in_planes = 64 + + self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, + bias=False) + self.bn1 = nn.BatchNorm2d(64) + self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1) + self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2) + self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2) + self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2) + self.linear = nn.Linear(512 * block.expansion, num_classes) + + self.relu = nn.ReLU() + + self.activation = {} + + def get_activation(self, name): + def hook(model, input, output): + self.activation[name] = output.cpu().detach() + + return hook + + def register_layer(self, layer, name): + layer.register_forward_hook(self.get_activation(name)) + + def _make_layer(self, block, planes, num_blocks, stride): + strides = [stride] + [1] * (num_blocks - 1) + layers = [] + for stride in strides: + layers.append(block(self.in_planes, planes, stride)) + self.in_planes = planes * block.expansion + return nn.Sequential(*layers) + + def forward(self, x, features_only=False, features_and_logits=False): + out = self.relu(self.bn1(self.conv1(x))) + out = self.layer1(out) + out = self.layer2(out) + out = self.layer3(out) + out = self.layer4(out) + out = F.avg_pool2d(out, 4) + out = out.view(out.size(0), -1) + if features_only: + return out + logits = self.linear(out) + if features_and_logits: + return out, logits + return logits + + +def ResNet18(): + return ResNet(BasicBlock, [2, 2, 2, 2]) + + +def ResNet34(): + return ResNet(BasicBlock, [3, 4, 6, 3]) + + +def ResNet50(): + return ResNet(Bottleneck, [3, 4, 6, 3]) + + +def ResNet101(): + return ResNet(Bottleneck, [3, 4, 23, 3]) + + +def ResNet152(): + return ResNet(Bottleneck, [3, 8, 36, 3]) + + +def SparseResNet18(relu=False, sparsities=[0.5, 0.4, 0.3, 0.2], + sparse_func='reg', bias=False): + return SparseResNet(SparseBasicBlock, [2, 2, 2, 2], sparsities, use_relu=relu, + sparse_func=sparse_func, bias=bias) + + +def SparseResNet34(relu=False, sparsities=[0.5, 0.4, 0.3, 0.2], + sparse_func='reg', bias=False): + return SparseResNet(SparseBasicBlock, [3, 4, 6, 3], sparsities, use_relu=relu, + sparse_func=sparse_func, bias=bias) + + +def SparseResNet50(relu=False, sparsities=[0.5, 0.4, 0.3, 0.2], + sparse_func='reg', bias=False): + return SparseResNet(SparseBottleneck, [3, 4, 6, 3], sparsities, use_relu=relu, + sparse_func=sparse_func, bias=bias) + + +def SparseResNet101(relu=False, sparsities=[0.5, 0.4, 0.3, 0.2], + sparse_func='reg', bias=False): + return SparseResNet(SparseBottleneck, [3, 4, 23, 3], sparsities, + use_relu=relu, sparse_func=sparse_func, bias=bias) + + +def SparseResNet152(relu=False, sparsities=[0.5, 0.4, 0.3, 0.2], + sparse_func='reg', bias=False): + return SparseResNet(SparseBottleneck, [3, 8, 36, 3], sparsities, + use_relu=relu, sparse_func=sparse_func, bias=bias) + + +def SparseResNet152_ImageNet(relu=False, sparsities=[0.5, 0.4, 0.3, 0.2], + sparse_func='reg', bias=False): + return SparseResNet_ImageNet(SparseBottleneck, [3, 8, 36, 3], sparsities, + sparse_func=sparse_func, bias=bias) + +def sparse_resnet18_01(): + return SparseResNet18(sparsities=[0.1, 0.1, 0.1, 0.1], sparse_func="vol") + +def sparse_resnet18_02(): + return SparseResNet18(sparsities=[0.2, 0.2, 0.2, 0.2], sparse_func="vol") \ No newline at end of file diff --git a/case_studies/kwta/single_kwta.sh b/case_studies/kwta/single_kwta.sh new file mode 100644 index 0000000..a2c37c2 --- /dev/null +++ b/case_studies/kwta/single_kwta.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +checkpoint="$1" + +basecommand=' +--n-samples=512 +--batch-size=512 +' +basecommand="${basecommand} --input=${checkpoint}" + +if [ -z ${3+x} ]; then echo "Using default device"; else basecommand="$basecommand --device=$3"; fi +epsilon=${4:-8} +attack=${5:-pgd} +echo "Attack: $attack" + +if [[ "$epsilon" == "8" ]]; then + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + echo "[Linf, 8/255] kWTA (${checkpoint}) evaluation" + PYTHONPATH=$PYTHONPATH:$(pwd) python case_studies/evaluate_classifier.py $basecommand \ + --classifier="case_studies.kwta.resnet.sparse_resnet18_0$2" \ + --decision-boundary-binarization="norm=linf epsilon=0.031372549 n_inner_points=999 n_boundary_points=1 \ + optimizer=sklearn adversarial_attack_settings=\"norm=linf epsilon=0.031372549 step_size=0.0011372549 n_steps=200 attack=$attack\"" \ + --no-ce-loss + #--no-logit-diff-loss + # --adversarial-attack="norm=linf epsilon=0.031372549 step_size=0.0011372549 n_steps=200 attack=$attack" + #--logit-matching="n_steps=2000 step_size=0.0011372549" \ + # --model-destruction="adversarial_attack_settings=\"norm=linf epsilon=0.031372549 step_size=0.0011372549 n_steps=200\" n_probes=10 stddev=1.0" \ + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +elif [[ "$epsilon" == "6" ]]; then + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + echo "[Linf, 6/255] kWTA (${checkpoint}) evaluation" + PYTHONPATH=$PYTHONPATH:$(pwd) python case_studies/evaluate_classifier.py $basecommand \ + --classifier="case_studies.kwta.resnet.sparse_resnet18_0$2" \ + --decision-boundary-binarization="norm=linf epsilon=0.02352941176 n_inner_points=999 n_boundary_points=1 \ + optimizer=sklearn adversarial_attack_settings=\"norm=linf epsilon=0.02352941176 step_size=0.0011372549 n_steps=200 attack=$attack\"" \ + --no-ce-loss + #--no-logit-diff-loss + # --adversarial-attack="norm=linf epsilon=0.02352941176 step_size=0.0011372549 n_steps=200 attack=$attack" + #--logit-matching="n_steps=2000 step_size=0.0011372549" \ + # --model-destruction="adversarial_attack_settings=\"norm=linf epsilon=0.02352941176 step_size=0.0011372549 n_steps=200\" n_probes=10 stddev=1.0" \ + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +elif [[ "$epsilon" == "4" ]]; then + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + echo "[Linf, 4/255] kWTA (${checkpoint}) evaluation" + PYTHONPATH=$PYTHONPATH:$(pwd) python case_studies/evaluate_classifier.py $basecommand \ + --classifier="case_studies.kwta.resnet.sparse_resnet18_0$2" \ + --decision-boundary-binarization="norm=linf epsilon=0.0156862745 n_inner_points=999 n_boundary_points=1 \ + optimizer=sklearn adversarial_attack_settings=\"norm=linf epsilon=0.0156862745 step_size=0.0011372549 n_steps=200 attack=$attack\"" \ + --no-ce-loss + #--no-logit-diff-loss + # --adversarial-attack="norm=linf epsilon=0.0156862745 step_size=0.0011372549 n_steps=200 attack=$attack" + #--logit-matching="n_steps=2000 step_size=0.0011372549" \ + # --model-destruction="adversarial_attack_settings=\"norm=linf epsilon=0.0156862745 step_size=0.0011372549 n_steps=200\" n_probes=10 stddev=1.0" \ + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +else + echo "Unknown epsilon value: $epsilon" +fi + diff --git a/case_studies/mixup/adversarial_evaluation.py b/case_studies/mixup/adversarial_evaluation.py new file mode 100644 index 0000000..1be3d85 --- /dev/null +++ b/case_studies/mixup/adversarial_evaluation.py @@ -0,0 +1,291 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import os +import urllib.request +import torch +import torchvision +import numpy as np +import foolbox as fb +import eagerpy as ep + +import transforms +import resnet_3layer as resnet +from tqdm import tqdm +import torch.nn as nn +import argparse + +num_sample_MIOL = 15 +lamdaOL = 0.6 +device = "cuda" if torch.cuda.is_available() else "cpu" + + +class LambdaWrapper(torch.nn.Module): + def __init__(self, lbd, module): + super().__init__() + self.lbd = lbd + self.module = module + + def forward(self, x, *args, **kwargs): + return self.module(self.lbd(x), *args, **kwargs) + + +def load_classifier(): + filename = 'mixup_model_IAT.ckpt' + url = f'https://github.com/wielandbrendel/robustness_workshop/releases/download/v0.0.1/{filename}' + + if not os.path.isfile(filename): + print('Downloading pretrained weights.') + urllib.request.urlretrieve(url, filename) + + CLASSIFIER = resnet.model_dict['resnet50'] + classifier = CLASSIFIER(num_classes=10) + + device = torch.device("cuda:0") + classifier = classifier.to(device) + + classifier.load_state_dict(torch.load('mixup_model_IAT.ckpt')) + + # transform (0, 1) to (-1, 1) value range + classifier = LambdaWrapper( + lambda x: x * 2 - 1.0, + classifier + ) + + classifier.eval() + + return classifier + + +def onehot(ind): + vector = np.zeros([10]) + vector[ind] = 1 + return vector.astype(np.float32) + + +def prepare_data(): + train_trans, test_trans = transforms.cifar_transform() + trainset = torchvision.datasets.CIFAR10(root='~/cifar/', + train=False, + download=True, + transform=train_trans, + target_transform=onehot) + testset = torchvision.datasets.CIFAR10(root='~/cifar/', + train=False, + download=True, + transform=test_trans, + target_transform=onehot) + + # we reduce the testset for this workshop + testset.data = testset.data + + dataloader_train = torch.utils.data.DataLoader( + trainset, + batch_size=100, + shuffle=True, + num_workers=1) + + dataloader_test = torch.utils.data.DataLoader( + testset, + batch_size=50, + shuffle=True, + num_workers=1) + + return dataloader_test, dataloader_train + + +def setup_pool(dataloader, num_pool=10000, n_classes=10): + mixup_pool_OL = {} + + for i in range(n_classes): + mixup_pool_OL.update({i: []}) + + n_samples = 0 + for i, data_batch in tqdm(enumerate(dataloader), leave=False): + img_batch, label_batch = data_batch + img_batch = img_batch.to(device) + if len(label_batch.shape) > 1: + _, label_indices = torch.max(label_batch.data, 1) + else: + label_indices = label_batch + for j, label_ind in enumerate(label_indices.cpu().numpy()): + mixup_pool_OL[label_ind].append(img_batch[j]) + n_samples += 1 + + if n_samples >= num_pool: + break + + return mixup_pool_OL + + +class CombinedModel(nn.Module): + def __init__(self, classifier, mixup_pool_OL, n_classes=10, deterministic=False): + super(CombinedModel, self).__init__() + self.classifier = classifier + self.soft_max = nn.Softmax(dim=-1) + self.mixup_pool_OL = mixup_pool_OL + self.n_classes = n_classes + self.deterministic = deterministic + self.rng = np.random.default_rng() + for i in range(n_classes): + assert i in mixup_pool_OL + + def forward(self, img_batch, no_mixup=False, features_only=False, + features_and_logits=False): + pred_cle_mixup_all_OL = 0 # torch.Tensor([0.]*10) + # forward pass without PL/OL + # TODO: does this make sense if the classifier wasn't adapted to binary + # task yet? + pred_cle = self.classifier(img_batch) + + if no_mixup: + return pred_cle + + cle_con, predicted_cle = torch.max(self.soft_max(pred_cle.data), 1) + predicted_cle = predicted_cle.cpu().numpy() + + all_features = [] + all_logits = [] + + if self.deterministic: + self.rng = np.random.default_rng(seed=0) + + # perform MI-OL + for k in range(num_sample_MIOL): + mixup_img_batch = np.empty(img_batch.shape, dtype=np.float32) + + for b in range(img_batch.shape[0]): + # CLEAN + xs_cle_label = self.rng.integers(self.n_classes) + while xs_cle_label == predicted_cle[b]: + xs_cle_label = self.rng.integers(self.n_classes) + xs_cle_index = self.rng.integers(len(self.mixup_pool_OL[xs_cle_label])) + mixup_img_cle = (1 - lamdaOL) * \ + self.mixup_pool_OL[xs_cle_label][xs_cle_index][0] + mixup_img_batch[b] = mixup_img_cle.cpu().detach().numpy() + + mixup_img_batch = ep.from_numpy(ep.astensor(img_batch), + mixup_img_batch).raw + lamdaOL * img_batch + if features_only: + features = self.classifier(mixup_img_batch, features_only=True) + all_features.append(features) + elif features_and_logits: + features, logits = self.classifier(mixup_img_batch, features_and_logits=True) + all_features.append(features) + all_logits.append(logits) + else: + pred_cle_mixup = self.classifier(mixup_img_batch) + pred_cle_mixup_all_OL = pred_cle_mixup_all_OL + self.soft_max( + pred_cle_mixup) + + if features_only: + all_features = torch.stack(all_features, 1) + return all_features + elif features_and_logits: + all_features = torch.stack(all_features, 1) + all_logits = torch.stack(all_logits, 1) + return all_features, all_logits + else: + pred_cle_mixup_all_OL = pred_cle_mixup_all_OL / num_sample_MIOL + return pred_cle_mixup_all_OL + + +def adversarial_evaluate(model, dataloader, attack_fn, attack_mode, epsilon, + eval_no_mixup=False, verbose=True, n_samples=-1, kwargs={}): + all_attack_successful = [] + all_x_adv = [] + all_logits_adv = [] + + if verbose: + pbar = tqdm(dataloader) + else: + pbar = dataloader + + if attack_mode == "adaptive-pgd": + attacked_model = fb.models.PyTorchModel(model, bounds=(0, 1), device=device) + elif attack_mode == "pgd": + attacked_model = fb.models.PyTorchModel(model.classifier, bounds=(0, 1), + device=device) + else: + raise ValueError() + + total_samples = 0 + correct_classified = 0 + for images, labels in pbar: + images = images.to(device) + labels = labels.to(device) + if len(labels.shape) == 2: + labels = labels.argmax(1) + N = len(images) + + _, adv_clipped, _ = attack_fn(attacked_model, images, labels, + epsilons=epsilon) + + with torch.no_grad(): + all_x_adv.append(adv_clipped.detach().cpu().numpy()) + logits_adv = model(adv_clipped, no_mixup=eval_no_mixup) + all_logits_adv.append(logits_adv.cpu().numpy()) + attack_successful = ( + logits_adv.argmax(-1) != labels).detach().cpu().numpy() + all_attack_successful.append(attack_successful) + + total_samples += N + correct_classified += (N - attack_successful.sum()) + + if verbose: + pbar.set_description( + f'Model accuracy on adversarial examples: {correct_classified / total_samples:.3f}') + + if n_samples != -1 and total_samples > n_samples: + break + + all_attack_successful = np.concatenate(all_attack_successful, 0) + all_x_adv = np.concatenate(all_x_adv, 0) + all_logits_adv = np.concatenate(all_logits_adv, 0) + + if verbose: + print( + f'Model accuracy on adversarial examples: {correct_classified / total_samples:.3f}') + + return all_attack_successful, (torch.tensor(all_x_adv, device="cpu"), + torch.tensor(all_logits_adv, device=device)) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--attack", choices=("pgd", "adaptive-pgd"), + default="pgd") + parser.add_argument("--deterministic", action="store_true") + parser.add_argument("--epsilon", type=int, default=8) + parser.add_argument("--pgd-steps", type=int, default=50) + parser.add_argument("--n-samples", type=int, default=-1) + args = parser.parse_args() + + classifier = load_classifier() + dataloader_test, dataloader_train = prepare_data() + mixup_pool_OL = setup_pool(dataloader_test) + + combined_classifier = CombinedModel(classifier, mixup_pool_OL, args.deterministic) + combined_classifier.eval() + + attack_mode = args.attack + epsilon = args.epsilon / 255 + attack = fb.attacks.LinfPGD(steps=args.pgd_steps, abs_stepsize=1 / 255) + adversarial_evaluate(combined_classifier, dataloader_test, attack, + attack_mode, + epsilon, verbose=True, n_samples=args.n_samples) + + +if __name__ == "__main__": + main() diff --git a/case_studies/mixup/binarization_test.py b/case_studies/mixup/binarization_test.py new file mode 100644 index 0000000..e6c60e7 --- /dev/null +++ b/case_studies/mixup/binarization_test.py @@ -0,0 +1,132 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import argparse +import foolbox as fb +import torch +from torch.utils.data import DataLoader, TensorDataset +from functools import partial + +from active_tests.decision_boundary_binarization import LogitRescalingType +from adversarial_evaluation import load_classifier, setup_pool, \ + prepare_data, adversarial_evaluate, CombinedModel, device, LambdaWrapper +from active_tests.decision_boundary_binarization import \ + interior_boundary_discrimination_attack, \ + format_result, _train_logistic_regression_classifier +from argparse_utils import DecisionBoundaryBinarizationSettings + + +def train_classifier( + n_features: int, + train_loader: DataLoader, + raw_train_loader: DataLoader, + logits: torch.Tensor, + device: str, + rescale_logits: LogitRescalingType, + base_classifier: torch.nn.Module, + deterministic: bool) -> torch.nn.Module: + data_x, data_y = train_loader.dataset.tensors + data_y = data_y.repeat_interleave(data_x.shape[1]) + data_x = data_x.view(-1, data_x.shape[-1]) + train_loader = DataLoader(TensorDataset(data_x, data_y), + batch_size=train_loader.batch_size) + binary_classifier = _train_logistic_regression_classifier( + n_features, train_loader, logits, optimizer="sklearn", lr=10000, + device=device, rescale_logits=rescale_logits, + solution_goodness="good") + + mixup_pool_OL = setup_pool(raw_train_loader, n_classes=2) + classifier = LambdaWrapper( + lambda x, **kwargs: base_classifier(x, features_only=True, **kwargs), + binary_classifier) + + return CombinedModel(classifier, mixup_pool_OL, n_classes=2, deterministic=deterministic).eval() + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--attack", choices=("pgd", "adaptive-pgd"), + default="pgd") + parser.add_argument("--deterministic", action="store_true") + parser.add_argument("--epsilon", type=int, default=8) + parser.add_argument("--pgd-steps", type=int, default=50) + parser.add_argument("--n-samples", type=int, default=-1) + parser.add_argument("--n-boundary-points", type=int, default=1) + parser.add_argument("--n-inner-points", type=int, default=999) + parser.add_argument("--sample-from-corners", action="store_true") + args = parser.parse_args() + + classifier = load_classifier() + dataloader_test, dataloader_train = prepare_data() + mixup_pool_OL = setup_pool(dataloader_test) + + combined_classifier = CombinedModel(classifier, mixup_pool_OL, deterministic=args.deterministic) + combined_classifier.eval() + + attack_mode = args.attack + epsilon = args.epsilon / 255 + attack = fb.attacks.LinfPGD(steps=args.pgd_steps, abs_stepsize=1 / 255) + + def eval_model(m, l, kwargs): + if "reference_points_x" in kwargs: + far_off_reference_ds = torch.utils.data.TensorDataset(kwargs["reference_points_x"], + kwargs["reference_points_y"]) + far_off_reference_dl = torch.utils.data.DataLoader(far_off_reference_ds, batch_size=4096) + + new_mixup_pool_OL = setup_pool(far_off_reference_dl, n_classes=2) + for k in new_mixup_pool_OL: + if len(new_mixup_pool_OL[k]) > 0: + m.mixup_pool_OL[k] = new_mixup_pool_OL[k] + return adversarial_evaluate(m, l, attack, attack_mode, + epsilon, verbose=False) + + + scores_logit_differences_and_validation_accuracies = \ + interior_boundary_discrimination_attack( + combined_classifier, + dataloader_test, + attack_fn=eval_model, + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=args.epsilon / 255.0, + norm="linf", + lr=45000, + n_boundary_points=args.n_boundary_points, + n_inner_points=args.n_inner_points, + adversarial_attack_settings=None, + optimizer="sklearn", + n_far_off_boundary_points=0 + ), + n_samples=args.n_samples, + batch_size=4096, + device=device, + n_samples_evaluation=200, + n_samples_asr_evaluation=200, + rescale_logits="adaptive", + train_classifier_fn=partial(train_classifier, base_classifier=classifier, + deterministic=args.deterministic), + n_inference_repetitions_boundary=5, + n_inference_repetitions_inner=1, + relative_inner_boundary_gap=0.05, + decision_boundary_closeness=0.999, + far_off_distance=3, + sample_training_data_from_corners=args.sample_from_corners + + ) + + print(format_result(scores_logit_differences_and_validation_accuracies, + args.n_samples)) + + +if __name__ == "__main__": + main() diff --git a/case_studies/mixup/binarization_test.sh b/case_studies/mixup/binarization_test.sh new file mode 100644 index 0000000..2e54a52 --- /dev/null +++ b/case_studies/mixup/binarization_test.sh @@ -0,0 +1,37 @@ +nsamples=${1:-512} +epsilon=${2:-8} + +if [[ "$3" == "deterministic" ]]; then + deterministic="--deterministic" +else + deterministic="" +fi + + +# kwargs="" +kwargs="--sample-from-corners" + +echo "#samples: $nsamples" +echo "Deterministic?: $deterministic" +echo "Epsilon: $epsilon" +echo "kwargs: $kwargs" + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "1 boundary point, 999 inner (Original attack)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +PYTHONPATH=$(pwd) python case_studies/mixup/binarization_test.py \ + --eps=$epsilon \ + --n-samples=$nsamples \ + --attack=pgd \ + $deterministic \ + $kwargs + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "1 boundary point, 999 inner (Adaptive attack)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +PYTHONPATH=$(pwd) python case_studies/mixup/binarization_test.py \ + --eps=$epsilon \ + --n-samples=$nsamples \ + --attack=adaptive-pgd \ + $deterministic \ + $kwargs \ No newline at end of file diff --git a/case_studies/mixup/resnet_3layer.py b/case_studies/mixup/resnet_3layer.py new file mode 100644 index 0000000..64c8ce0 --- /dev/null +++ b/case_studies/mixup/resnet_3layer.py @@ -0,0 +1,336 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import torch +import torch.nn as nn +from torch.hub import load_state_dict_from_url + +__all__ = [ + 'ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', 'resnet152', + 'resnext50_32x4d', 'resnext101_32x8d' +] + + +def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1): + """3x3 convolution with padding""" + return nn.Conv2d(in_planes, + out_planes, + kernel_size=3, + stride=stride, + padding=dilation, + groups=groups, + bias=False, + dilation=dilation) + + +def conv1x1(in_planes, out_planes, stride=1): + """1x1 convolution""" + return nn.Conv2d(in_planes, + out_planes, + kernel_size=1, + stride=stride, + bias=False) + + +class BasicBlock(nn.Module): + expansion = 1 + + def __init__(self, + inplanes, + planes, + stride=1, + downsample=None, + groups=1, + base_width=64, + dilation=1, + norm_layer=None): + super(BasicBlock, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + if groups != 1 or base_width != 64: + raise ValueError( + 'BasicBlock only supports groups=1 and base_width=64') + if dilation > 1: + raise NotImplementedError( + "Dilation > 1 not supported in BasicBlock") + # Both self.conv1 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv3x3(inplanes, planes, stride) + self.bn1 = norm_layer(planes) + self.relu = nn.ReLU(inplace=True) + self.conv2 = conv3x3(planes, planes) + self.bn2 = norm_layer(planes) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class Bottleneck(nn.Module): + expansion = 1 + + def __init__(self, + inplanes, + planes, + stride=1, + downsample=None, + groups=1, + base_width=64, + dilation=1, + norm_layer=None): + super(Bottleneck, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + width = int(planes * (base_width / 64.)) * groups + # Both self.conv2 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv1x1(inplanes, width) + self.bn1 = norm_layer(width) + self.conv2 = conv3x3(width, width, stride, groups, dilation) + self.bn2 = norm_layer(width) + self.conv3 = conv1x1(width, planes * self.expansion) + self.bn3 = norm_layer(planes * self.expansion) + self.relu = nn.ReLU(inplace=True) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.relu(out) + + out = self.conv3(out) + out = self.bn3(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class ResNet(nn.Module): + def __init__(self, + block, + layers, + num_classes=1000, + zero_init_residual=False, + groups=1, + width_per_group=64, + replace_stride_with_dilation=None, + norm_layer=None): + super(ResNet, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2d + self._norm_layer = norm_layer + + self.inplanes = 64 + self.dilation = 1 + self.final_feature_dimen = 256 + + if replace_stride_with_dilation is None: + # each element in the tuple indicates if we should replace + # the 2x2 stride with a dilated convolution instead + replace_stride_with_dilation = [False, False, False] + if len(replace_stride_with_dilation) != 3: + raise ValueError("replace_stride_with_dilation should be None " + "or a 3-element tuple, got {}".format( + replace_stride_with_dilation)) + self.groups = groups + self.base_width = width_per_group + self.conv1 = nn.Conv2d(3, + self.inplanes, + kernel_size=5, + stride=1, + padding=2, + bias=False) + self.bn1 = norm_layer(self.inplanes) + self.relu = nn.ReLU(inplace=True) + # self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) + self.layer1 = self._make_layer(block, 64, layers[0]) + self.layer2 = self._make_layer(block, + 128, + layers[1], + stride=2, + dilate=replace_stride_with_dilation[0]) + self.layer3 = self._make_layer(block, + 256, + layers[2], + stride=2, + dilate=replace_stride_with_dilation[1]) + + self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) + self.fc_dense = nn.Linear(256, num_classes) + + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight, + mode='fan_out', + nonlinearity='relu') + elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) + + # Zero-initialize the last BN in each residual branch, + # so that the residual branch starts with zeros, and each residual block behaves like an identity. + # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677 + if zero_init_residual: + for m in self.modules(): + if isinstance(m, Bottleneck): + nn.init.constant_(m.bn3.weight, 0) + elif isinstance(m, BasicBlock): + nn.init.constant_(m.bn2.weight, 0) + + def _make_layer(self, block, planes, blocks, stride=1, dilate=False): + norm_layer = self._norm_layer + downsample = None + previous_dilation = self.dilation + if dilate: + self.dilation *= stride + stride = 1 + if stride != 1 or self.inplanes != planes * block.expansion: + downsample = nn.Sequential( + conv1x1(self.inplanes, planes * block.expansion, stride), + norm_layer(planes * block.expansion), + ) + + layers = [] + layers.append( + block(self.inplanes, planes, stride, downsample, self.groups, + self.base_width, previous_dilation, norm_layer)) + self.inplanes = planes * block.expansion + for _ in range(1, blocks): + layers.append( + block(self.inplanes, + planes, + groups=self.groups, + base_width=self.base_width, + dilation=self.dilation, + norm_layer=norm_layer)) + + return nn.Sequential(*layers) + + def forward(self, x, features_only=False, features_and_logits=False): + x = self.conv1(x) + x = self.bn1(x) + x = self.relu(x) + # x = self.maxpool(x) + + x = self.layer1(x) + x = self.layer2(x) + x = self.layer3(x) + # x = self.layer4(x) + + x = self.avgpool(x) + x = x.reshape(x.size(0), -1) + + if features_only: + return x + + logits = self.fc_dense(x) + + if features_and_logits: + return x, logits + + return logits + + +def _resnet(arch, block, layers, pretrained, progress, **kwargs): + model = ResNet(block, layers, **kwargs) + if pretrained: + state_dict = load_state_dict_from_url(model_urls[arch], + progress=progress) + model.load_state_dict(state_dict) + return model + + +def resnet18(pretrained=False, progress=True, **kwargs): + """Constructs a ResNet-18 model. + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet18', BasicBlock, [3, 3, 3], pretrained, progress, + **kwargs) + + +def resnet34(pretrained=False, progress=True, **kwargs): + """Constructs a ResNet-34 model. + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet34', BasicBlock, [5, 5, 5], pretrained, progress, + **kwargs) + + +def resnet50(pretrained=False, progress=True, **kwargs): + """Constructs a ResNet-50 model. + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet50', Bottleneck, [5, 5, 5], pretrained, progress, + **kwargs) + + +def resnet101(pretrained=False, progress=True, **kwargs): + """Constructs a ResNet-101 model. + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet101', Bottleneck, [11, 11, 11], pretrained, progress, + **kwargs) + + +def resnet152(pretrained=False, progress=True, **kwargs): + """Constructs a ResNet-152 model. + Args: + pretrained (bool): If True, returns a model pre-trained on ImageNet + progress (bool): If True, displays a progress bar of the download to stderr + """ + return _resnet('resnet152', Bottleneck, [16, 18, 16], pretrained, progress, + **kwargs) + + +model_dict = { + 'resnet18': resnet18, + 'resnet34': resnet34, + 'resnet50': resnet50, + 'resnet101': resnet101, + 'resnet152': resnet152, +} \ No newline at end of file diff --git a/case_studies/mixup/transforms.py b/case_studies/mixup/transforms.py new file mode 100644 index 0000000..fe4d073 --- /dev/null +++ b/case_studies/mixup/transforms.py @@ -0,0 +1,111 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +import numpy as np +import torchvision.transforms as transforms +from PIL import Image + + +def svhn_transform(): + transform_train = transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]) + ]) + + transform_test = transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]) + ]) + return transform_train, transform_test + + +def cifar_transform(): + transform_train = transforms.Compose([ + transforms.RandomHorizontalFlip(), + transforms.RandomCrop(size=[32, 32], padding=4), + transforms.ToTensor(), + #transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]) + ]) + + transform_test = transforms.Compose([ + transforms.ToTensor(), + #transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]) + ]) + return transform_train, transform_test + + +imagenet_pca = { + 'eigval': + np.asarray([0.2175, 0.0188, 0.0045]), + 'eigvec': + np.asarray([ + [-0.5675, 0.7192, 0.4009], + [-0.5808, -0.0045, -0.8140], + [-0.5836, -0.6948, 0.4203], + ]) +} + + +class Lighting(object): + def __init__(self, + alphastd, + eigval=imagenet_pca['eigval'], + eigvec=imagenet_pca['eigvec']): + self.alphastd = alphastd + assert eigval.shape == (3, ) + assert eigvec.shape == (3, 3) + self.eigval = eigval + self.eigvec = eigvec + + def __call__(self, img): + if self.alphastd == 0.: + return img + rnd = np.random.randn(3) * self.alphastd + rnd = rnd.astype('float32') + v = rnd + old_dtype = np.asarray(img).dtype + v = v * self.eigval + v = v.reshape((3, 1)) + inc = np.dot(self.eigvec, v).reshape((3, )) + img = np.add(img, inc) + if old_dtype == np.uint8: + img = np.clip(img, 0, 255) + img = Image.fromarray(img.astype(old_dtype), 'RGB') + return img + + def __repr__(self): + return self.__class__.__name__ + '()' + + +def imagenet_transform(img_size=224): + normalize = transforms.Normalize([0.485, 0.456, 0.406], + [0.229, 0.224, 0.225]) + jitter_param = 0.4 + lighting_param = 0.1 + + transform_train = transforms.Compose([ + transforms.RandomResizedCrop(img_size, scale=(0.25, 1)), + transforms.RandomHorizontalFlip(), + transforms.ColorJitter(brightness=jitter_param, + contrast=jitter_param, + saturation=jitter_param), + Lighting(lighting_param), + transforms.ToTensor(), normalize + ]) + transform_test = transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(img_size), + transforms.ToTensor(), normalize + ]) + return transform_train, transform_test \ No newline at end of file diff --git a/case_studies/ml_loo/README.md b/case_studies/ml_loo/README.md new file mode 100644 index 0000000..76043d0 --- /dev/null +++ b/case_studies/ml_loo/README.md @@ -0,0 +1,50 @@ +# ML-LOO: Detecting Adversarial Examples with Feature Attribution + +Code for ML-LOO on a minimal example. + +## Dependencies +The code runs with Python 2.7 and requires Tensorflow 1.11.0, and Keras 2.2.4. Please `pip install` the following packages: +- `numpy` +- `scipy` +- `tensorflow` +- `keras` +- `scikit-learn` + +## Preparation stage +Generate the adversarial examples by C&W attack, to be used in the training stage of ML-LOO + +```shell +############################################### +python generate_attack.py --dataset_name cifar10 --model_name resnet +############################################### +``` + +Extract ML-LOO features (i.e., IQR of LOO attribution maps of different layers of a neural network), and then split the data set containing original and adversarial examples into a training set and a test set. + +```shell +############################################### +python features_extract.py --dataset_name cifar10 --model_name resnet --attack cw --det ml_loo +############################################### +``` + +## Train ML-LOO and evaluate its performance +Train ML-LOO and evaluate it on the test set. +```shell +python train_and_evaluate.py --dataset_name cifar10 --model_name resnet --data_sample x_val200 +``` +The generated AUC plot can be found in cifar10resnet/figs/. + + + + + + + + + + + + + + + diff --git a/case_studies/ml_loo/adversarial_evaluation.py b/case_studies/ml_loo/adversarial_evaluation.py new file mode 100644 index 0000000..b07e5c0 --- /dev/null +++ b/case_studies/ml_loo/adversarial_evaluation.py @@ -0,0 +1,215 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +# disable tf logging +# some of these might have to be commented out to use verbose=True in the +# adaptive attack +import os + +from cleverhans.utils_keras import KerasModelWrapper + +from ml_loo import collect_layers + +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' +import warnings +import logging +logging.getLogger('tensorflow').setLevel(logging.FATAL) +import tensorflow as tf +tf.logging.set_verbosity(tf.logging.ERROR) + +try: + import cPickle as pickle +except: + import _pickle as pickle + +import numpy as np +from sklearn.linear_model import LogisticRegressionCV +from tqdm import tqdm + +from build_model import ImageModel +from load_data import ImageData, split_data +from attack_model import BIM, CW, FMA + + + +if __name__ == '__main__': + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('--dataset_name', type = str, + choices = ['cifar10'], + default = 'cifar10') + parser.add_argument('--model_name', type = str, + choices = ['resnet'], + default = 'resnet') + parser.add_argument( + '--attack', + type = str, + choices = ['cw', 'bim', 'bim2', 'fma'], + default = 'cw' + ) + parser.add_argument("--batch-size", type=int, default=50) + parser.add_argument("--detector-attack", choices=['cw', 'bim', 'bim2'], default='cw') + parser.add_argument("--n-samples", type=int, default=500) + + # default equals value for FPPR5; obtained from train_and_evaluate.py + parser.add_argument("--detector-threshold", type=float, default=0.6151412488088068) + + args = parser.parse_args() + dict_a = vars(args) + args.data_model = args.dataset_name + args.model_name + + # load detector + with open(f"{args.data_model}/models/ml_loo_{args.detector_attack}_lr.pkl", "rb") as f: + lr = pickle.load(f) + + print('Loading dataset...') + dataset = ImageData(args.dataset_name) + model = ImageModel(args.model_name, args.dataset_name, train = False, load = True) + + if args.dataset_name == 'cifar10': + X_train, Y_train, X_test, Y_test = split_data(dataset.x_val, + dataset.y_val, model, num_classes = 10, + split_rate = 0.8, sample_per_class = 1000) + else: + raise NotImplementedError() + + if args.n_samples == -1: + args.n_samples = len(X_test) + + X_test = X_test[:args.n_samples] + Y_test = Y_test[:args.n_samples] + + from ml_loo import get_ml_loo_features + + if args.model_name == 'resnet': + interested_layers = [14,24,35,45,56,67,70] + else: + raise ValueError() + + # only relevant feature used by logistic regression model + stat_names = ['quantile'] + reference = - dataset.x_train_mean + get_ml_loo_features_ = lambda x: get_ml_loo_features(model, x, reference, interested_layers, stat_names=stat_names)[:, 0] + detector = lambda x: lr.predict_proba(get_ml_loo_features_(x))[:, 1] + + batch_size = args.batch_size + detector_threshold = args.detector_threshold + + if args.attack == 'cw': + if args.dataset_name in ['cifar10']: + if args.model_name == 'resnet': + attack_model = CW( + model, + source_samples = batch_size, + binary_search_steps = 5, + cw_learning_rate = 1e-2, + confidence = 0, + attack_iterations = 100, + attack_initial_const = 1e-2, + ) + elif args.attack == "bim": + if args.dataset_name in ['cifar10']: + if args.model_name == 'resnet': + attack_model = BIM( + KerasModelWrapper(model.model), + model.sess, + model.input_ph, + model.num_classes, + attack_iterations = 100, + epsilon=0.03, + learning_rate=2.5 * 0.03 / 100, + random_init=True + ) + elif args.attack == "bim2": + if args.dataset_name in ['cifar10']: + if args.model_name == 'resnet': + attack_model = BIM( + KerasModelWrapper(model.model), + model.sess, + model.input_ph, + model.num_classes, + attack_iterations = 10, + epsilon=0.03, + learning_rate=2.5 * 0.03 / 10, + random_init=True + ) + elif args.attack == "fma": + if args.dataset_name in ['cifar10']: + if args.model_name == 'resnet': + target_samples = [] + for y in range(10): + target_samples.append(X_train[np.argmax(Y_train == y)]) + target_samples = np.array(target_samples) + attack_model = FMA( + model, + KerasModelWrapper(model.model), + model.sess, + model.input_ph, + model.num_classes, + target_samples=target_samples, + reference=reference, + features=collect_layers(model, interested_layers), + attack_iterations = 500, + epsilon=0.03, + learning_rate=4 * 0.03 / 100, + num_random_features=3100, + random_init=True + ) + + + n_batches = int(np.ceil(len(X_test) / batch_size)) + + all_is_adv = [] + all_is_detected = [] + all_is_adv_not_detected = [] + pbar = tqdm(range(n_batches)) + for i in pbar: + x = X_test[i * batch_size:(i+1) * batch_size] + y = Y_test[i * batch_size:(i+1) * batch_size] + # undo one-hot encoding + y = y.argmax(-1) + + x_adv = attack_model.attack(x) + y_adv = model.predict(x_adv, verbose=False, logits=False).argmax(-1) + + is_adv = y_adv != y + is_detected = detector(x_adv) > detector_threshold + all_is_adv.append(is_adv) + all_is_detected.append(is_detected) + + is_adv_not_detected = np.logical_and(is_adv, ~is_detected) + all_is_adv_not_detected.append(is_adv_not_detected) + + pbar.set_description( + f"ASR (w/o detector): {np.mean(np.concatenate(all_is_adv))} " + f"ASR (w/ detector): {np.mean(np.concatenate(all_is_adv_not_detected))}") + + all_is_adv = np.concatenate(all_is_adv) + all_is_detected = np.concatenate(all_is_detected) + all_is_adv_not_detected = np.concatenate(all_is_adv_not_detected) + print("ASR (w/o detector):", np.mean(all_is_adv)) + print("ASR (w/ detector):", np.mean(all_is_adv_not_detected)) + + + + + + + + diff --git a/case_studies/ml_loo/adversarial_evaluation.sh b/case_studies/ml_loo/adversarial_evaluation.sh new file mode 100644 index 0000000..fb2b6b8 --- /dev/null +++ b/case_studies/ml_loo/adversarial_evaluation.sh @@ -0,0 +1,51 @@ +# strong bim/bim: +#fpr1="0.2630430452371708" +#fpr5="0.05742787427778243" +#fpr10="0.006814145480778491" + +# weak bim/bim2: +fpr1="0.8909015048587877" +fpr5="0.38117096263305317" +fpr10="0.05692284412332819" + +nsamples=${1:-512} +fpr=${2:-5} + +case $fpr in + 1) + echo "Evaluating at @FPR=1" + threshold=${fpr1} + ;; + 5) + echo "Evaluating at @FPR=5" + threshold=${fpr5} + ;; + 10) + echo "Evaluating at @FPR=10" + threshold=${fpr10} + ;; +esac + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Naive attack (FPR$fpr)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 ../../venv3.8tf/bin/python adversarial_evaluation.py \ + --dataset_name cifar10 \ + --model_name resnet \ + --detector-attack=bim2 \ + --attack=bim2 \ + --detector-threshold=${threshold} \ + --batch-size=1 \ + --n-samples=512 + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Adaptive attack (FPR$fpr)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 \../../venv3.8tf/bin/python adversarial_evaluation.py \ + --dataset_name cifar10 \ + --model_name resnet \ + --detector-attack=bim2 \ + --attack=fma \ + --detector-threshold=${threshold} \ + --batch-size=1 \ + --n-samples=$nsamples diff --git a/case_studies/ml_loo/attack_model.py b/case_studies/ml_loo/attack_model.py new file mode 100644 index 0000000..ad87842 --- /dev/null +++ b/case_studies/ml_loo/attack_model.py @@ -0,0 +1,246 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +""" +This tutorial shows how to generate adversarial examples +using C&W attack in white-box setting. +The original paper can be found at: +https://nicholas.carlini.com/papers/2017_sp_nnrobustattacks.pdf +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals +import logging +import os +import numpy as np +import tensorflow as tf +from tensorflow.python.platform import flags +from keras.layers import Input +from cleverhans.attacks import CarliniWagnerL2 +from cleverhans.dataset import MNIST +from cleverhans.loss import CrossEntropy +from cleverhans.utils import grid_visual, AccuracyReport +from cleverhans.utils import set_log_level +from cleverhans.utils_tf import model_eval, tf_model_load +from cleverhans.train import train +from cleverhans.utils_keras import KerasModelWrapper +import pickle as pkl +from keras import backend as K + +from cleverhans.attacks import CarliniWagnerL2, FastGradientMethod, SaliencyMapMethod, DeepFool, BasicIterativeMethod + +class Attack(object): + def __init__(self, model, *args): + self.model = model + + def attack(self, x, *args): + raise NotImplementedError + +class CleverhansAttackFeedableRunMixin: + def generate_np(self, x_val, feedable_dict={}, **kwargs): + """ + Generate adversarial examples and return them as a NumPy array. + Sub-classes *should not* implement this method unless they must + perform special handling of arguments. + :param x_val: A NumPy array with the original inputs. + :param **kwargs: optional parameters used by child classes. + :return: A NumPy array holding the adversarial examples. + """ + + if self.sess is None: + raise ValueError("Cannot use `generate_np` when no `sess` was" + " provided") + + packed = self.construct_variables(kwargs) + fixed, feedable, _, hash_key = packed + + if hash_key not in self.graphs: + self.construct_graph(fixed, feedable, x_val, hash_key) + else: + # remove the None arguments, they are just left blank + for k in list(feedable.keys()): + if feedable[k] is None: + del feedable[k] + + x, new_kwargs, x_adv = self.graphs[hash_key] + + feed_dict = {x: x_val} + + for name in feedable: + feed_dict[new_kwargs[name]] = feedable[name] + + return self.sess.run(x_adv, {**feed_dict, **feedable_dict}) + +class FeedableRunCarliniWagnerL2(CleverhansAttackFeedableRunMixin, CarliniWagnerL2): + pass + + +class FeedableRunBasicIterativeMethod(CleverhansAttackFeedableRunMixin, BasicIterativeMethod): + pass + + +class CW(Attack): + def __init__(self, model, sess, input_ph, num_classes, source_samples = 2, binary_search_steps = 5, cw_learning_rate = 5e-3, confidence = 0, attack_iterations = 1000, attack_initial_const = 1e-2): + super(Attack, self).__init__() + + self.model = model + self.sess = sess + + self.x = input_ph + self.y = Input(shape=(num_classes,), dtype = 'float32') + + abort_early = True + self.cw = FeedableRunCarliniWagnerL2(self.model, sess=self.sess) + self.cw_params = { + 'binary_search_steps': binary_search_steps, + "y": None, + 'abort_early': True, + 'max_iterations': attack_iterations, + 'learning_rate': cw_learning_rate , + 'batch_size': source_samples, + 'initial_const': attack_initial_const , + 'confidence': confidence, + 'clip_min': 0.0, + } + + def attack(self, x, y = None, feedable_dict={}): + # print(self.cw_params) + adv = self.cw.generate_np(x, **self.cw_params, feedable_dict=feedable_dict) + + if y: + eval_params = {'batch_size': 100} + preds = self.model.get_logits(self.x) + acc = model_eval(self.sess, self.x, self.y, preds, adv, y, args=eval_params) + adv_success = 1 - acc + print('The adversarial success rate is {}.'.format(adv_success)) + + return adv + + +# added by AUTHOR according to the description in the paper +class BIM(Attack): + def __init__(self, model, sess, input_ph, num_classes, epsilon=0.03, learning_rate = 5e-3, attack_iterations = 1000, random_init=True): + super(Attack, self).__init__() + + self.model = model + self.sess = sess + + self.x = input_ph + self.y = Input(shape=(num_classes,), dtype = 'float32') + + self.bim = FeedableRunBasicIterativeMethod(self.model, sess=self.sess) + self.bim_params = { + "y": None, + 'nb_iter': attack_iterations, + 'eps_iter': learning_rate, + 'eps': epsilon, + 'rand_init': random_init, + 'clip_min': 0.0, + 'clip_max': 1.0, + } + + def attack(self, x, y = None, feedable_dict={}): + # print(self.bim_params) + adv = self.bim.generate_np(x, **self.bim_params, feedable_dict=feedable_dict) + + if y: + eval_params = {'batch_size': 100} + preds = self.model.get_logits(self.x) + acc = model_eval(self.sess, self.x, self.y, preds, adv, y, args=eval_params) + adv_success = 1 - acc + print('The adversarial success rate is {}.'.format(adv_success)) + + return adv + + +class FMA(Attack): + def __init__(self, raw_model, model, sess, input_ph, num_classes, target_samples, + reference, + features, epsilon=0.03, num_random_features=1000, + learning_rate = 5e-3, attack_iterations = 1000, random_init=True, + verbose=False): + super(Attack, self).__init__() + + self.raw_model = raw_model + self.model = model + self.sess = sess + + self.reference = reference + self.features = features + + assert len(target_samples) == num_classes, (len(target_samples), num_classes) + self.target_samples = target_samples + + self.x = input_ph + self.y = Input(shape=(num_classes,), dtype = 'float32') + + self.logits = model.get_logits(input_ph) + + self.epsilon = epsilon + self.learning_rate = learning_rate + self.attack_iterations = attack_iterations + self.random_init = random_init + + self.all_features = tf.concat(features, 1) + num_random_features = min(num_random_features, self.all_features.shape[1].value) + self.num_random_features = num_random_features + self.feature_indices_ph = tf.placeholder(tf.int32, shape=(num_random_features,)) + self.target_features_ph = tf.placeholder(tf.float32, + shape=self.all_features.shape) + + self.loss = tf.nn.l2_loss(tf.gather(self.all_features - + tf.expand_dims(self.target_features_ph, 0), self.feature_indices_ph, axis=1)) + self.gradient = tf.gradients(self.loss, self.x)[0] + + self.verbose = verbose + + def attack(self, x, y = None, feedable_dict={}): + assert len(x) == 1, "attack can only process a single sample at a time" + # print(self.bim_params) + + y = self.sess.run(self.logits, {self.x: x, **feedable_dict}).argmax(-1)[0] + x_target = self.target_samples[(y + 1) % 10] + + from ml_loo import loo_ml_instance + target_features = loo_ml_instance(x_target, self.reference, self.raw_model, self.features, + batch_size=3100)[:, :-1] + + if not self.random_init: + x_adv = x + else: + x_adv = np.clip(x + np.random.uniform(-self.epsilon, +self.epsilon, x.shape), 0, 1) + + for i in range(self.attack_iterations): + feature_indices = np.random.choice( + np.arange(self.all_features.shape[-1].value), + self.num_random_features) + loss_value, logits_value, gradient_value = self.sess.run( + (self.loss, self.logits, self.gradient), + { + self.x: x_adv, + self.target_features_ph: target_features, + self.feature_indices_ph: feature_indices, + **feedable_dict + } + ) + gradient_value = np.sign(gradient_value) + x_adv -= self.learning_rate * gradient_value + delta = np.clip(x_adv - x, -self.epsilon, +self.epsilon) + x_adv = np.clip(x + delta, 0, 1) + + if self.verbose: + print(loss_value, logits_value) + + return x_adv diff --git a/case_studies/ml_loo/binarization_test.py b/case_studies/ml_loo/binarization_test.py new file mode 100644 index 0000000..351947a --- /dev/null +++ b/case_studies/ml_loo/binarization_test.py @@ -0,0 +1,415 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +# disable tf logging +# some of these might have to be commented out to use verbose=True in the +# adaptive attack +import os + +import torch + +from ml_loo import collect_layers +from tensorflow_wrapper import TensorFlow1ToPyTorchWrapper +from utils import build_dataloader_from_arrays + +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' +import warnings +import logging +logging.getLogger('tensorflow').setLevel(logging.FATAL) +import tensorflow as tf +tf.logging.set_verbosity(tf.logging.ERROR) + +try: + import cPickle as pickle +except: + import _pickle as pickle + +import cleverhans +from cleverhans.utils_keras import KerasModelWrapper + +from active_tests.decision_boundary_binarization import \ + interior_boundary_discrimination_attack + + +import numpy as np +from sklearn.linear_model import LogisticRegressionCV +from tqdm import tqdm + +from build_model import ImageModel +from load_data import ImageData, split_data +from attack_model import BIM, CW, FMA + + + +if __name__ == '__main__': + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('--dataset_name', type = str, + choices = ['cifar10'], + default = 'cifar10') + parser.add_argument('--model_name', type = str, + choices = ['resnet'], + default = 'resnet') + parser.add_argument( + '--attack', + type = str, + choices = ['cw', 'bim', 'fma'], + default = 'cw' + ) + parser.add_argument( + '--detector-attack', + type = str, + choices = ['cw', 'bim', 'bim2'], + default = 'cw' + ) + parser.add_argument("--n-samples", type=int, default=500) + + parser.add_argument("--n-boundary-points", type=int, default=1) + parser.add_argument("--n-inner-points", type=int, default=999) + + # default equals value for FPPR5; obtained from train_and_evaluate.py + parser.add_argument("--detector-threshold", type=float, default=0.6151412488088068) + + parser.add_argument("--inverted-test", action="store_true") + args = parser.parse_args() + + if args.inverted_test: + print("Running inverted test") + else: + print("Running normal/non-inverted test") + + dict_a = vars(args) + args.data_model = args.dataset_name + args.model_name + + # load detector + with open(f"{args.data_model}/models/ml_loo_{args.detector_attack}_lr.pkl", "rb") as f: + lr = pickle.load(f) + + print('Loading dataset...') + dataset = ImageData(args.dataset_name) + model = ImageModel(args.model_name, args.dataset_name, train = False, load = True) + + class ModelWrapper(cleverhans.model.Model): + def __init__(self, model, sess, input_ph, weight_shape, bias_shape): + self.weight = tf.placeholder(dtype=tf.float32, shape=weight_shape) + self.bias = tf.placeholder(dtype=tf.float32, shape=bias_shape) + self.model = model + self.sess = sess + self.input_ph = input_ph + self.num_classes = 2 + self.first = True + + def fprop(self, x): + y = self.model.get_layer(x, "flatten_1") + logits = y @ tf.transpose(self.weight) + tf.reshape(self.bias, (1, -1)) + return {"logits": logits, "probs": tf.nn.softmax(logits, -1), "predictions": tf.argmax(logits, -1)} + + def get_probs(self, x): + return self.fprop(x)["probs"] + + def predict(self, x, weights_feed_dict, logits=True): + if self.first: + self.targets = self.fprop(self.input_ph) + self.first = False + targets = self.targets + if logits: + target = targets["logits"] + else: + target = targets["probs"] + return self.sess.run(target, {self.input_ph: x, **weights_feed_dict}) + + keras_model = KerasModelWrapper(model.model) + wrapped_model = ModelWrapper(keras_model, model.sess, model.input_ph, (2, 256), (2,)) + + features = keras_model.get_layer(model.input_ph, "flatten_1") + feature_gradients = tf.gradients(features, model.input_ph)[0] + logits = keras_model.get_logits(model.input_ph) + + def run_features(x: np.ndarray, features_only=True, features_and_logits=False): + if features_only: + assert not features_and_logits + targets = features + elif features_and_logits: + targets = (features, logits) + else: + targets = logits + return model.sess.run(targets, + feed_dict={model.input_ph: x.transpose(0, 2, 3, 1)}) + + def run_features_and_gradients(x: np.ndarray): + return model.sess.run((features, feature_gradients), + feed_dict={model.input_ph: x.transpose(0, 2, 3, 1)}) + + feature_extractor = TensorFlow1ToPyTorchWrapper( + logit_forward_pass=lambda x, features_only = False, + features_and_logits = False: run_features(x, features_only, + features_and_logits), + logit_forward_and_backward_pass=lambda x: run_features_and_gradients(x) + ) + + if args.dataset_name == 'cifar10': + X_train, Y_train, X_test, Y_test = split_data(dataset.x_val, + dataset.y_val, model, num_classes = 10, + split_rate = 0.8, sample_per_class = 1000) + else: + raise NotImplementedError() + + if args.n_samples == -1: + args.n_samples = len(X_test) + + X_test = X_test[:args.n_samples] + Y_test = Y_test[:args.n_samples] + + from ml_loo import get_ml_loo_features + + if args.model_name == 'resnet': + interested_layers = [14,24,35,45,56,67,70] + else: + raise ValueError() + + # only relevant feature used by logistic regression model + stat_names = ['quantile'] + reference = - dataset.x_train_mean + get_ml_loo_features_ = lambda x: get_ml_loo_features(model, x, reference, interested_layers, stat_names=stat_names)[:, 0] + detector = lambda x: lr.predict_proba(get_ml_loo_features_(x))[:, 1] + + batch_size = 50 + detector_threshold = args.detector_threshold + + if args.attack == 'cw': + if args.dataset_name in ['cifar10']: + if args.model_name == 'resnet': + attack_model = CW( + wrapped_model, + wrapped_model.sess, + wrapped_model.input_ph, + wrapped_model.num_classes, + source_samples = 1, + binary_search_steps = 5, + cw_learning_rate = 1e-2, + confidence = 0, + attack_iterations = 100, + attack_initial_const = 1e-2, + ) + original_attack_model = CW( + keras_model, + wrapped_model.sess, + wrapped_model.input_ph, + model.num_classes, + source_samples = 1, + binary_search_steps = 5, + cw_learning_rate = 1e-2, + confidence = 0, + attack_iterations = 100, + attack_initial_const = 1e-2, + ) + elif args.attack == "bim": + if args.dataset_name in ['cifar10']: + if args.model_name == 'resnet': + attack_model = BIM( + wrapped_model, + wrapped_model.sess, + wrapped_model.input_ph, + wrapped_model.num_classes, + attack_iterations = 100, + epsilon=0.03, + learning_rate=2.5 * 0.03 / 100, + random_init=True + ) + original_attack_model = BIM( + keras_model, + wrapped_model.sess, + wrapped_model.input_ph, + model.num_classes, + attack_iterations = 100, + epsilon=0.03, + learning_rate=2.5 * 0.03 / 100, + random_init=True + ) + elif args.attack == "fma": + if args.dataset_name in ['cifar10']: + if args.model_name == 'resnet': + target_samples = [] + for y in range(10): + target_samples.append(X_train[np.argmax(Y_train == y)]) + target_samples = np.array(target_samples) + attack_model = FMA( + model, + wrapped_model, + wrapped_model.sess, + wrapped_model.input_ph, + wrapped_model.num_classes, + target_samples=target_samples[:2], + reference=reference, + features=collect_layers(model, interested_layers), + attack_iterations = 500, + epsilon=0.03, + learning_rate=4 * 0.03 / 100, + num_random_features=3100, + random_init=True + ) + original_attack_model = BIM( + keras_model, + wrapped_model.sess, + wrapped_model.input_ph, + model.num_classes, + attack_iterations = 100, + epsilon=0.03, + learning_rate=2.5 * 0.03 / 100, + random_init=True + ) + + assert 0 < X_test.max() <= 1.0, (X_test.min(), X_test.max()) + test_loader = build_dataloader_from_arrays(X_test.transpose((0, 3, 1, 2)), Y_test, batch_size=32) + + def run_attack(m, l, attack_kwargs): + # attack_kwargs contains values that might be useful for e.g. constructing logit matching evasion attacks + if args.attack == "fma": + reference_points = attack_kwargs["reference_points_x"] + if len(reference_points) < 2: + reference_points = np.concatenate([reference_points, reference_points], 0) + reference_points = reference_points.transpose((0, 2, 3, 1)) + attack_model.target_samples = reference_points + else: + del attack_kwargs + linear_layer = m[-1] + del m + + weights_feed_dict = { + wrapped_model.weight: linear_layer.weight.data.numpy(), + wrapped_model.bias: linear_layer.bias.data.numpy() + } + + for x, y in l: + x = x.numpy() + x = x.transpose((0, 2, 3, 1)) + assert len(x) == 1 + x_adv = attack_model.attack(x, feedable_dict=weights_feed_dict) + + logits_adv = wrapped_model.predict( + x_adv, weights_feed_dict=weights_feed_dict, logits=True) + y_adv = logits_adv.argmax(-1) + + is_adv = y_adv != y + is_not_detected = verify_input_data_fn(torch.tensor(x_adv.transpose((0, 3, 1, 2)))) + is_adv_and_not_detected = np.logical_and(is_adv, is_not_detected) + is_adv_and_detected = np.logical_and(is_adv, ~is_not_detected) + + if args.inverted_test: + test_result = is_adv_and_detected + else: + test_result = is_adv_and_not_detected + + return test_result, (torch.tensor(x_adv), torch.tensor(logits_adv)) + + + def get_boundary_adversarials(x, y, n_samples, epsilon): + """Generate adversarial examples for the base classifier that get + rejected by detector.""" + + assert len(x.shape) == 3 + x = x.unsqueeze(0) + x = torch.repeat_interleave(x, n_samples, dim=0) + + x = x.numpy() + x = x.transpose((0, 2, 3, 1)) + + for _ in range(25): + x_adv = original_attack_model.attack(x) + diff = x_adv - x + diff = diff / np.max(np.abs(diff)) * epsilon + x_adv = np.clip(x + diff, 0, 1) + is_detected = ~verify_input_data_fn(torch.tensor(x_adv.transpose((0, 3, 1, 2)))) + + if np.all(is_detected): + # generative until we finally found (an) adversarial example(s) that + # get(s) detected + break + else: + warnings.warn("Could not generate adversarial example that gets " + "detected after 25 trials.") + x_adv = x_adv.transpose((0, 3, 1, 2)) + + return torch.tensor(x_adv) + + + from argparse_utils import DecisionBoundaryBinarizationSettings + from active_tests.decision_boundary_binarization import format_result + + if args.inverted_test: + additional_settings = dict( + n_boundary_points=args.n_boundary_points, + n_boundary_adversarial_points=1, + n_far_off_boundary_points=1, + n_far_off_adversarial_points=1, + ) + else: + additional_settings = dict( + n_boundary_points=args.n_boundary_points, + n_boundary_adversarial_points=args.n_boundary_points - 1, + n_far_off_boundary_points=1, + n_far_off_adversarial_points=0, + ) + + far_off_distance = 1.75 + + def verify_input_data_fn(x: torch.Tensor) -> np.ndarray: + """Checks if detector does not reject input data as adversarial, i.e. + input is clean.""" + #if args.inverted_test: + # return detector(x.numpy().transpose((0, 2, 3, 1))) > detector_threshold + #else: + return detector(x.numpy().transpose((0, 2, 3, 1))) < detector_threshold + + scores_logit_differences_and_validation_accuracies = \ + interior_boundary_discrimination_attack( + feature_extractor, + test_loader, + attack_fn=lambda m, l, attack_kwargs: run_attack(m, l, attack_kwargs), + linearization_settings=DecisionBoundaryBinarizationSettings( + epsilon=0.03, + norm="linf", + lr=10000, + adversarial_attack_settings=None, + optimizer="sklearn", + n_inner_points=args.n_inner_points, + **additional_settings + ), + n_samples=args.n_samples, + device="cpu", + n_samples_evaluation=200, + n_samples_asr_evaluation=200, + + verify_valid_boundary_training_data_fn=verify_input_data_fn, + get_boundary_adversarials_fn=get_boundary_adversarials, + verify_valid_inner_training_data_fn=None, + verify_valid_input_validation_data_fn=None, + fill_batches_for_verification=False, + far_off_distance=far_off_distance, + rejection_resampling_max_repetitions=25, + rescale_logits="adaptive" + ) + + print(format_result(scores_logit_differences_and_validation_accuracies, args.n_samples)) + + + + + + diff --git a/case_studies/ml_loo/binarization_test.sh b/case_studies/ml_loo/binarization_test.sh new file mode 100644 index 0000000..1b977b1 --- /dev/null +++ b/case_studies/ml_loo/binarization_test.sh @@ -0,0 +1,60 @@ +# strong bim/bim: +#fpr1="0.2630430452371708" +#fpr5="0.05742787427778243" +#fpr10="0.006814145480778491" + +# weak bim/bim2: +fpr1="0.8909015048587877" +fpr5="0.38117096263305317" +fpr10="0.05692284412332819" + +nsamples=${1:-512} + +echo "Testing for FPR5" + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Normal Test (naive attack)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd)/../../ ../../venv3.8tf/bin/python binarization_test.py \ + --dataset_name cifar10 \ + --model_name resnet \ + --n-samples=$nsamples \ + --detector-threshold=${fpr5} \ + --attack=bim \ + --detector-attack=bim + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Inverted Test (naive attack)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd)/../../ ../../venv3.8tf/bin/python binarization_test.py \ + --dataset_name cifar10 \ + --model_name resnet \ + --n-samples=$nsamples \ + --detector-threshold=${fpr5} \ + --attack=bim \ + --detector-attack=bim \ + --inverted-test + + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Normal Test (adaptive attack)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd)/../../ ../../venv3.8tf/bin/python binarization_test.py \ + --dataset_name cifar10 \ + --model_name resnet \ + --n-samples=$nsamples \ + --detector-threshold=${fpr5} \ + --attack=fma \ + --detector-attack=bim + +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +echo "Inverted Test (adaptive attack)" +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +TF_CPP_MIN_LOG_LEVEL=3 PYTHONPATH=$PYTHONPATH:$(pwd)/../../ ../../venv3.8tf/bin/python binarization_test.py \ + --dataset_name cifar10 \ + --model_name resnet \ + --n-samples=$nsamples \ + --detector-threshold=${fpr5} \ + --attack=fma \ + --detector-attack=bim \ + --inverted-test \ No newline at end of file diff --git a/case_studies/ml_loo/build_model.py b/case_studies/ml_loo/build_model.py new file mode 100644 index 0000000..095e28a --- /dev/null +++ b/case_studies/ml_loo/build_model.py @@ -0,0 +1,570 @@ +# Copyright 2022 The Authors +# +# 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 +# +# https://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. + +from __future__ import absolute_import, division, print_function +import tensorflow as tf +import numpy as np +import os +from keras.layers import Flatten, Conv2D, MaxPooling2D, Conv2DTranspose, UpSampling2D, Convolution2D, BatchNormalization, Dense, Dropout, Activation, Embedding, Conv1D, Input, GlobalMaxPooling1D, Multiply, Lambda, Permute, GlobalAveragePooling2D +from keras.preprocessing import sequence +from keras.datasets import imdb, mnist +from keras.callbacks import ModelCheckpoint +from keras.models import Model, Sequential +from keras.objectives import binary_crossentropy +from keras.metrics import binary_accuracy as accuracy +from keras.optimizers import RMSprop +from keras import backend as K +from keras import optimizers +import math + + +def construct_original_network(dataset_name, model_name, train): + data_model = dataset_name + model_name + if dataset_name == 'mnist': + input_size = 28 + num_classes = 10 + channel = 1 + + + elif dataset_name == 'cifar10': + # Define the model + input_size = 32 + num_classes = 10 + channel = 3 + + elif dataset_name == 'cifar100': + # Define the model + input_size = 32 + num_classes = 100 + channel = 3 + + if model_name == 'scnn': + image_ph = Input(shape=(input_size,input_size,channel),dtype = 'float32') + net = Convolution2D(32, kernel_size=(5, 5),padding = 'same', + activation='relu', name = 'conv1')(image_ph) + net = MaxPooling2D(pool_size=(2, 2))(net) + net = Convolution2D(64, (5, 5),padding = 'same', + activation='relu', name = 'conv2')(net) + net = MaxPooling2D(pool_size=(2, 2))(net) + + net = Flatten()(net) + net = Dense(1024, activation='relu',name='fc1')(net) + net = Dense(num_classes, activation='softmax',name='fc2')(net) + preds = Activation('softmax')(net) + model = Model(image_ph, preds) + + model.compile(loss='categorical_crossentropy', + optimizer='adam', + metrics=['acc']) + + elif model_name == 'cnn': + image_ph = Input(shape=(input_size,input_size,channel),dtype = 'float32') + net = Convolution2D(48, (3,3), padding='same', input_shape=(32, 32, 3))(image_ph) + net = Activation('relu')(net) + net = Convolution2D(48, (3, 3))(net) + net = Activation('relu')(net) + net = MaxPooling2D(pool_size=(2, 2))(net) + net = Dropout(0.25)(net) + net = Convolution2D(96, (3,3), padding='same')(net) + net = Activation('relu')(net) + net = Convolution2D(96, (3, 3))(net) + net = Activation('relu')(net) + net = MaxPooling2D(pool_size=(2, 2))(net) + net = Dropout(0.25)(net) + net = Convolution2D(192, (3,3), padding='same')(net) + net = Activation('relu')(net) + net = Convolution2D(192, (3, 3))(net) + net = Activation('relu')(net) + net = MaxPooling2D(pool_size=(2, 2))(net) + net = Dropout(0.25)(net) + net = Flatten()(net) + net = Dense(512)(net) + net = Activation('relu')(net) + net = Dropout(0.5)(net) + net = Dense(256)(net) + net = Activation('relu')(net) + net = Dropout(0.5)(net) + net = Dense(num_classes, activation=None)(net) + preds = Activation('softmax')(net) + + model = Model(image_ph, preds) + sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) + + model.compile(loss='categorical_crossentropy', + optimizer=sgd, + metrics=['acc']) + + # Compile the model + elif model_name == 'fc': + image_ph = Input(shape=(input_size,input_size,channel),dtype = 'float32') + net = Flatten()(image_ph) + net = Dense(256)(net) + net = Activation('relu')(net) + + net = Dense(256)(net) + net = Activation('relu')(net) + + net = Dense(256)(net) + net = Activation('relu')(net) + + preds = Dense(num_classes, activation='softmax')(net) + + model = Model(image_ph, preds) + sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) + + model.compile(loss='categorical_crossentropy', + optimizer=sgd, + metrics=['acc']) + + elif model_name == 'resnet': + from resnet import resnet_v2, lr_schedule, lr_schedule_sgd + + model, image_ph, preds = resnet_v2(input_shape=(input_size, input_size, channel), depth=20, num_classes = num_classes) + + optimizer = optimizers.SGD(lr=0.1, momentum=0.9, nesterov=True) + + + model.compile(loss='categorical_crossentropy', + optimizer=optimizer, + metrics=['accuracy']) + + elif model_name == 'densenet': + from densenet import DenseNet + nb_filter = -1#12 if dataset_name == 'cifar100' else -1 + + image_ph = Input(shape=(input_size,input_size,channel),dtype = 'float32') + model, preds = DenseNet((input_size,input_size,channel), + classes=num_classes, depth=40, nb_dense_block=3, growth_rate=12, nb_filter=nb_filter, dropout_rate=0.0, weights=None, input_tensor = image_ph) + + optimizer = optimizers.SGD(lr=0.1, momentum=0.9, nesterov=True) + + + model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=["accuracy"]) + + grads = [] + for c in range(num_classes): + grads.append(tf.gradients(preds[:,c], image_ph)) + + grads = tf.concat(grads, axis = 0) + approxs = grads * tf.expand_dims(image_ph, 0) + + logits = [layer.output for layer in model.layers][-2] + print(logits) + + sess = K.get_session() + + return image_ph, preds, grads, approxs, sess, model, num_classes, logits + + +class ImageModel(): + def __init__(self, model_name, dataset_name, train = False, load = False, **kwargs): + self.model_name = model_name + self.dataset_name = dataset_name + self.data_model = dataset_name + model_name + self.framework = 'keras' + + # if not train: + # K.set_learning_phase(0) + + print('Constructing network...') + self.input_ph, self.preds, self.grads, self.approxs, self.sess, self.model, self.num_classes, self.logits = construct_original_network(self.dataset_name, self.model_name, train = train) + + + self.layers = self.model.layers + self.last_hidden_layer = self.model.layers[-3] + + self.y_ph = tf.placeholder(tf.float32, shape = [None, self.num_classes]) + if load: + if load == True: + print('Loading model weights...') + self.model.load_weights('{}/models/original.hdf5'.format(self.data_model), + by_name=True) + elif load != False: + self.model.load_weights('{}/models/{}.hdf5'.format(self.data_model, load), + by_name=True) + + self.pred_counter = 0 + + def train(self, dataset): + print('Training...') + if self.dataset_name == 'mnist': + assert self.model_name in ['cnn', 'scnn'] + data_model = self.dataset_name + self.model_name + filepath="{}/models/original.hdf5".format(data_model) + checkpoint = ModelCheckpoint(filepath, monitor='val_acc', + verbose=1, save_best_only=True, mode='max') + callbacks_list = [checkpoint] + history = self.model.fit(dataset.x_train, dataset.y_train, + validation_data=(dataset.x_val, dataset.y_val), + callbacks = callbacks_list, + epochs=100, batch_size=128) + # print(history.history) + elif self.dataset_name in ['cifar10', 'cifar100']: + from keras.preprocessing.image import ImageDataGenerator + + if self.model_name == 'cnn': + datagen = ImageDataGenerator(zoom_range=0.2, horizontal_flip=True) + # zoom 0.2 + datagen = create_resnet_generator(dataset.x_train) + callbacks_list = [] + batch_size = 128 + num_epochs = 200 + + elif self.model_name in ['resnet', 'densenet']: + from resnet import lr_schedule, create_resnet_generator + from keras.callbacks import LearningRateScheduler, ReduceLROnPlateau, EarlyStopping + # zoom 0.2 horizontal_filp always True. change optimizer to sgd, and batch_size to 128. + datagen = ImageDataGenerator(rotation_range=15, + width_shift_range=5./32, + height_shift_range=5./32, + horizontal_flip = True, + zoom_range = 0.2) + + datagen.fit(dataset.x_train, seed=0) + + from resnet import lr_schedule_sgd + from keras.callbacks import LearningRateScheduler + lr_scheduler = LearningRateScheduler(lr_schedule_sgd) + callbacks_list = [lr_scheduler] + batch_size = 128 if self.dataset_name == 'cifar10' else 64 + num_epochs = 200 + + filepath="{}/models/original.hdf5".format(self.data_model) + checkpoint = ModelCheckpoint(filepath, monitor='val_acc', + verbose=1, save_best_only=True, mode='max') + callbacks_list.append(checkpoint) + + + model_info = self.model.fit_generator(datagen.flow(dataset.x_train, + dataset.y_train, batch_size = batch_size), + epochs = num_epochs, + steps_per_epoch = dataset.x_train.shape[0] // batch_size, + callbacks = callbacks_list, + validation_data = (dataset.x_val, dataset.y_val), + verbose = 2, + workers = 4) + + def adv_train(self, dataset, attack_name): + from cleverhans.attacks import FastGradientMethod, ProjectedGradientDescent + from cleverhans.utils_keras import KerasModelWrapper + from cleverhans.loss import CrossEntropy + from cleverhans.train import train + from cleverhans.utils_tf import model_eval + import time, datetime + + if attack_name == 'fgsm' and self.dataset_name == 'mnist': + wrap = KerasModelWrapper(self.model) + params = {'eps': 0.3, + 'clip_min': -1., + 'clip_max': 1.} + + attacker = FastGradientMethod(wrap, sess=self.sess) + def attack(x): + return attacker.generate(x, **params) + + preds_adv = self.model(attack(self.input_ph)) + loss = CrossEntropy(wrap, smoothing=0.1, attack=attack) + + y_ph = tf.placeholder(tf.float32, shape = (None, self.num_classes)) + + def evaluate(): + # Accuracy of adversarially trained model on legitimate test inputs + eval_params = {'batch_size': 128} + accuracy = model_eval(self.sess, self.input_ph, y_ph, self.preds, dataset.x_val, dataset.y_val, args=eval_params) + print('Test accuracy on legitimate examples: %0.4f' % accuracy) + + # Accuracy of the adversarially trained model on adversarial examples + accuracy = model_eval(self.sess, self.input_ph, y_ph, preds_adv, dataset.x_val, dataset.y_val, args=eval_params) + print('Test accuracy on adversarial examples: %0.4f' % accuracy) + + # if self.dataset_name == 'mnist': + train_params = { + 'nb_epochs': 20, + 'batch_size': 128, + 'learning_rate': 0.001, + 'train_dir': '{}/models'.format(self.data_model), + 'filename': 'adv.cpkt' + } + + # Perform and evaluate adversarial training + train(self.sess, loss, dataset.x_train, dataset.y_train, evaluate=evaluate, + args=train_params, rng=np.random.RandomState([2017, 8, 30])) + + self.model.save_weights('{}/models/{}.hdf5'.format(self.data_model, 'adv-{}'.format(attack_name))) + + elif attack_name == 'pgd': + if self.dataset_name == 'mnist': + params = {'eps': 0.1, + # 'clip_min': -1.0, + # 'clip_max': 1.0, + 'eps_iter': 0.01, + 'nb_iter': 20, + 'epochs': 100, + 'batch_size': 50, + } + elif self.dataset_name == 'cifar10': + params = {'eps': 8.0 / 255 * 2, + # 'clip_min': -1.0, + # 'clip_max': 1.0, + 'eps_iter': 2.0 / 255 * 2, + 'nb_iter': 10,#10,#1, + 'epochs': 200, + 'batch_size': 128, + } + + # attacker = ProjectedGradientDescent(wrap, sess=self.sess) + + # import foolbox + # from foolbox.attacks import ProjectedGradientDescentAttack + from attack_model import LinfPGDAttack + # Main training loop + # fmodel = foolbox.models.KerasModel(self.model, bounds=(-1, 1), preprocessing=(0, 1)) + attacker = LinfPGDAttack(self, params['eps'], k = params['nb_iter'], a = params['eps_iter'], clip_min = dataset.clip_min, clip_max = dataset.clip_max, + random_start = True, loss_func = 'xent') + + def attack(x, y): + # return attacker(x, label=label, unpack=True, binary_search=False, epsilon=params['eps'], stepsize=params['eps_iter'], + # iterations=params['nb_iter'], + # random_start=False, return_early=True) + return attacker.attack(x, np.argmax(y, axis = -1)) + + from resnet import lr_schedule, create_resnet_generator, lr_schedule_sgd + from keras.preprocessing.image import ImageDataGenerator + + # datagen = create_resnet_generator(dataset.x_train) + datagen = ImageDataGenerator(rotation_range=15, + width_shift_range=5./32, + height_shift_range=5./32, + horizontal_flip = True, + zoom_range = 0.2) + + datagen.fit(dataset.x_train, seed=0) + + xent = tf.reduce_mean(K.categorical_crossentropy(self.y_ph, self.preds), name='y_xent') + + + global_step = tf.train.get_or_create_global_step() + + if self.dataset_name == 'cifar10': + momentum = 0.9 + weight_decay = 0.0002 + costs = [] + print('number of trainable variables: ',len(tf.trainable_variables())) + for var in tf.trainable_variables(): + if 'kernel' in var.name: + costs.append(tf.nn.l2_loss(var)) + penalty = tf.add_n(costs) + + loss = xent + weight_decay * penalty + elif self.dataset_name == 'mnist': + loss = xent + + + if self.dataset_name == 'cifar10': + boundaries = [40000,60000] + values = [0.1,0.01,0.001] + learning_rate = tf.train.piecewise_constant( + tf.cast(global_step, tf.int32), + boundaries, + values) + optimizer = tf.train.MomentumOptimizer(learning_rate, momentum) + elif self.dataset_name == 'mnist': + boundaries = [50000] + values = [1e-3,1e-4] + learning_rate = tf.train.piecewise_constant( + tf.cast(global_step, tf.int32), + boundaries, + values) + optimizer = tf.train.AdamOptimizer(learning_rate) + + train_step = optimizer.minimize(loss, global_step=global_step) + + + accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(self.preds, 1), + tf.argmax(self.y_ph, 1)), tf.float32)) + + num_output_steps = 100 # 100 + num_checkpoint_steps = 1000 + batch_size = params['batch_size'] + ii = 0 + epochs = params['epochs'] + + for e in range(epochs): + num_batches = 0 + for x_batch, y_batch in datagen.flow(dataset.x_train, dataset.y_train, batch_size=batch_size): + + # Compute Adversarial Perturbations + start = time.time() + + x_batch_adv = attack(x_batch, y_batch) + + nat_dict = {self.input_ph: x_batch, + self.y_ph: y_batch} + + adv_dict = {self.input_ph: x_batch_adv, + self.y_ph: y_batch} + eval_dict = {self.input_ph: dataset.x_train[:1000], + self.y_ph: dataset.y_train[:1000]} + val_dict = {self.input_ph: dataset.x_val[:1000], + self.y_ph: dataset.y_val[:1000]} + # Output to stdout + if ii % num_output_steps == 0: + nat_acc = self.sess.run(accuracy, feed_dict=eval_dict) + val_acc = self.sess.run(accuracy, feed_dict=val_dict) + adv_acc = self.sess.run(accuracy, feed_dict=adv_dict) + + print('Step {} '.format(ii)) + print(' training nat accuracy {:.4}%'.format(nat_acc * 100)) + print(' validation accuracy {:.4}%'.format(val_acc * 100)) + print(' training adv accuracy {:.4}%'.format(adv_acc * 100)) + + if ii != 0: + print(' {} examples per second'.format( + num_output_steps * batch_size / training_time)) + training_time = 0.0 + + + # Write a checkpoint + if ii % num_checkpoint_steps == 0: + self.model.save_weights('{}/models/adv-{}-{}.hdf5'.format(self.data_model, attack_name, ii)) + + # Actual training step + + _ = self.sess.run(train_step, feed_dict=adv_dict) + # print(step) + end = time.time() + training_time = end - start + ii += 1 + num_batches += 1 + + if num_batches >= len(dataset.x_train) / batch_size: + break + + self.model.save_weights('{}/models/adv-{}.hdf5'.format(self.data_model, attack_name)) + + + + def predict(self, x, verbose=0, batch_size = 500, logits = False): + x = np.array(x) + if len(x.shape) == 3: + _x = np.expand_dims(x, 0) + else: + _x = x + + self.pred_counter += len(_x) + + if not logits: + prob = self.model.predict(_x, batch_size = batch_size, + verbose = verbose) + else: + num_iters = int(math.ceil(len(_x) * 1.0 / batch_size)) + probs = [] + for i in range(num_iters): + # print('{} samples predicted'.format(i * batch_size)) + x_batch = _x[i * batch_size: (i+1) * batch_size] + + prob = self.sess.run(self.logits, + feed_dict = {self.input_ph: x_batch}) + + probs.append(prob) + + prob = np.concatenate(probs, axis = 0) + + if len(x.shape) == 3: + prob = prob.reshape(-1) + + return prob + + def compute_saliency(self, x, saliency_type = 'gradient'): + x = np.array(x) + if self.dataset_name in ['mnist', 'cifar10', 'cifar100']: + batchsize = 128 #if self.data in ['imdbcnn','imdblstm'] else 20 + num_iters = int(math.ceil(len(x) * 1.0 / batchsize)) + approxs_val = [] + + for i in range(num_iters): + batch_data = x[i * batchsize: (i+1) * batchsize] + + if saliency_type == 'gradient': + approxs = self.grads + + elif saliency_type == 'taylor': + approxs = self.approxs + + batch_approxs = self.sess.run(approxs, feed_dict = {self.input_ph: batch_data}) + # [num_classes, batchsize, h, w, c] + approxs_val.append(batch_approxs) + + approxs_val = np.concatenate(approxs_val, axis = 1) + # [num_classes, num_data, h, w, c] + + pred_val = self.predict(x) + + class_specific_scores = approxs_val[np.argmax(pred_val, axis = 1), range(len(pred_val))] + # [num_data, h, w, c] + + return class_specific_scores + + def compute_ig(self, x, reference): + x = np.array(x) + if self.dataset_name in ['mnist', 'cifar10', 'cifar100']: + batchsize = 1 + steps = 50 + + pred_vals = self.predict(x) + class_specific_scores = [] + + num_iters = int(math.ceil(len(x) * 1.0 / batchsize)) + for i in range(num_iters): + batch_data = x[i * batchsize: (i+1) * batchsize] + _, h, w, c = batch_data.shape + step_batch = [batch_data * float(s) / steps + reference * (1 - float(s) / steps) for s in range(1, steps+1)] + # [steps,batchsize, h, w, c] + + step_batch = np.reshape(step_batch, + [-1, h, w, c]) + # [steps * batchsize, h, w, c] + + batch_grads = self.sess.run(self.grads, + feed_dict = {self.input_ph: step_batch}) + # [num_classes, steps * batchsize, h, w, c] + num_classes, _, h, w, c = batch_grads.shape + grads_val = np.mean(batch_grads.reshape([num_classes, steps, -1, h, w, c]), axis = 1) + approxs_val = grads_val * (batch_data - reference) + # [num_classes, batchsize, h, w, c] + + pred_val = pred_vals[i * batchsize: (i+1) * batchsize] + class_specific_score = approxs_val[np.argmax(pred_val, axis = 1), range(len(pred_val))] + # [batchsize, h, w, c] + + # [batchsize, maxlen] + class_specific_scores.append(class_specific_score) + + # [num_data, length] + return np.concatenate(class_specific_scores, axis = 0) + + + + + + + + + + + + + + + diff --git a/case_studies/ml_loo/cifar10resnet/models/original.hdf5 b/case_studies/ml_loo/cifar10resnet/models/original.hdf5 new file mode 100644 index 0000000000000000000000000000000000000000..c4cbbe35b4b1f93d8739ebc8b695d1ce58c42403 GIT binary patch literal 4816920 zcmeD^1zc6h*N>1^5EMa>QWQ~b|R@PRG@5Q|e?8Er4yPxawe!C8L?wK=Z&YYTaXYQTr(y2>*rKU<8;ZH$8bQ4vv*X;d~%pX!r8OxNLq{V+oaTGYhdsl<{9oW&L=F~KO|UC zuPx|6s7b>A#eFFV{$l^;aOw#!#8smEDjX*UpMnVAC{M33KEdAK#3NE%29J;xU+AhY z!XxH~S4i+^e_vsj-=fQT#uvJTD$43>xlT)AbB>?rU*R|;>-D|)Vt|8k;!>>F4Qkcv z<7r|zEyf<0990xmxCogm_!VtxE-KBL2|K?{{Kt7wEr+w|ju_C5kprh}aeI3PpI=Z@ z5oA0ApJ^y=AJ5>kUm$K+!Ca@b5EGus;L~~`HjSGYd~S2Z_+l7*=4-_botXB^9vF-6 zFjK-n)fKgIfYs|5kwS1d2bp=-QW4Lilt9vitY!TNtB>wC#TX~t7MD^2?WqdK%B{;2 z@%4R;C+OKT!pc&3dz5E{m!F5fu!%>wpQq^l(BR0xz_tcfmdyXd1#m1WVn_>N)9_Hw zuy7&1(Vl_fK2roW{=uU{B7?m>f(7)7NR!l309cb^=aArWmYr%)D{uqpHmyU%FK?ptCGg!bgqbb5cvz!qSI?mGDL&Ta< z{sMm%=HnX~C?G;i9z(k5j-)YpdPVq;^JK{pQ0(I=nm^IlJx7U1iU^DJ5%lQo8R6+M zT1c>vCq`a=p1}f6g?k8OCPFyOP)~1f;fMwI!i5qf9EM=9%$!)XHLwuQi?@HEs5_4^ z&j{h5hO##p?p7zi=9IZwxQgUQFcg7v6f_q|q@|#6Fmn+7?5ypq?CkAqEPdLU+X#9K zv=H1hH!~NpY_xx1gjjejYz6m3Jo)-$4)F;K39mkdB21CtJ|4p60^|&HM11s*m?)Y3 z%-F&OlOkv`)Jh=X!-bRhC&?W;R8S{W3gLVT1VQlM4i>0aHGCpw1ci(fOuI*rk4QSdhM+cf zvO^PF1+h*r^os@CCp6qYP^2+}xil9@jFANSWat>jDB%A#7!iZM&W74X!D=uo5fl7{ z^3hI6t(d#D^S!#zvpOrBD~Wf4LV|pPBO-%DvhCm?oD#vc$Q%hfuT8Q9{j;V*vS>-> zzXUn!@WpCWlLw>f<|ND~Fj6Qm5+;kC@-GbpGhG|ulIf~VL29C`sU*(7k=YkJ(>k;N zuQ2-}Pgk3aSCiV>M4QoIOQELJ6zkv6_KT#u&h}S}+pBjeo;>n z!y!qwzxGj7(ISb&|4z2wO6XeaLjK<%p;XwqGROb+-Q}+I}HNzu)#t zl(WCZ_KSM@Zrfk`D5_|YMB;xZ+iz26`-STLf{ zwEaSRA$c(=DejjTWBe_)U)0lg+kT;3NFGHMEs{w5?_~S!>umoI*#3V>lC^fxW^BK` zB-{VP*{IqdX#XiYP$d;5l(<^-PLPU{_(c0RT#<-kt~#&uGrW>e*lOP`A;~3441N9< zmn7=xyIoT4jAP+JSHhyt#Cb?0 z{&%wd7UsXY@fYRZ>x}=m&-i>%9f8=^rlE`q3#MJd^R?g5`io+lI_v)vt-r`(NM27$ zGXE08jK3xH7xnbr=3ginl1EWRk0cWRTbX~+X^3BWzxOW{`&(Gr3p~;P-x<%ZKZpM6 zvYa*i67xO3l}Oi}S{5c)zjqt!uPxGFBJtYoH7nVoy?Qk_)%|dewf2qUY(LdfUsdv~ z7PTL*7G}&OZXf>*BQEiZqAuk686lTgZfXluB!yd&1N*-v-V%59-2vBE;>Icwmt^{X zEB_=qg!C(iTy-n%Ko9n<8efmNzPP8aNH^;@{xc3h6oAz^fS=(2zR1oGIRVL`&}V7= zi8)t6&{Nw935o9MD>2e%@;t;yYld>al@k!1jHq)0|BkbE-@66yD=Pq2ktLpM_#IaP zqQp|26Zn}2hdOwZr55~zJ+QZ1C#=FO_E1SHb`TR8#IDTz8K@SRTJ-;$}a zsFonAcF2MC0uoO+{BWwO_G5Q{${SQoQ`NpvUD)hDhL|%@-$FNIZhk@i%-4tY{5h z=K+3(2Veu6+7CiVw6zk0jlahW)E+F=LfQ9t0g3egR$f4KY@%+7@-JDUe0QR%_EZ9^ z$r4XJ{El8gvB0zcCW)PD9rqOFy@8vgt^;AcLq__4PYSbSxv{Fyut0hENjw7-=X zs5>F_BU`F0ZT^411o8D})}kCwZNUv|{eS(oeMwq-y?EBK^Np%w<`3Fz-iVu7AzL!P>=}aU6n)m$01p9X)_3w^Zi=eufA5 zB0IGiPl;YYVv^_Y@d7{gVh)SiQwUYPfJFL#D=$!YnCai-1-?7~TDy3&nk;b(@9*dZ zL<{jcFYq(HK<%5XC3*qLE8@?K>Ytf^{jpbcSbSxv{Fyut0hEM*>9_I%zx*lfU+T!v zzb08#yLhu+K;j2vX)zhf*0^9W_&m@l$R z_-4&FKcgTriFo9>4c*3{(5Nn%JPYDB% z;H$d`zTO_;6I>(EkT6V^F{8x|#NYA$>ey?gUjk*djp9ph5@_$_6C5u3EWN;FvoA4Y zzRdph?}80vJ}KVMOTc@<7w!d&u7bkbUpNz^A|w1oUnn;cf4^J^#C{Rn(oFFB8l!L@ zA8)~%(wMJ%2ZeYG-xFmtTJ+U)Bhi=CS)O?d2^DjUp-<4Apc7C3;D|36{_+#C@Q~3F zL7o$YluDRDre}#CAQyH0b)F6J2@46Y&MDCtBL$zB7k(GrLdcRI`mkDU^6_QPYm*9= zpHqel`t%PDjg0UJ^qlAuCZuENP^N~B#6=1DkjRLdP%IL0C)LvS!nq6-ekp1SNBHa4 zt9K_Ujxbj9J=%ZmSyVy;Ir*D-S93N5DIMYpBsFBUG8xsKNp*E3-MnW7;_O*Gb; z{8HgK$q88~#ZeLPSc@Z?OAn#)gp1%c1Ps&^-j@<{vWuve!(mIY1XwV&Y{A5FHL4}9 z!Z=k;D%+mJVK7*JsS*Aq34>)-3{~J63|8O9U{w`E6?g`NO?3=Rt#$QUp^L9E+*;_h zuG(7_EDT=T>UbrM*rqCmD%3F;?7oe`wkn1yJu(>Vt78z3tqNnAo02HAtBSV@9SmNF z>Ubq#u&;`t3LOjv3-f9yBw=uNthNlZe-O;rqEM#5sKGQk22Y;6_65!4Dt{H3L!LiCe3V%w^{eHkBv*YeB! z3QM5sd@-!6zmfoA&Bh8 z3GPOOMfwQ43KRToZf0(7VJ`kz+gS_VXl7#}$gmq#TYTD!o)0+K*;?4xTUc8P5>ZCp zK3<*^#qCAWp^$Em@jm{(exe|eiIu}WgF*v+n0gN;au(hb$6E|rI4KR-zv{|54%Bg= zjstZZsN+B#2kJOb$ALNy)N!DW19cpz#bfq)QRaFv1+nttQibEf$J{uFH# zH!R;QE>$=qKkJY1d23Dm5k7BiC;(;kh0R~HB}->}@sXwQzSN|;tP&CV@-s>w@!r)<1q9xxBqe>C7?!#o0SW8-b}WNQM)kq z<6Cw{AyW)rXJ`KMl>93Z)U-1O%qaXA`C$jesx5oXYOP2a1eNyejqfbQ@s1RuC4xqb z+_Ly;%JFxi{m+51`;1sS;I{kgEMWD#qJ|&&daK|6ZtBAJSa(|tT4`^|qaIy?-U|}Y z&dGLoT4gY`ep3)CYyOz-5*Gs+X7)VmQ+KGn^6#l070zJU=_K-2PlP^W)X3((D#V&+ zMdBKrM#j93#I(T`y!_K{dSGTM{$p?&y5y39#<))--qSlk%(=YKB6y~}Y7QprxkCA&0m%Z};1jHUg_+D2wT4b$f3swCrRt66;f*oHolyoBV)XXEaE z7tsf=#`G=e!KiBs2dvWi1gsg7MfNH6Bkiv>g;o)!bcg+}q+&@Q-m779#PWzL*%|N& zH8r|~8yuZXObi;L-EYT{u=LYpO3Zw^k^dRG+o$%0rt{Y$6@8h)vKbT6vZql#=Zscnv%h9E8@wgVW}jk3s7@zYLj&_bMTb)t6+KS$yDc)V|c48P4S5HcD&*c zFPLlc9u4)pg7t>ZLT`t^MNJ!+lU@pU!DnOR!bsm{X#A%sxYA-KdO7?U3K_0LlolQ( zy|S%IT9PYS@qRhl?;eYbPc`7F49J77r&7uLfx!))0^1hPg%O4?@ws2%@_v z1}$nC15*d_iPZjbs?E)E(repN)M>6fp4|I6mTz>GBu$DTHmesQ|7lU6Teb%i_c%Ic zWHVTFb^uQ3b`UIs@9^zXE|K@WuA)f|_{e^|JL$5hA<;f(MdpR+6D{34c&y?OV$?T+ zbZ@zhm$fPom&h(9s@@$@hr3hgl;EQvZ`%O*j+7^#-YLQ0!}n3rsbi#haUf~5VG!oK z^yc-kyh{bNyoc-gFDI=k7ot(6?Md$RgGBq$BmxbJQ75yZaKpAf{y--|f@ODH-gP%= zsa*nZTU^Djj7Rb&gw@0GJrUf0RS6|D-7Z(LvKcjYV@@~RJZslR}ixMd-EKGgxMJN7Q@ zUEx*u(kG3)7^h5%jWl@Ud=YlNGnMSo48U3514)M!C1gn>^TM%*L&(+!@9@~kWh8fP zEa`tz4W)6~77p57h<7zDB}=^;knR&xaqB(PvFR8S*yBT?lF{$+u711VWnLDKI*iVvBY@fNntB#!H+<6SQ`3sLh40M;q`cWlIz*)DKW9RiF+*D2*Va! z0hz&Sh2E7$xIqVt!pbL$NX!{i{(vL;#K=95>?%{o$+IStK52?X8_Vz-jK77fhrFO% z*Ehf$1|Oo&$OjQU3sdYeLzixFsS`f8ghy}5(IoxwXrdDwhvPh@d1e}GkPq=t2q-Z$PV@?WmK7I&bU@Be;|E2YyFsqn1uaWb24H(zxS&l-A-Ut_X6# zfy&SM{ngf!eyKbXH&qQMX|%;>i{}&P8`F{A*|~-E+5()dJg-n@(qppWd??8%FeNRQ z6p*CVl`weedSaP;jSRfDl2A82alfg3d2a^t@p8R~)FFpXWajc@5}i8u-@K zUFD-l`<6>c1E+;}x}6pBncV~zyUOv(^vcmkWj}N&E{&%i_n5R8y%Dwys6ftRi?Ewv zJ)CVgoY%;;ElOx$3fMD)9JAkm`|u4YQ~h%MXyY=X+~)!6HZdK>-gV^-?6nf_lwVHn z6_=p!6UJnL)H<9rv{PYRvry7w&t#n1-kN(c>oRiS*^z|(6(p)MlJsskuP`;OHEyZ6 z09!U1kDoVdh4l^Bl3P3-c{O!DZI`63wOv{iYDH$N=Be41=g!C)Y;*X?!aP%>qj`Ca)2&q&Zn7CP^AV1G zQ-KZjRe0B}FJkUgectoIop|oadc5(CEqMc4R${qpAMtKeMc({2{dkL#d+{{(%ki#8 zPUqdJ@5-wTxxx$HxDhY9qR&IqJK%u#d$DZmefZLnJf7b26Sy*EIi8;M4lijkhNpP8 zL1EwE@jRU?DcC>1QQ@+P{UoyCdQe(u#4|YLLZ#w4aDbBr(u?CE#&|jvG9n8UKb%0O z*L&dcGa8_Md$_#r$EU%kv8m8$WvjxTMXrTwC+nd*XYL@2{(2}nd^J*<<$~k8T*E<6 zXQTZa(=q4hCseT@4rPSDp&sc<;c15xap>t;sKpX4KJBHCr8qU$m*R+uUC*-XNVb#_ zth|J=>W{A%)$+yBlvA~!>d))N3DxfZ(-*bnu?#>=i5e5Ae`|fo*(-);ED-`oBc8|FHmVI+67Q>lTXLsGze}n@y?VA%b?oEvRuxwy01Zx6n z>Ub^6{Mr6#v51(mX8z2Hkz3YY)|BHK&Fe0!@llr9z0cvqmwcTyY#d`wz7EIESIWMx z!?AWFbN|=je)YTmoPUY`m-v@|YCUnhjvoT$`0_kXjmdyJRa2RN%layY+20YvP%n-@ z>h=v)o6Ne4&m5>3f3W_^gpnf_kc|u6*owbcvg@mw`;z{@_t_L36Ax?|Grn)d?b zjb(fGi9Ji`_vQ&)L=D(|Hte|BlEuQ7Y&~1D^=$dS=S}lZGnBI_8PVmR{koW5c9eg$ ztZko7e3=+?<_U56Ejtr>N(@(LXa4Gp{5#v%v@-_GFpe|w!;b3j-e=>-$Std%HRYJ4 zqpqyZftvel@-J7vU-OF9bNAAkcmCVgh1XVL&P6A3=4dny*UcqQZ7hgK;RLKHwFuc= z*bUDIW#Ooo?NIrMWw?jlCbC{tv2gATE7D6g06wfOgwot?FrmnjL@qN!Jtplz*LLK> zeLrQmKY~Us{U`|N6A5Rh45kJQ3;=TvDXfyShgu@F10wIdLNU(Sw7brBocMe>wQKnf zI(|7pEtJY&^`}!1zoY|BT_(+!>EZ&@9>vkE29AaG^*iAA?Tib9-V?Zvs-^e2x=}i$=M>k1&W(8x z*LE)*D{qYNBsGCRhlMcxULv`yaR^*G`jVU1)C)Zdw!u@YGuZJ#YvQ!~K6-v^4dNJI zMB7dB=_}^CNU>jM80@zV`(>n)KGZdup1u^NMs1)rJxzwjNor(QzBF&@)k$#YZ5Wxo z*_BFnUWles>O7NFTZ9IB!Mbq|$#&mFI2Wsl<4?6G?b~d|$*=nGhLVdQ>#kF{Y>W?j zsuPIc@5m+E_DOK#jyej=UWnwPR=|$TowOHKAA0Lu!|7#tpgTC2bT!r>oQ3!CwuWbk za(Dzr8*vNIfQr$nNjexOz!UIwU1 z3$p2`HyQ6}h8nAzV&6u4sG|{2;Yr6==*FvQWd5-G+!0yDsL73;FgCP3(MX(&JW5~D zMgiTCM#2Ip>9(92H`asbmD*7~+x&sNx;nzGj>Yt`t}+yvrb3>l$WYxjwkCu2T%kH2 zk%lo>27ykWEXe5UgUs^fcs^%sLq&^@<9*igaKC5^>TIrrWjZW@Xd?w&Svi{w zNNkCY^;k*{2=>)nb$UllyKx>i-rUY_onb;2ghZpti8GMwmTvU+^{>%Pji%V~O<&|O zK^5C__^9EW9+as~J=oo11#piXp*(|%(6q}+xRCRT8dq;FEthr*)xRi(E+w3SDFJtB zr_N`IU$zR-9si!(*maibU1orvzG=a8%`hTX3CH-mCw1n9&>N}o`(mM8z%2TM&ki(Y zcq&+CjYbjs7dya%MyN2SExrAP4%vB553gQ7kZ!rJh)UB{!lOIvM5e8c@T8(k2+g)4 zQK}6{3;lR<$802}wW}|-&NSj5yQGQx+yit&)|~F;umuOEyoQu^!}0AHE;=!c;yP-T zp|m-JamU&7QOn!!=@QS|j;f(yxX)NQ^0KutmJhVW+sR_8W%N4!kP2No&n*bqIyqta znJN5f7Ms!3G6j6<<9(#)muh`)t7Gn{0HwTZRyw;fHYVmi*qW86;Ur_dKqV)q-MU0u zPRSW-kHENGULTiT%~eL_P0y6ebCpxfU2`)#_uhs{JlF2IJbu|4-o5iBynBktyd7m1 zc)VfDc{2-v*EWjJi*#Ma>$yLjx2fJ5USVtrZ$`VeycdJ7@hFtSyZPca9`O1;8Kt$3 z*IC!lX+%^2uS4M!-s<-ov3{l}FLzu5?`oJ^;nT#&{jN@=i`#n_YMjeJqb@b&ac~cw>a@p& znP?d~9w5V8*0K@r;QI)aG;l5AXq`g~gY|HD=LP6o^LhBz+iqC8?QC2*Uk1ycibBuQ z2cZk?E0O$mTiifvE7knNcI=+r1h@5TY29Mb2kXs6Q*xhV4YeLOSledl;9l1DGDmjW zPEWI%{Z2aPp1+|@LYQ8zQlI8ID8(^rf653OwY%GMrhRnG34VMGPt+{NA8+R3-lPJP zqEk3hXeTDN=6O2G@;0qKfyZ>cjc+Ji#pimf@wjSN@nDBDc<%%aUZat!yn7m3@uXF4 zc}>)1c!M=#(Be`VUVP>gI(l)}!VP#SI=Rsqzt+^{#SBiw87&6Wn_tLao7pM6ZKK0r z!L9&oJi90FUhhJ9Wf9N2%`GZiKJyGOt;niyR*&wK{)IKD#m1hz(+)+vHi>?PcHJ`z z{o4BCb@#9HhU8ilxn;-{O*RU1I+HWXX+Xy$r~N(3c~sGDr)EKMPVUW@@*D@IIvu-u z+^JIUwUhgY%}x=?^PTwgK&O1$6sHm4W=;Xix^%d2w!`{PV2*Xq`$KH{964!yP0`IJ zY}G}Zw=LG$IN1-(Sw4SuZrRb!xvSk8+p0&HHNv_-R&bf0&?Z{0XpOHJi z`B)o+XAg2!Uh3GSm$u4%F+$HK+q{FV=?p8I&65Ihmv1SxiSxCx-uiB)P2{JnoOfQc zY|ah$$~Bu@X7hAWj7^+>xb>1}VAD6NqwUjr%6Z$C``C=MP`7#67OXW6w6Z4hl)c1PaE&7H%U4-*Spx-d2Oim=6ofa%#Y5w9bf6& zEcZRclhu-T(rCAv=X7Eh&w0^Z9zVE%SATmHZ{o5eytXC_dF`x|d7C4q^9myxJ54ID z=hW2s1ka%J0^ab1bG(1#$t?_2qQ*A7}0} zmzS2tq%fyVS-b6iQ{3}}8g#Jq)Rkfmi23+s zzfa7)uXBctr(AA)9Zrk69e@ApaID=(dGK|(U;XYs7suOQ5c9&R8cTk?IR2m7?=zu} z9|B4Evfn5FU%`*MeLU6Fx9*|_2WrL@tlz14Tpf`0_iojz|K}@qJ(T%SjN&-c-~abM zp4dOc^ekgW_N}SCAK$Vw_OHe8b#~@2PszU$K}|bjz>H!UBR}k*{_cG|=8W93_N%5Gvvkyz z)j3deA5V-f%fae!>=mo$2G7`Cr2M-AlA>O55DJV9 zvm{hGZVn#PWjHuDE`$>WS!ns1rNlrD$GV5Rv2UFcT? zieU&g_DG~JC%485#S2kN&=K-NL;t-j+1KOl3kWj&Ra_(io*o=AP z(->nI{-!xmIA{p6`dtd{P0@e{X%3`S!%|pCEYb0ED$ptO21+lLg1u!o=|gMfh~Knn z^p4DB^q_$9g8OGikXBEZ(3N(&WbMhNa8M_n=7B9gPIWDQ9e)z}Z}+6;cGg0d)@c&; zHY#|>h7M%2RU4Sxtb{fyTZ{r<59OO(y^Z4JTVuJszU0F4&D6dzx2V@UO=u_0tFW-W zpnaSkKcVqD^zzk9kU5x5g$|mFCfLNF{Gs=_erwl&cSDNaJjn!A8qYy)Q43M&_H-(B zjV(E;A%)`3wTDQ0K00TZjZU>&3|dY1!VLX)s3PkW8fN?s4%?i7ZnK6E<=(33NWBEO z*b(4L%QR#lH5xaUHbo<{X447lo4^{iI5Z|CnbwcJP4P|Np}x~Fcxx;`wmGff@gi$t z*vJ?r%=iQyY+J!vm$_7{w$J!)UmpV1rR%7L!NXu<>ja=Jp3}*RX7r6C6QO6$4O%yB z9(Xvmf-Sc5kU_>^(3$T_UyW7Hf3`n>a+SS}3d^6t#_}{O{>&}-WTg*>>e=DbZTC|K zu7&ir&>X7%PCGPAR*_CGks-!v=N)zpl7^t>O>r-o76pMD`;q}GhQf7?m)vfPLXpAg z5}13;1lPNzN8A-Ra~ zo=u^Dzh1CtZa3Oyem*zi`4#T?M_m5RC>a{c&hUFQ_TZn@YmTmsm*)@3UJ80vvw?bh z0gmo!hzHfPq_?c!24i9)Azj`C)RT_UiOQ+a?+-n^Z1h-Uraujyodd77+ zdjR1{zSP#YB~%kzBOGu^m0Cu1BTdgtrAWIH8r`);x=(G<=~W$3iS`5Tq7yXtmcJRg zYOGJr?F~n5bmu~H&r5ti9cQxS!6bfx?j!nWXaj0ca4u54z@ZxJu0drz{9)ZxIsC48 z5W1ST6t&uuNPFq+hR1sih~1qDNVec2Epv7+n&x?xe(O6B=_#clThk?!>b*PE%;$>u ztV028X_J9UCT^obJyl50E-R2bSD)NAs7IzMYQwH=1K|0KaI{OOKU{lhhs^9VXoIJN ziKbmw6sxzA3Qu}S4^EjuPw%;dGMH$L(|b@Ldv-WVE;qqtNtTe4p+M}`v`1=&ZE=>B zA9}Ac3k~&?h64lJL)H^-B;U^yQtBt+W25un($WLeyEmDXd+0lK+nx`ZE&HHoZX%SM zZKW)`Vbp6_2-51k5Vpcjl(HF9H`bdvTF;)04xQhQ+G&nN1`#U6>~3dzb8HAKon%c+ zxf5Z%MN59Gar2PHAO+HIm<+waatZG6kVc&XHq*233wYLBmgEfU2pP02vAt$P7N?sc z&bx!4J#GkUaBnp!i%o%*qym&wPN27AyFqI$nkou@Na>H2M-SiZr?Ns?V-Kk~^0wK2 zYP@SP^4GsaKYndZI=uCvTx>jW*hej*RK5pon{A12X~t1X87txPp=Qv~Y!h^E?Ypbz z@i%Bl{3et(z#nqLa*@&D?bH&Pe9G?OOSrcu3%wqqL%7}=6c;N)t4$3NZ@w}viZ;L_ z-`t_Cj~+)J^Lpb!la`Q2kN3a@?`i0YPb7V{-FQ;=a6h`@w-sI;QGwtE^I&BsV>sg& zitO^Tse^3?LC00ok)85Ly48#xFfein%IPVK3R-W3`?^gj&3236-U}o8Oqe3*j);Qz zp(SW|>Nb97&6yy0?=e2H`w4W>J4d}JIgU0D-cCpNb4G_aH(=|t5?WgACS~X(gA9k> zN2|L{cT6P9AYrLCHSK*pG&oHGO$oS34RE(7{pw9cv)2~$mvjywehsC0yBFl39{$td zM5QYV7?Oa?wc=n?UVU=?NIp29o&nRji>PTIPNTy88$j31frP(|D7gKw6k>Bb;W*>r zn??&$*u(h21TK$ewygnyGW1<^`dtv z78m?6ahK!U6V1^%%~0+v|HZI#;1p^?B8^rwYKWZ8vjp#_tB(Rs>5`s3rX%Aydg$S? zLG=3mX5`V+?hbM%GwG9;vdEQ5vb>yTiKxD6H)2uT5NYwYSrfikNd z+U_^TLwEP2pKTcr7gihrwo*&1-6n-~&yAN^EkKJ6B|-Lx?e%R^XrM}yj$GO+ZUk28_pFpt2{tQ>`Q~AHy)tl78PjQVs~z0 zSr;^7Z%>$fz8iYvl!olnPtptS%%fv2jHYvjyg<0oS>u`ZO*kv9)fY2~^ zZd+`t6$^Ll_i)eOs|0R~`Z%?8JiN4xLM^WGNXiRsN_l-E^x78!s~68AaTkJMf?PU& zTW+3T@nkjx=ty(B*_#uOSy5Jurt8gZ31wS2A zsI}F4+-S^sx>1NL*ZlZB%0^}|`9n$*Iav>)1`M#GTXj$;US&5arA4#psq+_7$8H3o z=z5W~`;|hf$#ZM)<}O8@9~Zzy@7t)C=NS5swLLtTcLvqFvWLI4)oyfga2mB#x-_A-13JF5k^-9W^<1HI(1cfwgCk zqm7d`qc-mp;YI36q&>ME9+CT+Kk?%sc;9*kC6{WCrtxFwp1riNef~5$Qp1y|HGYTE z-zuSE+k@a1u^6{4j{=zsL(rQeqX#J+VbKR&I5}@8?X+_a z6|cLL4(KzOzEwF82A{k^yFHXasu7j+iqvuNAm0%UoimfnQEvsi-(^xItGv;)j;~?; zq!IM#A@xA<%_1@>eIWMVbO*wUdl8o_E2$QGC8*bpk-%AQj6ZoOkowBH^xR>?s1H5E z9h0;zkjq>{XuSi&d1VzU>ct>RGwC|&F=`IV7^(%=$Dc;ir?-ML(~m*J1xI1xlX#Re z`7M<8+D$23v*fOMP!F_wokZ@t)bOXS%is{TleRzB2uT|cf`*sFA-qC^_PaP3yrdmS zz1%a@$IeQi-BcIt(>sm!be{&zLK+M9V!I+s-^p+@xj%0Fu>(n;MM_iA#Nd|Cl$fz&SW z$ups}T3eB~6QWSW9UC-BX*zDyWIIe+bqwpqCiCa-I7UIUR@A#sm%*U1A(=g43T5fL zpEl~Vj6Y_iGoE^D9Ui}11$9+jkL0(;;0xzviAw$xGSqtp>Ym($hWW=yi64cg$Ze=_h9-(MrQE&&P_-gTr z26yH*QJO(63H)1XmK($-zeB5wIh0$@V01-u23#6F9}M&zK{Ib7GKkBDZj;MFIx~qs z&s~wSGp?lEcAD5Scuql%{46-G(v?(XMqkUiRu+X z(JAqYbV6n_oX~6nb2`RC{R{1&oPNiBm7hZI(-@7GF35xF$5)`|q1n_mw{0-6%W|~Z zW*>bhs1NdTktHWWOA(451_qD2gNBbD_i&O1)v|0qOr3Wh<+iy+8FU(q=bSJG{{CsG z7blO-ZgUExv~>x;BFJ&;>2rY=prR=(Hh6z_!!Qxvt;n5X& z?9|Z`_IkQQo2!LH)8sVV*;hp7Pw$5YT}z->j(kHWJ|S?h{|vy*e9(a-%5=7LC!E)K zEv9o8(o4toqavqCQ67*@m9RaOy;XWj9XUFSmTlRaf{6*} zr2Yj;z2GHv@OmlV>1}s-P-cs)q%_Gb>9IJ+;1O(JU`A%9Fm$+*_CEx87&F80aWA2B8p_c+#sMG}R zze`4e!{r3=)gyGh%n$dDHG*blNw`_#acIH8eClQEy<~X20yoh00*om z!24V_cZ-}l=2^(YGm=fMh;Dx+cH^6d^cll4JE(6nk(P(pFeY7clHnqic4;&q7PQ@tp2eo8XqBLP6 zXgUktlRC`_Ew7kOb{Ng1$|IFgNfj2%m&JBi^mQivt zsrdBzdgQF~CSuW4m0sH<20a*=%|8&dO^_eC&6n3Tg!>O4qArgr=&6HdAvcTrblAiU z>Y7Owlsr`e9mVz3TH9`DdXrJ0;6>95QaN~y;|%J``vuVUT`meTNCuy4tB}VUSv>!4 z9I_s9mqIOP(n=o3Xz$`}6y+ritB)I__GTt9o@J3e`2D9ES8QfbY%@FTAhD09f+9!)sURh}}0Hs9k( z@wU%E9V<@3sXRp9+}(i^fkPf=8G_xLG_XsUiw?h=NQa$M$3vz&KqrU$+(BW==;<3xFy=qaouWE*?b`c=WRe{O5LINFjY7{r!8HglZ-w(&IMKC zPs&uDJ9?Hqr6ym|Cv$DIk#Xe$9C_3Y6@dW>beIpdgERqhV@A#v(7pHRLjrf$jMGEX~nvdo>9iVR4dxGZQ8Uyn$#G#PmEeY>#D5M*W zhAT66K|()G>>zy`HoM94R;tHBxA;T#rEquePH2393G_6(M4zpAg=~vwlgbfVyh)Zz(T6*Jkm%S9w(ehy zVjrv`4kf|x)G-^ieQZXbxT}p0o3BN(-5$gB&GOhvZZBCj_Z*dBejdhJ#?W#J285H5 zgjVE_KrYcfxLmD2?w&q_ekhxdj8^7>&iF$Gu9n-N^X7?Evw_jD;x-Sh>VfE?uOiU+ z2cFo@q8Yh(Vgo#1tpodAC&GZqpJ@LIE$Xhm3hBKg0Q*migV>vvM6QB@Q)`n@*2yD4 zjctPuDZHm%EfmC82|KCK@C2A0r3+_g_@l$r9CXmb5bdB{xh~t4QO065RP0}gJi;_# zX&MEKl#YSLlMyICWewP9HYd(^FQfYf{@CZ@3yR~Pj2at8@{y+v$+3quNcilDgq$7>d zlyVcuzfg=yf{3OVcR>3dM%a9(nJy7uaZM)k|?SmS~zlI*GPlB$d4O&t!jGjDi zD~vAKOsQ|Ckme9s@EszL5)5ML*7sr{d9Es5>|l-VG;B}p8CQTZ0^d_6F$(D9M>F(j zQ8M4;;#9bDs}a>FZf?HSu{`R*-u>V;(G-ol6pJ3c?~B_->Y%YF=R<0XV65S|kqp}z zfL#`3(t%0`xG@`n%Fm=J-Nz>&yVnXdtN&?!y>~6>n5oj_YVaI>zjiOs8k02crJ~s| zw3iQH2jE`HJ%wJYt|j>cN};I3HV7>!CP(#eqYFI)94n%AD8C6EpvdJC)wJ0x6ux&I z{h>6KUiP%Jz$UGu@2=FRcj!(=1|GIxJx-q5d2K7@yWIkYoHPR6at>uXDvIbyH75tc zc0sFh1^mR|Bx*iV2fe9$1j+Xl;bFi=NXya0fekWYFXE!+2j6iMUB^-lG(GrFtioaQ z#WhHFY)dN5IGWx$>Lr>J_J(RPbR;~Fo=1%g--lkFP$2f%cj$xL9#fODE}@XTQW!NN zooeK`2@Q`sL}%ZR2897O{NDXXlS|=mq0QC;diu3JX#ci_D6gFyI-5mkI;RwF-yKPg z%GSr}Zr-T!s2+Dwqv^;aXa;C-T~PNcYth6(j~!Kl4x*1Q9B8u^8Sq^78j?%X=CxC3iI0qRrB#iKP_Ew&cw&4UMJ^wKL(L4qx3mq>6})rUVz@FD<W!(&D;y)iMhn#}uhM~x_W{VpDwljT>}0sf}$1 zZ2;Tl)A79#95l`$jJ`igkwp1C;6EQ^g)9!uK@CbX>HCMI(d|!tN&TZskA#zrF_+t~}ah-WG0y1Z}j-S&b}uSB}Pa-$wP=w1b*`Q=MLR_z{@8 zHl|C=&e5$i;<%-^hr)sRi)o8eBUr241D0QD1cu62X_u^nbb?VLgl%7mN=*~F+KS!q zr=f$WO-s#)-2U~*xluhBIG`80{_ZJU>{E*BjoL(YEsCYjXc(gnSFBO8JEDxWI=x>6=DU{C-Bd3XoIGho2b%UqcU+sJNpXL02bVX2o_+69 z(Hjxf^-MfGd&uLzxx62}96EzfdpQID>?Qs?#{fzp$sFftbRveEX;f)pjkath(0%i0 z{wZx=YT?aQRQu6SQPYXiCsWCC~ zjiBQvnPQX2Bhckei{Qz?M6_LSp7_qfOqgpYjhbEG2UeL5xOI7JNV}+m967IGXvjIZ zsvSs2+Xv8FW)#mvaUl)uh_R=io=(9Ztd#Jfa}Vhq zqm*Fog--N?gnGExE|t7+e?$#`=nl5c3h*r$2FZ;E;cy>67?FMz4Jw!hkqd6a?C$MQ z?x9M0Rp0YyYMZCraebPg8;@V}$2)WAPif8Y(!m4JX{+X_O@R`wxBUq<+)tN#_~<~q zWb_6+Nxuxy8$W`cu{IfgdnMR*rto&_S=j9lJ+yJ)02DQAH|qA$9Tss-NHm=e%iPzH zEB7q%lzs2f)UNsv?l}pj_9yg?7S3Q&9#1tqez@S$hZ$sbVFuo~csklwbQG@ru@Mf0 zrQ-TQ!{N0~UnKQvCUjQ3jE14Z&~&0YX{Te3>A8o{jJPSZ?K*k%Vs&HK8Li_mLDiN# zlzmD!T2hX94>WNcZ$0X!yaVZt>I6O`%+c@zhp7Gj4dD7dXQHaypO~+i3=>y-Qn$Kf zqcQ8_pv{_XsGC=Fax+?nZ_vn_Ojel3@44?0JuQlZf|Q!$cTsVa{f#%EJis2#CcWf8 z+gcw_`LG>|k{hBX+b&QB7xd^ppVVQ`Q64y7P3ArfUJI`FigaWuO>cPH5ocd1L^ci= zAz@uRbm)&JlwNW+?a}-u z+LgW(H97JJ?Nu=t8)VhTDP3D5yJ9Wm)u{vNGjlCou0DiJFIGpgUC+@k&sN};*~Q#H ztgoOU(Hr=!m$ySkl}XgcvP{}WXFqC_6pK6E?gkM_;b<6Fj_}S5#^$SZ;H1kMeD#A7 z1l-(2+RWZgCQKO5A3jeD7VhMr5z;EieDMbQ`ZSv2nU_$zm(=6F3GIwhR7RljM|5Gi z|0H<6Q5lngjrlQNujtjjQ7~9e2f2idgZe&#Wbn0f)aV<}X_6I*POqJXFOEM+s|(gD zmeF$9GNU({+a?CoXL9j@k&39HnIY;hvn$LT+X}zl*bE?0@Z2F}H~(6|3>c>|8*8Vv z$FiaQ!Dnwaoo8{sBd`%KeImr%7^+Pw=wldcEWCu z4*Uc9Cr^f{>e8g~n>MhdNh0b+HNppyr()Xo3^iYsCV5`7P`9Lc(CLqD)O6!zSmxRQ zyk?#|_OK6he6{r@Y@NWv9c>pwuesexSc{%CcM^rAr#FWgQCh@s$XXQl&>7J(s`yRv z9&$!19%UWyr%o!*qE-$VL=TU9K{d)*i&_s8Jj>6#g<=(t)0fV6kUC7`L|@ zKHF>&HGdn2^wm*DpN>DGR!V75+JBhi?SUc4cS;k`d#wmjVFOUy6-`ih+#B0y_#*AO zeyGA!ALgVvz_B7FvV*&&V534Q-F3Y>xp_DQ+myx80h!~V$!TNiBhLoU->3m=k{2MQ zv%8R?sWP6B+ZZBD%4o%t`Y8WVAJnC5Ie)TDW0E-OAU!tVAm!XO4&OGLW^|Xm(0J=&y&~AyNqP4(*+Z$SbD%fpSYC`bTQ?TR34A}GP zJ+vDifYwZ3K;z7g$ob?>lyL8KfqMD_G|@E@^yhm*uKppey5>SSpM$ZYWpk2rE}AZO zvO%`bWvO-{M*$YqC-29Zg1K%t665@gR#R&ON492DyQdYy$laC5$+rnUmFh=ddwZ^6 zYVUvgA4;Lmui=64y$DB+g)m9cM z_iu@|>P;lwRA?~qr>p(y$0R1X^p4OUV#FK#S;EYTjE%m zM)xgMMzpLUTA&A9-^5r@c8TXtSm}mJj^*v%voDWc6uXRiBBPA9mX1SN%Dd17sW7gM z$|Bm}cn0*FfGTHrwH5 z7B^Ab$*L$XHWQ89yM-Q>yN22jP)z$zqi~sh4D!uVrH@%2qWQ`t=yK~dU?{6cZLwU4 za`#13v)sa{B~$xT74@{Z^{oSt`u_SbB2t$6=g$AU`B$9psO=p88zb@lvhO{|Z{JD` z&+a>`+imvW;y`WtOW){M-=`?)9KUc=I}2t1gKT5>vBzH(W5_HQmw(5(c-!wg7jOH0 z=i+U@?_B(6ueiPVFy>MZ&3?Wc>Nu#)NA3|LKcw zo!^Kt5zCFqKTTL&f4>9=YQ9Gywp>gWYY%I_x8|21`WGaE^=IsPv4gEy4oW7Ljb{~F zd>u}UX@1`H>u{|8-fQ!9ILXxfI<^1YI%>kd!hZjA{K&84hd>R!yhq{9zl0yMqBRa{ zC)AiPH|4h%+kqHHwd>xu@ax#PUy+iU>ulCPjb!AArJ40EKl^*KQ-4@{oWjTv%LV3r3pVUEt4~gB#SfP3 z`hTRk7*h<>-%onqf=$i$E!g~|_bssFW=l41X8FL@vt`Zu|ND1SDjXP`EJ_i_|GaK@ z`N5g^I(TjGTR3Pfrskflxct_7eUrTyuFlSUo!`If-I{jBfElO)A5IO_wNWxdbj5@oiy;)_c3ro)0HjwvR$<3P7>eel)*lYu^|R@4LQ;7f#3=Y=NMzrF2yd;Z*&uUsT>UB${aC1ZZZvcppEK#wdu66 z${1tb0~{V`vs~?kxO8zfXum#;2RAgs$%PN#)~P%!YF42w&v()n{WnlOug}n_J{*r8 zd`pgIEaX~IhWO-O0??;#$>RY&yj1xmc|0&uu-oD)o08RyM$vMx>lw!0Stz1WO`O2Y z*aN!`+s^7wC_r_l49XvjgH!_!E;T6_y1bmt+Z8~s+;b-rN8G@ZE@`ytQmNqE0Ikw) zaj~#Zb}fIrwgVs8HIJK|9e@k=KN3ZUX^?>LQoKl{%XFT8Wr-pKk`XvjWCq5pA>0zX zrbof~)#ZW<8}xt+kx3DQo z4aSe@P6l5hWYUS8%?^2GVO9@4!qJ##xey1kdbj6O~Fq`9E<1$oGPgMefkB5jLc+Ci=Iu$c#N1Y+gNu5d&^A`Hc#=qxy_Co(S=qKfp!JJM5Rw$=Db;Pf)1UL|)hBu&jNrz)NW; zeoXCH>eP2XBuq8LF+)zW_Re`c@0SyJ{$T`0#;?Rww~x%J$dJUmTgbPi93a^TkCSOP zvO#8830ij1#;qQK@OtG(2E}K<(WM>8cIb#jWkPteM20RCT!I&o)+}|5Ke3{{`I+3O z|86#lQjUB>@&C{NDU^`cmvDsz^{Hv=Q7(u z1zRs&z*W!Jlht2&iR}ELpkLX6V)sz!WT;JxjJ^2A_Y0tdMiecacL&ytI1hHgLD*Ni z6D-*nfwRPUon3CKVaTyJ?0mv9em>e34I_h?u*-VvZ0P|LKOV(jy36srjk7>yPB|*7 z#j+z$=8%zw2k@2NRakxIiNLnZU34Wq0E~kynBS)tY;~Wz^nl-1a%FORUY*^Q>K@YM z%F#MB4x)*kMj0DuYe#sYI6iQWJIRiS<|-R&aO$cMw(b2LK0V_!qn-jS5HKGds10`&up@8nGM%kI+*v$*-4h)m;!Hz zF~9q56j?pxEj>Wv2}@PN_EOhySw$U$bh zKUyCj2KSpk;2Vz>cyXFNQPTc~leQLt-S^(au1W{Gj>*J3!@oh0NjDyvUc~z}e&Ur2 z`qFl$M{vidNxXWBKTqlU90NkeVMU8-$?*80^u^jiSg&PD7p^kIWk$DI-PJQ#oT|)2 zS4TsZStSnNcbjc}aUCy6ZD)Di<*~D_IV{M2#H7!}LF4XH7L=U|>)mhAss2Z?>(SwK z?Uq`$Ksg9*M0gl@!H}{`O&(6ApJ0~kqwZd;qX;}bVJN*KBPxEFS zZ>C^k{&^PeF^VTwbf>}QAF(!n5j}4-9d@hRvWmB7nbtxfrg=WatjW(Q^)bPqphUQI z?>qi76hymqpWxIt0a%>$id3Qsw$2&FPH6aoN~iJQIOGg2Ta`%qkYGsR6U;0a1}}{k;rt_-rAL<|2-T+Wd6#$LS`Xkwn| z^3t{3#pWGkRF9zA21!WQ=dg=gmSd8w2Odp6M|7)=_!uZACTjyx{!+ zwKJq;YDZYMOK-&$uW0J|6h~%JTb_0UVVEz&V@K z)Xm*r6!ke9KEFzX^(jisF*E^;=_kgF4ow;U8BzKwP1UH%-&~2J8 z-y^={?7-Erc-i3~&#Fm4)0w)Zd%Ef3_Ka@mJuC!_sTxTOdM2T4)Jrd*EhgWWKy;v(vH*^l3>d$5ujI(({A z9#eFB$?nGN5LDOp#}4<7pkdZB*f7c(Hw@q+`{fG4?n=?@@!fQoqtFLWT>;b)$7_?Z zer&wuRdTXj8SdHhnUOBHSj|dlKG;7DRQf8Q=tzH@(Ol1me=H&+`{(j57Iip&h^(;2 z;4_KRRRIO5DX{WoD$&W?gY6P6_`Pjs2x!Ydp!;EQl9mE?n|=~c<_IxG91Fg2o)4@n znp)cVyt>FZaUWUN*v{txUXrl@>f{2;h#DVU-;LI^WJWcN~I=pJZf+j{ry7YnaPM?WS z4+CCwzYpr~@`F2?yV$f1BD~~11Dzgr=B;6xRIv3kvmc)iWZlE7D0DD+ z06V$k}5y`z%x$o^JLWelM<+h)-1DYj@5BrA>! z)rRw*zmTX$&q-F44L!6?lg>6X#H_O?(f89_82Mx?yWZ^uDT}`k^1aWJS8iKTdVe_1 zj$Y4AvXZz(#~zU7bwSXixC?X6Me~OAY5a&;FVN3*Wl2xFLGSCQ(0#2x?l^RnYTLe{ zg;_z+=&X!!XN>VE8uB4;AJPu*OX04(G2R>~#lwu!=*pGHd4&w3i)sNL6j|^WOB_j! z#zwm1b~5%Kejn~Xpitg%8W}I+3QA|b;I6`N0^LKk>|v-f?CP#cPrnq`Vt67&L-MLCyf=h$U z(a1`JOl|ceBORwg%n&WYowr~~?I_W!uEt<6Bb;PJw~|Ra^e|?QHJNxJ7&^6UC5>u* zp~~GK<`;)Tzq({tH!QpEF}h=#$wD< zcM|F{3#RQbWC!fS@sm|KTXJAOSvislGwyd6$Sry(N{Ze=S54G}>gWk%cg!-VI;8}% zOH0YtkeQeu)&oVu%<+ZKYTi9~I{Ch+7bwL3!fa2*;5POGw|>fD>Z`5czIh3xy$k1h z=l5V|jU1?J_Z4I^oMBJNosuk1ciw7g3yl*FfVb8R8n>;P^{$;pW;{6zp9}(F+L@)e zt0f1t#Cx+BkK*7>SqbU4^cF74Dp!9j;9Wnsrl|7iG1B=?-PM zX=owfFttA!Z*A3P2$8_Q-d=2Rx2>yR8DRdmz1Xu2?f(Y+p}5PFlYWr>=lZewPyK-} zu{-_WjOMqu{$Fw6XZy0mkF~T-jwE!o`LRqTZOP=Yl05hep~R2Xf5MNR#ya)k{XG}|Z9&(``(*1!VRWa;7j1`EMB>lQp|GmXrzu)xmM z>0o1B4Sj<8vZHsCF|aTKHrrXlctJU9bk4$dZ~D-Fk&*0{gOFZ2mSZ{IXj2QV*gGQ`L0Qjta@o~(^Qf#O(N(|!t%R=7sorDEujfP84|EzN_z#=^~Qx8TeX z%3cOdWd%V;u%g3M=vPrjG~zg!X4aEiFAjhyetn>^3!#eMlW5SHjeoa| zo?K?qMB(SDYV@V+%vLLCXicks87#Yn>Jqi|f}6AZJ*-{(i^|7{F!pT-l4%LujX9$@h&c zfRE!%ajCTvIWAj@trx$s9XZF*dS5B*9x(?uuG|1$<_E#J+IX~UIRnHhl6`%)22Ti! zaD%~qntkFqoh0wiUPJOHonoGJet89WM<0j;XuM zL`w3S?Am*47$Rz>;kQF!bg~6Y4D=UukwS8AX(&G>a|K<$4C8OAKamX)8PLD06nXZo z7nD6v$5GS1lewoCP?c1Bd_GHwPS5IvTa*Xmyn_vFsX~A5HE=2}(~7WdOM4b` z-;sowxnp~26&{>83lG0s2kAqm5`{85^j7MC?G7sNC9VN@y4nwBt-3%q%e+K6SdZpP zOGS%{)5+8Hv&*N5P{R9D>BY7L#%E+Eqm&!N_nHMtSi3id_0kVC=pbYt3Hwtlk{+a7sN z;8o^D6pIJ)m}(VxJl{ktWjcKHkw_{#eI56{6-<^%siL00DM~-OL2}2$Kxm5`_3x{T z&+mR?GkpfreKnU+HB%W3j9-zMV|9WZOO}J@>G@dIMTE8&mB8A>5_6{w#(@*uVEH~v z+u8Lz3d8)F!O*flNnG3h2vIeW!A_5# zlB~2`aINhKVe6iQ_w;GJ#AiQbL?0&mRBUkS+EK(}@K74N;wCwGzgXm?=1wkoErt8L zPBEpE(PZhhaO4RSp}EgaB=@Cx>?#o?*N%gmlcd=o-3Bu1-Y3>-@q)#k^2dzU)%d~p zBUX*n$9ci-m{+h8j$e$$cYP*`UJd(#?K3s`iARfJ%1~LfnK%wxANAlH;w`y%^I+5% z{f#9Y2#512LDLrBt;ovkxtVbQ9h=rCb?^L!En>VaxTJImBH}OR}^&}cZ9)S8U4~Q@5AQq*;-r&2u zC2u=ywJO5Rx1->|W@CEwP+#B%FYw5!nasnu6l>?0^5m3VtifX}E*PANPR{udX6nrZ zucf$Gt~$>!;Dm*<`OVOD%pbiDwf8Ki zlRd)u#`tjb+`Wgi-&xAMKkhHd8aa^WE{?B=}W}0vnAR-8&5a)&cTdRacHG-49Xk6 zzyAkQV%BkFcU_)9VVxny7Bq*rj_)&DXvxOb(UNl*^S>C zEW((Zfpq+RGrZt9n#`0ACuRjl0bA2WdZOdl^FbxN%eqeP&Xz50K0g;d`@d&TuE1&7bXO@y(7~T z*t5R$w&f^x7zB_cal&OASU@UoU1id_C2W z?}5QDmQrl*$?xy7gqi;8T-i>F7pwH-ruEvGs+b9J;bAy`S6AkHYX=O~9}5?*U8j$S z8uPAWgGtYrAQ(~_$)e_05O4SEU}a+fYu8nbQp8 zQ#Q~$AENN7qdd>?8^asF2Jt23i)hcQ`*Bv;dfZ(UM2`4vgzan>cvXedPB%_rVCUZC z`!FS{?ld0PJd5Mq7NwDe9yRE*Qj@z>ccwYkLt*UB3e1Xb2Wn39AX`}rUfNxOUvAdJ zoA1U%?pX^vxvP-LFZ>3cQ9$v%AC0{o!3KMECpI3Pan1c|^19lck59i2GpCf36<>$o zuH{lVFx#C!>mNZ%9o*1AaSDv`o&`4z{UK;;Jbuai$`nm(aOXs2?zgKqhC9je7)^Qp zD7G6nj|0B@^*eHN>^|&$LWTsq3B$ayZ)}jF6*Nz@Acxlbu=O+m)#hx+g&$0)Z2D%d ze}5GcyN9_YSbbb%}Rq!RR1zv6kU@ zzac#0)+zA(ie<4Rcrm<6(PQaSFNYN4B zE21Ng^1{pQ#?#jWoynHWc>W>dF^lZGgC5*?7@j{9>v1a9Z*Dta-3WK=pzH)`SKMIq z14GgEo95tPSHcR7%9y)FI~X(kjNtr>eXvIU3feWektJsxc=K30oP6IDA3PZi-@f
yeB{F8yU3|4GL{9e6- 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

cDjz7m2N4LrC4{4N=`dN-8 zbo>T?%>l`JE75!PM$UB(ecGh^$Nod= z58iM6t4Z)%<3ElAKkq*z>yyv1U#};Umi^y}LqFC{IjN;>9S7?F`0%^;y!!EJb<+T724!TGPt(5@8OcRWIkF+9{hz+GJk%yPyL;olG@>~KX&n57$-!INS(Z=)M|C81Kd;dJ{e}4TpfBr*p-$waAsIhO; zAAd^Es1*OEXa43tODbYC5A#A;V2Bz$)09D@+*s|*~ zzVCbwqEez!ckC;2sPq{2?==cNE2g6J6h}yn?SZ|*`|!vw=LC0V7~`Co^I*n4z)$7}aFfAf zcE6!Fr1ag1o172B_}GcKd07N{<@bPRI;+^M&DD^cr4Mg5>CzD24{U<7Dj$7*6rU-( z9(6azk)`6hNvCl&yi!|%U%#8u9(G+Jr#SoskAF47Ezkpw8l>V4mn)d;HVm$PTaIr` z7GUx2xp;n=J~o^zBM0S2gVy^cVD05X?}(nl<8Ck57?tbf`rFTFKgADS$L6wQ8+MB8 zO0Q;K+S9p1c>`DqGsvJCHFnT61urCYpohwlt(o~0KPHS4tx>2(7dv(EGCGKkCI=AG z3ZTaQ727!`2ZIC6@kZH0JS(o>efGIM;X^Vpx?--V{VyDxWnQxxrLP4qw=RQ^mQAdp z!G`^^_aPc;MhhO#&0o=LwWhbC}&^I4k`}CS3I74ajF%39$Y3+Jfe!~@iHR2HwQ`T+z@QE zoPpC*oS?-sl>Blq0qyJ}p|!q<44ihva%b%%)Li364#Xjg2(H1i<{bM@Z%+p4R**{{ z#^IpdcSRE>=AzcsXi@U&J-9f*7grQYv&j>^AYn7U~cSRP&l`PZ+(TEji)IH?5$XS$Q= zWIDtLe`KR$t(nGYHTam&8;%Exu!pP~_wV#f6n<_#^eP?7%Ke7Il7k0{@Z%1CBjgZN zq;0_-3%Bz!xe@fj@LWtDv6+ot6b9=?b22WmEB3L;gT_I@r15DWj#{6K7t*hj?{{ob z&d!>)|F{CToC}0hQyWx`+>g~2akwQS2dfgKd5S?9bG>&F!~4C&yiXRm`c)|uRENXo z524s^{W)^+Lo$B5uSeMI1k0^t59ZH~!P&!G+4JOh>c8R)JnmTpu162Si3uH8{m0Hc zIZldFI|V-DlnT8jUkFbxdt!B*HXk`Q3J-T)4+9N`2(-^UhGX<7sR&=i$ivyh*K!55 zUu(&qD~s<24XVRNZD&%pQx)dhtwNu2yq_U7RM?Mc4Y%on4O!o|mOy@XlgP5vkErYsPSIosRVJ zMq?%~8VMJ2Mv428hkXHkco*3$fx!(c?ma1ooZ-m?cdwRy@SI z(Xj%ZjBXt2o-$^%1YXQrNmi^b#a*|Pq5eY_x~0#ddW}sOlcU6~&ql$scNf_;IeEJC zttLC}eNW6HPmJ}LgN^S`fQx=VuB+5k;==mUh}Jsr-QAwO{2EBrC+?t`!@k0t)vL(K z16y%t4_jnS(@FW73*a?fgw_>L$WUb=4+yqq*A~`^hBocRlwR|=u+EZhFc4s5Vs9?n zZ3#`>_L@M@3W=70dw>W>EwKDk_3x2?9nG5D^g+6$uhfS0BZUV!(hI z6m!mEerH$N_tv}V?%jL$?%R()s53J))7>>y-96n^^-ILZ-8ZA=lR3D3niY=oTa1$i zo+O8ppW@s*%DByUAKudm!9`2fL%=}^rhK}L5h2PL)8il+HY^tO!iKo-x7{H2`?Lvb zSH_cz{wLVRiDJ~woyhYYLtx{Cv2b))ym;>zWqi4#9S*O1&n8<~V`^v{ungUXisDnu z^m95CU$+IFOESEnvkN^X?Vl84!uj@f&(QCM3e%oB3=5rHL2j!H?>X(h_()7LuDvB9 zw&BaMvEVha@0v(^>E5P2u8n3Js-<{SG5Hud_zW|@y%HbCZ^iKeJ0baY2n3hWEGq)nuTyY~LNjbIItU4xrJ}0as@%6+8^2e@!JgwbQhPo~@@sQ3 z$|Hn{840p@%ILZK7NqrMN&+dlvm$CKky!opOr!T z54j8xPS44_lW)n5m>ME;R_gCxri3a5;owx&9h#$zc+eg>C{OKAy;By_IW_BPnbl<8 zkX*}R*H6LX6$9y6mvMC4jU}S}_FvJjPJ_R@wj8TvrjWqU127^aLA-9EEY!;@!yODyBkx{dcB$aR|6CD+il(C$RAA3|#+Y3zfMU2lFSCNO7x>%{3HY za~xnh%d2?6;Uj2Ye2B>}cCoQ1TEnJsYp}!P2q^n#LT6e#@lm28rY_Bu7;QjFTbm;| zG}jbQeOr$eCoYTpOkd;U=p15euS~Q$?Pso`6!vQjK&`js?EWo1IBso3`S~yITTZOv zeP7%n>r)Njt)&PKD>~z_vyX|Bl_vf4YB1b>J%BAw3C5r^&lxtg<=4GVv*!z6k@o(^ zbWhwq(6KFM-$#rkW1{yVt~W!I(X&WrzuS29&BMwQw>p!+4$+W$R1s6%CgHv<3+bJ! z4@i1l1Y|sR68nDW3klR677w(6O^e#|g{p(YLM z&M##b zYpuaDRYJ18!fCbCr}1;lP>j6XUKAf3gS|J@z~~8)7&~u2YaP-DQc`zes>mOf#n^&s zT?YB$9e`8p&x+OKHH(>O_rrDgcmifi2}7um0^ zCvT!&ifykX!Z%HSV*L3!G1i<5KG6zz|E??)eJ`Qs9<-%n=muv+pY@84ApKQp}_hlmSjzm}(vYd@e zdWt4(vtd!IBcyTVR+57hy`%MD@rVreY}5hfy?i?AjGfFauGPU;{#-f+$Dmtp6*^`_ z7};wv8kiKPSUJj3b-O z)1gUg##Ix_OqrKm3q!$9((8~?=WbtrWruEU2j+!-s4pkgWua+CJG2R!YF)-4c zlMjZ{Med!Y8m5e!-t0ufz;&YR*g5QTeX)44`%7$B(Tgoe4kF_}sBqD+2GQre-+*>% z?Y2(Mli(Z%Z-t)Lsya^NnCP zcrJI(EFmT7a&+&;NEqXmistJhxK-RK@%8jnJP^>83Rh;5S2fqMG}H`M*r?F6N}Eut zc(Q1ou^iPndjhLZ=<>SQGjQhNTw11Vz|X|5=6m~y&~s%R39u`q8($=fVn0+$=SE4` z5P1*s7LLY*@!IfBdklUV+K)a{bA>i5b8+98fJM3Ktze2+s1?Ak|717QXPpZaoFQf_5VVKCgkzNjfNN ztH^z2+>jbs;=KLsc*QCW(H6O6cK^gHj>Yq5 z>T&kdaM8WC0c@Cx8JaE3clSD%N7~=ZhpU=b*wb~Id~Ml%)_b-NObWb0QU_+U(@)l8 zw=-LDtG^kJfoRap55_>NLl{40IojtY5RFN_fgZP|S})s(^HTS*xwDRo$d@Ygc3cf2 z{XI}H>Vo^?NAX}=y#%%dda>;z3dpLpLvb+XvIhBe?19!O9J8Q~UC-=~18e)Tov|m$ zx8-_#T7@R9Iiy10WEP5MzwHdJ(pa#H^Tm+-Y7KUpu#|}HT%hY-PrPh*8?Sy{Bzloy zNWEhYQAyEdGHcF#WRh~0qF;q^3y)!8hXSx(@dlEeirK6jHJ;IXD7P#aLA}ln#B)dH z(C5W^Jo1VRCN-tQys1TaRDTn;dUKeCj=3$;wN3($tGijdCq zw!my)QVgeIEA zv+oZz_!hq?x;#0V(k@9@>b8)F&zQt*gK{8H zLd)G_S(t7F8K9y-zYP3@3#B-HksI3((|(pTZmlVQdo7IbxH=aydpYruUE}Go&WTJf z+X8lP?1C4yBiXLIlxYoj!8qj{*zm*=Gmk8x!)i`pa_@P(ug@7!NG_vG_IzNn9W&U? zRT3T`Npk<%<^$aK?g{io8mUO=g6`t`5H!3Oo|5+WQ6B>7W5e$xPCB3N-meHEL+?XH zuLmsRyaRf>cf#O@=V0p@3r@PGh~K$7fSHUJQ@QvG)<${5^f*P>{`izg_Fg9#d-)PT zTqGO*s#v_;K^MBa#AB^+K$`n`1J0QKiak@dVmpEb_!@GY1di3`(Q#7!zPXC9dsbX$ z@&xR$b3II(6^FMDT*6Cl5eH4K!MB>zP|bZk9#H$nRw!=5l+VTB z9KQe`^p7T1v!&}g9lDFgcF2cbv-@Dk+=)0~(O~H1uY>n|4cL5fGSn;h;h95m*lOcv zEOL^=?mkT{AxaG#^PDkuktr(pbU>>%epp;?hT69caQCIFcvqB46mO0KrKX`|%?xFz zx3v-V8)t;=xDrg(JkP#N3xV;Y9)P^XD4c)Gh^t!@yt?EuJIJ4lJGCp30v zD#xLkkrm453?)wt$FZ9>gX#K$bl4a-2CDBIg+1HyNx5b(Zu-&}{o8571~(;e6MrIi zhH@5AIfp#GAA#kQMiJ);Vbn)vAKetQnOaXZr7BNmp;hfVxb(^qv;7EP9_L6K3zt&O z%WXm9`W~*-`4r!{q!h!Z?4V-~>(i$@wBcHuI`r9{$Lu<2a*NxX-8a}I((7hI=QeGH z(gB0BzbEJHQL?}Qj>~t$ME?OV163g9(E*_i;Eap6GF>E)|0+dmqXJ! zD{fWf1VcZr0s2({({t&t?Qk)$Im(!j!_i`!C9Jq*g0lDe(WT8|JYpcB)**d(pKXJ< zS;<3Oou@&=d{bca!nRx*lSS&bma`%Cttnfx zqoYoD;Gw$4{H2dO54krKI!SY`2VGa-6VA3`@^M|jU`@67?33BNSBVeE_&>nceTN}Y z?~PFtN=O%R6t`?UpSswshkCPaRP16xe7iKG*BEnpuwxEuzGp#3U6jTmwKk2h!PZ$+|_~Krx~#Kl^2g*ylR_2e9YM$IwUGhxXVIPP~hT;NT69aZpMYJG874-kWd7 zhi#|A?#q&@bB`C|rm6FAZqh(}^(7sT*{&gLS_R^V*=zA0%ZGI#=9p#R15KNgASwO@ zDz)~2H5V_y$?7{*7DrUc`)zF)yCWtC6K682(wS^=y^7<{G#}WZVB7J!Wk3>ZX!EWBJle1LgF>42KVndimNT3!8Ia- zo34jSb1Q^_e&SAC|XZ-m60(rLZ34{f&0hP@mprtp1ckV5N zpIUE)z9JFm>~D`NUZq2uE~g+#qZeF1l|<62&3Ks27}#!QN3%zsp#60^(`l{Skxa=r zR98>@E8(Ar~9&w!6yA6Wj ze* zEZ%on^Y&;rb(OF-b8EgKta%H5DH^@@^)qG4BGcb}3-;fgtGk z;vqy=oEF8OuOl+ek60%yLojyq=VVRQ1PbmP$6eJpd1% z@%)f_5G?V`z$vb4(SF=S+I_A&=u9=h1W^K54sfhG8z#?}e+xm~kX<-A`!l9wnd3;c z8#rNc33dsYCU(dRgYllD(W|#19?CbT%hIyB(iVGm{lgmKyW5I&n;(cdK0RUYKw0>< zwhc<&Zzfv`H^RkybNsxoJF4i`5%aY>#BXP}qMg2$6HT3L@Spw~v^+IQyrn4wHqM6C z!3#*>h*P3MO$)AfFaWREO=q5O4f&3k!)$M#-FVpT3KmF0*cT&RZhvkSnSV8rt)KQ1 z)7MjG-75mkWP0OsIR`>wrFmnAVW@-Kr_slfIpk+g0d7X7pQl#?z7_&UA%;k4K5~qgrAx$PfK%3Dp|B?F1XiLiIP0VV0M-hs+KE2z0qA_-c5~(9=pJ;p$0T& z*D;)-u7G_WhC}^(ds?Gl%N_Glp#JqC7?8P{EL=6ADrmqv%c_%S58r*YA`dYCexj6_F-LGnZTQms*|5S{ihZu0$lvUYhPa&${PE*(II<)O22ah!FOxgL z))!Z?U!o3QxP3b9Rieq{0hc>8lVW5X#wt=5l!tR6+p zYT9GY>UcW9AV(b9!v}f0d|W-z4n|DrOvkoj5Z^Z!uP;tQb!i;$DZf#~qDLfcHXBFB z&YS?@W?o$F!b)OzLyp%=PD6%5G}^c~u?tDHcw}K89+)lx$HIxw94LdM>sL<4?L%`hZM!nZFVS54K_R~GdXwZ= zY-QEmc9Z8?-$?S|3e4Hq%rg7+W-GJ%L8p((B%qHTQN1HeBPSWKo!pN;*%iuOB^OKA zCsk-ygJa^bQTmuPcpY9`VarZ-w_!EARd|?UI-Wn_$~s;%;?d!{Q0?c=Z^fO*+l|Yx zD$0f$XZB;xg_PymnMYc zy6msG*kvAuj++9)W^uom*Nf6cfyTbQ!p;VgRcxY4xyRt$-r&) zRHbbmyzSPO^&Tiet66gBUG0LtAGE1&>`pMfJEJmiYXHPN*ahp_TqJoZ6#xlNIPct2 z*z&b444PJj7e3+X4cyM<&t= z;dE8^DWk+5x#zI%u@NUvr$bWKEIP9|lq$O0@F7)h{8}Anmv*(2=09o8>tB|F^5~Cn z)Z{i4hU}KEB^2^O1|2y$9fXxhi|CNqy{VkP6R)s4Tp8bFhV_0AuzE!sx-_=|#n)Bw zg)~Q&>6pooGvkJMe<$FJ-##XW=T?%&=u}>^x}IJ(-hsRAMnG{u8Vnh84je;Il9&5t zV&+mtmZ^IK9xfoQ2Aw8KbE`0QfGJ&|eSlpYA;sr80^)rtQTk7bikni(9y9nutGdy_PIL ztiY7!nbBT2gOWLGY2q;oU> z6oQeg8a;mgAQYZ2z}Vv_Nk6w-5~z4gobogtt6bVr1(ht=vd0CjQ#ykC#V{Urvm471 z%9(-xX#QsIR4{BFAwJ_L&&^}4=*WxPCALJF&1VVj=cajSGKVxLoxOnKoRO z-*mMS?W~pN@k>;LHNm4%95o*vmW{=ON(Nx{GzR-MuL7@`X>cT7%+9u52vLVy!O?50 zan0s=pl)#o{ASvSH0IZn%5Kx}MKfp0C&S%eX(ME;cp-8+-ItxHmBV>=uCoGSLi^i} z67{|F5x$qwunUWu(% zSz*zstKu$Cy0YzqYH?ow2zLCGEQBd)wfGx7qw9i0o| zY9H9PnL0e^%^sX->WDrwop?jtcyPO~3Nuo3arU7UY|6UKhD15Q;=@tY{DwTwd1XL9 zwhc$sb>pDp#Rw*{FCgX{m%;f}CrP(ka@@7o1TOiiN{?Kcgik){Qkw*XD_8bmD_2cS z>*2wiHx%NIy9nDSX@H&QT3mQ374KdQA=}S9LWtW#m$kb@EEhTAT^7Wz&F?~=6h?w& zqb~{AaR47Y3L~$(-4LBN&p`jcLQpb(Ow?q`@bOr4Tt3%Eba&Pobd8_O3~TSPnO$V}665{+xVT;us$O(hvX2-x4=x_v9}>uchDU z`SdUI{rdd>ZO8v}<3{tp#JKT4ClA*JKQyQ3AF0IuzIo68R342b{}S@}Eg!@msq1eC zzewQMc}2^(lkzhULkoM$sNvIc;=f2+zF&QQ$@}on&SPNl=0{66{cPV~o0q42_`%;I zxBsG8e!Kl&Oai~!Ps@Dl-0K#L`O%=Cc??`zn%8o*XUmEIByF*ul$SrARP?jFe^4F+ z*I)A(xc-Ck7__vzg|>X(x5%O8d<*^c`rp3}VEpOlGg}_{dx`(Y`Ah%*yt^+?+)efbk)R_k9sht2T?d~{dT;WwHD+{cS4Vwi_yON7R+E>tOQES$syUftD^>;C{0sSA5~bcbe?O zsRv_WUBpy2SlBppNt;k;{ZyP@zAWLLcGN0Te4~{*zOQ$Ir*G`(qlRW=d)tUaU!BR=!8c&dTqC&p z{1j&O)#BIAXJD>lU$(F^M`YBc5dAfFK+yLt+~|A;csow7YHwJ1vt!WFM^w7bVIeXZ#_oLvc>roumT|wM> zY#=-y?nff!lc-FmIwUi)NX#x}I;;5+oSe7;zOLo05yBuu?jX9|T92ta_rapKX{?>T z4!-NO3l?kl=SQ{E&}~@<4u);8U`!vKpGs@isTC_gviB(B}OhE`{0!z1Tt{4%XG`~J}sV^&RpkK2RTbKk_i>%x?fLAFbi!VlPgx8JoQXjrMsPx4bu1VraRp*CH zIr9i>Zj`VIku%}J)YBqGcWs(-V*$4;Im0X*Yss8%CH!1zB$3yxq3Ll!u<)=iY12gu zoRzjR$Ntf{Lt_HFb4(6ZEknU%i7lHjr3BK#H^ISbLkK9yz{Ne!;{)y4^n9HOj~`4h zXP$zSFudvMUv>#6N?)KsZAwt`*jES)hE)JfQR9zajFiQ z6{q8SXY_d ziC$m_;(P>PfMGWn_Uto`e|--U6()1vS(>zT+c0?V(7@_^bH8jsX{(B$taSr*w@4x70p@h$NP8%4AH+YN z&*KZagu&x3XK`7{Ev&Wc1rI8ZLbvXoe7K~5o{co1Y>+a^&wt9p0?Z)rfisOYTga2! zd}O9grSNS?3Hr>_gU87UOznL>UNGs4on3rUHtR6ccohzN!rXY;5GQy)@ETE19)Zbh zH`BS%7t%ryg`gLBEO@rq!$b*ZnA@X^i7{Ijd{pEUr9~+##PNNOllJG2L6pTp;#TSnk)mB}L-R;#Ik+8On^C*F5hS23%&aM8 zMF+H`V?!>fsd9o;;!e*Qk7aSGOVLev10H=onw|Nmj+z!yf1Q33HYKeUe3_yxOjIN+ zu z8|QDR72lY9%x&##6B?p5$h&*} z=~JhEsMYlE8Sje2VPr+I!Cn)@Zv9yz{%cn`^7^SI43-zQZ+qvr`X8jxH8; zFis`*8hycOwmI4jqg*BkOlGW!9r&anttAeZ=Xx?q}XTj zp=&#A+dc~}k2xh;S#uM;iku;O!%kdvREmeTVk=vEXB0m6@y6Hm2+jH~q6QCrsz&If zixqq_(dUCYV()q;w|p1L=SeWgcP~5CP7Cu5^V!3h8Psb{1zJyv2H&)1^r#U*(PJI7 z5WZuU|9SMuUjc`c)Oqa2uWYS(3HJBCj|HD?dDe$q(2p!7mp#%*rm+U=U;-f4P9<~Z zRbbhX(>R;iL4`dEj>+sEm^CIIdL!{V~miz$3(q*2Os937Y4>atemrcC+llH27(1BbimmFml zMeQ(n|8b(XGMrm!dccWF8L4lgDp=GIaxLHmjBZRL{Vv<${=5CilY#a0tJ!is;<_{j zczHBl^cDD%Z6kqOoP--D_2P~O`n1c9ftZ&x05@1`b90wtOn=E%{v>1$89k>xT=GhX z(N@{i;++`2byE^weWbvR>z|1>mN{@cvnVXtY6blq?o&G{)>TSQCu)5@35KaU!2k~t zcOJP4!g_mQ;FfJfee*i(v-SWsA3aPS>YTt5j>O!gC=y7I|Fc-!}8{+u*JtWL98a2M2!`l|i;F!!dvU=A#aj!i$MLJ;@ zF(gQqZhs&T&pU6z5pK=6xYq^n&rT){v6Mv9Y~K3NI4;un!Y3}Ww9f`@E`RGTez27K z{T}>C-}LbZndxn+n#x4P>WK~A@9YF)_w5ufXq1umXT$JO@GN%aVs}*J9JwK|E??4_x^? zN#wg~o9K#a4)dSZg-2V@mfF-!qV%x~yc)BJPxq4JGDA9JqIoz>Zm-DCuNjT!C#KWE zx&<(J)iWZhQjr{;dXxuMG?3OuT;S$NML3h)Af8&0&$k@{{%AoI(9CC5`yLlUui+Q) zcDt4CQv!C2Yih%()wv8X@X(;;A={x{gEm@r83}#nuHnTC^m*op%~boFH#=5m#7`t| zM%`H{xZ_%`sOG2|-aK57bEmoS{DgTh;owc8H_?@Ph7N@NCvEAYDZ{Z)YB%j41hDM= z>5!V50CP@l#EbgF=^@2(w5`4k;v0%suj>e!% z&ph!>yvDYcxRHH>R3%?Ge!_P922we}05k_{@T+ZPxv1+JI2f@3$;;FDg!hMZ>nvFR zO`Fb3iDu#pPV_;39dhmXw-{_?5-BkgtD?tm%1P^suPTZEBzx8s1rAv*8QZMPr8G zoz!wNGVCsVwf|0Lu9ye|d?G}XYEoIk?eBQves305r%8I4mGM5EW?>axqZdu=h)wsd z?C|*^Fz(F&HhQruE@)T7Is~VY&$*{?fGCCR3b+9)d;z*HGza&OA$V%%eB9PlO6@d< zz%rZH#G|$rt!-5?TbiHh(VRZSXr?cG@|IyKy>G%K6MwR#l{D*H;!GYwH*$;8PHKHY z3H-Xg+_L_->8BpG+|;t}`;XoS98-zB$iv8z995Vzd$S7^&V@FtBPk@_*bsLjLkN7mOUMm~7nU!YB%C(fAbi(dCn&s45$X+Y30>+6gkB5o3wsZ6VephR z!C_f1!D)1?&}-}*VO?mUFjmMAR_<6U)NP6sigTlc8I5j2m$T`@HB1)xfn;IywH%?% zwaY^CtxDmPN$r9w!lZ4o<=Y@fv)(A_RvV^L8#lp)2F~YFrr+J?@ z+ey1CAiP;S&(@f7S-fR6XKE&8v$mwq*k$KpfCf%weeVW?}!54Md#f}=n z-rQK>;;jtv$bzr*RMi$7a{dc$P*{e(cGb+}+kL8@GfFb}m;-mK+#p0`ZQ{>LO$E}S z51Lm@;#Y1Dq#peT30)Vf2+Kp;No1Sn@kI-LC=S?3X9OMO6BkEw|F^2b^O|ostj8Oy zf2<@J?F!=_=M3ne(cOg67K8ay>s2WC`Wf^%Hj-0^#_m zA$(JtD7r)MHfr2|feT%`OGy8ED(QNOE)VeJ1Dyv_MPhI;r(Yc3_MnOzHpy{+*{6JD z?N)lD#7q*lxE+mbH&!?x3={e_Dod{22$1COXfG*iSS^wD59G5YPTbZ)MN->cRU-dR zgADAL&!0T&E?N1qtwg4-jysO5=3@p}OP=e7V;+|gt~eMIjkc?JV}~}9MZ@Lz+X6Ys zr<+7#^4OX$HQ6MYl5;|uH|G$2y~IgaH})dm*>NNI?g-&=6%}YER^=0xtfebgQ9i6g zDcOH=D!n%+fu5NgDR^gg6_jE^1<71%Ny+M~yy0LOY{pbc$)}-*{(1rCAG!yzxoxTA zu#WWF!#j}N)r)>w?nwt9F{GwmA7TB22Li`o-wXV_GD2A<`+hNPizEsEXEyQ1$0?S3dbn)5qVBRZ@ z_K|r3p-mNFQn?0B73_fB&+|c?+>>^=RZD%#&p`07Y{t4* z?2z}QG;>~JY1>+l(%Kty9Jf97bvp6AphT(54#%*2_Z_rfF(;Q1$xi!EW;(qIa4#%2 zvM)|d2rS*)dROV}%kN5hh4wB5m(?YM?r$xracS>3|N361jAcEYl20!$b=xIz61AIB zay#7K>F#D3=gIf|OE3FdmXuGkaVimaDe)`r<1nRC|#H9+~{=a zOodb3`2t~qG}}jG=_Da@a)K~DvszfZe2;KkFHY!PmMU~`NfQh{6bTd6ss*yMQmEc? zMX;`_6q;6*2#2SZ3#*>^3w=&Xga>bPg>gsD3lpsi1SgdvLY0-ju>0#?VYEi3@Jw@? zaPU;BU|ClsT(vkYw3(GEG!#b&w?noFJ70zfT_+wBg12oJwiNCcO4AMs$K`SaiyP^} zkmfAGWkH-!9h)xbyxc5Yes@HewkTY9QjjJ@G%!IkZ;L=DB?^UhTLjy)mjw0ptA)MV z5rS|sO1Lm(pP)SYfMC0{Lh$L_B=Fj`Lj0?#LjU?y;i~ykVP{Bz(0f>dV5o8e$H`9R z=U+q$y>DFMUuP*xtol~bhq)cNT!Mu#TVh8|DlS)*_xJ+OZd~RoR?ACPH5o}3?Ve0m z%d1K}dw2=5^J4gF*32hohPx}=jg`D=TrWAIv6%*+KEl&`+VJNWuk%SeeT9%!O*}E& zSkk|;j(51e8@1Lu3n@7_AmNpwq-dTdZzH#sR+-J`t1iSrUmZo>*DjJTJyXN23-$Q^ zPhni^ih-ot-f;dZraK;V$>%|1+6tMEErpG)@{;RSg!@g~LN~7M3!O5qp<{8Pr2M-K zpZ-Bj@@Yt4$>qzs64Ov=E~VA21to0|8ZRSNeWf9hanvExj-*TW$9(4ZH&{xneAKz! zxzU16`eun-$Igil#zkG=53jmOp1kPCS8XZ9^s%di zB;O+vpB_CW_B$QT#0EuG~* zdVk_q+~I%r{=_-UAJ)I=XT$&6`kkxo5B?UpwaDu?`tKouU+t%5-Db&8J!+A{&p0)= zmg5$C>e+JQKS^8mCtSP!(7(|?%lik#sk!|cr{?zG6sOkG{ubIImloP`zJ>n%^S%>y zKgac!N6Gx|??2A_`v3m?KkDC~+b77j{!yEQHb3ZJ>u18d|KR(rpZQ0TydwexrXZfnVd)P6YkzjsBSJ4@WI_KGW(i^Znt5 zf0G|Y9h}(Em(E;e_%T=uwv4U!r8`#G@>`Q)>6hAWw8Y^N?(E?QI)gG%XP^w8A5_kQ zydCJvhc3{u+i7s?TncjwkHXo37FDO4)yVh)L+UtZAN_V#iXr7FL!Nf-i`IE=yzbpJ z?maFFzKrqZQIizuJgXbzYK;jD?ibB{W@ghN9^YZWCO`5n?s)>cr(n9=4@2t8xp=NXo_*5SR4#$&(h>frt^g=9JP!2wcyz4X0eR3BZAK62Y|=YtrmzP1M2-mHOn z>X~Hy_={LLb~#*|-ic4fdZ=&KrZKFUX^sxy*Ik+*Mehi9@G}L$AO}Vb)!?6d`O$In z`}4Y!QFQasJH@tdS7K3(q@U;t7`2Oe<7!g&6DeJznlb3>d zWBYelwr~)iSDOW1jb#v{F_?#DZG(|*)3Ms|9IPsMfaw+XQor1Xc!qz+N45hnp#Cuo z$~EQhkIq4pLJd0L#3x+cZ#ZAExDjK6!}*y zXe*B6a_?a4Wg2u}e`WrmM=pD~%K?)2HIhqvigAMVaz5Mf5gZZB(QCgZEfV#`KK5Sd zJSv8D)v@AH^ZlrnM;Nb9(52(TPLmYhN3cXImK#oPM|Td0#EYt8cz9wEcG#{7BcoK< zieOcm9&-lzg&T%+5z2OND z3+*wz-~(|sHieR}CPY;EfQ=6RB)+R+N0pUM!|*aCzI2=q@sG-&o6!n;#jN1{_B|9` z&Dh3^3WkH`sn5{2YX;hNJO}X>T_7v`Hj0B{*|I}@*_%#s+`9dI8ve!GP{4?;bjSsu~_#>H=)D8SCZ;P|v zMAP^BWuj0iri)Tedy*Z0oz!G4#nxBu!mPc)RTkQLBEKnHP*$ruH#ml1x%@sBy~@OM zU!JgcZppCy+7XC8{S{`}On?b92EyZeI_T@mux@=WQ!`yDI`H-oRLqWtJtwc=okv4( zd}3>^anFQZ-dF^OM)#oQN+V!z>o7`p6hi4^O@3otqx0Gu;BG>}*inFOeO;|4HmQs*x=Xw&QgRYNdI+jZh7ZK(1gg zUdl8PH#>a6<}6dFoT9`t)PvbjM?K;+s~eRY;J}ryr&i6~ahJRbFy>q6Q`R?HgUUQWu3$m{6cfHVpcTg)7&?-B$LrLM8;ix%$FwgB@f-%4@P>##7Si;W*;_ z-UcsM%kyBW1V+<#kk2WD(ILT`m~T+x`xd#Q{Z?ftS*=UY%>!6f)s0rj_T+dcPZhgFcJ#eb`8x zBgKpQi26jg-j|(iEW<7ePN=z9ofmI)6dTzqf`7y;{Qe??g&KXpww-RmcT9qtA}Ow_ zG|#>2_8Hi%dMr-Z(T%(vZi|<8zQoM$-C)#YKRnbx__LZI`u6i}*mXM==8BGhbLvPu z-baF$%&9w>*MxqqL#dkG7$zu-NL!V4IN-zvY_(PuraWcj!qD~DYQBKhq7}G&%2tTE z6DnRmP1^5|j;C6-$KjEO2}#`&ijyzY!|IOd>;r4fcNr{&VtZvsJ~0IL>uhHizH;0) z>lT~3zblz~(}GtfzQD565$yipXs<^Cu+MG-_r7*Lt69zYZoQ4~-yU=h z&!)TYXZP;i_x;U3eL~GS-F5oZ>8`H&etBMIdTeJH0)NIHXj4yxo58(U?!~#>+heWt zR_A1R^GgqOI=oQt)eoq>IgoB&eVV@7k&Txc)9Iz6CGa}y0E`MBB;n(e0gHpil3XBJ z=3)Jjmams^B!`^m9?boTj~^?6v~3&r{op)E+?Inqb5rr9=TqF7W{$%SG>cSt<3M=q zBz0fcLY^I&&Y35Vuu-J!tvwaans*MJX_Bysc^?(+6~xHjN|1Sg+Q^j%}|N0cP@+}93AY!Jh#xe1V3 zQiL`m58{AU4VHO163gy=z?$0K7|6UaE~E!9y75T)#cJ-bkOPvZj7f&?F!k13YWpGx z$LQ(7s;u*pV}-OsYa6fSViX4GufSas-Jn!Khnse>1M_z3v9qcrbmbmvl=fLnhFs6Y zrg#maefI+Aqfo;oTJ^$J)_uqet8TitZYP-FBFT8>05v?LjOv2}p!7>UM6X%SOGHUAT^H84v>z`wu~E*={Phd)O5pIpd(RJt#YN6dLaoTd)|Z{M;drqFy=a!b1LXTj_~K?fMLg4wUThtKd-sOJ zkr{Dh;g)vHnG%C@cie+(XZo@=&u-zIKC^IneJKXCH=?-H9UI@|L4&n~AILw>eEX3lkxPCTP|nZvIl>5oP$1gDrC&#LEOaw zrtILfa#S`t%uRgUihh0$q|JFSePm-wv)i@MZH_B^(cVoSjBeqX@`LsZHbNO~XjhOr)p>Gp(j(TL;yxnoj_c$atktkb;}c%$!4 zd>*<4dls)kLxW8EIa>#+Pgh~Gbb~~X8l>e$HvEiKMaA#Is4lzTRl4^QTCFCrn|9y1 zouTWgx1a~Zlr5OOdpgeW%|<&mT=XDKjLDMR(Tny!sOGHQ@Ivh#tZg?T!HF)+Y(PD& zKK_Y%sGkAH#d%n9yAR6?34;8PeejX*#=MWu!5MR{*?ImV+`CjA#j}-3_Y+t4@x3Hp zTd7&XF`)tc^g!(UU5Pp8*s%I@_aSjae`s(2g6HjapvDq^38%+%P&e2O;*U$n(3vAy z$lUF?ciL*)a&bP}+^q!Zb%SBFeHm_uk;e(0M>wTNs+f5x1k$pDh<^X8&~^O`&O9AN zKW|oKgZ$Rw$tkfQi3{LfnjNQ4Il^{~&EWDco3Rxh138R(&q+mTv7&PuxrXmXxL)~# ztFvJ&?%b%$$onQ}xu=9D*ZiaoUt@6Tjosv{uY~8QV;Sj~(TwoEF9W{=9Pf&ROJ~VD zJaESc7j0>P&aZulWq)H(Q~)^TlMR!HjieTrZJ6<=H8A0BJpKM_KZ`%Mjf)Xqpst5* zh=Mk0v(w8zzVA2)Tc~3}a@Kfx6cn;f= zaYE}h+#+;gsms%_u33m5b~GaY&HeOtX zY{70$MU@fX>yy|Dy-M^qe+#{*E++=PCy?da<`Kgg?&Q7nNOY@>C9jVj#Vzj2WM^&y zx9W@)W{&S64b6#Y?_-V^J*C;Ym<_CU#R76^?I2L{4?x#~XxI^0Us>{11{wy+veh03 zxcprbZmO%4!Wggo;bR_1qSmWo;t1!^5*>&E74p*hZjUXP%2ZPo? zxV3f>mtdKN0bynkICnBl=GPGVF9X7>y5RSZ{oUL5>6Qj-)8@e;hrN&pq0{8#lgF0P7J8F=)CpZ5rQ=2A9-0@s12p;hC{))YP#U6f}%A93gm8 zHG*!`%#d&js;~=wzIeD+j=eo(4gs%paZr6SbspzSiXXkg>$#&@LTFoXN^~ykE^M}zW15fN(#0y{vApLy?pPcRm+ysB z&)}=*`y(H>r`*6@XLo?F|0?q3oD_MYcosMD_h61i30?8i0UHGkuFZ<_5P5S8`b>_& z^X-mYm{8(tu+ZVPtQy1xe3x*^6{@4zzI1SX>qTUGy#p1Q9Q59>h}LXe#Is%W4##_h z(1p9Vahu=_HQ6G=r0)%3JDoD{Ow2&cSIDPU=BrucoNtx#J}xZ!wJ!7NImJC#(1yDN zbzJ7m$Cx#<9>*#>!U~H53`%A+_0&$(UeJZh@7jTa^BvCZNj{_>u_32wmczQv23!&x zUiqxwbsz(UxT432UH6Oy1!$pdo^@z)E&grL`6xd07+n zO*3Iz>qhSEnaZ;P@_DGcPX`nv^TwMq(ot_>CaNZB;)*NQ~=)Mqq~v@XHrzs6$4_#AHk$#BkOpDVj7m(D9)c^|g;ZFQX^h=B0fQ;Du! z3ap*do6T*!!3npua^uf6aQID{9lx*wJ;ny${l|UCGRM8J=us$Qt`k0au!U9?HgN|Z zmm*g*m(G9wofl`|3iH8;?3pW%^Y_|e{q3n>bxw$C^%AbQ-HVA@y@Z4G=$OjdL60$` z!Nl4cp&i7a)G8O<)(&N@!6hQvKz!DAv1CMVS6J8vylUEd1u&eFj2g%PkbD4lED zZH6xOCt=gFNSKkk0{4!O$8AbSuv2d?*&eq5YN}VGW@vx5?cHd6zK92Ny@OF^$Zjk! ztA%63-eX~f1@m{^gG#~}yl>i$<0kiG&zx_d=CwUId3}Gj;hAJy8k)%I{8~?ZJ&$2X z!A@rFl?{7kE#UZ+X}GjNpMCWl0&7ou@SY}y;(+zV^zF3MaA0GTsITT8{Osm}v1^7= z?Q}i779L5noNG9X1_5y>wu9YHiP%<^i>J3Og9p=!!M$Qe<=A^t_~P<6QP8Ia7!rMu zOUli_pv=Wd4tk56E)H-sru zAC{y10E(WjrR&V~S ztX?Fs{Rl~UC?&xexX$rZV_`rQtxV96 z>%rukcI0|$C(O|(LA9SHbWU6rx5`9 z;sUW5wG*2^x#EYxy?En$yRp}cO);{`9S(Vz5!|3 z3;kL55^q*k?2UImuVIheFR`rRF!IdC7+z{7h(-^wA=$;7>9d82%uc5cFQctUJjH<1 zA0|uUg{t(Ge=TgX%HVD)hp_xNt8u2RB0In|L9JjJ*W&RCLcTiDBAr?;q(MZVe=cI1 zU9%wm?k~{%l7a(|Q%rXl$ZiVlxH-+^c-iX_2dvr4P6oWB>xLM!)(!%33yy+%lr4Pk z`2|CL2jh`GW9j^%r%3Sy$uu%fisXEh1CdlWL=YdQaAPPbHnc;BQN{G&oh-T}Hks|S z&~eqxwq>0Qa!@134>ph5f%8Y7hVpoA;yf~$nsjU<-GQp)i_8n0up}4U??uyfW~aGB z-4{8VPhFH7q{zEDzZ_Hs+rx=Fp5*FQ17fnYrp>wqlDCnHI7J*p)3* z_ufT_oazGCr1pre&XxGCuUw{gAI`*lXa-?W2e4VhXO7`4)K@b5yWuc%@>JTf=qy~*UX5+T`-$3LtCADHP9Z%X%_UEpLM&o_ z;AblH+L0r{dS$&^|i&=Q$f^9NZ5z8XVf^<6zBWy zC7bgnigslAa04fd@urGGn>AwI_5m2`nFPm^lBKI zbb?!RSXb0}U%*y*sMFUf`MCbEGLuO+!WB_^a46&pMuqG~>DrN?I;s`f%QR8Olw>MZ z^HDTeYYX@8V7SCr(-$H(eSI=$bA3d0@foznJ@lB|99;WqJA^+z2znPH;6>X+xV|G7R(w0fxegyr z17a7@vzOK2Auoq#e^3#e)=WUdUrt1`_AJjeJq#Pm{YxVdppKUVd^42{Fj)3KF~ zL|@|=W{HkS)=r9GWrGnh+0a1qwN7J-MWkr+l&dhc@H9#24_N#D7WZ;-CZt@L0vG#_ zples>;f9nHbSGwviygxXQ*_DGtqUOH`7Wm6Bj8rPHD}Hnq9K1^3LX$`fN*WfEXC0f z@KivXK1_41omza6!{Hqv{@Yp5ui` zX#f74`=Hg%_O053JP#LK(wk4rXYp~*#t?jT$AH)A<%+|1t!9lab#OCJk@R>J5To+G zpxiMF>f|iY-ES2+V%18EgQmk;^$rZ^SBkU0HKF!Wx3ga5-SovaK%-ADc;F}Wki9d zI_tHe2pt_&;^`jIV4cZSY z+O^rMJ5hLH`g+W+6~VC>Ihd#+nK#9hV#bRK?m1ib4yH-w5W6N$;%vnhWO`OOyi_>@9^w^Hem(~` z_N_vv%fYZ{!5(y}jiu%_DiR)6b#ytopQFn+;(PH;km)u;huexI{FEVgVM7FJYzW6A zbS<`osem`XhSr$LkZ{F*BvxJ#(l1_x;@4Uv*)tc@;2@U*S2HajO4?3J!g`H%d-icMEg*5Gk~l;$x)jVM!Z&q zd$=#C7rC_W$_SY|hf!~D9^HQ1iN%f>&*qGiVkdt@!r{ur)Gbwp=^ly1FW0O|-!ya9 znDK>Il0ASp7p%fD3!aF|#w^B})3&3RhZH+-N|VkRtBx_mmQ*b7jmf4vDB)57&nPiz zlVbX;B@U&$c7u;e1UK<`4Yzs4E^Nr@gFBl4dqUVEqQ0H_$`M4w*1{~jv z5W5|3zqH|c#qH$|%MN5E-(S-dt3w#K-4Z8@Pr?X~XQH_0^_;AFEVSk-(U<<_=(Auo z&n0m$j(>OwKiP(gKq$=;cQw<5AZK#MEDJhRmU3TvZUE2d890ePqCrY1TB`TPRmIuV z*GR(M`@wn|RKpuIY%|z%gOMXs=!1neuwu&sTslt?>XZerO4ktj&k2D0 zNiVTdLkex~N0DDQt1;Hv8mA{EqkKv%O!;vD^4D6U$=#W&Gi>JhlNV8=VmQkaqtW+zg9;_t6YV+ z!+}`AZ|8B2_O7hvW-nBFm2M)jwL;HWj;WbCSOSfpry*Yj3kpv)_tnQ{}3Gk?gN zGO3+zN|XnkfE%3WCKHlh^_6azJd9H{c}m+VKTt(=U+giu%>`aPg}27nVYtv#;WYdc_?m}7!UoXl%V}+RdT~L z305SylikZj@XTf)Q~vn_%(GGKFbJBV_pS%>{7fRak}e=^VMSIu zZ_8FYrhMl(?zps>w$@p&v7H{&^R*f&3=Ly8H8yO))KA=k8yh5xpVi!%`4=(iiyT|L z@ETQ^V1zMaEothLt+Z9^J&ti2z;=uf<)M$^UN76>?dY z7t!XTI(hot7r}cFye*$8ayNa5UlaP_kD%$izP3{E@`VT;of~NQc~|n`aT^`3yMWWu zvS21p$3k1$27GfMkvHtyF-d;VUXl250c-(TqCa&4Gp;{{bCMLe*$%4YX~8tSLQ8O9 zcRKmfUCX_DVG5%p>j*wq?P1QtI^?p4F>YW7=Qd1YpVmy~_S-n(=}04{^7T00|2~7b zcYeW!sa<$RYc$fzEO_#v7mgh+ATx0(Yb?)%7AuCg#&|IK8X0`?;V5k1CBrnF!(m-Z zA65{)m{sjQNH!a&u+vlKuq%uEkc>((=JuARilaM0KA|^O<7sBJOPaMmT!J0rf8wc` z*CGDxU>5g7j(Nu`u%Gk#z~aO<=wM&DNy}{52J;m#dFXm<{jAKog01oUEGOa_HiT8Z zF=WHM!inFVPohr~V~EoQ28JoJ5ZYzQQr#UHlS<=utrcSEO*J++^Agal^7uY+$%r2r z3AiKaDAu?hL8F9?@Y=JT+7(W~CKW|yX*7&zzm($5ap}T0*Tcv=cWG8OPo}e zXKBH(yeyR3+I+xZZVXNiy@yR+zL=kz!C3`Mv(1HDp(tViMti=6$7ghS7DGPcF}V=< z7U7LoTEBqv=R!IxwE*@HizAx$lCYF(PPE)|5$!pcP7AGhFvzMAX18>TMD?#})ZkB0 zQt^tbdZa}LKhEa93C`j8^cOhSt{#t7rj2+%ND{|#!<^aZi*dzGKTJ*3B0KGO;`Mkh z*fOqw_K8ZGRoLNiMZn+Q zLWh0}=ZSCMh1V5&2tRBfNX3m_-~#ER-s!N!*dMEw>Tq5AjWPCJD!pR*lXuyFBDBBE zq?c1BW4P5BjGVTc>+&6j{T9~2YkhMTQ2Lqkeq&0WrC#6yR(|62*=Vlx-f;Z1BoGE$ z6hTN=4%SqOY2WRZFpH$qrlq6tPPYK`Hk8qKUmw8hK1%FP@g#a{fS4PwMggVAU6i2F ze&B|Dx25?t*XhRDS9mWj-I8Ei2GQoiv5;eUO%(FZA5T9HB_Gm?sO)_MG9fU6Tb?@t zWxN$2Q{rD8R3Z=f#^PaVXN%I$Vl0 zs?Efjfn8i`fFi6~l7o}OT500m!8q@eBAUz!g6VVQL`#cYxIRND3|(n~)25%GgUeRK zXi5CX;9IgNnc@ate#$<8e`I7d_KIn#xaACZC(V zpe*D(JWLITTXS6?@m?ZY$HsuI(*V?B2dMn!Tv8Es2PXC00cp<|Zf{mSdR*6J%f;_u z*bgzhO?U*u)jx50(;B$y_unW#Yz-}Wa}g&5^by4>Tt>NVXXwP0$(TRd6URxo(?3Y> zMRB(!UfX>Q*VAIW{_rYJ%rImp_Z@)(`wz5)H=D$)65xStM)dsnuOQ!Lgei`}pq2HQ zK2x285v4BpjyZG2mSvUu2bV*^a~^I_-y-^Q|2^DXwFa6MH1K{>EN))>mab1B)ct1! z9Z@So_-4VF!iA!DLJ00t-T-sHd18CHJpEX<9;2f+yCy_<;*Sf7_^c)a>^s#sc}-1j z-fU0sKbDT6#SA}^VhHG?L|=KH!LvsOLbS95E14dLuPsl&y=yWQ5BFj%j}Kwni@|tH zHW{tWXS47@3OHc41?cpDMF(gbFc%40@@*AMFvyT$TP*exHSgp2u4WS$re@=+4fzrd zfW72LT?YIxo5EQSF9x4YGf_4%nIvlr2B}#Qcz=yCxEA|iOsW-kSHp7jtDIvYl< z$-zr99r)?hVJ?<6Lf7kO__cZ&)Vzpyy}L6FO-`3!i+Kj7x-6w{wW4wAWFNNilQPWy zbQ|vL7@&62XB4lG<5o|P#fr`Kbd_@_zJ9!)CY?HjHedULWs^S%JQssndQK?Ub(DIA zYLEkQKs08?K+6~t7z0vFdf5pq36upEsDt0~Iz%$kR`6oA29f?W5YE17N408ccI(42 z{B(04=-T9oE`6H|H*-(nDqGdz4P2tmE{tAD)spQ|rKblL6F+YHjC6A5 zy9|7FSHV+Lbn)r)ZaC~?#3s-A3X@zS>6{U3(D+jkPkWdw2Q};P)u^+e(8n9zPO&A^ z?@P0Tq7!(2u@?5s`M|Sz_zWIbt>FsK%ONNA37ZbpV`AlUJbw5r(okvaRWTiU@-$hN zhX)*x4gmrZyDPxSD>pIA730Ay zT9G83d<9?TMPXD-Uz8n{1omeuaU1807q9D~{rSi6sV5624Ne31v>co{MVIwjm4cV0 z+oAM^IvSQ9rJJtAi?*GbNUt6nO;6Z0;4D1~%3o$;g~1J8KbHhB9Bn{ePR-=r=GuUE zzah+SSOOZpoCtDG_H=#lL;B*45P$S-!6!;5F!=LEJa2IZN%?(lWuLy-Vb_Lr>Jd13 zLMK>c*7D9g+lkWs6-Y^`EG)ZHN52zi_9=L|1QR0}LzX_p`uzTwjuKq5~r501})|0z9NPQYE-hYvnIQYu2 zpp(uRI_M;74EKesMN*J7rysnEPvyS;=zt@y2au+^{ovs*5@jEBW1)-0+@WD3$>op) zeC}KVBi$I+Z=VmjeLfJxn@;d*7TUsKO?l3Giar|bwgRc7ERc6Rg5!)2ReDDzQ10hY zN$iCk{NhsKsCNl&?HowsbEf0kv~)b7wi2bOA!$Al$*nzMC=y4MLV4AGyv*yzqGPnt zj2kAJW|<24{d92pmp+_N;rg?m#`@w!UO29sc~jKn;0?!SB|>3PDA(dz$sKZ^0IL@f zH1!=tHB<{E7$p7Bp?yDR7@kAB?UtcelOr$U+d>%K>npEvK8HuUkMnvC_o0~+uY-~> zmv{Jq56bWIrW&V=!K&ghwVouZ{3X-Ky(?W05ED%^T(hyEtcdsEiJvG~g43K_Js5ol zSipGU7-sKj0-}|RarZAnT5jKftyW&}D$@)mD)G6yVi|1P^8 ztfHT|^-v-lgVtwy5!;}T__k~+Q)-@pM=JFoFwcS6&q{&rHAh2TuhRfv0YwNW3K;LpAHMze63A6xN}Kd>cmReZ?n!6Uny8eAxZP ziJYJhFlloGsyIsGsHiTfo2`#e+eV;)pANo0yaPRjr8wZ8F-EP;zyryPs9Ss{Y`qqX zmFihA-(>*TBsGwg_pL?ER0n+Sb%gf~Phvo$G@2VFAyde}xij;4Jp5 z2FsDw+-Qu>&Zd_A3P3(smPLH<0Y$55_;N1>51)HLRdywCzb05n#!w5evttAeGM8fY zCkd2&kb>_TE!ZiEby)gr5v)=TalL!45;nB=B;t2X9MT4B&w*;yGDA@AiBwn2why8y%=ZPQtK>-AV++{Ir_v=KRvWu=!G4&9; zE|HC$9)*tn0=K5aM;ev~$*aeX>=9Zqr7h}q>y|R%ejq>7sD)A@B zNAD*c2_Nx7Zyo0O)(&&Id>Ypo$aP>Z_Gm{idpV~RWz8eda}dXUjkJb!lGx!f-jbLt z@`3IZUWOyzB4AHfFHwE#QtYuxg-y1@*wOQwvgW^oWKG$F#_K$YXwe<) zSRTmRB(d=$@+d}Cf0g(~BFM7`cesL>zSN@eCY9|rA`xG@aDo4voV?ZAB;J+U9Kltk|B93lPIE1J7-{0Foeslv4bWpvv|SFm@L#q{xku*t`c zR?S)mH61~itjRwS`xjZT6zS*KE_jV8eZ(j()M9dP`Vqt8oxJ>U3pw-N1K>3E zhF)z?D&Lrv;Ah91ILyHS>-)r@u4J8hFYg^zmXBkb)=Tn!WUNW-xf#Uv#9=tNYc>fm zJ_?c6g!z6g!_NmD$mTr)d90{?ObGYv z@BvJp;EX|M!)zcn5+JnwyVy9*$@0VPf1X^ z_+2O1O8ht04jCAoK8)-!I!_xe*HbQ5nKY&F$ziJ@y5GMOHAY zj|tg3e*`;}*2eV{KIZIvy&)pq4sYciguSWVyjvQdY5n}UwAQ_gDvcWpAs&}SyWbk& z#iA&%n{o(Cx6S5$96gBZMwZc8*G)O=npWJd@5(;<*l6OyqoM zX3h()`OP{|NSKc4FTQghZykdw$8(}LsypbXPinAE{|VPMTphYz21C&Neq`$pGa}B- z#IsovUrnen6fLnPrLHF+=nxMc(nHj*S`Ek4-Vm+%=|KyZ4kmBH7P75zv&f{WI;6jy zB)efx4c*^$fZWd4AuGmqO4bA8A)zsc3|?~*KaY}d2k`gd!3Pg3y>&C-QDYZVFZeS#Xw$Hq3POk zUgP+_Y~i*_)VCSH%w5xP#=EVY&&#)zH^B^_Wh;}_@q56$x1d32WH8Tp!5$BG2T$ zv|!}ZRqVFH0j%$JhYlTc3E|8|*!m#>pA`q-q?NJ^@2P{&)_9m|DZ_Lod*FEAt#Ipp zA}Dq4BSga(kB91U#y3vWF%o~zos?-X+cFU!oH7FUoC>rzet<11ePN`c6B&Pg6mF(& z;BK>$OYHv|FNkmQj1AS;`EYAUX$Zxh&`w^YO>d@OpoentrCgq}J2`gn63Fz8$F_7+ z#^jH1lrteao+hGVS0B=DI0%!w>d{2E7~>uv;UXTI!q|jocvq4}(92hrDIOh9)C98J zWJ5^|fYoX6QA92?d;%_NWTKfX5TC!0XJ^-p$!xeF@?YXjG2a-kxyX=Zk{pQ`zZOgz>rXTs z<9KrlqA|#%77qVB%+3Ae$i}+alDT&p(6;*vcKz}|jTLKgxX~_rc)5)0I2Z-FIqB3! zSr1-akAhhW`miBMn+@>o$BwP2N71!H+^*S%87`e%;-z#jS=J1*Bx`>CWy0u}A!pEF z%n(LwB$$CPnLOX<%(mPZ%a&fq#T;O1xQtnJ}Zyf3lOMeq(Inq*l*{1rUj zc%5_1&||e4JvgE?39gw(fYnW1vi^P*RTx+*stLHrbq4ik&!SJ!b@^RjX&Hew8lk9k z_?YO)SY>cAmBi$@CF7te+GM3DiuD{^fZnBc5V9d2C!8?kQf|nC|A&3J@40}Pyqphj zlnda&h&bHJ<8Z6~NG43T<5rYWc-U_sc|C0-*T-}MF&#P%Tb1r{-4$}|4j7AqmgwLF zPLhw)z8viz4PjpI@4#)8lR1eXJ0a};nvSu62E*uoa5-gxi7RQmK)Q6DYz5Q z567U##}2v!wNS^a1mAc+$KAV@(Clx$Iqdk{zv!vmG8-&+yCA^Yj00gj|qy8+H@m#jCFI4*g^5cYJN6_cK|YsAIp z))>)uB#X!yNoKA}#+i54q1xGNT;Rb$B&InNvsYZg0sSPrgKG|fg{>Nq?-~vU-!9@R z{*>A@zH%jQ%z;qlc9i9TU1E$@Rgv^ z$BRsGozD`cj3$=L`;y2?1zdJ86_&je)T>|^OPi~Q3r*hQcIOa~KM+o;{4_97>AhsmH<)GJO~i2{t3hS%E?oX&7ao$Y zKt1*AIC<(-Zu*`8_^7b}Gr!K_3EPTXyjl|J^b>`cHOUU8&F7diA5SL_ca@{CUCJ(2T&^i}I(x9rxT@JoZwGP@#I6^JR zO~GWUm-C&fuZ%&HI!)|7a}Dt?`h@B7)~Gi0Ft?{sncHz&4PGsHMibBe;B~!yA<6A9 zAX-r;Fi4t%&)g!q@WfG()UZg-U$FswpCseWj%KLw9K`fGJs~7=vB=ak3dcJ|(G$a( z!Ij*_vcA>yqwrg0ujhkt#MC)tbd)x#48KU9E;t8z0fA63avX2j8x;s1IGI&m7>8~* z>ac&J7TVw1j>h&BZAbWtn)vc4qy{AM-YuTX!%z6{h!d#y8+qXm)Wts|Ec};vF`NI7 zA}>fw{nv5eGB*5G`+qCX#^x=5$^XHf_&?gHf86}vT?79ud>O&-e)Ok8|23Ws7s<&# zFUdb`|IhsX;8;nm`>X#M{l4G-4xSB{e;dz+%fF3h!{y(`v+*xt|KWHx^#AX$Z~ug# zB_*Z(yHow?FAq2UuKjPj^*_STs@nRO{E+{d&iN17|IcXP@AggbyJbed`_G?-{_p15 zIP<&T{;`*T@5g`Y@sILfYvAuZ8}i$KzyJSQ>|gf&jAM>&{O`;Cu`Ala|9!bXc4Nqn z|GwP6RNz18#=qnE+2FUP{&e+!*2sUn@$>l-}U?}E%N-}sfYLtwqpL(E+>AB%MXIdJpQ*DULu?yNQ9Ka~sT zE7gqR-*~Ri|KZ#~!iTnz<_kIeD>X;>=XeGDshkCW!SvmHhk!x+@4m_W=vmJEl}n8H zht!YopEdQ6#|cUN7bhQ+0*@g6?m;v7eJ6YH|>nxoU}nlhEMrov^< zRywYnNF4gFzwV$f{^gLHY2r8}YIoT)gRc&zCPifmwZ#sfo=zS%%5{cAt&o;|b`_QR zsLXO~lPz-0sXkvi{-?-cwnwBx+w2?%Lo;vtZaZRs^}dUv+4kbH*j{~w@51zjcSXu& z@+m2f9gBWAD7KA1rPgR_cXLRo{gJuv9KLpbcBo7n?9klx#zA&tX6fyqlVzSOM>@{% z$hB)cnOwGLRCw8Q%W&c7JGR1sw>(dUc5HJvexlkT+fBt`p=pO*MX3kBh<|{uuIW8AbE6o+j|$^?2|b3lsR~Eh6~$&Q0Z~Srzl;Kg942->>G|F4@Z8{bD#@ zNoE?~e|HE!NHKwbRwILdxhkIjT;n)D`|&cqmWgu2nv}SYJdR zxJ?xAa^1zY|9sCi$R1^HVn$$0wvKpd-7#_UF`FVDQtV>WHQ$DIVV~j zL}d5&V%IM%;isk9v*;&TbY7ObI5B(xOU)}GtM4OD3zH)rF}X~0StES4OJOU;zsUF0 z@nSh=NAUug7PgGo(i!zqd=LLtR<$yWjbArhtkS<+ys}W0i57)2tDcL*)gzTn9a7Al z4-?UmGk1}v>w}ruCo`sZWIqJI>SW8BWyC97yP0f#3gg)s^JhxWV(VqDva?x(88$Cx ziTVA-@@<~tHiyG(P1q@e?GEM9;VX}C+QX1Q}u8d!~`G|NS^cCN}b%TG&W4!pu z?NaeslX@H;nJCV&y&_iKEkk0T3Ha~MO6){>D|AnffVxN}{z~t93F}FO_^fv-KYz<% z@x23Cf=8PUi47LZi1}@?RcBs$R&8kNUG?sK8ksPBusE$ET3o5H2y;hd^M{&h3)U!A z(N}wF`0o9>#JyUclE;^Kkriz&tn12B@@9ldmGgZmK5wu$Y)i2d#~e0f$)(T5ar(_- zryjd1&$0dJh==+7Kt-jI-`Xb#%v2`{j#X9&rnsaELVZRF9y!DavQ{q@RK%WH;&wqLxe-_V zf|{L`g4z2L1;Y<6b#&7C;%HT#;COrKc;W8(^Bj-z-j-EX#|iu1vJyJmo-SD!k}kZ| zGR5iWT%Pc}t(T+W<*mZ-_Op&>Md$55uWEIC`nl0@SA@5n_UQd(Q(kUxSSNi%n6|}N zSTtv!kc}VUcz>#g{$lv?Q|I5yV0lwEf`?I1|0bCi3j zFI;}VfUzP-Ir*g>ESoS+J+2p{O)>2So|^EahdOk@?}HkI(p7B zC@a}vE!@^D<;06}DASoJfoCY{?_{PCD6AA4mOdJO(6J|cUzum09S(N(1rEzLw+p|t z?-yn%uRf)w=jYg{DP7hpTG`>+rX!`f@839-z5vISD=SO)A3y9^zkE#D*;hqEEpCgj z#qqrG8lX`2#{$PIJT;-dw7R35LY9Nn>NMfYGe;Z~70x*RD)~^Rc51Lt<7r<-Y3Byf&aeK#@l}#SNUC!jDo*5{>WAR-hWv5*YS71Pi&6+*Z0l+y_)BaQb%k%y_VTs+azcH5l(fGes&41|+8~e`!(!Kvue6Qc) ze@emc{XgZO39G6)1v>~d?iDE_uD`A_3!=oPd)xo z{%Z~Vov&nb%U|EEe=YT&_Wr!*+KKwzy<~GFo+L@iLko zQN`CQMXN@~QLPnEIs3a+^pVG4T0T!7JAbW%Rkx2p^!8-hczZ5<@J&ap{)y#_T_F8if7xQI5O%X)3S9hS*^n#2e9A&Atl1Wd z8b4J)OvvADe9@0jM@R8GtER%MX>RQ3++^DN@Bpn|Q$=aE8C3Qu7MnXyW0cTmdv!Sj z5BZ@Kk5>k)=n5(H4Pu zG|xU7F26Pdhut}lerz!wH9kN)x{Pf1EewUBK|M6sR-iWTjC z&rcsP0P7nM*$oQ~`muB=Ni^SQVUcfr*F4Q^=ea5}wb2xVNBpgWUigK@(#bU0&2>lQn}tgXp(ulzLn z&#K1cjssXZ`~<&tQZb}Wp24(2^Vyj2snm1A9Hz8uP`&d2>)SF4yxhbE4^JDbnH7b@ zTXIqASQyUMb|Js!12pS<9k9^5{5!Rm%;T~(c-kFcao5vm_(pHA%9#fpb=lT&?@nRE z$R74H?=JsrI&V4b%?Vmxra_Cg#IPS~4@h$MIXv%CVl!x&JYJURfX~me$Ygp8{+LO4 zsyU9e2>pD89y2J=QJ|k$>SPpFNk4pbM2at^srP^#*m-JWU1VZ{GCGe;z$b*}`>E44+qj zke-C@q?g_=vFZI-sLMEp3+CvOsh-3CyDIeZ_6mqx>`p)Dj%QNa4fw<1MWnu}gnbgs zB{ye(wHdvu2e;cRqUEYSUT?DwYL51!XWz$yP5VOVk($YWd^(x6SWbY+m+h%2Y#X-w z=-G@fv#Q(KsQ?z{fmCf6!(XUA1IPSsvzU@=V>y+MU)c@Uo+*&Za|V&U+abRqNc28*G)=r)ilSUCI5PPrJ2%Ul z^BZvrfcdR0W}eM`W&zlv?KkK+Rji}-4(qhxqXpSHDxqrco$_G)ezh^3B0 z(FZvuKEy=eK8=O#b`Bzgy?IzNT|`4)O0du)CD1)ViQSS{p-FZ(a2Z#O`p?gCQ$ucW zsfov6@plROTHK4uO3!f7wWr+0jV_oNSA}AG`}q5tCSu{!K`^f+oYKcB^JhgzSnG9h z&ZT!U%YPMw;w!>HeBMo{k4mNQzY@qN{v~@?qYmSpWNhounA)!7l6IR2PaNXdgEvRH ztug07a|y7J7iLT;X$l%-7BZa9{oHHST&i<~X zgR#amBxE$5|96ws#iuaE`G`*6N3pl6Ndlu?tZvNwIKChwgOBi&po}6%T6!=J*5t>b zVw+*@vcdx}Pv#qUC2Kf6R-a2Rjtr$qAG+8(=>#e}Vgpb553zSA-?K?IXW7g1t8x87 zPk!QGMP6+~BgUETqsmh@H1F|XXr8tPpBF8&NwfCm^TYu%H+Zwd0;{n^Gl5UKG@H4$ zB|uEfJ**42p*O`{tZ+*<^OZltf;y+N944{c_?J)KH_q-#h~WaI8fc2jc-<~!GBu4 z?1cJ#lo_`gG@S1I?U*Y%k{N61*=Rz@8>u$lCsu zAN*R?pQ|VS6TkUO^(a$>62HD)}nXHeOE8pa*x*8s2qBq4fec z6KIT3p*MBKe8BTrRPw|FhF)0#;Cm47-D?8TXM3D{O&+Gb7y=WQZls6Br);F1bJ43_ zRy4x9j~x{{P59$CEh#&UZa-Lj9a;&IY?lGpH1f$S*)p(yAzIA z?%m>3RS|YJM?p#bDAus!BxTkPfgJ-^>3EGAsqC|)5|_s?-B^+ux`)BW6kEs%k;92& z@`)?d!*thhVt*}3%V#pF*67mPhEFUhAc$n{#LzXdB+P!DO^RwYSlE~cuUb@S;*3CA zJ?TALud6~vTA#URp3|V9BalL=llPkUhuuFtjr%OO68g4E(3~SKbS6}uE-CMXgq`YW zu9Zibj#XT-YcpNzR-r+f6G%R$fpLyAg}!$>JFxZu-9ID3SvD>7)FqS@!(+&B$CujN z9Bnu@0Ps{pg+Bk73{e*vAvi7u#H6}NT>d&P*^B@~pn3AAR#{w1M!q-C#^`)SB z_&b)bc9{(onB7i~yI9$vT-K``%NnZG$aW>N`s_haTdzmEysBw=St`@oUW}h^0W_*z z2eG$r`Bks3vSpIG)atkml-FhA0!cUeJ&M86#HG-je}G8|%(x*o!|HZ9gwt+`bs)Vy z2DDpJ&}mc!R^`9M%pXJf+ev-6egAxTRe6!OSY3!i)R)1ptC^yllry51LHh{{zp$I- zpDP3<;L&^@v${onVva-Jq^7eSEgLF|8|?qw`v7 zWYVopV0@KUCh0@_`$TrLG@sdy^d+wkDs?ALcCd9vv#B^Fo@;&*DQZ)0r{bOAq|q}E z)yysF(wQpuE7hBn7ZBe0>C2J}{&2U4jc2_RGMV{}Zrs0Y7Eb?E%J~J?2n_Hty6RC* zZ#)m#e3Osmt{UlrrS@*T$ZLYh(?g)R`T;BQNaOUozcHKGc(`@w9lXEX!3<4LK)%#L z(tjHWL5tgH#5(ZM+PmueAW%Nww{ww=d@x!hRaQptYv7*O^ z;NCzz2C?HTDMQkB_-IwSti6q0khCTD?!#pDS05=~AfAh|Gm~&PV z*&0L09n=WrnV(ooTMTp9cA3exn9!>w0rXH{12Tbw`LbP%Om#L3eWPsfcZ|Z|?<-hz zfHq#A9ZUm71-K)qoPModT=!m1lT23}pd_VD%-QK8TJB4tU*9@ef_Mn6?~nrn`_&@< zPbE~pQQ%OPHM2XtbI|JEAUZEF;+8wCg$HV%(>wXrXH{oGiA!zcY98RZ8Tvm=e` z*rSvH2nyF^YR45}=xR;U)u5W6)8B|H?s>9`zNCah$wdKP%0DH{r}kL3Hx)FAX#3*Nc28jF-`D!bucDtLS*#8h{S9kiD_hfe)~pFj zjtM-py7^3e;~qHgl1%$NX42Su1(cMKjD_o5aK!ro&=Ma3svDo<;U^~il7Gi>t&I;p zo}$BURd?g4odV-!UjcseRRoy~GuWL|jX!_S!h0k9sD0{M+NqdH$9zY#e((2OeDO}o z{Z)w(oE@aP|7J$roABc1R$RUzl~8pye68I@nSJ$;FRYYQH_fidg*LoyAM|5kQJGv zou^K6jce&s)^hTiJ%pB@d5gVmk))HWE;u4K(^%u#?}Ahd}Mz5O|`t0#faASi>1{sPQ$Uy)jYb`raPoWbNs9z;s|f-e9(8 z5xx5H2%;>HFsE6_WE#?#MPUfEA7u2xF%z72A7I8>ub9e#M&_tB-`dY(EVSzlaH9tV zcJD}CK9ntEj5ueDzueYfLoRZmGR+k~ zim?a(L6yMU$}jU`!=D_W+v~;HB~@oKQP|4qISL)t1GjL`ggCY?bpy$?D8X~fL2Q(D zBokd;L&1~dxb@a;RBT+&OkXcyv*abgqpN`b8-0w0bQzFUs5(V=_;bF!S6Fg(DLe4D z22?fI@R^^6LCera+x)*A46(e4-aoeCi~JzetQbx0yW~Mjp zE21wcQ|L<4Zt^TtfyE!{AY+j!%zK~>5f?50Ovbj_C_H^(EjPO948-DMw!CQoUpMDq%!y|#Y_SAetSa;_U5uFV2rIe~@*Ne_ zq-pD>Xjm?`4H~aHlItT^xbw$?Iw!gcE=Ea6Reyjk(gW<=U4-Hsc zdllq;aHGWUpGdkyj%t6NVGcjy;Mdy%oAO()Sx2q}4;nOt|HC-SGTBS%W);l4x{AaGhjKN~szLtU zW#)ZB5+in;qAhQ=c#q;Wj4ODL18x?SeO!?Zt8`_zRpZ%;=1v$iY&}UIOQXHRpR-2? zjp_IGSroO>0~U`SJJxq#`@gR|PP+s%N@Q$>j3%r2{hBX2o{u6i z8LIt*xZ}_&DE8P+GRc3~(=}o6#YYtug#Tr&pYP#A>%A~y*japHf8yCY!R5p&WG90!eFCH&MWE}}atE{P&` zC!y*_Wmu^pI2x7GVAFRsnA?|0J*6AaIq*6RGC9pJ|FHt(HKOqG8x^kEY8#6lq6Zxc zN7&zkYe9Bh5H5K7oKH6`f(rw3bXHP^Kc01(TQzG6No=U$eV6S4gY}GxZiCL*I2XMD7JD|(l0i=qk%qTw+gh(Ug43j>A!7IZI=d}9*zjqoHcJOeF!X2^8`U$2-ypt{@;uzh=W!gH zeIl9_t8Hh62Ezbe=+IS{M>gm9RH*W~#nSVnNXNqm*S*uHzs}YCs=rF~e)SVPa;zL4 z=Kh73-=yfpdN=ZwK28B5TfU}Z8eB`5NCVAH_)n{n|GQR!nvdpETvY@MF^lFGeLu>k zskLI%P#3)8EWt{v%%~-81{D2>=GRu7=IWNaKtWDC>Itk`7tQ%>^qRrcMD8$JO@;X; zj$!ZTh?sPb0_VC!iyQ(L)6Vw^oPu~3#vKc1Ry}EK^r$lsHX($)GtS1JRB8yJN$_s zxZmL=-zgseA3cUr%t9I3KU{~21)9V6KVBF#=A7D?5$FLFSG z4})N6n3mvA`;HllROzCxt*~$6f!wn}O!^eI&B((YA2z|~&mLs;D+6U`@1xdZ!%6Q% z7B}yh5uHd|0n3h^hqUMJ^xjOO?pEn3=9$>b4GTL(i+%R8e&ajfE(AP(S_tt4*l%Hu z3W;R%cIiRjGjoz0dK{8po3sAk#t`J9OX)8fnQEgNy-pRVL|11p)#gfk=wc7cOjn}O zviJCB!VoB%u4N+`mx?p?z2~DH1xMedXuhfc9<%mcjvCdHVD>7JivIq`HLjTm#o{v| zYr{B7vc7Ip;bTpyUn0r$|;IC3C*XCRn zP?{_X8qk5GQ}b!xsuLu0>>BePSxcG%hbL<9d9rkS$UfY$ppS9MBuhzjO3MMYBBp|G zvOP$DyNXt7QLsklrcH14Z9HH&hqOw>Sj8$!fbw|u*GH4$9rd9#;32&Y%t!ZiRV>Vv zLD<^`h!=9Pvn3d3iOSJPUGa_r4c`0y-(Et$28W78DTA@!EEoNontyr~>3;$u-ldk*}4 z8%lGs&(OLFMr_CSBucpPL^RCSi2dHThji6buz!Xh)34NG+y2aj{3#Y>dDj!$K6=6K zEuT1(_Fp!8<&&xP=WLtG^~-7AOH+8#<3L7hS7N5cExzz$D7@TI2zPhN{*eSH>t%Nkj{&jVY#6E|*1*XT0D$+P;IraBI=xm_y`l5{8FA9>TS{>!BYa$aQ@V zoUooNI0VJ0<-M?nGz_NoXAaSttW0umJ4)|u<-q&AzD?k!CwRl;D$Sjd%7VHg;ay)j zX__|D+WH+ZZlV~-`|Hs{g%PBgI*Dy}TSyC>ltK4*E7x-^hh?1=htBSKba=Woj8wge z3duZ+c_L4h&-XK{b>jRe8D$DtyB=j;PvD;=<)VXe0k3NtL-L*>jGr=>Hq9}iN5u?v z?i{2?8tJ%IT_2TxM$$TAo;8{z@WhSe(O3K(mfsKHHHW!V(w9n{C~#*xpN-@^3wUe4 z}%z0_}84k7ysN|8@MtC?tR=z%LY`aL14;Tt9@e0 z^UT5X*ewj$wTdiXPbBB6)nq7s*ZT9Im()^{N^@FoVRL0ahI+a|pTlC<;#eh`xv9 z{luLi4xk^U1=9pq^g#(53UcpY3rz2^4%gExDC8!cjlMzCEf|SHMfBw!2d)#Z*&J;c zMxB}lY<{M=t#K6Z^J zv_0k}HB{ODcem(|^dGdY@wRCe=7<&Hm)V$DCF*}s1CK6Ok(Sd(eB8Q-Y?6C0B0GfM zztNx*8MZXvJ_UD~zd`B4W5L!n7oWe*q*0!mDELnqW{GX5xdNj*d(=hNyGDsU7WTyp zCJ4R=MN4=by%wZ6b0+5;&V`0=Ceil?EU?K73~yiN;#cehYeiXl`aFjXj#x=GmrnC< z%_G^Rv$NpieOvg~GJ-DJjDUMC#oXzQ`V{W8kW;#(KohgZGh>4YYFsB#cQj4av>Z5*ztAcN}lKq&tiR$xyV}r_gxVU;MjGZB8`}g_? ze%;HV)a#rB64N5^)j$`!vsjMcgb~vi*bP+!`#{!18e*d-QGe_JixK1wTNJOc0n8#zDZZ7TsjP!6ArV%XYX0x5u8--=U>LT{1p0f zcO>|j1;e&|3G}_^LrcBscyt09GGz)CwRwVp!g6nKH>@c1O70- z$0=;SS{hYYDpG~d1?DN7p9U2r(iER`(pE^O>4jY^qoE0{!~SDcSM@lfAzyGk)9@P>h~->9I+#uaU#X zR`%v)0+o8EqQhUoxi`xY4lg1+>lFiSBeI}IxEK4ZJ{j#+zhG--?xErjkMYpj=iI7i zN!WK6Y?kQnM$dnWSYtdNn@aUr!MkzCS)Nib<*8M(zM+q~-jXJKbS_tzPx_gq>R<|$7GgzX=h1IP7gQ5XqJkm` zxG}Mdy&POmYLizmd8anca^+7LSe1x&PUDFeWALY5mo{A`Yc78utQ(pQ9OY1`e+BjV zl~|{LcOtt-&7d^B8LE;GP|DtUD5vuPlPyxbxwhf`p_AcJN zKB(@iz?Nf18uV_-UfLtOl`enMgq!`g^e$i-*)6h!kdQGpzxOVKx&JsYw3dX#TX}HN z;f>9<6M%7-pW6JjT?S_#zJZuu_JYSvldG^YV(Na2=zT;44j+`y&)T^V5eSO z`zVSW!^h!)ih0D}H4(K-zr&k;^GI$+2HtajQ;TCGnOgN!T=_PeeXaS*t}WVxP2FYO zK!p7t`vEK&^nelH=daDrxF5gB|{T&a+ zUp~qV{1nk(rm&mQ^C8`7e{42x35Mx9c0z{W2R6_Mkh(IG%m>Y+R|}GuqkR>3E=UJ^ zZdc;ldrL6P;5GlrT%Y(vdwPDU!RBm^1Dw5;O?t(5;mbZ($dHQyscEnAN4*riKORa& zK7WNBBrz9NacYWH#L)XDFnC2L)Jgni+l6QQx$v8m61;?BYR|Ljy;5X)Q3W=&FK4QX z>a=xNm7rY6VLc^gc(F1IDznzX6`84|65@l;oCaf1P!`K%T2S9Nne~SIkXTGJYfo^) zwxU*>X)WRK|Ju&b7CkIq3&Y|P|@v!||HQ0&1K-<4*Oxo)&zu=V$jqS)|K?PZ~ zY*Zt6KB*c%o$BZ6T3wjd=45iqnM)$Md#EGq&?dY{z?X|p!3bp|43^Lb|NckJr6e3) z-jik{DjV7RNx3w1LO8Cmix35#JWPQB1KiQmO*V4v&UpUoLGTf{Ft>vDQXxl^-8f~H>vYhNdapG@p&?c(h$SAQg#O|yc6N(0oIE$o;l&nJ;* zC0Gu6%Ua7SnX}qaHp6)ceo@}eZXS?Ek1T6`oJAEpj9mmX=3HQ2H|@x)X$Wlou?=+J zc#`~ubQ}3rJBSONYyEJ12+T4*PLXFL(M#NfhCct!afbEGR=15=PWgyA5@*>+@zrq8 zD1}|y`aqPP=~6pY!kMblJ;*2{6~}0}5s5aCmVzlRFrUCI)u@)YdCA{R?!^}tl`JSK zhHKsbmUHTu3H?FO*~jgP=sCICBYnbJ+~7}r~b#b#~#NU*%7?i#ZM@9?JQsV z?KS^v%^nJGSV0L)aDylNQ{j5yY`gQ{RI7Qz@kDYFxpm)QJL{zI*LYQk{J0-37v2WAi zx-?WAh1 z(ks~3cg=U+-&>LBZX+Igos6!MG7!0W8znuq#V!RC_--4IUH{zxx0fD#NO1tBDa+HQ zBzOMdsQ>s|-JTr(G6h(mCuu)20hJ*R)Nyzj-R`qTml@@3cl!^}S`6T*w;Q+QpC#?i z9E$mP3il3d#P1saQN!2Gto=ec`>ZvQg0Fle?{}lYq)^0fjdg?6tHQJ9>Iwe)&c$@g zzMgrve54&l9R6MO=z2SHY%o@n*^A^gi0dER>0J6`sg3^=aq!cG$jTV74N zZo8)@mj0JOQIp29%grU^e6yEaH-~b^E%G2e?jSC<^P>H}x9DW)Njj^a&a|g*rAOyg zXpWjJiI2I2gWt`fbyi|^9>PrUGV&+-mI&Wx&3Rzi5lW`MUG&qz9O6bU#;zYFd{@sQ z8ul%nvPNd(rv-Q5*AHiKYqo&+fz9mxk0@NJpoYU8OIc3aJ-WVNBCW0j-uht$`o_OT zvD=&A$>&TKkP!wycBj+KAED%3wul{DeGt#RNu+JFC)2dtK!BUEP*xoYgC8_u@3wOA zs?GyfA1hmlHO^4}0lCMMW$9n%&e}5{Wyv?{JUY8Auk8v_gc5yEKIM2DYkLz%^9;S| z&GB%!u*RFo#l6PC&ZmWE^)XU4tYli358~H+VHePogvzU9>DY`)t~2)>_Q>UsqJbp2 zw>;w9?=|sdE6=mhC2ceiIalC%PbK-eN^}NpQ+U{Kdb>jhXRh{!#U-T>-EanSXU6kA z(FbTzmkN2FcY-(2&sQEz;N_OLvje}DlWvCu+QppZ9dI~&R5%O=ZfnrTEHyg3ayNZF zJdXtF9VS0@=RtfomvoFl%QZC!ygP?{F1>{V<^wSL`AFLwYkOF%TFP!d3c;qe*SWxu z54aQ`;S|1+6}~>mwuJ2<&uTw-7-&TW%F?8qpAG|c%VB81QOerxjUz_yf=4ZPz&wMP z>5|FtVxI@aWjEm2jy!Hd)-q0CaNRC7N}{oAcR|^TNU}+@5_sfqnBWEBwvIkV7YEw$ zNPjy;><4AJHvQ8;R&rhh5TP&vc3 z4kY8H+3EbE8&hd{(_57OoQl2*Q=r?Khb_O9V8X~|vfon9o$*cNH>%9Rn!;%QV_gGw zR5oCj;WWOK_oQ)6$@nM2A4l!@f#pf_=|MpcmM*YEzX&aQqpr)wdPH$rH7BXn&>5L(xCC!89?r9v6OT#UmA~L9|F&VCqh=KBHksEIE!g zmw_dpiupr}58(pl4}HZ76I3|v{-%Z>@>ij?02?9s3D6tPd1%yTZ&&B4wXTN6tvKG~#Zbq{6) zoag@NWzwWKDYR9ofwBzBXv(Ssm>B9yO@&oh>N=f?Z>vRzN;9mQ97)CUqu`qifVx@* zA1haZ2kh_gV-s(K$`36X`q_j!EH;p%g*v^6JWR7RLm)4xlcj{3VZ^Ok+%tR%oOhiE zW<7eKFLn-G`fXu-gDKvcqGIbUt63v8J&<+X-waAls<@zD4E{Pv!4k_?xOiYT%VO>z z{n`O8KD|e$jKA<(4mR^=mi)$mh2!w7^I@<%t_CVCl9>8!1DI4T#OL!a*|TCT@*W?=jy?%EePR+#J(a;%4a)7K;H1f0*5Eh_s%=D>0Hr$nGgo+PDSOyF^&%F0PKSkt9q5={#IF0h!<3VI zXsFF^{N+ISWyeis-ZqJ!m72MqRI#GtyL_$=$p^KN;*d$^Ylf-v$7yv_MC`lfI0ca(S_k50*gKf z)cJ)ZURS}{ZXQcHU&2|!Cso$_?WeFS|IJM|_=I0%zoD3zGsvaIu=VdW$vrv;pG6mg z#Vr+b8{Q0Mla*~NcJ%U5&kgWtrYZx6lhBIU(bC;s(a- zNyawOP+Go7oxCop0Xe#R1Baa0c5F;WdKyc@;4`Mh98qEi^=5`%W*%)on`6()O`atm5F zP}*r(=(?yTWTmIlmiozbW99^UkZDNcKmI{`&V{`&X3S7uiREsZ!R$L7_+8cM;B+FA z8=v}uOERnEBImlWkzHl%@`lsQ*)W%EY@2L;ozccOrU`t^(wnetNCpJUJzy6#j45o6 z0eO4a6UZvl!4Y|sdT;_+d>9My#jp4%Uj>prsQ_K_YtVmD5_wmQfR8igFG3-2c&g^1=s~U0U)4}jl=qhx^gi+5!XUMpg#rb|r;O9Ragy~KTDV`N# zzn3o#VH=jY5 zDk~eq`fW^AsuEdpG}-01l5?~X>8qV$$(HLOcvlz=)j26TB~{E0#5<9Hfd$^{*unbE z%s@(X5XJKDqvb!q)Zu$+$>1M0b7Qi2!x!qHJbf)WCN$vSuPx-i*A-5W2}XM}XKcGS z1Hq!{-JL7dG@=riW9r^gUL)*gNYfn*z@&0>UqUNUu_IY==p+v z*aPG|=5c>UDl+-RZjsjbOgg{pCQhrBXZF3fc{?G;CBwgll2y)hqH`4++;<7B@YO6tsi zE3yfvIf(t3$2L!wAW>x~EndG1`p@4bQ}qbT|Gf@Rs?fb zl%suNZm=;<4E(&$)23%p*wlZcHck31`o$T;6@L%T*(SqU>uw3fwA^Dy<_>}I7DuvI z>m-AP;?%iU=s0{|2Ca@GY+BpYY%BJMlH`9U`4K-m*aM+|vAeYvuify*dW{$CdV~f9 zbnUSi)tNq)+vK-iwfSW5j}rte=)ZM$FM!8KZ<@Ak#)udWA}JU++$q!_O7^&}X# zbr?*UA)=897Pp?7RyxtTX8ZI}g19uI+C?KNyf<^)=w zw2mTFuCXC&=QAnh3XhfAFyML|=hU^Gl=P?3=J&Ut@7oU65+h#cCZ|fr^#b7B<|}Af zzmEPWEu!U_i)_HA361^4Y&CdkW-XS%=6uP(lX^#?I;903ct}zFo7bSDu$v0b4Wg+Z z^eLfIo!wk1PWiIJJJ#YLM*m4>o*IIu>y9&peA-9vt{vys_v&C9O2Nf@oosKv1nwW= z1&@S#^V`j_^w{k-E88jyZ;#G~WETbMxm?SJUfRQWxqIyC-b##Y9?Im_FJTLoNieJK z&p2`GNdB3@Dq0zzg0tW1!_j|AcsKemA0YM+{MW^@iS~^wL6`@0KiJaNC~30Xu#1Y% z?dGC~ts>q3R)Qq>Qu~ijv{Y{d?EU%*Kgu6t?z1cS8>9a)TTj7vIej^;lGsX(LVxp( ziX}xC)bf^vf)CzSA50!>rA#63-yr&m?b$jgZ=HdztL|6^s}#f47kA)xt^?B&9pVpP z+=|y6rGa}t6oYz`Pp3CfN#?xlEa*_`nitWA+@R8MKe#wFhSo2EXy3z9>yY^cf0!pIUk(V{7yYf4p zf9OY+E8OU z(;7j&JEU0o6{3*Z2zcW+jn=fs;)>h7cu#QxyP`UWg*nDCNyA@|w{|}~2})p@zHuPt zjcmcu2+A={0$l}rwtp+JrR4_nQhzvfoa%t@LRTe0$h3PW=CJzuJlgL(iN39KVzLf7 zAYVR&#ws_7em7=t5#Ft^T)5TG>f21GB?8EiwCXIbN!P8tw2HRAuqDf;A}XzH0)y@c ztXk-XeC<2L{1-*xt>b@4hkh{u`9-DE7koqY&i4N)HQc=s1!N4%*tbKFP}yQFF^E;u*59rT zbDsOYuFw1ZfwmbAd|5qBQhm7shXs`V;KTU|R4s%Dws0Mvjdo<`iyC60_<(&assRTa zC!yiZDmLMJ8rpaLq|t6;V3ndeM3_s$;pJMi$bKEnP7T6Snv==y%3$2@wT+zPci}wE zvy8cME3H`Gg3BLEp~*1iEdQ6YJ!& z!PR4g-aLDT?7Le_{ed3K;4;?@~(2crAHIrv6LP@o2xzWD;jvuM)w_4bhE7z4KF_rjhqO}g?`5iK!9IB_T(j^5sb zWh1S)G42W~4Y!da#)UX4|5#wWCJVz07Q*($00+J+fL?7mY5MsU246NX_lkpX^1pNV z*E5r-igz+wHcr6VE59&$4=!S`po|#Q9mb99F)mMYpQ(HjMaOkULi@i`qIh>N5#;B= zd)@>%kf8!DRf=5qSq*bAzngJ8D}!q@EpS}31!HI>j*s?C7IwWqi|gI4(&2=DYCr1( zd3i+}Aaw;QuC1WY4oTDZ^fvkG=RqFGKcR`CUR=KKxZs`WH^EKj6Ui;ONsCS#1(W#_ zczXXTL7GzPnhV*7e$XEgYcNVF5f_Fx&=h|;{0}5y zYN$KWB4+&U(ym)t- z(dbj-x77TkGaE#Nb57013x8uFc$E-LxLsp|SB)Sg_8KLRGN4pd4yd)fc4^@z?Nq<^}f0i#H^-&6m7;5y`X&=hKY2rjS0J zC$LhB<{dqXKo^e3@!0|NGP#d;mWROLTY$KCli1Uj2hj7)acG!O&h87^#4LHYmN$vd zpuyL6fo!fCA_t)!n{k@xE4tv4?%5dPSpX{&bV$N}Zw#}Vj;pjcK^c3U9q~w@XA>6? z(+eG}sLoaJxO$0Doy#p|Voo-n)b~##14brX?o$=hA9fLY zei|`uEQO328u;5H6n9ydFaZh5MC6YqCbY?eOVmj?@6bYfD@Gba~?Q|cJ4&xvgJT4i`}!yI0GPKSe@VZ^lH49(8kfvrQ=81X4X zV zy)yh8c@a#q#d%s1Jrg#rQ|AlTOF^PA2l7uzK`NZDmykZ+7o-o zZ52sUFIkIKtwmsCS4UzAvn0r7uMVlC0i~Nc$xGYndpx=FOP5JoPDdlO{R1}FOXLE_p*HKcwB#+*C-c0KPG~vbda)dLn?2-jf zQSn+f`=H<|WQl)eT4w3f_a~%rW%pGuHYlQV6}q|4`60cREk!o|N`jc!(AF7?a-|wLn8|g&yFRB5I#smEX*}MrI0~_w%pqjY67sJ%iI(p7oS-i;5Y zH(Ez&TeBIFTR0Pgbw%MxnF}UQctbrd<_o+v-jL;-bICmDEeTG}5^Ty(Cd0vs5O~=f zPp@1`ewr_34mTPyDo(qhOhN;G*qz5a(gLd%`97_MPJLvV7~G@ z`t@Hsk?6ldv-Ye&$ALhYH^mhz$}_MwW;QBH`or6?EF&^~7QVe2#5sM`(YLpZmh5~> z3e~vJgYlsqtBi5Z+#xC!mqp|gx6mU6%?$5V4#vg>(~I+?u4s*yyzl6PUSWG7MB?FtL`b(79+Z}vhO_Zh`bqDp@*lK&E><4)V> zyjd2Kn7lHFO^LF^weuBm*dG`seH8?G_eA**u1KNVrQ_`KDho6k{lt3`*bk@FMd+?K&1{BW zK2^Cf1NO{W0C}zv7`8PFFQ$E<%HB^Jhh8kBs@|q}OJx!+&z*o{-7@Lt+cn^`ei;<` zW|MjsNY2S6jzH%knBXxKM?pPG|$mx!;)54iWrxh|8w^ z%Ob(YZ(x*GBlfE&!jlcr5PCupTsL2Y17qZb!cfcE~ zY{=oimT+UcGBr4V4}88x;;AoRz*gZUGdk@6c|Dj3ZyW@)WV#<-ou&bW6O!b~Xpec?rN zXzW>%p4C9DEfUE+JvVsdw;LvY3Brg0KAZeF1p_1(vl_i|kh0r^-FWyg*u~w#_a8K< z%FEk$#rr1x^7sX$waQTYD+y$ds{uJ+@Q!xxxJ`@wQkaYnab%rEEw6IdH};OfLO8g0 zC1GYN;P=MAWR{jCK05wUP&QqelISY>-ccSN?^nTep$)266w$;iCUT`fEvf*&rmp~t(hR7`k>v9G`9x{39=^(~gZYD3z^bkqPAUjU>1QF@7^Y$K z-n+#9-~x=${m0A}^@a_zoG3{=21=aYOy*NB;mVNlZ~r0u^Wi>e*XX30$|-ckCl|Ko z?>7AAaf=xJ;1jns@l>qr5$#mc!G{?~LHkqKfNz!Y4rg1wUs;F3Z$+5KC<{crulXJ*CZSj%5h8(xT7 z3*}LIbv-E0kb=$@C)|Fyid3WusoQyfGDl|-?w^nhr;ZlGsrYH;cEd-}POcbZ)||t; z8fP&HeqM^w0!tVd|7J;{4|b&Xu@Dk3IU2 ze7SXZ=k^i7&=w2qeQOFTiJkEMYAL(x#ZSV_iUFVL14Mlw zgeI$U`;u3q)Wm*_@U%?~Ss^L{SLrX>r#^tW>GSEaSvkzH&F)yru?&7_i&MR&p^dkP zS_<>YP4#4)+oZuXXoi!SzpU_6`Y@dwwGf$YqGa8o5RBC!PS4MuB2jJ;HfwVgMD;lJ4f)#R=f}s(AF2@s(wa+Pi7HWuZyHru#d>rU2PJx8X zVVrzGk5-L|fi#T{vOp`9IJ-y+gCjn(I>~a7d$*hJAIXI;#s|rqV_(>Y^`dz5)HBv& zdlHE^3dTU*X=vP)z*f!v%ubuCLjpA}KzPhXkYBwn2zRMF(?))Zl(zy_lCU`SO za)35F5>zEPV)}$)8WsJB&U)>FZr)nFw@*8n(+%R7SUZ-lKedUM;9vmSN{+aqMh!mh zawH{Rv`}s3ItY=PO{%vPW)7Ib`~AO8&zF>McAv&j@ftaPxTLO>JE zEMW5BWGpjt$0$2Rwjo9iO%|MH`H{MK%3&$|(EmWhd@9Ms_}MVCI1r9ht%rg5&Co1) zg85uNhHj{7rVgi8p=j`1dP46AB##&8oBfsNulXQF4WqNTyo!f2oe+uy zTQO|qbCBVff9qAN(AC2M?5{*|-x*seJ4Q`Nv+ZbCMK&3%I!}C`m+`EVuh2Wr(!ym8 zZOmTbJ7%|ZB%`V8Lgx-epl<#K+`4ZI9m6b!G2Bd`sYV&%J&VY>2s4y_Y(~%I%Rp#Z6jR)Z@BEjRzHNUfYqgV`Cnu0B?Goa$=@VVV?j~Pz!l<*< za+oHO$~z-ni&VarPTu;0jG8uL{aG>SxS>J*s#X#=aXYwvxrj{Nnnb4zr@(&>XRvYi zQ3%bH;=fvE4;x+v;Zw1B^yWc#tUu+>xSvsn;yI^D!0ZwdT3rk8M^>|%zrDeYn>GJh zV8;8fayz+jm_kG#q|*Ey&O-TZP14uc@n}l=q3y5#rgC1h7z|_ zXOO+P9#;N-Nsw6wOPeYnOH>;U>g17~t~bc+)8(YHmLXE?GgNz$1y(ulP*G|I%H4d( zJ+Ci`5yzE2SazRka*VV>*)Fo(x(hW==V51)H(gk<8b0meoM7Al_Khib7InWwRVyXX zZ&o8wNxsI^_bFrh_p9`5|8xw$qXyjx=TOv83lA+ype}dXiAGBw?)qj9I->^QvscKx zJm8I`98+Wd2 z=?tYSN^{WTh7?TFP0{V7L5^O;?urPx z(dI|)ebl1SBaYx#Fp2+6#u>XVPsPr8@2M4Yi-f0Nge&Yg-lTPZ=(_JiOt-Z!P2Ba6 z&Y4%;=o;5SW98#Xo}U3eJr;x)bl1X{h63upX&xxgsv}-)W5|?qgLJyDA9MYb3O?2Q zK<5mOSlW9FNc<9Dbd47=@2G7>}O}%%HzK42{^9k89VdQb#ixnEQW8+ zXGSE9$Vi-{@LzlYhURrzt~Kr_cXa!pc#Ro8kGe1LEx3h&O^fkmS`u35oCG_6eM~-~ z%x~=cL)70}3QNAp(e?MvgVF6zf{E3su?N9%6hqN$&+(59?EsK}k`M`gmGMzNTt$ZOGsnF$y$!5w;j zpTaRcw}@GzKFV2$@(pcsnR5Pi-11F{o-#4v+ZWD)s?z&d?ja4+PH4jK%5yX>QG!Zu zje->}%3#@&4-V?%QEm2Z92=8|Q9pxFSZNuZh*9T+%M;k8b<9-HWIswhZ>sdR`Mu*(?QHQ>1ay2}NRfVm=<36Gr`&pZ~*Q{(jOHorB4d<+Qm%6&Ba+AQh8mfzH0A z^g(_B=YEbMzc0kXs(jOyngi-7Z^v<*zmEqG@ur)PCG_Y zn<~M&vWJYyYU7(39^kBej{IsniK+9y&>tfSFk{nN_~{jZ-2u7yrr|D|`7xJzzCQ<+ z-}4A>vR#mcS!fQZVHja$Nr@DtNLP9vAkL zvSW8i0G_9*$4@d{neOyp=1U@D>WR~@_Rs@TtxTPj0Y18Mmz?yG0pr4LRK{}^IrFfW zw6BjO);(v*Z|@vx>^lk59yZYVijPU>q^BgOg@U|gI?c(8z_Z^~1klNfS8<&G5*(4cM(gKtIeTk9JkbaL%x4%>3!;C}NT= z=vkaW#pSmVW7kzwIMEM28)n0+!=^CQ&+$Vdaols}3vr@m#4mY>_Gh(Fquev}N-IkZ zvcHlbH%qd?#sXQJtHdv$ggz_`$KrJo@aoecI{3bY7gwhTMmx^Z9uuVPHj~iz-z-S8 zI|;m=7|gWZPc4hBpl<0w7+TjrPrl^ye!M?JuW7`A*26$HIW7+#iCsn=^Aa*Lr2#f8 zRuL1ITsrBW2<+5W=0_|A_+GFEQ{Fv8i3(Lr)k%fX^RD!v)K6ZVtO5+}>cE{h%W(I? z)2w6GPsVBDUUEDh$j8Nt@S|BW`6o><{Hh%Ip7{t?T>fJ9u2ytCxE=J&Bj}FG67IPR z!dj6k&{H;n`u%m(gUi2$pd}rDQk)Jj%BX>Im>a`PPne8mI&wGgp&srfrDlw z9F_|uE~7z2@kTVZor@AYe|CWioGjUm9#=8b?sUsz0=0mO8Fwd*&JDs9ojoMW* zXq3B#E+5RrALq}rvOBn}=)pj8u(+5wJpGO@mb{{G&bXt_Zf+N0t%LkGu5c%D9{Rb= z!R~b`{L6(^L5Kna1U2zw@?` zSAsZACvf<55zlg79ub>7dTi=s;G2A-;jWv>knUm{l9!9q7qj4}7eq!bWZ{TaFPVG! z7Y-jwWcFCp6V0f9kYvsyi3#^`keXw_Q_idJ;0B(u3!uj*7nVH|(0SuD>E&nj_~~i} zp}z}YC`|{&P5*K8>{D15X#h5V;y_ONHe7o?iaiEbusCHWIvJV6rs7b@^1e)RxAxI< zhu@>(p$Oi=&uRa6!$Z$hWqPSggm0QW35yFqGmFeV(j?z{>YruIY%Z7zx5dsfChb+s zb$^Z->8(SZ?VE^K*J>!Al*U`yy^SnC^nmd;@*);T!|CYdM>JdTnozea$gEinP3mi4 za^Xi>{BZ^Y>aU1=~84>gQ3X-8dY_nsO2uVa+pn|uSVb6x-= zh4r||qZhpO?x99zIJj<&r*qAn>B1B>q2cU89CO=@3@D6+a~_ETS^d?hIXhn1C(D47 zX*X3cA0dg%F2=*;6K+-ri0TPz`tp=E28)^riw^C_?qU?dW{F`B$X|rM;>50n1Yui_FTyZ{h?i$PbHi(e> z!7u2Qq9;_&uMKzi>a&@JX_(|E4~wpg84zXZ1IP`@f(oHZ8OxH;(C3o|&z z#up?+xVc)$dAz)QEB$uN2O{Ncu&UFRil2Q=UOim}c7|Kvm4N^cX9dxthFRIp46lMCB?myiOOu*h zZKC@hyaw-))g)u$1gwsk1P#Rw=oq(z>eVy+4gGPX_S7J53+^Si&8^{!+9hJC5l%~r z)(FYvOyYgB9nG>t`4!ugA-Hi53Rjnr#Tn+pAADm-ZtT^U&758s3~R2dU6bQo#MJfViOQ)0vnhT}4l6{H4!==AgV; zHTiYD2^JS1y=A&gxMR+F;$i!i_5^H)oee`M`6q~J8s~`X1~kD&ClXS0&XEn#vN-B- zoc!_$L7i#)z(Rf(75c@~q?yB1VXB-^es?DM(Ah|O%crm&3VaZ_-Q$^`YXOz81f0fA z^BzZD#&^mkxb@Hv@?k+DY`VLc$h>;N@(!nxoxT(KVv+guqG~)8%Uyyuiw0TWU`gV^ zmnC9c#>xL)4%UgT09*U%5ZpapSi;0ZOiUx4bF+e-wv~as(!m6$9VUtutBBX9A9RVh z8#Q`<9v07cVLV=!u#u`wbbR3{CU2ZC(|j|O6wdYMdP=hC{p>xcVw(cI?s$$hi2>ea zbLfcQ02e2!qg+80T1Ic7`vSb+s!KT$U*-spv+l5IWd=0MGY-G4HsSpV7qC}PsM4IN zpJ1N_L!T(C3apEEvUSI%gTxXZ95FEjZ-*B+ZR9CAFC$6TRU>VTP=cb*oQs4}5(raG z=?xz*n651jpR~Ems*^1k_)NiUKWAckdMagxeX!|53mC`bknWY-@4+ksmldwKSx*69 z92Y}QZV4${H?!)KS(LF~ghdhQFk5FVzuq|=67$rk*DnQf+FKR#>O%3&o2w*JesaXe9#LT|_g6`v_H7OV53K3K@4~v8$;W#*JyF z%EMRSztxWz`R;K(bS$I@VR^d`I_HXGwM&c}p7F}ykMI=g&l5S`B`!x@oH z=p#8B>cs3(`BWrhyM7VwzVn-QC^le^nwT}>4DFac(N(50DTV^!r2L*Vf@!9l=QQu zHP7ww>rGp(@1hPw9R^^N(Mf7Evjsbs7Li%37DkU#n2}e_PIxdI zBe;F+v5ldmw1c}-?Y>5ySZ^Vhq*h_X5SJMr<$7bZ+}S+&VvOIVhw@@quwuQK(DhV= z;8bQK6mvZTzb=jymQV7;(xuZuExC9Htwe;bOqIua&81KYoN5QRPlEEQDH_qPd@E>EE9CvSmB z%|jBt?>$pGb&H_O)fz2kd?l4*++l*gI_GH3fQV&NXm0lhs+-Rz+f{j-FIR&({*QZ( zU-Ow~`B_-0Aj?dsUkVqp^B}9YkmM#`WxvJekb6G63A_uTj|_ZJbHxP=-yTom7jQZD zFSE(>3!1!hV}j}XM@{7Skwd82cb^qmnMo8YdssE@{qXU=fIaix29gebph7M?{m%Rx z%6)l9)QvZ@!-t;}r}!cGeRwArO)jT%xc6SG;w9$WUk?m8D~}u2$`SH-3!YS%k4I+} zFe1F=xRrCp-gQg_##IM8-an;&tP;+PeL+6%@E}2VZJ^Svf)`}-onl@Q$+=EI>aQ(U zEluayPiTZSF^M$k*AL8z`M$w^kmm6V)Gx@N5GQ> zc|%i_aQa1_{j-OMRgW3#SROH(7>$n)STfUR)l%>3B6On2kQ+9v!4)I&O>R5=sFguY zhgagZa4~2YuR(u0*Hh2x-4N!J!ubj=(lynGu_3>U9(tBY&irbHm{sPmL6y%W)XBq& z9ckbdA%o-6cX0QPP+GSz0qwj!@noKm)*46AO>rLdjprd4|A=G1cV1!oBP?)>dKnGe zo<_v`LP@bluH|3L4*H-~ohQ8Og;!@N;NrQ#Xx3XnLcYtwp8+8G4pZs-q9OX$VHp(c zyF)r%gJ@thr8%B!*bnB4u>VC9$=;w&g3q~9L!%>Tx+8q+B{6H>Th#bGwCGtOdt*h6aH`+%MM?i%$tx}9uY+s6m6pJ-u-{}_Lp4?A`h852v+-*R*SB$IF7$^V!#2B@ zRMSojeSL4>%tN-6PVWYpqbbZp-ZNZuZZ7m@gn`S~c61Ka6OK`~2AN;cxN(a&_H5B& z-VbQtPqhl_k@AFe|LcTz{{_O*;R_IcT>>op-_n)yRA^1jPY9kKLr46%%#FJPt=aEP zwrwuudTI>V-~(LVTkJ8D#xR$rw|O}-$JR;ecJR*4L?al6T{3yV5jhdG=2R| z4(fAv==L&<`BX`5TRJfLdld8x-p55@OR+ynmp7?hh?~|00PS|g4f+4jL(t555Bz9l zM<_kpdz;=nHY&#i%* z<7UGnI~SbeHHIG~VN8Ndy~&##&Ntl85Y75+BuKT6p3zPxC6oH;!}utoCTziazeNzX z1TnAN4GmuR)8$t>Y2Cm%T(N(ya9O84UbM}Ge(QcH|4_&rSEJ7)~=a=N2>~9Z>9$HmuGVMGCja= zdQeiMPVA#ML)Dy8G9yd?mL*)~Z~h1|k_*J+*VTlJ*G_=v`F=#I_X3%L-_Z67xz}dTE9&{_&U$@^1bZ$6Y!!t+!Gg@9WfIc`pjz%p_xLI9}E*9ut!? zm^S+dV0$}&3@*8V%WGJCP~Sne6qYjwJ4firf+<+}T}N1TvYwop`U+1IJ@{{B4+-JU z^fqhMg;(`=!G&|R_~rNpSYqG7%*jgSIK45KH+j}PCvWp@-9g%czOjFP8#C8S&6tPU^c9~ zxdsm98iDM3Q|QvO#513bspftW=;nLSvCm?0=B!Jgup*A!O=zTRYb?=po*dsz)E@$t zB3WoY3nk~T6}W`P!kzx3*kq{-f>RGbL#h!LdT=wJrSE9lraAa!)E682CK9{w1vEs- zneI96f++(#kf(l^#Ax4uz^e}lPiYLlymtZAO});Z;ZNkhpOTB0O`lOtpG{ldd1K#R zL;9%x3|8&dh2`4=QM%Wk-XQMyz-%e3&~c!Lbq5)`9J@RAJH358 zmVGuHCwNwx3$n(YG*mMIzI<$@TSK$qsZ1m0uW#ekHFiUFeH`y@+7opcw)h)!_icMUcTH!eeP2s$ct=yA#c0Uz*fH=wD@g*;|Tp zFDv25=J%8xPR1uYN64FVUhrq^OIjW00AfdHVQGjRj?rl%UMr07Re%fKYhy!3cG@Ff z{tk7zw4St;%0O?{9}-Zh1V6NTsKK_^WX;tf81=bM9%S2t$pj(Mc*>m{oGVd2>^zMs zYo(k^KmGR zRl&S|6>#^>g0{q^=q>RQH*(&V4|AlL0pliiTYnLjC3C$Z%dW$pzlT7DTEnbmw(vg5 z3I+m0Kuh=^S}5Elk7t)+&)+Wg$dE26ae2oImY6|Zxg|SMm8HvHzk-Tox$y7%aa?fE z0&GMKFsh65aY%W=l&66-ymT71%6*0Rvg0^rg)<@f*!@Cm0%3hRhS~=+e_9*cuu|=Lcwz zS?Bp=XNw-_T5xyQBTB~hC>p^|_Y<`W#am=WnguUYJxcSm4 z{2aL!3ZHU*-@!yWPsBpFd3qSAWnN)?BSPWKms|*N=Q=;j+(6;vLt==t>FA8B9-H_7dwN@hywW9&BOrpd~|bW>Fx*I9P7+sV*RX`EU0M3 zUM^RAcef=NDyGouu732aPnSUFHpiO%=pcbldeDKJ(QU0m>dxJJzx}hIKS!?9rTVgP z;OtKLDHVrrcf2Kg4D0EN?*}ompbm821d8L3{@5;G#I9puvv|Lr;G3YEmIq#P?A;z~l3HFsUtixzR%D3M?|~k4v~MpN z6dOZli;PkouQ8zepo*%CnxcZuKhm7sPX62LiAI0lV^sPyu!+7$|I1FoE(3dT5hj9l z?_VZyvkkUBkf1{aVr;ShX}Z_z7=D-F5wcnoyx*#V?arMvu{(~0KFp+JILG?Wa5etw zKm$}B>kPv?j-b_#KH9g2P_b=J#9@m-pi>r#wsU5}a67lRFMGvXWYJDCHossbE^fm8 zfelQzv(u#@zJ{$>;R-6Jrq8z;XSkLGVU7tNehy17vU zu6TrTb2l%@bhpRybK+1~sSBSt7EEyz*|f{qnBSbnbrpXnlgl{n_4r2ov`!ap1?Ga) zvmW|yZ3L|J7-F-gMUa5G+|FL9HioXz7YveuX5al$%zbiLY0*=hH=e&g*hzpIMewD+g_-=cVrcmu4D z$`fj-w1=jOP}t<&O6#tQ({TF~@`~#VDDsHpy$JaX+QKKK*G~-wYE7tB^j)Uk%#^OU z;|$G?&)DblIPaeR6pXRXBTd~h_%h`wFQGq+4*v8(<~f&{w1~wwlV_lmwgP|C__-+k zI0kNylw)4sFp*GtPVVkqNTy_5MAv5zIXCZII5>X_m@eVY%Wlh%(ws_ zZg-P+Usyt@AyuB6gj2sff)IQ{MITjRd2j-B9I3>?B{8@x(;lMlx!^2Yf)`fX;&^?3 zIvm^z%9oU2V()I`zbd4EK37w(?nu0q#izXsLRputvo!PaPP%UM4dz?*2(xL2Iny5d zfLF+|Fp+TwAvI(VK3lgB4Ti-aBW6DsP3wV+a(ptq;}7l9T@0B@L9j7ElHYjW4D1%A z!@6JT&>s7YVV0N>la5wqp&*H5#+6gAH81FtuVdi%Hi`v%*bafN1!1;bQ{iP$XcCF%89>_`51Ds81oXUSH< z>3D8FCnf`XcN?R`D<8b{Hv&F?iifBkS3yM*PV!dYU3G-c*E~Aq9pjmc*uPbK`XzefaJOLaI1jpKi=~hDmRAGql*r~A9jTO zrJn;=|GuNc_H7*3=}C@lzYY%LvPtdZnXq6`RA||M0wrr|c)`Z2NOFNO1aRl0AW9!ve>ec-W$x0MYqkLM1yhP|f)T!Zt4=;}eS)x~$k? z%4HOyODFFFRI~l9s$7HVB zFEV#LhX((YgA-!jusSRkw@PiGLs{ebX<;$Mexf%vj)oTs>qSg{S2S&7>|wV7irz+mfFc;jm>S6WfC4ueyF}TyQ5gihe z$cCAQq;oKj1Qn&yy2NnYSnLlUH>R_xKYs`Y)+^%6Nt)O@;}4yfbe%A3p9`c6tl@zTt0VtHP#^hS;)jP$bKQa(m)HmH&p9?n z8h@iD>Lx6Q{af7dwQDk6Wi$cZ9rjbzVP#nSunl|aWATRlB2a!j14VYQG|O-d)Wq2n zr!Cnu=ivif1A)$PvxOBDj8yfK>CYz)z=jjLKh2dOW?7zO`5i zO?zE&)a?~%N$%ynTJV6*hx-`2)fw_twP-@;dCa<32$S8_c)>HWO`zHJdALT zv1Z1E{Q1P~NuE@|hOSZiJz7E77%GH0f_m_&;0up@=_5X^HehMW2kmW+WVrJ&Gt~Ty z*(KNvv)XsSg3Ci}@P0(IpK6fSd4}Dprh?jbA4t@`g`lDpO((>4!a>7qMDJRh_r#6% zy%Qt0x2NJ?CndPL+JLP5*~j{^#(bvo8kxe+#(;FLp6gN^DyN3R*s|NOL@x?vZSuu` zQVXHsw;J(yQH|4-rLkpFEE*n&{$U- z8zE+Y<49(`FU+DZdC{dtOE9VDf@ zP_V@P7`vum9=!PwK^=WBvm-}r8Rd`TFmkgpc-r$x!nzCeTKE^5eegC7zu7{IE7R%w zC9-HIWd<5=j*~9QJLDzLiyTurNe9J*aB$swGG5@0X6r(5!`DOz)(+>~4zj z4y@k(_3(GcOgMk|0O>zi496;yKvC5kZp;Y7EV1+Sp;!seWxxi-Bqrd0Clr_u91Fwa ztzzxu=ObFn3w!O2sh-IkQa8E_*XXY$i(i~3cb$chcv>1vcMOwvN?VA?7tWRPA&3YU z^-!VyEoL@bM%PF*(Y9rGFvE5kni+p3>1+LoVyPOOdn?WLVi{q%V<}-u_j0U9GI0{& zIwF^a;Fjkr>6YJ*{zuW7|JC$%VYop_0~tz^Old%*BDJ4&giu1LWTprq3KbzK%~2{% z(x_3XDAn0(ok)mCzLF_2m8lF-lIh*=AD|z6&ffcZ*1GTO0{ONXFnnVOui>6UZ9cl7 zqSb=KAddEDZ3eB{FG9!14c4mlk@bs-biROtQ4jhHU7j>(3N*(nzmeIke}FX!-S|!L z*TnU|$L`*0LX9o`M1>Xkyt`}Fn04Fa@LFt}2u64u+@XmI|wU!gu)C=C&9@K#wX+F%aQ>Dnm5$r$ZCVWwMpZRp_ z(I@+IP2zzGw3|B7Nh575V*qM?(fiD${ul>R>LNS@G$3W`pEapPt1XLvsJ9kF7ipBI8|SqL9!a~}^@*szU; z>TumxQPLBf%NiCvCBtVSyu*W72)-~G_fA+MurkasM{GpJ0|$vLt{)_oSZ|8ZR)-Zg zwo;YUGSFSEhmle`C=vq>9H0x6@5hn*p?sF-`GXx^naomlUl#8luT7@G2C(%{DLjmv zPTP(@L946IY>H+9Q}3{VUoskW&rzRlilu1!kBj0`okS@9w~VE3Sq|OLG-1o|nS%56 zI8_K86UDn6q!{dCzW?@7OGO8_GfNw+9&?}-YY$(-lOT5Pcz)beKN#Fzhuf#!VJd$Y z!YAkR?A-mQ+$x1Q3c4Iju>-DAzOz2NBFwTS!i+KfslbY^`^l`1x8j}wGH~v6HW%(R z2(Dyj!-J7xoUEWj*Ow~8xT~$O(ZwFN9*u;vjX7xD_QaxZ%zF5^b^|@yW)3y=miW~w zjID^0ffKP0&~yGBNa!pE=f)?TM&&fxV}BG%zSju33NP0CDGY*2WNF|tU2~KEpIJ62 z!ist6Y)H~?I#?WnzxN2dUzB6EasCj}I~70ctf00F!aJ^8*rp8~1YI4CBzNHeERp^t zIMMIYoM%d`OEVEO{$FHy+PU_1C#`2?*-GS{=ak@CiKAAqL1Vqq)jnW6X@Y@V>nZA9=9qlhI&~o)HjP~W?O!98_RC< zvW|!Wzog*swZC}qfFC+cd55#Uou;r%Vb3iWPUjyEkYpr>J?eUpy#mH;X0P}&%%I*z5EwfKQz5D8~k5oK=lS0a{BX&r+X7% zrA84ZuKd7cM~I+y^mx==dl?`7?Zn@%Z}{x@=6FJ*7w^4jz%Khk=r`*s4mf8_(V|Qy zzAMY?oAG@4pAcS+j-kIu_%_b>W(O`uP`J-;&U^7woO-^5WnbIM9SUs1FY5QW`F_r@ zfF5DsW<$7j!VY(I9^@^u<4|^x5tZK+T0s4uV4q$q{$7v)n-wy}bEntxcl)1ZFBJo^ zzvdr|@4ZIikE;B!y@kl%oJIk@FPY`-LD-|70J+(_X>ICjygu{tDWu$V{o$atn#)*1g*!fdoxJ~~muTFjx|B%rP zJ6&)OSxa>9HPh3wqncYE(R^o`IN32=aI#E>7ct3rqjgioXG1%X$s$%J(!$q?H}Q__ zLXxdrBxE*+L(t3R!j8-n4BK5Pw`UjHw5veg+WV|oRgH@qH(Knr$(@A+-efFmG8IjA zq6>!>vRjj0@zupPxNBw&x9ZLxHvh?Vh)_L2m47to_vs9_(KehYZ9Ih=`$KbBE&nXz z8@WH1qaz-dF?0VzrcgcuWB>eMNs`;-Uzvq*IVHHNJ(QjCX+ZO8OL*N~3S&pSMZGUe zz;VeP{=e#tRH80;=t>(faqoNlSER%qPQ8w=!pf*+@<<95xWu=Hr;xmmYZ+C$gO)2O z!NRW_1h(dJylna$BR1T`oW(Kp=Ci=U>3OKh>PFkLBGP&h16`m0v58}9*ceAAJQj48LKWwO zTGw4XFU%ZN7g!Jp=bt^(y+AVZ5?EUAp(PFj=(ev8Io-ZMrZGbAVstEs8xpAWYZ{j9 zvVdAec}dnQ6N=QX$C$}Itay4OS}&OZHQ!W3xYZj5ZM(qN&)0`X8xB%kLmsK+y3%f` zcFIUok~qc&2uzZl?AG=}%q*sypB58CNm~q|Lbm`$&N@kfASEiZ4Zx81 zu-w5GCXUKr1?syf`J5YymPTT5h|t9?^hVWHAKAOUt>|Q9N@gLKNLKJSu!hyFZ02#= zTVqahzt4rD_W|_NI0P?OIk51>iF7hw6ArA}3L~1s`P4xG|I#m$qyH+X8IpzU^$K|W zQRqL6c#MO!r!&*61+ZZ8QrhMkjFcQqs_PBGJxT@Q3Rc0l@hebob`?t-S%SvWJDBg` zL@Y4M2K5uGv7d7mEs9FO>QAoNws{dX%}(HbD?`9{`zaKajez8&W-RYp3d82b5Pxo< z;0SmD@@~V)lI-zi*?5RB3!&lVp^(zGo?9m5MV|(J1xw=+7F(4Jlk6YvT;971dc0jJ zY2hN;v{!?D+AT+?o9bv4uH&p8JYfpkswq^@lb@CIlaH?bOGD8QH?}P%?KUC1Huo&M zKJ5jcyYLmPtJe_jy^G=F#AEEm!VMrbHj0{_q|ylCY;~o{7934oNN?GA7?I^i7rB1a z)c%fL>X*d1Nq@t?4gM5lIGzrEeuBk%p2FGwIC=aVL_6|7a5Ixsar>7j($u`d#UI_x zuITJyQhiIYUFZ$^HBJSyP)mWucb@FWxPz5{9kb~yg2j4o5GC@NVQrESZ=w&5dLUHSpX#)d#_X|#}& zI>est+`#hAE*2PV0ibbATBOso5pFdEzzaDql3uSQ`SM$XyJ9cR%2bcSx=i7@ko&|# zjTX5V#-p#i9yI&;vs)8}(i2M|iyf&8`+g*m%aUU-qvsgy5V$cVtvC2}21cai-p)^d zBL&KPs=3h%dRgDU9OzE@$!$Iy!uoMVR5d1;*8lXw@eg%)xv(5GRhI$x`Ut@t?8-Gc zDUk-J+`~*PBg`qIbZ;V>2nvqm4zMk3%jHalSD7 z@i3PWCCs{sgC8{Gw0@Or$-Y}uy26P1IgA8jpCI1p)@amLZDh9#{#e{q6=sL7-pr_K zGmJHk#siKw*=1W-sG4vMoxjG>?kq)--0v`cyu$|^G2V^cvl&O5Q$*CRlOndbA4%Un z?gep2kJ#vE5oH(apm_Xy(7Y`N9~bC>T=-|P$#_j1`zDm?f}_}u;x-JtzMT!3>qK7* zJ7J{uShn|2E^Azviaysz(20MWz`^QA%K51Q=Ta#IMdu>-G& zEzm0TP&_X>Ld5LhY*$N!#Vxb`Y{I+aG_mb9D`Cp8?z0YRrLPC-bz&tCT+#Xs(9yj; z_&&;pre;6nuiX_GF1L%g!-q6U5|RO-!rvPpa7GT_Urd)wPvVk>dhT(l6Ta8$U>81* zq!wRyT2?WIKdM^+B3Wao>?gs%f3mDo+aF&`O@v#n^Vsr$d8lh|0;N07v&qSGNjol+ z8+BqHeeukr^ZTvn^G^#X4LQS1x#u|AxB|A!Fod_m+L_bhb-YV?5xcx?FCH;jMIxnf z?2c3;$bOk?(bv!d-WyWky?Z{6X|biut)Gb3jbjEbU%3yVC*XjbHajwXDXm3%X-~&Go zJIfX5MN|zsy_!Tm!;J*iT^|2bX8|439U$pT2_Y?P1^9B)d2`F(C}%6Qg+Df>AI{-h_VkFBBU&NsF$1i^4$} z9qi4iF6Q*zgmf>quy0ovkk;yPbmT=SsC5M5A<-V}D_%&i+^({c*=Lz&&p4W)ZpO_F z9mRIOJqL2vr$CEZ5GNKdBF(d9Y>1w;L``yuol6@9o}F_1%^9&^7MMl+wK;4>##44^ z5iyCKz}8F5hJLnh#NnGaL*Ch3_Q}HytiJQC^qVrgbZ^ILY}I?(fez-M>+FQngHZ?MDw@5j-kqVCsEsY7z=n(#G*X@gICh; z`BB#f(+1n8FgVhge*JffTptQ|#QAsmk+>Ob_6&h3SrzEy|jz6|WaCyC0CoFcq0&h_w;$}O0_K$Bf=^T*-UKiT$_Ozw%$ zi5cDdiCY+90^=W4v+X;CUEol`@3df#_)cCb?&t}Fp$qNVi)R|d-<=N6-yMfsmlPJZ z;R&8r4x~7D6^i(*4A$|nWW4SUUTm02DMx(3dE|1ak`87vuDRUyX))+qTqus~tYvMP zOG$b_F)KT%A&K2K1O~SB;f_iFxU*^o@LBNclpYyPwr%IdZ@dtrP1Cs`J;AZIuLln# zs-sWN8KM8OldI_;OmFRjVbzjz_)W?UAMSaAF{T!9_@N1dk%i3DNSZmepMl@T?o=-k zb`sl?NOyN4Rf_&mz(f&P`^Jm&r2_anmxs`3-B@NY$cOG0KZO6(@8j{tbV^#QKr4iv z%i^_@t4e3->OSXBvy!Z$Z(PzUSs4o1Hl zALzcR3Ds;0M0@WGyo9g98mTW9`o@=8*-kmK5&X|*zU;;WZ!WWc9cDDT^*TIsO=aCK z{&YqN)NdUU2re@$L33U(oRgP_&PV_FxGO?GQ8f}CeU;$nmx`coU?F;%UPFWK&ZKbP z$s(1&58{5M6JWTI&9NN$8f8j+$@h#jxwzkB_Q4k!uYa75OWt8`Kr_od-h-Xb#LTmP z0ZS=Xg|ZWaz+tQ}9eSq(U;1vt*OoxMl{7?Bc)yz&MR{Y5%Rf9I@gua&p{Qm45IS}j zf2BAV5?930v|nX-q;L=I?9!6B_zS$q&u{Qp(S3Gnkrw$|1G_B>q5dj7Yk9GmX+AGcmKg@uiXWTS0b#O|F^d>-v&(~A4S_<(qr z)!&(9x69FCX~g4GtFd+NDQNjJ2-<$kg9q+*)McVT7vdMtMVv=@I*!=3RgYdA3_*v0 zW9;AQV;HFsOlPI5@z2;adNpqV+v%i5qt9Gr6YaeP=chb~02F?aIJ;sxF+K&n}2E-^Sj_i0H3u934++WcDvN!u1pH$(ahFeEK-dSzF2E zgpR&(s{(#Z$%fXDHX0p9{Q3V*P_@;Ts+xNN6fkfmyi^+~8FOzdXK}oe9&GF{8Si%$ zSMCz-EqY)0KKTqjsaoJVSo>40Fgw1U8Ai_+TC;s7oAJU*0n~M82Yr@g(1E-NZd^z+^Q^m)|$O zVe<(7;i1)h)WckwTX+R$;|Hd_(U-Pw`~ycu3OvMvbID!*1ru$QfiFAy(5b5)9Vd+E z-V~MarAG~5grW{V^YK^qeU%Kl`Y#3UojZ7HI^wQ~3X9yaMXb@UlF82~W~mpAN%rM- zkWnng(YoC%xaT;Em0DK&)(rMoiD1boEABw_92#Et73Y2HPhW#W!&qGNj2TPys4p0@%aV9QM1t2<};12=@m~suOk{U5BY!7+9x0FWlc%0 zd5?w4x@=0|(*!T)bKzSv4n|j<0pl@`aDdQFPTM|*<{n&%bDCCAr_nQ}mNuODegW9_ z=`+cWPkXC~CGM`BNS=-cyH7IwrUpdbK&J zFg;o-+!^DptHIMZAJ~?zljtL(NWVH?GX0Js7`m>RJF#IfDR%B=w@ZHEiB4HGDb;|j z$zOTRf;dQ7D+B3cHc-*0$K)-phaQTQc4c+yM!cGLRB>w~& zGGQT}t!e?AK4Y-_Hk(o2a;hpBiYw+Gqne=`F;ln`cYdv*I_XPnZTldY6t5z>Rxp;1 z=9x%N_R5LW!>&<_Ku zF7Br{foEA|U{!B9SE(rpU*PXXMAHPETcE>snJmC))Yq-Hl``}7B-_I5Z~Tl-S= z$b2Ym=!TO!-qWKyk@UWNKVQe+q0#Xl*?6@qHm_2igupmwE$~zP%C8FE%`>>zYY4rb|Ag_x3D&UoncND#sAr62pLk zX!v1P&yPJm0o(%Oaj~R`{j1vo$9}#tS9Uo{yT%X0*|X-;EYl>k`MeYQhP`E+c0Fs) z=uaoq1($gW{{W1{FC0{=&S^E$*dLf7E>@XIuObZxZv2SgXr^&R_2p2 zo)YZ#!M#R?L+)<}r8Q@mevb!#syB%D|Dh_(sJDRbhnXxn=rz83bbwX2BduH^59#k+ zsQ>eRF#7odDmd)Mat-xxyztxgyEhf2`@6%>!+p%4FPPd57jU(^oG4{X9BZ~2L*M?+ z!^TBJB+o8QrmF+fS$1L|xtE2)DBBF0=;VispH2mN_KN${ITsGEe2UYAnQ_gsU$jYs zQU9a++0c6l;GQ?0^fvG1W;j`5zQ87#a;OB)tPXKPyiH{gz`QwPOuM!nPi@S zf&04bA5IedFNtej;M%vEd}`xiQha7YH~!c%srmVEc==+8+^Z%U81|G~SrZK1o3_xx z`37X=9Y8vzk&qYn+oF4R4u5S=1gbvSBJ4hHR@HA$w|FzC4}J&?7>D+26m-r4wBAjo z_X{ox{<#tquNle?j=#^mcJAj_H5$;rfA(PZZX%iwOs9vO9sC{^1Nv*;3U@rtBE0D% zs4YHDQzBMFgl7(pn{W{)Jg=uM@mJvQlgTjqtA^xx?BdwmKThTSLq^OGT=yM=Zc0E_Mx zqTLvGatsu{Pu)TEYK)9zj=2M^Rh`T9yoGFxttM~jF&G;MuEMPWrzz$1VbuB^$Ug2K zOeJem$^JqnHm?2ymgk<}59w?4qH?e($NmV#X%*w-C`+=veTcQ{HZY@mM$k{`DpRa_ zj(*#8NF!hIU}Tp<`HGt1XJPF=yM?XHibH5uVix;|AUP$*yVhaC6cd z;a%dzTGfKda6>y}#GHY~OGD^L)*cE@n;=oMIaRsun=e~ncm^lA-G@o^Pno< zQvGrd*dG`UQ#>b=x!OVW$yI^j2TS>4w_EJcO9i^VER&wU%V3|o$ASJ%MS*>n3z)kJ zFWod}zHKL=^yOM~iMz+<->jiKOUqCq93g@hNsGc?J;277W^BufOy+3qLG0QE=6E(2 zqmOk(aGg?41igcr})389hjqwu$StcKqDE?=1nCtfs?8jrbCwv&zpxPs*%#HU{dqA4}o8!`OdspcEQ6R*8T`V#V1!S z+(e3S`b<0%%g52gA}3y?WCC^Cu5^8S0&{*i0GzED-9l-2Gd_;bSN;#b9*V+|PmF1A z#&o=!>i{*w_1Iy^MBU?KEz*qo!+<^`sD9g@>HM;#Evf-@@V*LdOOb=`dlrDr@Idxt z$SSsal$5wAaVrhlG>|^+OMz_;X~HgZ74({Jf>Ea~5qH><qw;X&O?F_2x&yl0^c>2+4#)Rb$^LVt0du_FgJ)f&i6P&}i z9QW54vGgP~ZLno2kHz9sP3QUbL&f~8A4>G0ww$e&Pp9}t8C+y!g4i<5N+LWx3bvYwXhMA?J1i-oL*LFUISlb@d1)J0}1-zVCy- z3I+Vt@K4NHYaa2RgX!-6KCsq$jq70+TWNd)N1Kd?wE_X-ld=juS8eBCwyNN)ED>HE zC5t_4(wP3QMeNV=D%{fN0zX6Is7v)PvuEMdQ#gTJeB&toa2GS9G7~6hSqw@yJMhE4 z{#=XqKssokLcOA5>~AVUKbsW1QW4L;|2K+W+>U_UxoYI~SeZ^Ls#nvLYgotRCEsS-9gyq3M}N}$OJ z-|&Ory1jRCB)@h_9O#E+vZ030SVjMdm@sF$@GL6O(Xpx$1W3(F4&_yt9(SdaH1>{h}#}m_CUv>c2(R>X~3sQO@4& z38ZirKi)c}KUEqyk+XUZ{vI_6%>Ih;l*C7vXXJCr?Zw>hBbPYEyeRx@9fb!T_?6$sh{hcdI=M=Ybj0cu_ixn`EHeI%LtX&y@&EhmKx-=pocXZaS)Xn(_&l~1ON^QCcKMG3PA z+r%4qzeSA)MOfFULBIT-VCmqaEc~G~%t$)UFDm`av#qhHSTY;#4~wPr$~-)9FNUJ6 z$H4tDGw5QgA%C+~V6aaY(Olttwy^Rfu2`V}zPVyf`p9(FUoC*WQSoCYy@M&Ix`Owc zDrDRX^k~g8J$Um^fo=a%#2K`7fWw)17#r#j7u-Cdq~|^>ayZI9c&}ko9+zVGKvf!k z*noCu?S}=kWtqmaJ0wXu4CYJJpzBC9rmy>jR|}>yNyIi7ls%mG1V>?Ux)(iKtHJB{ zAp1Sql(rkj;``PMY=qTln4mQcl>G0Yqr(hrDxOcxy>_HENQdJdX^>~v73>?MKC@xs zCrav2XVXXj$1DpX(D$M*q>i6Krit^}D0xMCp&g0icdI~K#TYvLBZk}>`mj+kjd}+J z&iE8~LwtE@A-TKnr+slA+y4!xadd|)qYiOI(!O7HN>U!gyF`xbA1 zdpY30U_Q*pmIRqLMlZ93(O)+3)|+;SwPFOm&nr2KtSsmHx4z?DUnx`Yn0R4!e*kt` z_XlZ@BRH~hJ6q6T0K+_Auu%$&FnSmVp<4O4Dp5vM{Un|}iV(6EOXWzjkx}G$4MA&N`e>nri9#PZ-OrEYcylYAQ;AdVLv8a#h%?+cu$mr z87D1aZ&D2|8=wpZANC0>L0|T`qKWI>aSSrNeECUI%{aAIPITI31uh$BhW{?c&{ogo z?9Lno5UuFJg&LXcx8h>jJYqXr?tO-tta64Qu$s2(M52t{Qt}v^0Hfr!Ves|MFhu(S z_w?-bn|FNtEJSz|3aL)WFIN|O=sx@BX z8?FY_xK~Ls(c&4G9*{zNb7R16elzKL52p1B@&cE65p3K3jP2gtz`m|=VjiVSaQ*%% zEYrIJ^mhCOr3cA4Yl|8^lj&g23gwKSRYF(ZE~D-Z(%jd})9JyGU+n(R4rZNGi8)V> z(c^Q$T>R{n&}_Dj^`AalwBJpENlVI^_beiH?^RT=HzuQ6o4(cZ zy7x=jr&+hzt5vG7uj((`WN!-Vq#IaG{SPeX7_KcGK^=T8HI5&~3{+($sgLF03O|Pu zN1JgQnj^@{J_vrzcgO8BPf}FpE*9CG!*-ZNV)pvy-0b(a__pDzXjQNj{ZkQ`^ScAM z>_gjxzU2(kdcTuG9Bx=7ypt#U3V&Grdm8+jQ%65~y~L7>!Q|j5^hu`M!Tq4KkUMUo z;A(VcMe6@h=7XZ7;;bBm^sI-OI1k|DvYDzUw}bAwbrf}KKGT*%wkcYf`|nybZB=Xl zPjy|e=~iRQ&+9{PPb0lck*7_59bD3i+h|70(6s3Qi!xuyFO#x@m9-mqztBaH+PaTs zywW7;Nyp%AR~b}=##u-dx03N+JxX691E1vQu+z6*;eXSFyS~0F-EwJ0m17g($kY)m zUh^G`O+3o_HyomfZ%!~t6b3CYf=`~a3BxfH!&jchibVobFjUA2c~=qhcmk803duFO zlPfTI#)?)ZGVhg@xZ_(8E4`V)bUMOmvycD(8Q*9eb`G1|_p`QJY2-QQEZW*?(xmN2 zVTA89)*!eA`t4Mqjeka>NA4~@T2*jK9L!+(H*=WvQD-M>9_~7vJfW!P2u`?x`EmDiBP?9ITeh$L~@UBvyG2t zR&P)~N@Ts4`52>fel@e(DBsh*YpJeN@bD`>k8a5>!fS+H!vajU_ z;9FulIxgLhqQ+FRt2zst>+>-B!!`11pA20ur07wSEM;VAa^eRU;M#{(IPu~&wjt>v zZj!#r{6cNAtz#U=N?N@877&t#t1yNB+xuw$RfEtXE)a$VQYHo(nGocW{SR6T26-fmG}V^D}(+z!Vub%)M#@l8It-gzhelrhn0fq;xM=7(-1l-UopRM7i%~zxuA-G) z`;Gr zwFw-@NYBp$bmS)R=gl8u#U<7{b zR)iAoCQ3cO6RIyyg9yt6f|d&I;N$&pO(lyhmAj0#$tx+)A_d~sFT(HbgGDcMTxqOR zAS@j_9P58ABeqY5N$obEyS+Tqce#wlTXjXnNfW3sOiJjd`oep=WJ;+0#C?w{<@$O8 z0R5k%>f0<@u!V5-&03sm>I%wHj#QHnNj6o+OjqV17t}7W=$xNW!?Ai=U;BuAGT{{K zpJyVPHX)hxy%ov1;5Rc#KgKep&8eJQPoFF&Vb-%|%zeHGV-}xaE-w=y%~R+BY|?~H zZ_d-MJ1=?j?$zw!wjsRr0e{Hvyw1LhkMrWA{^U`=4wnDjB_8uGli{3g{J7^?oP&G> zGvt3UP0L7j?c*H6hU-kPt&Zh(_=<~*Mze2^wqm}+ZZ^|%1YJ%Z0DCKyfvqqng>@U) z$Q?o4&g7NgV3CRuOTxkR`xS0U>>Ml%YT{Fuo@Y(3#&8=~OysUwt!B=ToblY(9yWUX zb+-F}6#JE#hx;A#&~ey3KC4cFCeF{K)6sU=bj24M{>_CUf;Zu3>H{*gyTFJIhW%F~ zsJpBgzb`$+k5?N-Iev*asx_Ti8_U7yK&{Hh;-j=SZ~z4*DzS;zDBL?!`vAUZ&X+-_~?}EgucfJ`l>e!UcV}=%o>`; zJ!$iXiJ|-G#s-0NaVCxg9iGsgnTpc!@vPFo6DF3VvRz|%{$GJ3bi z4D2dxvir*~{+@$L8;v-Js8WHk+K88m^=R!b!ING47AM@x#0abri+f)1^X9p+3vLsr zwpf$;Y^J07xiTnap9KRNn`F;VSX-bwsj{{Sm84)IbXz%oK2_K7b19e z=C1hGW@Vh`a+hhuWV6LBe=HJ0RJo_6xs(^KaJQhShwibkmxZo)IT zx1<~`DmGHrieSt*^n~5+xDSpU*O~W&v;2~n5yDw{8A>ZfuyX6Y;CjB3?GpCvCdNPU zgNX;9%?+e2A;29ys0X8R=Rom+QM7YKA)NMdN9h(hKKT9~+8?}-9BPNt`wPvCAMlR9 zot_097gzJ{H+H~byGGhP&x{ttoM5#NJ}~8~$%I=H0LNtEjoY47{z(s9K4(Mk5y2zh zv=%O2c4sgD=An0#12||GfKwxnYqjpuxRz(^p7aD*IBy`DTO@$2^lMa_6v9nBXhH|< z1)|gdf}c5a;0p>quZ@Wqo}WkdYf~WjMIy~JYNyogD(unDNdCUC-(KH;D|=6E7}fWk zzhNy0`yE!ZRnFD0?7$y9e0~lkTyEq&V*_YRj|{f04~0#NvJ$n*DKz^J2@Jm$yt@28 zd!uxYi~94O%})#C64P_pwTdm&p=>4a=sWR`3vwqEPC!srKZ@FTj@`IrL|flo1Noi{ z(0{fTW;!8XJw*@p%QWEn#OIuTnk>!r*v?G1>r=zGz4S2N2Of@og>Bz-X{f9Ptdq}$ z0YNWtoBCypw!6ZX>Ca#;`jlw@~XT3H#4d0YxV|F}7ovaK~$bnTw0b zuInUQvGp^{`L>5S-nj=~{tTysbEV+I^oKBfogT$UxAM#OEn|DPYg5H52Tm@!oR6QY z%HJ9>iUM4_SdU#F&a~PJ1_xuXqjCkGJP=^lf#GzzSOk_4akTBXCio4$#7~sXqK(51 zg{;R)H0t-7H9q=|!we0W`rAx4ZeBmh!6a{f_K$S%DV;=H_;lRgI17gGBKQz|23ouX zr-Zj5{LoCKB5ei!;sgb_es?aee!LJEpF8f%ffX;FRwN?H7aD z5wSlE75`xmPd%Wc^K*!WcN?Zs8vMwcCVuN^ru`Q zyM&wW)bR~Zw7@n(P4Jvsfot$<)?ZspD`kd~^@3{X_;Z66JaZ%C@^-dZJc!cLTP=Lo zcd&8eqFI8|YYK`Q#*X-@pzMVkT!FbgSV%5$e$}xoXIv{5D0Q=BM7SgKnMIg|;)w$==~80;*P-QP zuw06!7)6qnas`uZt`t0gn_*Ub7N~8R19OLW;Y_q3WQ%ZHwh0A)(O}up`Zz(DGu1`? z#~c*bqV3%T-ZQXKtUs)UyI(Yzk6QAC*Iv5ALU(Heb>6aJ2G#QH{O!Xue6p{Q&o!gn z6Q&Be`Qy-6{8ijLPZ63Fr0MI$7`zfV9-Qs3(=yW}Si3@<-jCK0oj!e?&8a@jFlamU z>bCO*gSYdSg@4y#^@tqY?I3E#B=Vo`hXWr=)3SMO=(t1!E-ehFsZI72kk!U6Kbu0G zRWrbFdxX&G@q!{9H`FNEOX8yG64~eyxOaOp9iN^~=1N0F_X~@mwrxI|?en3(D+I4{ z=_tut^<%uZtvWpm)8sz6%Ja>8{-M>P^JEjLNJ-uHaA+vfz;A*R-SZ@v*5Af)M}zQv z>K-z-s)oL0TI`39H0kC9!{hn?*wd|^v}#QtrK=Uumn{+SsOL3a?FfO|m-#bowrWUj zo%&2)!yGVjy)rnBY=E+bda(BSFiGjIOsrR01QPxJB;6`-`(Qt7eH{RmabM`h@Nk&E zHWWT;3jF&{4J~ zyp=>QO+9 zUNGa(2e1!2kG~)MWUFJpP|^KBXcu}!--;^XhRg?uU#K9e?;AuFyW;TE@f&UD?Qe%&Y|`kqnE=-O2Rl_UCTS zSPg8X0_>Dg0^=vbx2^XB+naD24jmaw4dxLP(tcbtV#qf3bme%-{(C2J*MkX?Tk2sr zb&g2n@Zc`Gz8QiS`+Kr}kN5G%-;X96YQ`hI+N@_@EbA&?K}&a5qP@p+VXxc9-(Foy z$Lxw(uURpA?wY6D%(_n6!6ALENYTv}R#G z%EUF(EuS+m{go`2XU2jk@=3&rL5p>9cEk` z4HK6Hqm`Ex*L8LnSDfC>7julJ>OTOvjb6B0Dw2I}w#7?L$6#^pMYeIkO-x$081$bS zfll~W_A@&OBh2(5DKroH!Z{iTZ31s%qQR9 zm2kgw4(xIJ$`3L$A}7NUz*WbfkLOuRXq-eZM?}Kk`fl3(cavzG;Q0x=na^FUyGqt2 z-*NBGWNRMie-OUcxEWtDS6PFAJh3YW`kghq6=H;Go9W3 zEJq3pMvCl@Y?Z89P{s!7*n-=P*KoDBn3WedfKloj=nVMF%jlE{zx_@j=Qe<)y45rL z^P?d3?i%LjZVxd#q{z6zlRlSRfO|t{gZC39>~B;ECu9#nRe~Y3>Bx!RC9H!{QvK+2 zsu!=E5A5>jm*TY(9>Ba)8O-|RM5?!O#iJu8g54D}I4g7;&sF5mc}WO(Ms1)|#o93C z<#qPEt^sb3HIi5t37qCVVMOQS*pGB|DCyimo&jQP85Kh9^DNob{?Ys)jaX7E72J-I z1`rxF7k4}4)AYSn+_~H=ahUQ*EG%p#nbpTwm0U5nUpR)}eNIB}{=4+mW)!v!n#5O^ zZQ-K8j7QmJj(KMd#sHrjb8LkSg1R`wQYm(o;`CZa-1 z8d5#?b!Zr6q(vE#6-mXHMCkYY{()ZSb$XrWzMt#*eBSSx$N zIW_d3EI8V}j~TtCO9NGBqSPus_WWxfT3n)rWoKRSZf+@rM*Cr)YCbz0dmaOYcVf!| zjwd>=1-I?_2i=(_Ow99iHp^!Y{FJRGN7>UjzRHD}Gb4~@nZ)A#EBC0GC&%wzBtcf5 zEhQ9($jYFzmcoa8Kz{lK(ibetdc=Ezq1SKX=y3(j@76MlBgD{skYn0!p(O3=QxbH& zk7m5uOq>gfaZh6wV>hgcRabe;5pK6|Z~i{$)6fB-d9Iifv7SnItFr6jjWMw91!+;5 z4*zi)NM#jD3!4EcuHTpS?UMY))q8lt!p%u*6)g?-6cXJK@N&FnnA;H(Y zOV)W><6)I%QtN7s?-rc_UzG{4Y|R-`EaFAABNp)|*z!=pg*!J&>}bh$23E}N0E-$? zzC~gfxxV*2&S-oO=5oRUKZ!gVEa^!19an*KCDXBG!X)&)DZfverQ|vNs39N=g_-*=TxSA_~4%P#isS zj9$9<3={ASyqMC!Hd%X zSiDjWPN!#r(Vw%-t=s8Tyd?n!%vky+Y8=?n5t5y~kMYQUO|GZKqMdCOnVWPEb!v?1 zz<=R5>mJLN?JUNDOe8H@Vz`%MZuif0VOI^^VYklbp@TskNjV%zRI>80%;^dfeDNF! zbO}d~WxuO?FSXNN?MBoMPp3=r>tXSQzuf!depKAF3fAkXf>rl!OcC#->F4s`QQ|%P z00lVv&NO`H5lesS=NPgktdGR8N$4n9bU|rBiD=fcXW-Xv&3jx+r@A-f?=%Xw4xc zU_m&0RPX?gg{@=7I+BRxp4CvKGX)e6yD}NS)nR+6Ic|TZhW8)F;DZy&)YFk6bv6@8 zbdD95+uIIi{55;lX zCs+EgR0OxDwJ^39o!B#(yHI~a09yQ-j&7nz{+s-Z^sG0hfp!r9XS^+6-<5@+eQHFX zKNXg8yV2%2uKRsP0~B*&X}@nh{Ul?Ex2!g^_ahTwjuIbc>Sc3&L(bc#{D>-z&VUOi zGC8`p)kNimmu{7?prQJib_+YX-kO%(x#b~wq0boNK zn98<_o+%nJp1 zFl|19_J79V+_$wTk~&*kh2KX{(q(3= zs?+yK2?U7+xMlfoTvo9h1Ey8eX;tCqDDMWh#Q)GN{xPDex*mgNH}a}9qjBYnVCpv1 zLLGi7aCbnCL6JWZCR>%DqP7cJ8xTYHMhkHadM)%Q{tX3g-|@v;bsS!whjX6Wu&s&b z@S{m6W)utY_5X73pfP(;^jaL&-qv6WH;UpHGY!<{x;}SC6yd_}YK{}J7WAJ@;>)z$ zgW!E7Fe_smMwT37ZgH-dk+<70Rk?y(_ZQ`tD<9|bUitVf=ML>t{7S~R`_p$LVfa#~ zoVI$3(?fO6w7paZ48w!?!w34<(9$A&q8N&^j&oe^rtu`dc?B#O$ie!=7KV3j6I^x? z7l?+>;kJqf!umw~&^il@s;^Rsj9hB{ypuh0`U!ayA0hZ9ss_0$FW{dWQw6K? z)2aM|TiE@H@D1JO(={`1)01sH9E+2~z!&nYWbPUA*mfyCaXAdB-@IU(ek3TTT}Qr} z7^q#lh(#H;q|$9ZE+`J8_hpp8{l`zb%PNTq_S)0^lO*_JZi-ml+euq(4xz)M@|w0t zZE(>-%LCDJaI#B-^JdK_lb$6qM-^w#XUC5dl`aD;6%2z*ZWVQs6XSMtLD))13Gc=! z-reR5_`IfqT>kxvdfK%RP3b6lMXQ+k`tvfu*XAf&zn{)4YG6O5jhwutj_1>B z*i1(?$ns7m9gn$O%>$01lYbtSS8(rXC9fIdMkRc;=mHlSaAse8$^y41!nkJeC++`s z8yj*5=|8{U*c!okHutH+rlXCtY1|ZOs0H8}P-*f|+)q3$08H;CY}6 zGq~$Ny6E~++@!%}q)lSjMm)t^eNKsg@nIf)_o$Vu@T{Ots*315mq4rb7INWEH8=Cj z1e3HV=#iO>QdgH@ul^`4FyXoyr{+;pqbU05(JK0RRibuz_;>QgcCnW<1?_=O%9@m*>fj{za5eEv6f*Jm9V9Q=Egj zWMf4V>O5=01gT~CO^Wjyv{DUuPath0v|E~sKRlTF@ zGLkqR8@J!$3xoe09(((>7$y^Yk|Ewp`qXN%q*_uii>HN}YZU~l^#o{l1gxb*N+BUmnQ!o(D;=#YlryxYU))Y>qPcqhT$EaWlJ$2c~%J=xQ4K ztr^$Pn*hfBcgc&b8Pp;FH10Mc*gcR7;Tx)m`NG?rZ|4c#$xWbQkrINS<2zAk(SOyE zYCmc5qsf@pupHCgeqoC3f;gVlZw}P+jz%uMLSzDT1f#sWbTn0qzte6pKXu;{;B7V~ zB_B(umw7UMDjA2;*S6!v2pOjMCg;#<>f`wLSLxo(>G*WA5)5v(!$#JO$Z+RlL8U4P znO@`g&V8``RWyjH9z*Y*C-i>lER+k4Vs33cO;i)w=)yE5{-s}{VD(88J^c=$UHv;= zYB!(XFs%z~#M2qoOXf`0t3=v$J((z9Q3jJeWq2ZvVLP`RC*IxzblU4=Jg@7_jMlZn z;>87I=cZS9L`R)^1fC);?|5+kp$goonN1V2l1b;sb9B>4H=UFzM4eOD(^h41dMZbR z#wOyKfJ_MpaFGjoeHg;te*X2@D$El&|q%3&|_CPx9 zT<=3eSL^`0-#19zUwyiJLkej*TuhJEe`bQ4)WLt+esDcyNSfEFkpgZeq#u5OR-QNl z;@pf`&C-eF-bu#ocV|wa#d_y4lk^w}8C4>;iF zhyHM{ehYkRs$nXH_h6$`GJ2`SK+W^lWY$+H?t4$9g3qG-wuk2QrNaT7F)Rl!T*N{0 z=yGDd8IZTWn)S3;OG5k~QQ-)EG-^i@DVxKLDU}gp#aYnYehO>OHW0H#dN3*-R3j%< zPJ5P%;ON^S`bXwC5oY`7X(Ks!=ss64BcvOPT}1H6E+^b^U>OW0dLVzA78is%4oADK zsIglvUNO=FR|h}xDDn^F|23xhj=#uQks%XtdlkMjRb{SC9U<3cIZo=T$5dx;31q7j zz>L)_*>%bepDYbQ&4IHp657j7cYA~XTn}U6Xb-NeR{#--&s_f05zn{XV0>Px!T--o z>7Y!q)oO(NOT0)9Yz;>dDG}^mq)YrE9kZs^6Unj2mi+m%l{P=~q7&AxB1O|X=%33+>EEtA>hVJcuj=^W z%A6spZI(%njhut63d-Oa*-ZA{xrCOIY2fB24Z<5zVd9(>_&nz=b70>bsIRz50`Ez2 z847*)_wXm-#^Y3QXAU{=JDwV1oSs-NK~7>2(EEW12s-XY4?{mr9k% z5p28t9oOu#C$Fo#;rQyKlzdnMzbd$$o?0j}>$aibRUO=)c#GL=6K}bvVj;%H+2V>g zA@FY5PN%5MfGNQ(bfM{WoTxmh`q`6RWUYS)Ts5TdCm|l(KL^30IbX@ingQC_=uX{w z>Esna21-&_=8cfz1#A3J{6 zA2vfcnJ!;yvrKhPxk|;)q zalGuH7qrZCHe32Bikimn!4B75#BEd_y-b|RQ)@}Q66TA`3}?cCcPS0{7DgUhnSko( zM9}7Dfism&V{sg80dW9i<# zn$Rma!nu97L1JMS32dH@D=NIPXoCzoUcODqvT!_*unS&vS3~52^^`m;B;Wa`NSlHL zEU(qW`CDT_yjDKUD1S`&q1RX17wTpd3yZmLeC(QAvoXuQre=c-tetxwM7ci0 zHPy=`GW7!Nb^MA7(taFIip#AdPmu7P4>MkQg6?@wvM@9o-)GH0ua^_?+YK&PU)ROF zxF?E*F1=h&VGD+S=3$LbDn#jTg7b=rAnmUU`F_eUHL3+B?CvL}nHS({Mh;$Hr4J9v z8u6=*CTWgL3L@zXg0<=h6F9Hh}U96^3_O z32rN7T zblvBMzfv-J7lOQ5@;riUJ84FQnrdm>h$~vj+A<}3h0)>3MC_B1fr>p0`W((A_IxfI zS?CNG{SH&xYto!+XFZMQ=E&#v{r|aO3YTOoa8=Vk_FCjwmYAzShn6kun0Jb943^~> zAIIbu_HCPTo~PWs`&5?E=Kimh1_=(Dij%=^(Nteb%Z|GfHBDr%lh za-VO+FZY$PL0L;+fAlPDmUv0M3)*Sc_#NcXG9k{x$jy~5ys8nazYlIDUzod*HmIB6 zLWYhAVAkowC^0N5_@wNNshQ(Q$@y={4~fNfPI)*jWIXKII*<7@OIqM9BaY`5y5o(h zF|;lJEV0y`4NqmlIKGU%Am8pfdY*qtH%)D!>6&%yYll2Mb-9whReMQ6_n5#c`ZGCi zXiNA}=ja_H9dh-&6q&U6IBoPA0GG_aH28QnedT`!ohLnD4`g-V@z-?}vgPqzk0?q+ zC$XW)GubV<6(8R|1Fu~cb35j8{JP{F{tNm<#8+Ry!QnSFM(iTpyl5WD?&^V) zN8-^>D-FCiah>aytvKc1dgA#zh;}#d(6del&rK_ZCMOZB{5^}~#BYIH+n3Tkl~RJa z&Bo;L@Ii9pn>6`;?K$b*CnC>;%d`tkL$zLA+_n5A`>C6-5BwBhLmok)hj!3bd4c?& zgY)+8X%uigmWRGMm{gaJVcWRQCa2gAY&>Zz6E*azbtCQgnS!K;g$4 ze%PV8m{D$nceXZ=g20WqBO{e4)ps)W-%fz!A`MhZ4g&R?32^s&KL#6~!1mRxn0!R{tPcmOg?S-9XgK%cUO-^I#rpf+-^{bcN7vv`8AI z=D%XWXM?a{wOSMyO{pi5e`)!xH3Z{ClcaCq(Pr&cWc+KV;R9Qr5d~HVDaZ zGou}2wB^%Y3|yjst=u_Wxa2fADCt1-jOAPwTnWAJ%|i9$c;>tb50)r=WfdG{A<|O~ z)?Ce@i#8|Wq*-fWc7qw)b|iyt>s|^|xZeGy;DZ*@A0F3CoDmKOp9aCsXL~Kiw*TmmkBqWEc7HT%{6C?uUtCO39?L70&{EKroCLz`~VEt~Qn z>2d+ctQ20J{SP*|Fa2{C4n zx8f~^I7j2a{R@PMQoR8fGI((sx(bO%;3yWq)aoraY__F*i6b19}-ZU-n2?)c3 zUfjT_zz{`#Hi7zw61v%PJYiC1{Kxf81D5Z>x8kLkxvUuU zno3BA)F%iUw-RnnxJ7!*PR*1C%g56MtV=XK zm?Xr%{UwDI<&B`T%6P~LHN*ukQt+~d59F3^Cy&R*W0Qy$j%=(2iBt*9{MJ+B5TnHJ z#*aLi9~bc!=Zsw-avicZo~X`iS_`)p3PVAQKa35G~>b?n|(__nZO^^ zIb}X-9WfR(2PM!1Ut@g6-Ru32anFMzn{eK>J`%4bk8Q^z&@6T`iKtN)$i7=gVy0#Q z**t+iE=ZI<*>Mv!%bvkpTXli6rx6}L7=R)hH{rGP&7@@eLJ%YtvHunJ({0ha$nF{3 zPNMNCCdhmR&70A9opXwKaeLZpN>wySxR^u?s?Y*uU4hT?04lt!5pv(AvWq{NK;DM0 zaAN2d=h$6GmKd9$*vx!b?faUpTM|W71_87c6mZVxG&XUy6oz<}o!yV0=^q`gk|Ht7>EShPHqSHC2%YIq>9=08tQk!tD zo&jKF1gt+O2fS;c_^n(I3u5D0%jI`Stz#V<9A}An>O4$poeRH5=Mw#mdGO_ZHuyf= zA=oh|9Q;hek>t4Z9KY?PQwIJqUsAq7-YY4=QO!zlTRoHNM}EWwh2bcBB!pJaKTRe& zD1mFE6XbrVMWcfYnM)=2iBXFc3Kz_VcUq~qV{<84zsa00XxD_2Kb$-LzxmuQ!-gI{ z@dbTGJfS=B61n3SgTFgCcY&li|Ni!ycsl$$I-UDNf(uuWX0P|;fp8NwnRgqk&&smi zXXe1?@@I5LE1xe=S%a(ZXQ6#!E~H2*3D(YQhF*_)Qkui<6Y@C+feDXeahbu@kGpWJ zVKEte5rSb`$HBCWJy6^)N=Ddnti7?4h%G(9DqPg8S!wsEX2p_)P?YkHNe+#|3ezIq zqX%+=Kl{zl`K$)X?Y+z{Z`{QzS@4%8rR>4niprX@Mk|0#Xw+T9!`$4nhGUj}$*_i;C|me1a}wA8aDvX3XJEe}1|Dt^=4M5iWM5wo z7%cnA8#)d6(d`+m{Lw?N9tg+Ji)~TZv7Ch4Cg2stfvOKVj7ga9WE`MfF~Nhur3=;vgMNc z;H$lrF?riZv=@z%>N<6j#$Sfr*CavD?+%H2zp6UlM<3c>>DRcf*!TrSJiro+(p5&A4dh1-d3 z0V2HuHA1g~SELw(biKee6$>c3t+7z@Dj@;+8aS=I9O~YVl7b8enyYpk3sM@W!46$o z;-gAu@A^V?xvp1Vn>9mRV(8gdI<)Lf8_`*)fvLsy?EcxRXn*MgJ8sEbS{&oT2E3`l zHLLAOOyy=`Ju-)Tuik`N;xl0MS0gLOahD!>oB*Nf4mKw=BjB?+j5_r;vOs%cP^3rD&oX#RSgwB8q1AVE%DG9{qcTXV70$ywJC2K?-9`2{U7|rLhA0z$kj5EYM-wjtCThqQ2Wn4onWS=h z(_|`0{>rYtV7-sx#CkZ?e4HsM(+1Tg=V2!2E=rQ!3WDw;swyvsOV3S!{l}y^F1rM1 zx;c~Y6@}Dw&>k1GTjO@)T#USxNe1HQTULDiLzCu>!+B$^@GqEQOvf>_$A3HV5qe6+ z22Nx5iEU*3auHse?FNvJ4J>NeTEA1D+%)+G@wag2WPugLUs|Th?>5-_3 z-r#f4gIFxBBNv_Wn2mO_;5~h^VBMY`cz zeGh&Lx5DyL&b2f38+cuEWby`;v2S)QR%hzNH={u=Q}zWTw;y3cTR5)%tfg>&pBmma zR^?kCSHi&Aet&NSUWP8yhz!GPfFcju;l?vm+K?fCB^u`?;hjVvvVO+KN0*V zJ_c)!6D~iJOg?!ZfyNvy{9Y`E5syX5Gv#^s@a0j)t)UafOIgs}*$6rx^T-Cs1?(>Wvslk66TsdBlJ?>pRo#ZZgM*U|jB9BgG zQXvh>sJmHUR?%og^r-pM)c8U1_tD3v;qz1ME2B zi7m$qne-t^c=RIzrze*YvECGN`^|5XHR>!U{EWqXG4{i+EEj_u`Hj%iY%uji?|ryEv$;Fx|{ z2gs&_Mf6r&7!#&0i>u`$z;(e4?mJ>ZU-%Z5_9T(9FJ3frZ47PN+d;p{Kc>y&-?00h zTp>^W%uxP~4W3{5lxT)z)3s~#=tRi}bnW9g*sY;URgtwVc*NscbOwVe=Hi zte%8H730YE=Fu7n?)Mn?UJk=ggy6~lHdwwCPb1^GoqvMn9eU%MJ$rHBQ;n=&50!a6 z3An}sZWwVOZr6&af%*xQbGlCQ-y{&L`+7|0`eSq_cddPV2^5eVNMN@j12U@P@6k=nu$ zV)KemADNk;`s4~C@?<9%_VP&i(L8+KkV2Nt$fcJDKcMxrRpj}_9L#qQXP(!{z@BZ( z&`(AN@3m_qU-A!FYShyi?t94>X^wBiEg?ZR0-OHmZf zg6Agu$L(|oh>u<+&-9%+4`?^a3%_7J`ikIgy(hG(XM@Y-05aOT1FcSk&{xwMYCQN? zc+&$Y41BstW9nAphk^BE-GWxkb&n%DpW~_hMnzB?d_fm2?k5jK#9{uQC_4V49VsyR zN}rk{`6DJ#-C@shDbskg`lSWR%}oYA&kZfNUd7}xiK-ReVmKksm!Fvxj$8H{LNoki z#8ZbkCbt4;r`uuj`6^hOI|bU`3e&4QOW?%fjTo`73YX<1phe*%IP_STIlnX%k6YD} zzgs+LyTMj?ygveqmi%S*S@jTYi57CXeG31zLK>>N)}W@!32^n>K|k&~6FJ`Iw7D>{T2M`Kl_IMAP6==T*EtK9^Xu*`Vuh4^pTXf9LnYJmS3hh$I?Ng`5#skuEf6e>ru4k z5uM&v$c)sVhUZFg{|b%JXvU}-$fiu zCLjmE0(USM%v{AiBQs*){)IAZeMP7h$Dt3}BS9nX2cpX@D?II<0HMV-=x7FlormV( z3Ajx%o}B|l-+Zz*PK3Uy7v}%)eFd+690$9iQX-YY=W9NG$uT3&(Z|MD;fdi>V)ng& z4zCV{?S-3J(V+=Y@PLOF>J#`%yb@~YBFX<@?~bqZ&oV##`@kpH5?9SUhZ#x9@Mox< zWLjN;jKk5Ow=agM_fvAz?=}88G#iX22|#t;W{wvYj55L5lzp@e->g!B%f~fwoAW$) z^C24RXdZrgF+det4FxWrqUrjR7s$x)bnMT%4u(5E^WIGs6@*GI#*3$h;c=#b@%}K4 zM7|#-RIiDAPhW#kr-INlA`5Qp%EWJ12XT$ED^-7^4S}m$$$vUc%#F2HzzA-Ek#i!5 zwYAkm+?x(`r6J$b<1>-o`jzKyt^#(2H%agCf9#aYLa=i97u#aBn##M$L$b~zD0wTu z`hjOqkg9>DvkU0vUVZ+U?+aQkJ52l9iiy=034Y|Q5LlI^PJ{Oafz#OzwAspeYRV_W zXV>-AbHPlwDSaEGk{&>Zf;XC}Y{Yw0mQq>Q2sovYgT{VU*wpqJ*DSt@b`g?z)l#cOiD z$^t!Rd`9c@MP$0|LYP?hlaz4I@F7`g`r}6mO)oz|L_D1^?3f|hU!06}qmSs${wX*^ zkcBh-+SrqiFM;)x84$2u2OV#BvOe-#L53{D5W}g@%u+{AF)D$c=@|urjfS$UD;Y-yCqW zJxML*R-mJg3utY-0ta>OqJgy@U*GX5)#_^}-?;l;cu$`YDr|`L{u@aB3>3Hc=$pbx3?~$;g5IH=v&bcFjPp#ciCg*@ILy|Qx4-SML_7q z8QSc-9u+UU5K-Hs9J~7_3D;Q;`wEx9{GI#BrPQf-aZU-dqVovMEK6jb+q?#wPX$zK zN+#O$E{1f&L0)p$TjKPIo3(H|sL0=PuyxLAC~#B)vDcKmSkS~V=@(KJ*}K^MVKO7;7uQFkiT@SC@D?F7JVuu<_Sku$w-uHh`1l;dJsA(2-_dTaEd*kp*!*9q4m%@PA^^`7MfKN`%LuY3#qTXQ6uX|U< zyj;&^K{E{aD~}lBQ{fQo`V>yp4i3URgK2OoTn12RI!IiOfq&k!sr`l_JTW-L-guA) z&IzvQC^{FP*481sHK(Q z4wo3rX)=Pk><%b;eGXr1{GtKM8t`n|N=vWX)VUeTnjvTA9bJFnAhyFysF5(fDONSe!N@&+g>ojOA6Z zD0Lm4jkpR=U;am8TV2rT(_)Nxp#>Ay=W>jqdXn$xfYD#n;r7Apbl~7a@_oW>S~s~K zrAzC`tB*>2=aGxVSL6$?_uo_IUCa@jdbN$Y6?YIT-5RMvSOR_zk_YWY77+AC4W`y| zy?V_EdTi@@e7;JDx=e`#M@?C@yX{uN)zMDn`*krbAc9qwX5eY9FUYSo!Fpn9#w?ME{?K@fCyB!raa!$QFGXz~4nLPH4ExuVM zhqnusVBC^Iyq-P-5;qOQ?+@L$ZpkI|JIOH}=9QuEq4kiqhJfpLDYmVEp}LnVal5Uk z!0PlhdTYmOxH07p#fMd-R@4>-oUPC%b~UQ_oZxLBHEAZ;@2|Dl3d>SbJp7YU~ z(ds-=?tDvuiB8;3cGX_aGpK@gqKna|GJ|-_Dc}u;V}IQFh8LO)7~}2TWZsUGG}yb1 z92q;m)btR82cDnk?Ct02 zoEOjOz}GumesUV#pP0nl{V2c=(=fKA;2Pb{#=5|mtbhE?K466fFjf?xQ|yEVS}3t{-bri7tzY+DU+EI zjSl`?w=nKCjW^fAlR9C{BreM`aicVu=U0-E^OZ1HKwA2{UM>j$iTp&Gjb=m#ZF<2lMOP0RcO_$znquT;1P`^2yoN|pv z*Qv=IPsJ1BjB?qKY{I-d&rn+#IXECI3?222q*|?=z6@5QXYW_{~S1pX##=fS7 zbsb3b>|npaYwGgc8F#4OBWnKcc;(?C7&1-5{>|ca@2|zs8l6fnkyf%<*AC{)d`m-% z@=;#BnSEgH#q-=YkzZlJ;^aW2yMVaH~kq>?Nioa74eEko3+lAe~5r<;@F*y%5C(^G8+>7?!+`d{aCH2?9MuB<;pe}q-xWa(F=q|1)_xYoeT zXB}Aj>J5}{`#`q-w!=Md<+dpZ5#7ZsrP!AdYwZlPv3_Ci50$Esa*8#RRuV9&=wcCT{}Szs`LO$}dodU-km zUAbJ+av%iMMY752d8_er?l0)Dn+Zn^WHD@}Ie8hj}_-;8+;Q#9REO zS{0)38zdm%SQ%#f#p0|jVI*&(CEm*trq_8+u;E8OOw7t-7Fuy&WLfW%01RmTK@}zGcSW#0V9OKXa zd7s2sZS{s zJzAsb+)74gSJVC9s&Jy3CbZWIv7x5>@RSMH?GzfvPo1TKZjuYhP}WP_yzVDl+9ipO z#RfI4lBa2Zco)`=D&W&Ko9Vl!S{U*`3Npm)>2jO#a3$abw{L%hYwyuwF6L(aer)f}83 zwVvkceq#sXJfX7e6uM^SW8||kka_=rK5guw`BRlRo|Y{>nYOg*eyru%6H*-byZk)Mv8gv|A;ibzf9|eKao;>aTw$F zd@(&2VBY?H==pRR=W?&&_83)oMfeO(|8Rzmzx|q|&bdcU9OCqvO)E(FnQZ)fj?aWQ zr=U!)1?En=42Q;&!K?l#d*9NNUJTrX-vxjN*JM-kbE>$x$R6jF-ekY#tzevz3MLEmZ~;dpZBD;Te47G+q$ez6ly# zIWNjO5!`nDCF}hsf_&4~hhD!r31X59S2l1s7Adrj)-cHkWUp_*!wA- zoLAU{ZkO}O&HGu^^uS~2D%uI@1(_tC%W-+`b;6Gm1ysaBh|h1iPBt%^D#*<3V+NY; z!4tPQI2~OBM;-iON$fPf=As95<{1Y#X{9QVD%eL|UktH^e)}=}g%BZQcL})5;9bLs ze3q@li0q6SD`P#lY`PNDZwT|fg7{dzw}I*|;@J4g3D6_@3yHKgoFTxh?;peB+wwe( zr4bmA2hi3}aV#$sY7f2vW7QWmqs^@tRSnyyTecKv-l)T z2kSo$!;ZQ&H2T>vR;aLO${wJ`ZyvExA64lO-#GNUF%A5;OlGffzG$;mIFb0637_{xsn z93$^$78AAFQkdi!X(CY>T46k)3I%LJt-C?otue6fbh+3oYwF2Cq^o?x)u^s#ua87XFHn!-wKJ?3U z5xsJIl9lp;@tCCyjn2Wyck;rfC*gGVu@z|MpU<&wr|?ZH`B)na<^7r_*9tf&XG%iP&Vw26%&K2r+lR`J zBIv~DRp{q96}*E+uroxPvVKCaYho=vzJ8KsoHzs%Wn+;^l*4h7GQ`$M8Db-~aro2} zj5OK>mEC`--nLHam~YEgyG{eMKuaKY;sXB%IXsK-xzNC|V5a?jMEe#d;Ng;Z$h^ie zkt>Aof#Pvk<@AGa*{X;|hJinBjFr^<$7-ftlH z#snk~w~)D7H^^U)6bvo|y4&X^N-f$=k92LtRSjq1bYT?EiarZ`$p-W%m@2(OU+$xGd{@qXxS4xiL)={HWO@!s0vbH^@_+2`9@!;PUkf z;y&_%>RivDPnH~o9q#fp=s-T|z+!CtI)OhZ9*SRfbbv;%BYx<(PwIXRBRjGP=XF1& z#&ToqyHm%jEk4W@tan+64Nh9P`JXg&vz;iay@2{|e+1nRr-FyI73`MT18U}rk>?xA z_3?9PqoWF5s$GQkBA3Yp=cn*@(E<46_L+R&yBF)Hub}1!9^i~}dCqyV9zKif;b{8= zzJ6~NUY)4U@|x8_^F=p$-#O2{yNcqCJ<>FAxhS?}E5o>z^YDw&1$dg@#suE1f=MXK zSFhqYerl_j-!GPOZgGF6H{~gpwYP(zOVh{}x##$7FrR0hcOD0$H2C@6x2s8&0>lg) zBZ~DJFuvmoxE{#BxCEAeCEag3U)1h1wPlB{E4%)1?m{3{V5SmiLEv5Rn~ zTlRh@MZ=O9((j7p8;1xlP#N6+Q(+=CTG*=9GAL(gKusH3*|!H2@zTQoC_P(Ghm@UZ zF85x!z*-8vy^-TvR%(D>;1DZ+*OVW3If1ym_rTXfAym6u7mXKrP;m|}rr!OW+~wxZ zmu>C9>w*W(OcqCH>j+Rd8V<$E3uuX45)HVm2QCrCG==M&Ja4yVK7~bc|KA7r@L4-4 z=~blsc@@Our6IP-9s~#3Qb=l_Dp0NMqbgow#MDHIJr(hrw@hmj<8V9?Zr%wc?j_u6 z;p`kZl#_&e$QXzvjj=B_pSN81=Q};r7>Svw|2U_sGhOSY#NSI@U@kewm@eDSafXNJ zx!DI%LMM*P*B3+U%n{c1NDN$Oyy&RhRoKzG6)kTlasB^7V)}6(J<=k=_PBMRzxz7y ze>o3M>U|{*WH&6C7lZm_9_F0$>b{?N;%|CsoXHCUZ}h3w`eEXe z_?7vbGmG5Sw<3$(bl?sv0}EtgY32tlSl-!5&301qLtPz9q^Aia&uEjh3yX;5k@A{D z6TeeUGfQr6J^_Qwcaip;-k{_VMf%Rj5Z|-)%!Qs$%#xRy0E|A$>rH^D8y|@E?ByW) zfSUtO&LF(bIQseNY&6>%%6_?7L`sfCf{~Oz6uVv~t5fDc>$By2S^X}{yQ=HJLvs-> zUDiT#LWVKJvYp&yDUJN-fti051$LPQ^j6wtwjfgq=C6%_!Moh$IM@FV+LTj*Nm8@Ilv;$ zxofzCV^d4Xp#-@CO{`hI;Ny{WbbDF` z+65b#psD}J&m(jBICKKX_9em*t1%cCHVupuA6ss0UyAg96rG1dP46Ga+bT+fBuYw4 z(V}tB^SMZplr%{)6OxsX%oYvWsc0{iL_~GZ^SMbOyU5o{G8Kt_;mr~t z?(c$VvdTwNJx&Fmc+`;#q1E^lqiB}nJa`loO8m^M*v}!9E_hW3XY}QHd5{a62wfZxxijYn{dH(79SJ^7MeLW7YR67+w~0m3DH7DK`3KER-3qfW zr~rTGOk7;u03lHubv0mi~V5N*L@-kB+!LX15DFpBa}@0Ne((+pb{2rQ3qMpFbO=JwBW|9)0jH383}1(8o0b`M1vx{33x}7j~&B(A6&^5n>`SB zOcF2I8l$*zF{bQ$NUzTOR@3QR#bjK##;&T6L=(9Po~h4es@Y#b9PbI(*+59b$>%t0 zZUY*eatHCd5fJsp1o($GV0y6|Ca3R2PvK;sUrCbv(lgqfFbP}?7cwC7GM z-5?dRhj!#LImNoAOW`X89eGFgevRilS_k?@c$)&*r6?gs!3V&_-}4U z8ScRGv!>D18AnL2UldMlUWONM71G8RUgXUC>o|{_g~oPFfSbmi)V=K?j;5xO%fsKH zVcH(5pl*#yb63K!cLH0~^ML-$)j;Vd<8aPE6!Uhc3j~H1GYU!N$cX!(CvPIh>5E6Z zzn6K2I}%yRrHK1$I9}$9>BO?P94wqR5x4C*G(Gbp*}dX29-@XMuS|?z6`D!rwS{5V zqdaQN?Rm8{<*>U{Q)uct8H?nm3K#tMmf9Db#Yq!3;ka^n2$w7Zk=N2#Ij2SNAXgf; zwckfymFWh$tXCsd zah{3h^^!ui%aN{VtfOm7UV_1yQc&HU#^jD`pa=Z;BzMmoWCvEG-MJ-PMm7eUcix~< zORA9JdVo#_CrQ*p6D<2H!(StGfE}D4Zr;Q)BEfw=bxVuzTcIDldH*Wh`XmSQMY0gx zim@P)$2nXdlV_t3m}A`UdRRM=iaw5`rok8CHPx$4ugK4s|!4(0#Xx zsb$4IfvW;Cwlo?~p&Qjrm%pXYk*cnV>eS zftkH8hxGT)70w#U6`UYHsP2V>q@Oz{{Qe|C1q=TpI-%>xDoatyxii_Jtvot?+zvaCg>xFy$+uRfikAXdFjwoXuwhUtZz<_pK!2ViAZ3 zG%#KZy6ERuX83baKQ-t2`(c07$eNv37%|cSA1*nfnA$dsUde-MXDb-{>L)!VoR72h zni-SF>Cjxz05O+3VAkd~i~|Ad-Y7#0A&OC3R3Z4pfWDh)$7w-HOn%@FTb&g`?*Pe@B2-f`Pfi+wQ)KdDEEf0h`I}! z>vv)B5h*yUJ_g5aJP3}W(R5{$B38{g3#(SXA@iO-;(6YxfJ>i#2m)27gG`baSjdZl zD(97ujH{q-i{r7JJjLSymzjH8Q>~>&udy$ywb5!*sPOpI00$Wma0mtvD4Tl5(Iyz>h6^`(VHd8>i%YfWqgdFZ4)7g~Q@5lE+g6Ab!ujE|ik zX!jgBlpE^_lLEh@(f$tF>QF@YtScwC{O%I(=eJO(w;0UjPh%`oi7p|_gzGHBXx`BP zMnCf*eShOK=p1%KGlQo%&3-*-iir`E#9m6M7LLzV6tW-QaBi5r=xs0!Q6`>lo}5E; zVv@n(SStAcjlf0Q++j`s5&Fsa7G!q3;aw^IOD3v^LQ33f3dWbvR;3kvjW*%b(i(iD z3b1G-9cx}TlRd9`z|JQPZrqok*O*Q4eV;KbZvV_~S=x$$IUUsAPy-K-Yerk89I)Z` zt?`BW{Qk#jq}u5P-Jg?!Q#S9R%`vXne|jr!;h2eA9OCeuZ6y&zZ^0GDKPk6hqOZf3 zVi-5avYYD04?Mn-jXSr8O;lEbDVNvKH7zRmjJmdu?_!y(u>&u4z zCyyO_{?hCx`6Tu?#|5@wXxo1be$TbwUr;gh^My=-QkRP#?{JZ;t9ADgrs{1;qmG@1EK75WoJa`=H5*QMZ%e5X9 z%dvMxUhTideWYhQ7mViEMst!VDtlcb8&AoD=in5&zE}_64k@FDcq?i3Kf}x}ALYEP zlKgcU;dt_^6xCWb7XB4*J}H+8p#M6Y?D{8#yWiXvC`^yyo!lx#2aarF-<(^7>5t}P z;QKP7wss?3Q76T>?YKy*TNG)b{A1|dww|q3kiztu7u5V-J9~0l4(FCpqwV7z;f1U( z=l!{gT6^T!mSfrEwQ~*WiyUE9hhH*_btbZ$m5o|&mIjB924u#PyJW{(31RkyA9Vcm zX0+b=j-4^r1uQ?H)}*!JKc24gAZVS_<#%#C zRqNO7%uUmic)z&?cj#CM*R9WmM!_rSI5}Pzet_GdT_`2lI^+58oj#J~T;4Q8UKD4? z&%y_B6xYAJ#QWX*A5C+8!}z9D!|p&Oniwf3?3f}2USld@`NVHbhU;kz;aGvIcXRWO zJq$g#1L==vu^^P3hxBnQz!F{J$v**qOhe)PI%OtiMLuS_6o5i}ra;vt6bGhoqfFa9 z=rq(xlqPwCNi>(!EbD@%=JD7(m_+;Du7ctFfdYq3bLfBN<-$!B)8N|`53o&i*~zOmlv*w z)tB|bGRTRnS(rooNHke)a}{uZ3l49z1WBx?mZuE1#WGpnacB4)Wt~y&TlIvdt+F#Gb4?e5wiLJ`2v8? zFPKl<-FCT89=!10g<;PuahrAtIonr2S3PG*u*F^0VDS;Mc|#QKo%@KSJT-%)%{hYo zFcHH(?SMz`JmK8)M%0ywxukJNKD&E-WyqA(Y7b#HjQNOn9E=d zB1k_e;k9HuCQq-K!kG&VH1TjDiF(^jXXrSBTi9y+`o)Ly3U-kB6R$GK{%dHwD%XYB z8&2IHcoCzdBy!Kwk~Uu!=em{xlJTR7?HqQiPU7vO*_K z0IzHNY!J{tunuV(tslb=!RiNU$05=Ew z(yg9cez?nuhLp#kdi!kV#p9XaU9_FuIxNPwABlj3OQQTe50`TsdLc1RdO#%}4iJx~ zF%aXH2|=@?N#V6tvhey6n0-eZ=lzReDm)}b&u&rSdsS%lKZdN>c3}2) z6VGq4Ft7bCot3G}Z|+KiV|VY<+j0i{zHfgRxp+Qg`?-Qw@)i<%FPoTH)M%T*)^mT&~fC9XFfFPS;Kr{8p0o%@1MLiu>$pl|JSXH;L|?Z-T=%ZeZi} zoTxF)7`f*jD!7RWV|V7(PH4V>W%fbBZ$k#c-)R9@FfkqCtFObA^ilZ!O9_g{RDg!Z zVpMz9NkH~5owNA_?blMmTxVN{#S+-_XcgL4UdHsmQF7|RJNjg`F#gpMzmh{0Yec+;vc>3^m;p|*%d=zTPuR2>p_IS<4vmV)u z>m3d378+t>-Z3s`Sq{ms=FyQ=wZwk&5YZ8fp)GRn$)kpLDzf|-v52i=Wt*E>OxcTv z>n_4z!+K`gj5p-d{xJGBy_wvPttAr!%(&gFD(Uu7fwV(9(0VQ&-pgEuI|uF1)pIhn z-#i7gWu4gsU2Z0n^OtHrvjP8;oMScb1<6T5(rq*b)^%4fUH@cpZD=k;Y-Hf|mbsw) zJe7!lIR@XW`gmsYab)RcYmAzl$xFZZn)EMBhV9Phi07RW;-2?~PWq?-M~(DZwK=)u z^9Mr3DmT%T^l9WtPZiayTF#zsIzoTuAEy~7Wue8|fpm|Uu#>~(V0okyMrL0Ck+XhK zDs4TAv5hE8S_1aE>E1z+{p+-hbgsi#QhU7$p2W2yU#+3>0>5t zK`qr(-UxydqvYNsK5G|vgU(2>C!3C5AWL_jB}Q%oq+8`K(!W=+?N%Z!_`L*XjZB5) zhD7>4Ta&D@vZRjuXqp*A;LD@aY}(|1bZekI`aet|=Wnb;ov%|+<9QQS2A43(=Hp30 zX8{`@FcC#e7+%*Cb9`>@PWQTTyRV)&TCBANzgFz$-GFt(VE7)5n|2gt^(VsOfpf6x zav`@{7o$2|)8Oy5K4yEdHCfv&&V4t%uvd2z4gd9rQ8>4bel8Ee0HC)k+w4M!6%;mkj8;L=6_53N(^Ik^nwM@Q+> zR6V}_++$2a9k(|&%g5K|@z_{lNac*%$?J+4d?lSgc5|v07}*#Jn^G09cK2$W<<$zF zp+59?mMJ;rw+wQFWTDD6n)7Zwp!VM5pwvAO|6KZyHvHfiVjnm^(zaz(nDv7ejeAcV z-*R61@vnH!QlVV#e;ST2Ze)YMpQf++Oknas?pbxUmHu9`9_}0ep+*mf+279p(cI@< zY*|P;Bh5Y6BK2Mqv+M*?)aec`%Po-%ZpPhlu`uCNB4XhQraa~fY(B_`nhjf+TEGA3 z==X`>zbY0&M>?&PZhWWx%T;l%P7PTzxsa|};elILM!=CiPsaO0Bpnn};EPS@BWt?G zQahVwfyuMGSawQ-$Hoh+?Piog-~9+!wQD>ck$p-m@0tqDB@`g33hB&XA9$WvLX{k^ z3$ilAapqQiutIB&p}z#ajTwfm7j1-|JxB13xjv5AiNmbBtSSCN-_Crxx|9DAy2)zMCpg7(9h4 z+>qv%Z)#!7xQ>VNl5*k__KnuyCmPFTeKrQfL-)fW%KRm0Hzf&AS>Gko^Ag zm(i6&nT)HC229$1k^D^TW{BNm_^g*fOoAifgjYLjk{*XfDtmCj!#;GM>kggu2B@cX z1g{@tS@c!MrTM2A9bO4B+8lsirh9Tq>@=1=845Ao+IZRb7qye0gcHAXqS}m&RB8_r zr(Z?nLj&hH-YpI`dlli8%?4O@<2aG|_l133y&W5toAVO`o5+jONZfCH3{ulF`C6}| zK=Y6+e0psyEG)Z18l~prwTqHqHr@gxXM01(lW$POaSoOLMVl`9X9N?I;)z|@6jkLtpsn(7s2^jj;9e8M1LJP1!4O7=zdUz z^H&UV&ou=|PyRuqQsT*rIk&-0b}{_hG1ekN{<~%Y?-IHEUi1{)8YvFW!YN>Pp;pi!_(S`uyU9CWAGp12gjSO~)&|>>|9>YW z_^_2&r>COV6J5SkYYz=`@2Q<(vy&Xki^u2*wwU(xAS`Xrq?;d1!m{rD=;2uir4Op; z%3n8WVjQ=dOp~R#GY^5i(P!qv=O{e*AqYIK<-+z|G4%5X8N%c~CvQHzr==dFM18|! zJYYQ;e7O5xFWrdU|1E$mV^fH~7@s%(UIjJ5Ts6R}4X)1i$KMxGOGN9N>A3rWkAw3d`q*#7E~j z$`?22>QEK7Ou~dTbyqTL_Ps|HC4b`LHiy{6R&u`!Ls~DKf=7a5iO4es#&Dj}$)Vk( zaZ5r7wKGk=}rKRkdZ5W{{WHSqM0El4PWgqX%?PL%~;FSoVzb zJ&Bw`Tk~KrD3C!h13S9)aS&F#I$JwkX)V)V5{~EgZ^ZH4G32L7Ejd5oBx4-a&$?Z! zr9-d%t(_7?i0bT2x*@%betkZXd9ay>VNH)nW^x@JI+sPc1U?+p*az*#(_n|VIDDKX zN(F68=)=5fqFEi!d}{Tpwk^J~IPPH_Gr2Oljerc1KaSi=nW3dJVbH_hyw3NYcMnQ7~s&3CHDG$KLTsp&peQ5E{4~ zy8bGYvm2)2oQe!+uG-ApyzqzH5t#`NdRnjr)SHp}(LyGPrIJ~qAIJ>1F=&<(N?i(% zlh1NK5RmK&+B6b&y_7<^!E;=PcQ3mCc2iX-j@6v_8`vkplvBYeK7LMA)5Ph3Y z-gZY@ICw#p%Yuy;&P}MG{znG{ZDr}?lXoTImOd2pr_;1%LSFh7Qt$8@^2t+ymX0%l z(6`l0sN*iu(yXMVG5COF5JTYWjDcqdN$H8w6m{kw`W_x*0;G z`pLi8r(p6{j{cEuBCCoxk2XFf9@U>v>vt4b@v0cDkCrzBo zqE1#UYr!=y&0$BL57dcUz|T(_v~-Fds92>z`MM(bY0ks@FS>E-B6GgSUk%|>n?+FZ zbQkyw-ojr0NwCZ@gBGqWWc0RGl7kKN;Kt5Wn0z=D^u_eB_vck!lcYFC z%LtaAl_M61?tO#pmrg++VbGYM`P5@>Ld%4mV@EY zYOpFf1|cUU(XccaQ%aw~;UlwZen{jEF3GkvO(Fx)AK`-JV?*gw8 zl)T2mOtHVTFi2Ur^=Cp~6% z5a-#A#p$`m;CXqJ+AT{b6C`}0tfr2TfM;aGnXOW?Y*31AsPsZUNxgIJIy9gaw{cyrF6AFuiQQ@BnMvRO=`~xR=s<<6`r7T#f z^SiKOoEo-mT}*l1&q;D%Bz{^RM0bWA!%GX!lWALK(Z=!u_|^NKp3=C1wSO{T|L0j~ zS~&>(>y1SG`x@BkgXG%P#WX7C4HGlvwzc;pXR5$!VB39VxcrnQ=*o^qt+rj{)M70% zmdiu8a5L=5bF|5(J4>jYry1Mq^PF93S`7ATi8v~`1r&Fe;=jkHpj%=F1E)n{@3Kx@ z*m{t>Fs-NVF^*7UaSGcWPojaBq(Ld%oXbs1;-kCTSgVvk&;9bCV}>@+V6HFiFZv$H zYh~J}sR~!K$D(%`A6h4SG7_aVT-T$9ew`eTo7GGx@0$j?i;6+Y^jYX8xsopbn<=o> zo`Ek9RM1n6R!CIT@mp0MC5DZ7W10-MM9VW7oi@1l@O_&7m7Ak|o&o&$LE_u4$82bA zf#8Fm7_~hgX#1=zR8zY~zt%sdKllud-?^J^{Tj*?7|p?x8Z2e4lgQ5}AyC9dgO}<{ zW=&KgHH_VW;<-u0=i^&=pluGAa)R76VW3%AgOnNUAyaQ&K)zBjTVct~M1#kY*vq#B z?~RUAkMVzKZg3VXQJnyjj%>hx4p!{gs5UAwJq@R95~ZIlJYcHw7PxyS3-ms6Oz2W| zym_V{%WjmCV1h3h%dyt>c2dEYk{RE%$%n+tosz9vt%O{B5h-qq!k zC&_b9B0s{AMjm-Uqoj**z-vS83;s#!pOQzd8%wwh#btJ=%$u$nKOZCy8qqzJV{x?| zg}5DAWZCsIBx#ctiMhbwvC<7_gMSiPN+7uznq5auuYT{=Kag!pc!=!emXDv7DJm^F& zKb{Bi155FgR~A;?odckG5^PNczyu}|#Sm+*gKEHT*`x|tcUNL6_ud_?n~TrY0#PJI z7k4c=L-Xr6UsC@maQ>IUTQlAqMBkUu%`Q*amP=Q`a)vI9sWioUwIpzvb)U7_YfB^} zjf88X2AQ(|#^TLZbNryu0OyYGz??x7xcDg&TE|tQ?(;aowO@Zp+`m1ra3~u0{tgu= zcoku6g9cpI<~pizw_(A>*L26VM|ACx4KVYp9?nllW@32pv|;IVJkQOPT&>=dgwHR? zHyuq7be_aE4`Zm&j9^+vRuUgxC|Lf9L)Vm4Xmx62zI}Z`6sLKDU)oXBQaBDPr%MYh zUQED$Uw$xw-R+oN^IdRNG#unChRKt5dHxJT0M?5K>6hlf+?U)Op}UIPai^iJ-*S$X z;0<**)}opCGq6?-r=CM|;nDW%cvxaTdJo)V+yt3mbNT=(x!xvQe>|iit23!>ZvuA9 zUt{{W9R?YnEb4InI4t-x5ssT}r1J)~c{N7XoYT)~Iig17C7^e3Pmz^;mpt8A9D07?vs#rix z`qcTU`~TF+JrE5L(9(4Qoa2Aco-(cj zdbt+Y>wBT;+EOss`GqKXyc6Vwa2!p;U%YtRYWCxdC{U``;_{?R@a3%ecIfg|oCdv1lc|lh3EaNsz#2R^#NV#6!n5hp;4S`*_Ivmf z`~8z3$2<|&8>BF*^$$SBX(Be(jE8cU6KLsHOm-DFfz|x&kahbN6mgknjd(Ns<~zXU z{wJi-5P| zH8HmPPUn1nMO}9XaoMY-Wby&-T_Z6Ij^-ERmpwXYu_}!i#J7@M|AJwuKz2*mRy$pV-j#!HS;hIH?4pT zH)exP?@!i$!%Zr&%??iZN%7l5eiCo(F!Wn;9&R=S;J;Ol%*VtY@?t9wV;;r8<@99w zq9ul0?HysAA6USA?mScW)Sd*y1)=h_aJ(?Om<0PJG4qmL$xP{=&^=;`d5`Ld)`2)i z@NFhESt#*UKPW2irSbQjn_`fO#^;hL&>*qVTYga0x z+}F(Y98Pj>Y8h0zG?VDYd7?pR2Cmt6h#omrg6%b;nBcvVe3!Omx_v}oc#J5(?{RFw zwz0VESwE$gezc%zl&(l}gv_!;5dWSjn3W$1c8aEqmhmDeoxOo()dn-Bzs946lQ@na zD5g^BqcklonVjBiPWLX6#^{(T7~f~kKkw;CwsLtPuZlwQ+V39D-;U&Yhbc&>aCyJM zFF4iB02O3E)3ixiWbj!c`+DwtT%rE zya9c^TBy6b5n4~9@TBb`Jn^fdkyH8XNBwsc_ABEC-?3o1>mfO)&BC($Wcn}IAM4-D zr#bVtV8Z-(f$7r}cA)qqJv*)uowX@`=lW(5ZqCAy;AmoKEKhD3w%`+q8rpHH3HGdL zrSBYaNzQ}{j$fX`EF!8xf2C?TI6TUo-J(hDY9FE*Tt|+rT>!5)^pHm?T<+g`Htt_| z4uqS_c+sa9Q|s4nm_yfNNKk$fJk*I}&Pov^OHHBqnFsSRLIeLKX+i$C$L#nIV)(}- z9bardj=SGIWgeTx;0%>`CD5s-S~luT)zxfmK&Jw1zF4%VGSu2>;v(! z9_W2U7Kg`h`ykVJi0(QK`e!}Jq?1cQUbBjxO;0CIo)^(4a69~wOGayptJLdQ8JRhl zhF|p*U?3`&W8lAp$_Zv5e+)TCHP>f~m=4N!FH%z(39`yD6t}NQAsc3Wz@By`NHi}Z z!XqJ2|6U3-d0&Wzb2KVW7BYYPxn9w(W$epDGnTYu!mfocY5DI)vUgNScXzIZS8EM% zTMtX~{}bZUY(rSYWd~gnB+&QyHo^v^W9PPy)F)>RJGp{eBsD6jTz(HCM=r7ZkeA5O(`dr712eiD7_6o7R z$8}4BaY6!#mHA4mtkv=J-b{=+Ek{slvyPqrq>JA9vn!z$N};_?JU7_@jS+ zQI$VBc-6cX!(Ef0al$-sKC+8$-FkvfYtJGxnhugf-2P$R9S^GgB#ZiPm*sNSS{T=A zNw=CkqbsWJ!p;p9UgbPW7++!w56pv0PsLE<_DR%Smq2fIJ%`$@1ROdQA+%>ce!VKs zXLtV~*DmKl)A$r(bx#CI`g3-H>j$=MQxR;li^YB1GxoZaG1PXgfRT&gWX$H3uy{o@ zJ-%oISc|FBruYpsa-uDUOm3zZ|HRTDj{DkpD~FLy<#Hc~^r>9^ERfV+4!C?0T#}|} z^h#7XiO>BWTen4E*WLysv)Ec;qIo;^ATc*6M- z6?}bz>vQ}J2iXU1)ZkME%}c6-W@#P%ots{G@9IVP`)o6B@2o_0&U(gltvZ9@Rc6rO zw+jx4oT0uPXkY%TBaL3gWmNS!PlDx0kevG!x|CA^pMajBtEbx9;X zL|Pcr*ML32f#jHoB0MNhfry{eg~s;((QgaGK=EB6dYT==s56w@2#COoxhG)?H>W(W z5Dn|Zke)ddOnX*dfhR*DRS<|WR z5D(>K)-nHVrRj{fr}0x`G!bmHg}auUY0el+ny$z7B-As&Li{Rd1udn!F0Q3w&OtQg zC&&BCz6e%h66mKVa&Tbde%3B*4*sWnlF8&4Tgg&NBzNE#)fu}324}A#yBfub+Jzjt zZr%=Zbgu%2O6kG0Z<+LilMGF#f}T;P3>Wr+H#t8Hjo7QeN(AN))KIiAZ`;9jvA zR6b`K{uBF;)^()N!q+som7cU*aD)QU=7Y6n&}&pF?bd@ z->lhbVbs3$*v+v6pFWO9mCqqiS;)<_rWx_A3Z}xDS2IDPMT;-<_za|O&;Gq^_-mmf24u4MPHyZ9juAtKN`*C%H4x^X-`bE}!ySZOJ;hes*$aIBxpAh8#}R z220yc6#YCECrP-GjeFg2a9$epoE&A-R-K0A!ZOS`a1Y`F^n~egwNzJWG3|I%538P8 zKx*$BtbOH!_n9Y9@0&<(FZsqm z>$e!5dfEsH)ybg!qPe)jp&aaWJ}?9OB2a%BK>f<=bnj)3!E$}9@Gr;fTz0#NT5dLj z&(lTe)3^ypmGoib;3?|kH3iywHObK8K-#6N#a=f`r(JV0Vfu+fcvME6iAiyUO&>L| zH0vwgFg^{E&bNpX=e(UGW{BeRUBNr?u+^fI7vTKU6Y#y@4r$QTBa_GSF``5bkJ#GCl`6UogOCFueOKgr7uRB{=PHms||v;>$++A*hjQxCzov+k|A!5JZ>(dil;>6Kx~{l z4jqp|zt8V5AgYSw9U70%^7o?2zXAM2W|G%CwpsgSHIcr1X^^*2ne6_#2JX5A(+$FD zMDp+qzC6b-i|H35nG@=WK=(N3ULH?NdXk`4lw%O8wGpKNaU$-}FwVlV%%oeb$}0|LHkc^j{KXZ@njEm@(MnG z_-O=~jTB+nM@9bKbzZdO*974=p^PxMvx|sNOJ)D>GL3oUj=zt_lD1$Uyf=0+1igPn z?u9s7-?DI}XA+Cid4~mjZ=D8ojS9SK3BpHd+d;^L;KehsIs*;eA zenvNj#L?WP8TjRI1TU)88FOF8ks4<{yZ!eCIxeo1t?O$i%hfDc?aMass-P8BayDU{ zSP3~-_mjOIJfA+8(Sct_PJ^jLJx(u>q3vGHKNVqtnU=X{#!44rC0RCcKn`X;5r(r1a7?iY^J z?lqv{QYF5h`Xj1*;x+B5LUwzy7!k4F$Smv2CNCV1(}!OtfU(~N+_SZSn?-Xzhps~M z&G<1>EtL=B7H6|2UAGZAtLqhiGycwz1%$6Bfsai^Vf_iDTuv1a7azlSMaB5;VH}!P z)lt^n0~dsqfP{q}{Pg7RHAk{hYVCIX`>Y)JDOqX>sUB&tew&AQb2}1O9ICF zg15{I7+!piHJK`oHY0a&+~2WuxC-F%@-pJAB_t9His+8t(n9^^)!5v+3dOlTiSxhJ z*mR3wy?@IJc|8`eX<$FB6imks?r+|D)DU>63=36~@Jr-x@P4)f5?-Xkx9u)uuB$gh z4Yy+bNF*P9;JY(OMNiR$)6!F~5gD)mr^5l?^3Konj?> z%_$p;M+Ll7Cq~$pHAcAmz9-y^8WjA?EkU8~cXoB`C~edEM%R2Thq`#crAm{Ly?l)d zbj2a*L@_LCe@C(>)eBrF{-dGHIka$(My;4Ra5Xd%^vCJK#`vQsu|=LL%Fn^VktX(< z^at9&d&7&r8G$OVUJ{LW*-U8FZlrc+iH30@N!W<=roaMUxr$JoB}*~fdJfuhS%x25 zvT^IpYPdA<0quTx3Lcfrg6JBKeg2}F*lDe!S2%{D?}G^3`Y@0fZPaC2=U>5`)&@4% zbG!Amz#53(?1m8IP7jCxSe}s*+Vahy`=B?>Z{WI-s$x)jd=>dPb~PFq_SA`*Lf zoX_X|{;dfk<1Ssk24P1)1i06#K~+gE}F@GE^QX_E)31b4L6O^ z>g6G76B~i)s-^gDo;3;4Q-IZNG7wpRl{dh?MO#OERIph}w{RKa!Z8v4+UqG`KKz$X z@|L29+C*r^@dWb0@(>74`lI`|Z+OhF4I8C{arrHOEVQ!|JdKH1l)q zf z>Uc?+iI|krS7+mPmvb%I;@G)*7^&Jo)i#<4$~Q_2c7FVey}ZZBGvVg)G7}WaR6(d-8GUkE38Z(Ipq?#@Vsqx;TDB6LJ}$<~arN*+bP{;yiwW%Hx^cXT zFs|M(7wgMpaNw2#2Bb>zw>VFRANzIj=hOt&M63%2)O>Kr(3gf+aQoCBoZDdbM8Pl< zL(G0yK-~UFB9o;mu=p0jw`#YcXU$EKNnasYl(HFFiShiaIy}L=i5B$Dr5tMexf8rk z$CF#0%Zc{26f{`P?YCvkKzEibVQg6_`o(dYRkeWcTaIOe8|dj@-Be?WJ*~KQ9z2Y> zF3q(Mw5_LrB$Lt5@C&Wecc%G8&^TKTZM2mxq*z@7*lDEI~uuGl{Yavjk)kr8;=in zlH3RBoU6(lzQ*)24S`|UBP@)yH#OPvCSPoM-9x+A*1*xCW-`rb2hLaV#K3N8=Ffh0 zxLg_lPj;`SQ|jF@cA&S;!VY={~@x$ylr=#2?KHrm5{G>k3U8(JFL2 zwY=#C1|QbIR@YdtfBu{mQk{>oYO>fO{~huS!&rMo2K(74lpUEbFe%!DXEK9e&ZB>H z&-Lky|I{S7zPy?ha#27DiE0vEkPG{Vq{+sU!h*Cx9Wahw4S|+@yIbvwia zHftZ__Pc8t`^n0fq9_Bqy}uCsgvpTFZUi)777k8`C3`b^;ZkTOS`W*CHQP>u^1_Ig zW&{@MH_<0Q)L|9Jl=<+Y69+O>__AM@aenC>Dk=q#)O(JKm~c<)lJB&x|1)Vmt5qlBb)R-9Cg7I= zV_ckg57-?U=pJ|h#uQhOdwI6_%BztiSA9c^OG!8;zLC}zOb4AeO3>>3gr>+DLj0`5 zIKQ!krOPJ>7G0M?-&Mx^lJ~!9>0xi2Y7hpq3O%4Zv57ut$!1>e6c${m+(abwtBEV; zP|o3IspCFpamUHC$fWRq10dti+Ex5_PbS0u*EP7uM30KS@+K#@)^Oe49sJ*BHlUDw z2MtzEhKZkr@qO1RKn3&qRNP;e(pHIRkmx1mdZHdKZ{cR!w>Btvr;2NZhNuDKLHA62 zK}mW9q}Aqw%e-)?7;A$?heDVaT-Q{YFM(}t69qQS=efOK05y%94q>k^5UtIIP|_Iy zr4x_OeP|(sg#))>gM1XVR=ou4L|kkC{1&6<(qr+0R|%waodUxkZxr}!uT?IA_8^HC- zBC@CQAY9NxntAaut(q?h(GD8Sgn5hT8&ORdvW&v%SB7YC&@5tdZxvLp%Aryn*65l4 zh#GQUCNa4}x|n+x|8lM51(+_Nv&?k`r@}fRcb6XBCu~RSx=hHkj4G_;{MGPD2E7U{ zu;gMGRPsV0ZE`m63S}i81jNA&Oc{+MV{UxQRXFzu|3zCD? zwC!3TZkl2X%B_{aM)_df4MRNBnFG6;CxTjj3iipN&=}nrSRD|lKksS!pWZ}VDjcXI!Ytq z(xF}^VSfYk9p-lVChFL5!%&d2*ObI%WMZV`UGylK1Q{n?P|@oLhG__a;CU;^ZkC`c zoD=BfSVwfawiWlh>|*=kqR39cEiNNiPprjXK%nO*@@$egEO`;j#?@ru@UKDCT31U$ zR@mYEmVCM@M3PAVdqI_x?-4gCU6P z8}8%}8SBFG_nvS=WCE7A`O;vHVbNrn2(k)RkoQlX4wWc^igOwKnth#F+8IF26Js%L z>oF|wJc~zX&t#gMv&oq0b-K1?0$Q-L?55uPP$|?vtCs#pTT4wDCQL<;Fy{;r7E)*nWM zbFX+yPd^uB?|0~oRbWeHWcpW3GuB@h0U5}z2 z4Fa7h!DN8zHq^a7gomw?!2U=!oGGf(?j;i6bIB<>%w=Qw~isL zC$VT+A`aQyg%@`m!DMVd9GUJ7ldhzL<@aV7TvCIDH9v{z6=mqpT0_52IZc%=MnlL* zB5|I#oV1+eyO>ofk*O{ER+bGVS)8>a!c1=eiF zom|jun?Z4U2IOv(W^9dt`YVV-2!9Ri|02vW#ntJbu61OmBFCRPlLX=1{$%R2Ciu?1 z_?D`FL0cJ7^792tt1m9Xg*RV-)bcE*y6P=8*i{N*ZjDrXpDq-$KN5@r1cj4k;LTte5!5=m7uY2DZaZANnl@X~w__ z?!JGNxfb%C4zG!zGJBKAJrQAasM}8(vu!YyFU`;R@r>pd-Jm?fn^fe}MGzj80yX78 ztowVP7P<%HBua2{?ggM@q|SA` z*RUNe6+HF5IkjJ3Yr|CsVDcjcOeW)m1y;vl-2P&mx9J`nj)-JRHabwFYvu`!!DJb{vciv6+jE?P=Szs&=w<44dM7T>lg9hskFx)@dC@hS zf@ywGHcGs#!-G%%L;V?N;P>N1c1%`{AMw!x%s(_UeS@lW{{nIB7nw>le6zr^L;(Nd zeNg{1B{9M-SR=QX^__Z}TG}rLsYWGua9@V>OpC;*>9g4xo8{rmjJbGp#T>fgQ9Y}W z#)q$>h2)=1B*$!>h>!2?WbTXdNs-boBqWLO#w{eG^Hb>CL-Tm*tOWgNz71cC?PA|@ zJHBZ#yQ%fiS~zh_oxGIc_I$-VaBA{@v{Zivz78`*#|>OQS^ErrFXCK*M;!?r3IL0v zm*C)WE>D%a3{Ezmg#98EVs=i&i+xd;V08)eI<2vL(hyA~Ct=^BHSnapoP?FwK!}(p zOqt6^A@e)1Y(*MY$9tkj7{xQu8}TDwRd87&9BMotVTy7ZBnp4Up}}o}5Q__So6UHv z6q#8kmoXhLMn9vsSG=arryXS$ES!YK{m*Fz#~eBnZ9_wbL72)(!ObuJ};hPxvGD^B3C)a~Sv>1uX) zM=`7C%5g}V0%2)BOC1i(#`_1pk}j82SnSX3D+>N_^X!(hnq=Wb)n>vC8}=E0DU$S{m<1wb6F58-rdSjs37|lEg|+p8OJ`0WbY2e zk?3<5VYA&kV!LKPS-2tv{Tg>e+{JX?2r1V#jfl;%uUr{21(DF|>r%|?D*PXaTR<8GN8y4xogMhcw;(Q|C^lu`+HP5(x`8pP4?>2$O- z?Pu+_JFuZ+GjP9SDO}uM0+JECKt;_M#UH=NppYbN9W#QJzhlwLLJRzuQ)rmofmz#U zK>enbeBSTf*f4%3Mo!{(-2dKC*T3Iz2aUow32ii}=%T6|pVj+XGZvXHfP}GM5TaxW zcOKkDgE<=f23-q&Smq$r>un|WmVv|?qDh1AB-s0MDh(VOAouKcVDbV(czks`ih_9{%v*?$8K49$aH+h z%2w=Pr^W7oBH>k}hnwrlmQIH>@7+|P^fb=@wh;E~iD7m}43@h|!rWuKaecQC)m6Gp zthrmg-1=fNr}Z3T;Ix>yzcm5Xm_77w{W*LrP{+0Esd#v12}#snQ@8K_0;#guB#3R zXD8H-7re|$B!Nk*;mwZo829T5T$uS9H4Kj8MCfY~G*kv4BxFqm4@cj6Kex*?+>b^Yv-ZKr- z-G>?e(K6iA$CBGFbMRPq2(>%+ia1p?lO<=y(0RvRGB(qIzr@!W79Ty&``K_9IOYJp z`W;PVZmOYfR0R6DPZzAcEY7dh9wjaPiv*gJrb2-26FTwKdAgFX55X~QRD(SLP23#t zH+LWGE|x@DN&^$fZ9AQ3K$1OXAL1nozbg1DO}=-cDknEE#Wc7=-bQ>4rRO0x0W z5?|cDQyTOwlc`KfIq8~^0H2?Kr^;+B_};$9ocng2WTh7nwS)z8FI45!72P?8d9^-d zu4W9bUZl(~UlvV+Tc-&gZkWJdkl=-jljMOnki;(Ed4^uu5RRRKNie#ugZWyPjkaCA zGs_ z*q&NO692W)7nc+T*Cdj-ooOwxc6Z>dx$uZ8$Uk6uqg+ttbUNpH-_1dsE6M!d30Rf7 zmfRDcFX(!l1<|>^aPe_DnXqCSe!~x#{A>Wa9@&%m|8~*8wdt_H_c7=?MbqBCWQdED z8|IeAa|q-F1~JZ(TQ=9y?1WezgTJ`*eK2?GLHHeH#3Hgs~&C8p0MtbJ?m)JeXh(;{~-;_2vk@ zr!WYa;ZgL2h6i}(nxI0RJa;afj8Fcphr-2GwCp%{3+W`_w)H;l&N)O~g1H%P^;S3| zhP zXkLR-zl3qART|#cP{9~aj$6}JL9-U7kbHGnzE*=Us$`kr3-vC9RSi%w&4J!@Gv;lK zLilyElkB~Aoh@9qh&ZSFk>z`An z{(VH4%YtP`9OD?>6H(`vG8x(L$8o^Q$g%n$Qucm~SMX?n<2~n~P_7oLoKPgs6I^i5 znaQwbI>o~ieCgzGKdC9XgXJ^KxsLEXYBS?E{_CGkZhPg?pcjGow$^~V;qAbLu{2g; zW)Y1Ljs(pwBJi19BDZ=DqaHj!*~%^Cdr%&#`ZW@-MsZlR_9R%HSxnA~Z^FeH4{2W5 zc0BS>iRlqF#!}(4RA&|gArZ!8!^Zt!>DElIRAl0V%0T!TbA^7pNQvNc9cXXOqMRX) zc7L9Ul2#0^{!OQi$s{FZQRZ zyFF0VHIl~rN#mu4{W!2|XI+GmD=*GK60Odz!=#a^T<0nc-}|-zGshg_HrHa~_qTNF z%PLxs>V`9menWgTkEs7KfESuS*`KQ&QFnM8sukq3A7$Q=%7A3N;ui?3i{kKiMI||O z$N~P$mc&Z~<~ZIth>Z06!zR(GxL-~klDD0s%@c~~t5?lj&OQNTDsr*0_Zx`pwxv!@ zlVN3;Ca&L5L2qo3g^#ZlG3==%`Yw4+;`;Z{BOOy7*c2LgTTN z)nmND%x*G%a2UHOL?NOXqnc5Vy)&Jh-|R?rn)+U-uPY-jh1Gub_d_^DN+f z#TwO~<+*9%GuTt8z#2Ot` z&w`k(BC{k{2bRc=2g#;940kyT`9b$^?f7C`b|f0gW&hA`{>NzgU3EAm^Z+Dtg#?j} z9@zOamc3ED4JMrHWOd5R*>ZNyXFzJDUabLIKsx#Ikuc5j%%3iD1By#Qym z)wrON>kBlUf*IqNGd{LTg4hyWSWqtkk80|z{VQy7)~^&OnDI)XeOc7wcxEXt4jO0*LB-td0cyB!Zvr$>5nc8%cfqQWWQIh4@VRJj?mS4KjpqYe+N9kJE$|uHV_9(6x+VN->+M?*@XLSQ5D85%cYH02XdtL6apk zAXDfjZ{31Q>f01SITjQ34|l@j{6)-xEmE{4@;*Jy?LGZfW9Z#urm$rBN}|VZ!>INa zD&pgWMUPc$FL%3xsAd9l`}JYeUz~&Sag}&Em7?Rz4RF~*1Q$qOXBNI(M`W$s1g`t! zsiegQj^~q(p{Z4n{z3?g&Af^9G$&9l_QB*8)#T4%H_)7th<5R!c&jBBw@uiO+J$mB z8vGgMQWIfQO&%5Nt0A-V37H?W5B!w6*kzBdQ+ZxEtZ4g0_jMQJzZ3fq^Yb~E6~U9ADm<0{`~yg&2~BUyIfF*OfY$r3c#S(&#lPP;T(R7{FvI~CKln+l&iT@{2SoV=J^eKHqL`p!@GiL3 z-N2@g2g$mibL{h;%hdEu1Z~Yrrzba-qcwFxy=_a;eWf#vDBDS`e&v&=OU7tyRuyxz zY!&z2CI!d1{+eq4e0cU}4m9nt#4F0pOtbYa()F5i_SJo44(v(8Xw!puVC5b5-V|4N-u+?XUKQ0v=4^U|I$bqBoR^+FfHcnxL#p4u`rxl&HM1{RWO z-nM9Q`WY;jl0zkNj`Q~Q9xlz1MdM%1I76$Cx8?UX2r12kbsKZw&R4FRmb4Bf8U|?G z-OmuSw~Xrsi$nhgDSGE>EB#y=PDb{$pg~AFvAvcC)$v!+B=;=ilCDisM}OcA%WvQm zCy7DEuc2@&=V>0X}cY4v*gNK{%j^j%>DdCm%0gx73#%>x;B%+1suyxIM zQvO91C)`cMD}hEFf9);82Q|LGRS9cZzmzr|j-s6+Z{c>cJwz|*0lr@kN&jyOt`p4z z@8NNR@FE6$BK+wjUmwQlA2NTJJ|{t`8X#YpOj{p)qQ~@-p}0X&;PEa4{ylTUm2aM5 zLdzbyvs6Y9exMrI%6635^BFo0gu$slBf`Xr6<$DEbANm9;Zz^ z-sh5|vsdDDRuVUf%m$IZ+mPj`iGG(tseZQ;_~a!(hn*ZhJvoeb>tqPNmAgd0e6zxT zeP)>EV8mB%P=RqX$6(AzhfWqhiY;qO>dq%$rU75>QX|(@jVvI zzq$bS=wUGohJ_({_X)2%MR zR~QF1$sc$^9>%n*EEKMvOh?|IlX&WDHM-Cn_~zSJX4@@2!H4a4$cINQ z7OTd&oV&@;>{^}VZZ5d=R@&luMAc=YL zLxBicTwn|m8tAq4v+&2!?@Zy*0s5is3q2&H1$W{34bX6)n7U^L&@?eG%xDOQHs=E{GI$xC7rqATrCWeMcMF+aI>yV? zN(5W^_uSuwAO2gGfV=uF;7PPHcKOc0m(~{e*6s(}k3Ce+c@+NC)=`mqb+*m^1Zd0( z;QYk3bq^)P_~Ik~LFMbmb*-NsN`*xb|$HM z514cI$@q^XL8y#2s4FhScegkXgHAqkM0__n@QBOjW*UL`x4F3b0@A;>x8PL36OO65 z9pX=j;5*d}dKbN*K5Pxlo1Vvhp8t^?{p3m_&vSkW;VaNGO^mpCN5RszTAH39i67?_ z(DB8`=@-uf@aWqn{9v7pdd1_I)fTFF>HH-AQI!c?7yT#@n?}wpJBWun7J%k9hUiCh zl9DQKY&bp#%6H`wE4}leabBD+n-D{k)`^1X;$)`y`E1(md;`5k)1V`GH>_Wf!Z~+( zi0*_{u<%$H-4~q$;d)c?{pT5QO-KVLc?A$v>(8{TZUZ>>CBeo)K#FRw$1;!`5gD+CWV zyW)H8Q#jjf5$XTXh!-qMam@4%i#@3y7Cif?Fyw;>%(DbTs1GE z{ULM~RkP_sm&oHAZ^+Tf{b+vs70+}y9p{b@q5-N-XmN2H6u}uhci#q#lJik%>O9KS zClQ;Z|EQ(DhTzn&J+6>;L8Id}RAILoW~qgPm-kd?e5M4OqKcVaPbQ(V5x47EaT5!Y z73jrUuGez5l~zojMK;~Zr?0mL2sX`H3`#pJF*E!p7L_(qmxT&!n6E3gcPs?5LYlTp zO@TNf3t~lDu=B`Vd>?fS4c<;7DfUsgwa|!eJ@g-2wFb9m6!|)ce2Q`wrI%yvY+4h zZZ8at29OM6N!0eVgH;Y3v%0GWpPD*?!JRE&mM|MXmigh+=7r$;dl#I~o+q&Fh=rPA z4e~2~vcTY48*^$?F>YR1hz@hh;r#KxC@&<5>gR<8v!85-miYP5x(uNvV;ZfJ^ux!V zJUB2V9CGG#;_BjF?t8oz-)x;rXI^q7t1=z1r&11<-nzux&ija2slqrhI0Dwb`^xPl zvhd0GY+|+~kbUP7ft5pfu%i17=2a=dRjoNBE$S;9XQ70S=PRJ;ryza%g3FJSr@U zB=62E;W73zP5WSqT6<%`NX8y^tdbTi+5ZektN~H`*MOp;r6hG<28#97q56fqy6XI8 zm}-)Mw^IJ$592m+MN9*P)OGo~!av!PZ)u?KV2y`tQ)t3iDSi{YAPY8Y;O!6BV5Ck2 zbEHI&IeC}L$~`6OL&s@OrYO!_d4)__-+{9R2I=dZQ>4?ciT>SRhgZE^n2Wqx{AI5I z&u1-x7>-?=v^0lMDOu!CCge)>9r7r;iZ|Bs4?f>mPWPVVu~8))D`}<<_dj_u-j3*i zO1D2m$mN>!yLi>|R=D`aK1>~b${Sm~5wo%r;lWA^RQ$CO z96QEi;x=IjyxRn~c3-5UR%dqxi9CP$K$j6QqD2-Au@T!-LOKE}MA4;gdaSX;>=>sF%Q@raA-88Q=mX65wGW*|dgPYg1 z@ITr}A8)%$<^O0C5$^pIw_pjk|K->QTHGA+;3`H;y@36<)am!yS-7*^gBi0lquc++ z;k5aeNrB@JVwTfMT|XF;`GIFSrm+sythOVBbD<25ONFKn(R4-YPW*c(j4H{!%tE3V*j@{TNedkX$u7a^jOH<>+(ZLmwWnm#x+m-@{= z%HQ@nABML(f$@bRRL-(Tb@NTszheQ7w%Gy;u%6DC7l?^7EUDMO$F#-eHvROZlG&`R zh9(d~in#nh>dHvkzB-z?zYqfd$0xwBz=b&E-=K#>5>ScT-x`=I!g?1Y*too$C?u3K z=ifBodN(Wb;Jh?GNvLPcv>sy19DUc}+=t-n@rADU2mAcU6;|Z3IuB9m5&5Kj296DZD8)14mURQIoAg{Bdjz z+5UAF$UGjUa?g+AMVFma&2Xxq-+V8u^3J83s*WM$WUN`h`7nP#!1jG{?<$xzyxHU)_~$ z!pzBum$3EdGloyKP&Vi688I?y zc8eZ=BZTpt17Me81;L9Y1p3m~A*-Q+C%yj|-O-*%>PnI@nHF<#l#TT z$b)ZGC0bT*LGAbb)S}%QpY^yw(~`SX;>%2!x+xNyN?N$xt_7AoW#P#Z3gcW0VY6F2 zEz!@W=EF^(I--K=x6*0O`OnlPa-879@(s*Q?z8q^(Rh4X^%~!-jDbm8BuQ13{_ORJKir)1{=EbvpXUZz=DsMQphErKexhUH8iu@j!Hx)X9l!J1 zc!>9o-7?J`=KI8>iE#{QZLWdb86jM5eVBe8zDQTi7sIzFYH<^n^Oe9b`c&v6+PH<2 zI*mKbZC0EgU+9B(8^UPiv}q`E`!3a!4JQ{pPoR0Jtib&t=ZH&F!?Gq>u!>p_gAH-S zAmu6ar;XB})Hv#T?*fW1`$X((6!_13Jh%?EFEdFy75!Su!0dP|{O44Smo?;J@THu< zdt?wM&o~01={h7_Is&6+{09loDoM`+z~%FUaOK4ccy7Oy%=5eg_gc*9g0020_{U#r zANGrNJI=9h#%uFK63BQifY=yqLA|j8-|!HZ1?%&sHx(<`<4Q$n zayl7ioi`+##h>s3A4{NG(>&;Nd&R0WKZS`G!ceFtj((l;g$G_iuy*rHu=f-GoSF+0GRx`q16R;w&SID(?}1I=gvxCk;~+tmXgjr1?LHrPx2YQ% zeTq=}@|OH&rEioQRkp8g&T&_aqGAdhV@&+>~o$>O4XzVWjEvC$5UJEQTs`fr?CJs z(PZNft~=Jd4Xj7G_jlhkV(~!=W730I6~7eBwE01%j8w4QU)wOna|sQ;_JYe|6f)A+ zZQ#VlAJqP*89QT}87uVW5h)@YX{N_1`e#)$oA$>GXREK|>mE-hn{54=b;X?!cbtb^ zYs1JnLypD&+!9YDo~Mg8B+<+2S+s7=VyZp)CCO|)LS`6!BU2JxaovDC%@A6NCqwtb z!8kM0I=B`g4|Tvci5M|mn?upizD)lt8w0h;HJAXmH*Pjn^{rNbS} zV%kfd=ae&wjs%@;q9N`_BCPq5PTn~r)5D!&tmbcJPJ zt+rrQoya`CxdD=2UxEYqnu2(ZR}hpNL-agYs*w1EikBP!v!n8Y?F}jTticzIT{ZZp z?`6WK(Rf;!+sEiMbwL~b#WBW@kX*+>G&0lR8!fT`rzaoSo*rS`zcCtAfB&QxU3sXz zE)hNLgF*Y@Z>D{@JS{vm6KuDL;>QJ=c>VVw)_Y?QNpmXXygthO_i$Pbo6#obZp|09+8Hf{|*a(jk53RLj%t6_4nbu;ES8{nru z{^Zd84rXJ<1>${RJgV^ifQ80Mjz`1wmwq)7&pERM=RArDcf`k>g6%Nsq|UGGTtb|0 zJcPGOhuF668<1^L&n#~1W!4)VBxP4PUb%q{|51<~^)8eXyf*ga|NX8n_#>_e)8sUX ztYZ!l<8m-J_gLV9V_bhSaumg$ox+qg=J2whi$wd}p*lZzu>;Ioa;APa9jW)jgsI8o zYf>VWI5q<_m0sbT`OEO*w&(ELGz8i!@>pG62DG`{_$SE>QheK;3I*2U%FvT2aZrq2 znfHwSweecVxe=pj8eVLt5(xI@duk3+Xo3*G!;64f*kL(l$nSS**$^bLiQPj?(B>+}_a zOka`}6aRyr!AjcHWRJWsA9x_V2Mdd0mJNq8gCl|tiel&fi%XQV?8ATqe8s_AIPx`^DyAo6OO_55Bt|jLhEb?=W)&J%-esFVhN8^_A?SG(gTc2G*qF`&cDR;7imMHuNwZ_T0vipw4k$zCoHKdCE+^Uo~c_70z$T;Mdb#@!^;-q8>W&Q ztM{WG_opzu1ri<67YE-(`HK8}_VLw-ncDt)U{@%20OE8G7m8 zTROQTmR&Ea$zSK7!0>vQiXKUG!si*Lp zSrYJ%l`@~s&w!AFz`h@w2Dgn_5_B*Hr%&GwGwXiW`RgX4^}bUWvE>eLhNC`s8duV{ zM)BaD`ixQD9F0#Wo`v5HR(Qj#m+q0R#|UN4nb>p|a&>MpnSIk>_x{>P>8h;cks3UVg>{XAHC zRux>T_rR@2Gk7q6fSe2V#4|DuaAipxG`xC5)QrU-blFz=+;9<*@R>~(24qtmBSX~x zDFwApJeYOvswlZ^JgUpBfR#4YOq=0&q8TwlqSL={IffE4UAKl~41A|H%Ws0(mk{>F zkydL}?IJd|AO#Nh%*TPJJBf6#0}i!@qixGxnEN&ug9W$Y%i3&eCwhTNv`EK~dei8( zilw-#;SMcUysP`ks~e;Q%jX{v+(hH+2);wlj%ET;}~tG4(Iu5nq#N)SM7Ol6y)xm#Z#r_2pPJ z%sYC}U5zBzN@Ce{Nf?F4v}~al3@1FHTTV~LuIx)Byy7SEwwyqnl4jBHAoIFprK@ON zH5sz4LSVhdA2LQcXL48ueHz;V(K;^ZI!hBPHpY{?Kh&|R+Lc}nH6UG0E7_48Z}MjO ze0st&9tK1rn6tbm6Y!S-X zIHS~!yUfBc8~Siw6-|kaMdkQfU|NM>!{%NXmoO7e1d9c{Cr>zsJVm8+3p5>^ixO*h z<1Y6Qh_wSez33A$Y`zC0k`Cmpf)tz>?Ii0mq;c?52|4gb6BYB`(ocb}$cn2ML5SH) z&&<^!xuLtzSN$~bR7!x%DufGyQgpf#jNMYfR4>LDCTKl|AfeH^=@@*Q+q*w zRv8H9e7-^Hq*~s^F}=FHkA!@EQclx#>KN}|H{s3DHzu~#Zgxn7U*UDs%XV>^{NoIqkX=iu9{&!p0605`OX;=To4 z@FeF3U1e26{r9Ajb+yq{b5RKXT%ZnG2WR5$jCpv()*a8)UZ?uOPw?co7+4@A&9CvB z&GEhs@zbPa_H|A==wSl3INxU`_NT$AfiM#KB9xSH|Bnt%L3-|OH1j=^k4c>$IiJ~6 zTCmQQHB1bD}$0k^J;qfVl=u zRQ!km=?bzY!xK^yWml+f{8>PW|fGBOhE3sYaeBg_4|=z)saoXdMT zP%{UVdGnX*UT7mx#vEI;FN6ksHKa?vup^Ozf%kcCxbto?2yfNoC($nEZtjnEO^jh#N>Yvg=TC)x4e{n*1?ASMw zM&A!7!#=qd8Vd;pR0tR&U`2Do@)Rxdnbd(1f4Xm(i|+t zy`jfPC($!5iKwzUhL>wEg?X!|vdw44fwyZK8Gq|HZ`DFSSTZb6=PO>rK9d9N3tV}Gg~@c7 zv}_65oi_!u1xK+&QW^yQ%CIr+A2CddWxr0iMB6tlqwA-r5Z?M5uvy_bHQVlv!h?z+ z=CK!(_8@h)w8IfcZ7?fM!A9eDlrv1leT6p|+s^xF#xVtCCL8mLbNCo))<%0PqUhqg zT2yn+RYLn1QX}6?G?cxt<$F9TE}RAhf6uck69$OHyF;vqd_67q4`EBL8(4=>w&Kyl82>Gj?X zkG}|nZbgpU_)0-A=58Zcp_9S*tL8%v=K#AFE5q0K?8Z+!&x6?8*Sz8Fdyw1m!inYW zkb7hs%$+qx_h2%d@QsCe@%?12whHF-+km=p0h#DkL$lBLqeS{~Ox|$<4<5VAZXftb z_PNziSE(r8+?Ol(C-%gngHA9w&iqMKkL+Ok(rn;=6rG17)!!S(t%NkpGBO(|MSTgM z^V~Geh_pmTqM@{erjd~?JDa3LrBd9_d2VG@N=g}NkV>LKNsIb@et*Ng_uO-y=ko@Ki(M!~y+IJnyzh<=k>h;XqQ>h|2H|6RRH->XZ( z=FV-PU+#l{mKoFVw0QEG{XsiVJ;Gl949+F64uXAo_+V8&`(wd#`g-YicJAUbDCzvi z@u&(!Ja&W%Xa1pb{%dJk(;hs!`Y@y(qWIx_Katy&KQj$uf z%bKb?!;P?Ti7;NYJ%dJmx)^XK1)qc);2cQ}72AZe2_kMHz!` zAoq5do=TyRvA1l-h+3F5+3n;3@9s-cNpm0O#l=|MV)%;GCMhxE zmd>Q|ur#=NG(hjA|G3X{AwHdc89oV%L%7mJ*m!me=m%&+-QEjyZ=?pd$I+q_CCX`} z)={ilXo+tpa5+4VQ;?3D03!$UP+&TV>?pnjip$r)F+U;5sGm;@R{X&^`ZsA&YZ^On z;}>ge^$;uPaQA05E3)JI2rI$7AZ|Z&$^4QHWJ?tH)(myRp|MQ1hJT!pb(P@ZM)31G z9{9_*lfXTbaM1E8-&VVxo_F7mTa8qK>S;rf#3LGfNCsV!=F!U^LowrfG3kmnf_L&8 zNU8~sp7}Tx_m=)8f{tkj*3A|ltbD->32bf+d zr{liGW0u%M8fmu$uiwssPA0&xH38JT^Ei7&4|>(kuJ3K-+Z* z&5mC{4nsLK<(tz&-xb8DK@_|q>d0HkLX!BW5}uWc;ZRf|=XKvj7U^-_2x$t;yqigQ z(C7hv88c;aZl*EbUY|&h&K|R>A1h!=<1zx%ZE^Te7QKIY3VX081Bg{Sn+a=iYU3jk zxhRxQAjinV>~5|*MhvICiJ)c!0vh=*9A`iK21l=E(C-Qw%&d3%Sb3DA55_lg@9dXU z+RFeh{kF$8F0^aVVp1aIp_3rKnI4fAxXxjfoall$lN zap`b0=bTWdd(AXp*-bTQB`>QcaCeALGnDE0^7Amhc|ESb_?31q;(FE`6rd?%Hr-Y8 zi}92?hox25arw0lcJJev=oB14t2#^I*r`4YHxl9Pn){9zmhdp@T{ih0GYyXK)#F)e zl%VCH8(bY5k01PZ5nJ0JXyy0g1u;dzx3Mo|blpwZF*^)3pIk;~msRxYO&MOp`9oy8 zbvpI`)Wh%aokmNZ$TIBm4`f^G5)!NuPW<(snJzGrge1o*Hhal++O?}6*U!smcRQcO zPK!8nJ{AjpgQ5HfzvJlFtWo--R)bt$ph1hBt*EfCQ~)ZZW7bthwWgF1cCiCpk85DV(s` zfzl3g&_1+*mOS+#4I(8(@<}z*mA(VlEO4jCOJ)<@4XLzWDie3VdW-UkQ&7THkEA~@ zz_RbExL+rPnc`>$c6H(OI>+q~Uhn4|{C0R$SP5)}-0_IKKKiCyq8r3CaO-vzd?)kP zY{i>eqT=|2^a#b!ppF1kie3*phlC+iyAfA?O~&fkUEn0(?m!vlBxc72B+{wK1p2|V zsO`v}ox~n`lt3OQ-XhuERah-A&2x#qNCsOs!=k=Rbo`#@jQlAhP!T@>%jVgl`UwxP z<=9KBuY}A~Uqo!Z#z^-1NAT+BCwkKOB1*j5jVXtx;G#uE5csnINmd#gy+)j5ZzuRH zLW{&MTmk{#7mx_~EzoN}MQ}>f6tk-2Fp+0W*VahFu^~xz!=ZGhzH|lnyX^w2#*OeN zYBmaC5&d>Egk5%EGbI1wvEmPcaqhHccr>5>8dYdEpg{C`5kG~PD;r?^#MQ3AC zqYy4X+0KrP+JZvMUpDdHMC@8Hh0YXp#>`0#}-BG~iPR$0faPz_}tP8OtU)lJhQ^Onv{Cc4*l$A_w;3 zn{FrS8(&FWa}psk(Uzo)U&ZzANC>vKdV`;$Fj10pWtNMW;)t%MlOXy&tz1I{K>v3ApDQ1~~FX6)JxwUfJOn)i56 zA6Nz#>_X{<(|S<6aV|dc$s$R)esuU%G)&r{Mbc9$iQvRZ7>qN4-ux$^vpAV*$~jPU zT0w-)_nAprEW(C^!l>&aNB}({5Dg@d$IV z>pTokKM4x?EY+-wBzYBdqoN915yeudl^HkE3wGY&(G18*+%(Pct_b;Q6Hg;PQs?g0M|z zk$=aGbBrp1dXf=OgF2AEzaP@o$D--pV>2-3<$in|pT{wiHZbqaJTRTB3FL+`;a|T* zWn5>V)t_Dr6!U-%eO-3#savq*b{#!D+Cg<5{v-!un%J+OEWx?3 zjXv-zgvXeOX-{MLC%&{08^2=6f=6wr*1;EObW4sA*C~gOkrm{gBsVJ!Hzx~XvZ$w8CiyLOh1ShdBuNKU zut>iUQ;j0XyWl2Fv6#s_v1TUqP4mTf3ytB6b21g#Crg;iOL6?68X{7168G%xC+_h- zsiC<&%4>1m1zh&4L327iNB;wUgAm#+jOLF&>qri765=UMEdt5HYy2}npm}){o~)8* zcFoA=GLrjX^23evZPR0z`#B6VS4Thxci-AU%)!q!9(yO6n`*3b;CZI*f;)~`n7*0E z&Bip~@u?c98cifmE55M?_V#c{ZIJ3ECZoe+GuY$y3iD>#GV8B$-l{PP959^&)tXz# z>Z`qQ-G4V%)pVD&7#Bcqt_#O2q9O3tm!PaLilQy1~n_03I|6gfKjSBY<)UP z=MhzS(-4fG@>Y?%wml?gN-;Lhb7zg-O(pTF!PIZ@AT#ZjBB>gPzTpHr zRGKxF2APb}^Wn45HTFCh|Gq_gwa>DPJhI4<<{9v#`6Ve^?SbrttK_A0H_25WB|A3E zf|X${>|LuiA_(%Q&3Yl!>_{ZKMYT|a4H4`~u?+kkH9}L=Cy>!szGR1Y0eSr{kv5)x z!WwLKfr#|8X5YT;C8B?KLR7?3(36nl?J*lM`x-dTAI4o7~TDYh-6?F}ZiJTlaL%qqlBqwuOm#<_kx~Lod!;)cx0TR7N(c~AeCdc=rRPZi8kuMm&M<>>Klga(9xSDJf z@C_;;xN{sj-Ty@FYi4ns=SZi!zoVV$GGN<#f<1dZkGAA{Vk&pWNNKM^^@@G;CdUR( zDBncf+{EZjMIG#1dz0*OiRGVOX-~S>7L&@YJfiou5Z23PpuXiTMpbK={VhC?YUakn z-h#(eH+lgC?c7G&8|Q$(gFYT>UysVScEWABlek0s)sEn17&t?C8Y9k^qg6Odx3CwyEhBJOl;GHsTq&K~y z=vTS@Bm~TWh&M9VR-FKEwIYl?ybKm@k;Wj6XuRp-QuTJvQg~)00!QQ`afXJWAV6Lh zz24_CNA&&3KI;*fbW{>jRwWSr%h!AZ$=R$(;d0dT*g*!9G#HnGD|q$gHahm9nQS?_ z1Q&;=;fKRHFo8J(9V+ACPe>>Pm|q5wuPaGos|3&5bO#!r%qF!K3Gg~W501~D$9jLi zMRVKu5Vvh6(_?2w4}J;5=+jE93HyVM(RM|PXO-+jd3kvE=ov9QEDqlLACsMxQm9rU ziL<%R&yY$JP<;`__3t^7zfs;~-F-Q@pEMnR1Wtv8d)Ygkv zX%E7z>{obKydC=67GrFWxFG$tq+ros6_|Np0`OhSG1JH&7FtPT0COLoMu`yn%}Qum zwgc#RIbPD{blfeF1GV3)A>@E37V5MyNn`g}ye|tOb*t#tFX7|gzLAp0C$X|f zoX9R%LTCLE$L+OuS%v+RFpT*^txX9I#+vwLZZ~{7 zy@V(U74eTN6%)_bwdl;{sxQBb0Ote4__O>R7`AYCk>iyp$v=SyGj?-x?huR_n1o|= zK7BZ?hxI=xOE0~APM`C==-2Rm{-MUFw55KCiQHmU9d>;xHneCF*{fvKXYL#=m1OhHWpT?cTeA4L1eMu20hTJZ5&njG^zn+96l1mU=E6`mVV5kMp3z3v zJn_b`mTKnp-d`O5c8RQvtRu$x(_vq$A(PYbgwEOgfwBG|Ow~{Mp#~!$Q(s(Xzgbz~ zVg7C+D;7qgZ0ccELma=UXbyf@FiPHTYo#IlfAql0?QGi1DO5@?mo%kE!IbsNWYwh> zHnLWTiuo(S2fqZO8upX;t#g7_?oQ~by$|j`;`S5#`HYmW2{~}!3f>=);)&jN#nK~Z z=(pO1RJkLD-b^dRY#>DO*GfjI)rCL(M;ylK9RRN%hM48E6YVVy6DiZPwEtxx)U_(2 zn7Jvs1Y~fY{ye(s>s`)c7KwY^g$d={DK=KcsJOzD?%+7)Ya+A3Gu{ZqqG}kax?wyu zX2tklT?gOd3b>x;B1lUM!4E^@c{4VY&{<|VV1H(aOg5TFw)W&vUr9^&;E;^7ei+i< zD?T&Xk5b6;v3>BZQ&jMH`2t8;9!k8k+G%YhkBa^+LbJD4;9j){KfVb>qLqtyM1t}{ z&U4?jMk1xKA0-!9Qdw>ulDWR0mFu|HCP z&Il1HUXJywh-3*)+uNNALwUU}>Ki znPGC5IlDg|Jp(RMBAkYDmbv6#hCi)-HwhK&OV~ZK0xB+|z{HLP)9o6AsNKC1ZhCjK zn|o{FUsEfqGKHYbZD%-VEh0GZ-&7KO=N9T6t0QYgV#wnvSzg(gFixm;V%_qVfX;+6 zG|!R1uRkJ)kVGQsd2s=K{B$sU`$t-DVnT)UXW>R}j^MFAj{GQe1S$AHs~lv2E{Fwv z&hMC^;z@faBw*#{{wfjX$B$8kuG;oTUbF}QFUlHYol{Ba$v^c zwfJzwJdhZV%vS%S`1MaB^?4tHThGNn|DA6b>gYudOx_I-BWpt^-@I zMxcwaJa}*FAnR3E;qlxDeiYWqNUBJ3h7+rO#UyQ&9X!|KsjM!-@OoU*;~JZHuQvrXSh+=PQUC$6}Rjw}ikG z76Si_P|~+J7^fYop^6Ktseb-#D7hLzdYZYNT^2qpcBZqp%(#w4qe#$R^^b}>Ys zBro<{XU;fS@P7X?N7dD)*uIQo8Vnv`_p8-#UPTek7|z4K(oIBNm1BVX17RB@QWZRX zJgMw2q=sL{!mp_G_?io-l9!CuRSRL+`4xeM%o?E`ZguE>WA< zU*ymtd6+(--ppV`nEcDXLj(7WFz++dVf8r;_H4T?X+IcEKZky!3hTA7;qZE}Ie7y- z*^g-a>NVZ>SqCx`rqf~DI-EPY1Lwp|Mn&TrTn1T&a|!(-yCv+9a(9qtA~keUKs^n4 z(*&Mk(PZC$OX(!vuk78VIJ`3dF_~`kj3$`8BdQ#`{OQG6*wfWP`tMw&RWBTI!lPJ_ z)=#23+vDK1hXM}wDC3J+MfgA@3Z9&aA}Io8JUrD4e)!#|(LLeZoM0whTb;*sSU7;W zcOVrTu4RAKFTm^z4phjZgdB*;r)U0tC2Za;vsB9lQhOnqUKP@!=hk@Or%@A(s|z7t zx)*?ZuMp;oi$m=!1zyd;5*l0jf#g~kgYQ`d3~!1j5i9bTdhbni=<^pQC-w;W^*|DY zcS>U8jN{<4?hN@nX+P>NJW2lBr9>V?)stuEo$w6j9hkeMio{E3-~w*OuN`}d7%b$N z#KA0T88;c8sOn&$>SHF?!wJK<*_%|cBaJT$M))F0=lncFt!tfue@+A?$I7Uaq`F|U z)IU0KpTRr1YM}bifXta{LVZJ~gLz{!Id0Yr$AvgQ{_AYI_K6X>)-XW2T|;4j&I7l~ zLGrKb31NrkgR^5S6Z~EU-EDg4S7mu({v?_6vI?xI~`$;3Od6{}%ScRt6kEol- zd~{fWjMz>o9CR7atcZES22P&AW@;`WEynj~Ytsz0$xngh$?1%cWH>bn(I(9|-_jp{ zHsko2LU@_;<87>wLH>k#`oZ=-gr0Sxs~XQyQ&T^B!Qw1^_T(A8H_@5x4Vp^b^JIwV zw;j~kvjzKmaxmBX6>A}?2wu?%oHNQF+cxFUk?0%}Uw?uc+kW7@5hJkSXav)cRM`2Yo@&3XV$S3g(WrUlT&7M0b|njg{p+K2>EBrDEcA??6eNLf4CQ*o^}uML z4gOUHW0S>9wA1Hdv;^nT?&11=ZpvYA?RglwB8oGY)?=yZM9fiWBSu3_%pd8EXc=n4 zJLX!6!lAOD?rlb9{o%T_G|I{8v!~GObp#P{cm&%TnwYw`?jSsnhu6ByN$ucrydq}= zC#+2ANf%og5m`hx8M>fel>Ok^z1m3`FG<%R%2e7J@_b(ec%J_>Td9eY$ z>~=t{MH`8*`UewYbBAeYU?$LZ| zJ^wvzI%)|2*4g4^8VX-(Re+;HusG{Gv$$&^yU%NYtcet0itr|ysToG6D|f=%eZ!Q* zH$aZL6zyek>tld}%!B^o4%pSWNR+D>5*a zO(JU|%?{iTfnzVmGhMRBsc4lre7v$4bF3W5Y=i04eD5F1iYJg&TGec{u0A)r|I7Yu zoI)0Q-{d;)gdpg|Te@TBLgMnUnz`_{k2LM^h8?*RvGcYI$f(&t@L(6MK5m2eQs2?D z4}vz{@;K!aC}R#Y!QFbC^M!qF6HX zryRNZp8{5T#W9fq0l4aJ4$9e{A|4s>C^oy8Xm2@4>FWz*KoCuKMJY2|zB`gU`w%J+ z(#L$~cce;}rD6&~;J!ZrAD_KL|L+5^uPJAfbyVRw?;KrxY$e{7kD(VIpCNR?G!#=f zh`M78UfO?+5t)01R%EWis>QdkMs7XxJ648D`xxT5gFdM9B$a;2I|sq&iTtlNBztQc z{iUIeZL&Oke%p?{!tKS|j@3ZnmW9lgBR^>CgBr7|qm$_LECa?f{TRJ%Hy7;ooM1Og z{iF(qHxc33%gmvbhmlBeZ~eG*`r*zH>-MezYoDEjPuA^Jtb^;&_IpB`9=xNge@Vgp z6b0fdQVv3cX{dTE61;wLT^c+yf*$;8&k`;NdmsWYZF)}}3?;Gk(PSiv(HOdvU_|s5 zS{AmB%DJq9Bz+rlZC5=_S$~!`4`1aQ_%_h27mDbiBncP4Y$MM;^)e|A#we|JjkTC% zLH5Zkqa6!Z;0a?N6guw7)(zw`J5*m$;P`0W+4F#39gH;zFNoqjQK;l{&vE%Bq(0*) zeu8mOF&07Ri+f-um+`Ot-~bzYHi7grai*p&8s__Rvv=>UW-__TSb0qg{ zSZEz7tr_N9)pPq-j|33To=f&kI!*7{O`)5%T|(XwZC>_^Cf0Q8LBcsZs3*rve4jlP z7yGKf=+ZIzhukNg`F!Hl{}K9Ko>tHAG6YAPQ}}#aD(CBXf#+hy>F%9&7_FKQop$4S z_F)+~(QzrE$yc#U%#NmTKHgPTlLe|;hq3!~Gc38<3I&Gx?1vq$j5L?=wTX+t?T43x z=WHKTj&8$!yOeoPA4TAKs5J8~>!c?G&%?9ZN60|_XPP<52=pk&**T6-zuqX^*~9tW zXV}4OS9f=pnX|3$Z+m*T^nH#Svj57U7L+NSBKGr zrMEEaq(hgr^H-~`K@bG|#E+n2*2NJ_xY)!Nwcs)y8be$P+IvGm@$6tp;z0bx=_ zQ1MnB1|p0hr@;Wmj!yus?e~e3W+^k!qR7*Ho{v+X2n&KzOQE_d0=E4aA|f}uacbB& zob_t~F5>nK3o2xw=dzq>Y}H95-Cp?q=qze{47mK^eRSCvih65pFj>f$%k24);rCM^ zvQ>u-SZNBo&dtJvo$*w8(n2zwW9^jP9dW15Oq{SV4P!I7w_U_*h}Vt++3#l5``!hd z+Pn)iBxM9KrY7v_1Q)y{d=cxz#(@RryX;)`1n<+EOqS09xL|ULjFXznh<|TD-$^XF z+K@nB_LP&BiWYA6nhmFh0)Ne_w z?R`U#A_b%?EE;T`mC312Eh_SPEqp)Lfs#j0p`&jyzlNI^1xsd;1M`ZEBVE^$tE(^5 zW$gmu@%tZnzIr?=M@YkgAu+l-DTUdul}F8u?QwLC8|MprLy|Qt5gOl9ws(RR zrr!x8(#fyj#6YfD?Yq^mO8XMMd~r9mKV3k38%k-{s|So1lu)kK1eESulc+p9l--s{ ze&z5;Qo}r0?;Vd%Or$u@P!+apGluN338Y}oWN=KQ#MfUG_E~MGT1E2g>5M|Ua_e{6 z`S~tP$ccp8_uMe|NEmckoyBQP5$PGx!+@F}q|T$4EK7UJ^qZyflSB(>_Lw3zI8VTz zzZ}qn^KZ|cc>}flM@fM6CKBL$kX)QPleQ>i}ziF&QK10SSO@VET zHh}EybM$I}D8DYW1T;geLG936B5&YJZ*1wo;7y$n>hqXhwUz^YEDzcVJ&oRnspS)qsl1w@!Xq0-bZD*=E=6TGEV`i5f1Nnq8x=s*GKE0CU z@|3)G*Wxu<>y`_2n$l*9`-3|6!uEphB9gWbtiTj6bXztW_oP6K`y&)ye;~f$s^?HG5 zHj)IXh5KN=j1?^PG{g6@*(7#|`wo;}qT!dmFcWRHab~hEW~Qd#mX~{R8CKEAKTjAp zCkDSd$fHizHX4HZ^xt_MxH0;djJ3MJ%_I-dbK8wDo>B*?`?x4n9BN#JndFdWuuZ)| zzY8D72u&BNQzi$ieXkQ~|Md_)>l!}4|CL^ug5WwV1wOx(@tXfl z;9h)r;4T%bQoxadMfB14nQZ1|BRcXh9qT@b!TPcbq@3%{xp`2se;ZnIGNT9M_yaQ45Ln(w?|UY-o||%&GjI9u7DgB%4S8J&SImCIKFx5 zj$R{6F|JV`DMmjtS)fMyUH05#hr{*(~+5e7K{1`)* zty;LNpN;6hH|OXVe_37$jZ9MZW+#@F4s14J8dPnvtPifyb}{> zUo~Cy#3B@{yk0U}q9 z5A4e*ovx0rrW(R!`C>ZzWEt%~R)F~{pR=M4k*WW7k{J>K%*|)p(eY>zwU(BkZ$2o4$8a<$>kOmjA(NSc>6^IUcO`u>4T=AD zaWv2}gl#IXF#5o4Vjx!oYd77)D)%@d`1h8~Q%HuKzvjduUQE;ltU8!Ck_`mfSUoHyC3G>AyoZ6>ds=fi|a`mEGcGjz3_ z3|kgwVOZB4j)B`saQl5T+vF#t89X+jlAJs3=n+`VAtTd9ZVe6mSJ*eyKj@Q>A6S;u~rwIt^* zf1{l?kEqPCuOMhj#FKBt`O7+I(9M2* z2byA~Q3`6j(PURGPXMvnPsG_*oH$loNB`B2_-_TFpuDu4{dn7itnewITe5x029F-- z_a7kz=c1Xc%voSH{v>*uXHn~ftAtlFAGiK!qEEQdf4kTa<&P_dUFDT@s4bm(HQVC9 zbqi7B+yue;c12hb9Rl@B)3Mnz0mIX+VR-c#8u%)cHdMKT-1BytAhs7|bjP9RCSkU~ z)sDK3)u5$UpxLG2eWc~o2N<;|X3x|%;1WS3apx^1-EG-Sorg0H*a2;rJP+Ue&V%5s zC(NXE=Hqg)2PAVA=gBUYr}z1m1tNLN#>V4CI%UejqHNP|6pBZ0rMlH zo1K*#fzEsWado$!Xluw>e#)L(baQe6`C&Z=V^9W^TKbuuyv19tK{E2=@C*@}^78=`L)Tuh#FmN>Qr|uU;wtWiY4<83NwsNx{Iq`w2`g$DnzMH7>_DufW`cU z*!!}Oekz~DY6Tx4{pkt#=*j=xtbjEi`27BidUztXnQU8df{nB&Bp-1F?V0?5EYhi9 zZe5au$D1pNb8HO!sa{5YHz8T+6AbwSh47+M5#Bk)q)2x>bGnq&%gKe+*atKCs^ z(Q&?)_H_7{YJ(1*-dz1GzHfm)w9RXrOtm3GHs>z*h=|-wCPtWZuy)6 z&rGc0*Rx+t?y6wM`9wRVv7!)C7()y^kd_F^U}t+3RZL>oFWYm-R)Z|sx@tcN&k`XY z7u~0KMC@Qv&P(!i%@Z;O_At&9`LL7Y;(wn?qnq}spg-qB{ba#;sl12DoOneD{Jj|L z3kD#>`w+R}osR5|CuEK9BJ5lHg}l`oB12P7f@{NU$oPE{Ur3!GC0@$-X!8wRR@qHo z=x5SOo29&UAx`+{uCIyn<*PWUW(&O0<8tj6c41k6ICw1cg~Crex!RY12cJG4@yAQy-tioZ=AbvI~=aM3eUNiwpiP$^c2nJM_&#E&SOz7e$S~ z6PFGK?k3vMO;fDslh7R8bKVHX+Gm5D`Y8y^yiFgwuRx~{Ntmg-)^tsQn!uhkqT&8m z*q(I;F9koq6}vu?v$aRS=hq36^dyvgd~=UH{JDi5AG1N7PXyJ{6$KwY`_kVXI&hN9 z^PT&sgO99LC|^?%RF8397D%M6PO)%T#v0!9<>AHwaabi>M4sv|LCxQRFmX<<;Fsb= z-ZVoQo~i$K%ry9qw`$%#a!gg6=U4a1^zE%-aCCB>X zB47L?z6RgvB+?bdPe?rHo2&U1K_5I9;_0wSu%e#x_p|#nV=%HY9$R)tvrRQ$n9=aNpkkE| zb9-m;cK^Hvqe<;Fxw?{F7C94)f=r>(Ii31AjnQ|_92S4j7B_9#1jl7^X?V~$!8tb> zv$NQ7v#p+1#DXy*B_FoFba{HUyqkZ&c`4~U%KnK}yL`d*UZo1&*jye+1Da-R% zl1uBW{?Vd(f?MydfFElk@Ncgp_CMk>mD}xkWe-2%$)|6qY3n5FRxC$%`BTi%Yhpc{ za&Tg)CNtQm$gzE^$&7X}>b73&Qv3U=`;+Z2H(qOp|2AYw zYm*u3Tn|a+e`XU}c9ZuC;kfC$1hrk03+q#^uyXc?uuJhTWUji8mU4wyQ*{c2P=?#D zFJq4=DS^qtU(`+`g=CA}pEKfA3QVQP%(j8?=VY|A5WvVt9$LMr zLdA7Q@Wo?AcK^r}-kmyeT6@b3-Nv6FLkD(~{axoxoqB?*F9gKkohOIbFE(pohrJR$ zoOca(XUDKg!wgjY^d+y1PBPgCq~KXlJ6Ta7$@N#a5=Xl#c3+$eG?X|(sjxlNR9s}v zZ&bn3xC0=X{F2=G^%#1i&%=cad62Qj5R}F@6T?^ucyshJb?q=D7qiD4$2qv=P;I_pCZWm>;-^gWlm-h)8R5L;~ z?s~u*ePfdJrkvPwZW>jgHJFf`OY25{(WOQXH2#h{JIys4Od_UIA@z-L%X|WcHubQ- zT?x$|odHDIk#3)OhR7BiMVq1d`1PS8d;FLKyq%zh$F{Vf-t&U$2gXKZzo;q7ochT; zl8}WNDyz5-#8y^(hZWY;C9!YUC6K4yrm(#&g#-o*vup26WKKvQA{{oayj@ikb0tpU zdLI?4tK49A$0Y`F-8JwD$YU!aLNRs{OE)OI0JysoPO3P9*=7cF{-y)XegL(1Me)!h zO7`yGfwTX+2m>D^u-2y!v;MV{=ifhp_%sXnWY|o1wJGzS9oFTEa=YZ&_nK))WE_0z z*-0}0mXX-pZ!FwZWS?o?h83T?$@7Rp%;I>iIVXA2jpK8IoIPDTTNLzUmaXNb2(Y?lV!K86~YUh zWw7M%6i`bHC2t!D1P)(>fXxY{*!vWgJv{(sdX=E05)G64im>xvG0Y2SLrd98SkWSj zw^bR&c4QEf(?dz~+i`;AB#uSRn97s;y&l#Jcd(h8?-F%#j4B+N$(%9?rEj19$1ywV zgiGKO%6u$6B1M*aOx>w@7BkAg+4(mJKm<$J^au zFttPjt?eSvLA{t*elf+RLZXYiedRBeW;(bn9E>!jpKOIQ zLrbWRbTnJuE)J6toT%Zm5@Pu}5oaf?CDL5(U)#6_&1+=M_SRRx$xWfKM$ZX8)USB(eAp8*P$KU##1Y7cCPg&N868((;I{Ngf`PpMZV5YI=KE1!ay{5~a6i z>E^a4RO?#=+Ql@|s|wM0zgP>ZZq6qUT{#Bz-$KkfPUs#nV`h(2H{WlUIu3Qu#R*@9 zcpEJ__f&Q_S?KzR>AP4?#|t~+n~~4ti`;qY>OT>J>x(g%$itqdR2qI+8;gx@Fv?Ni z=n_qOEp+~@4k*s* zg~dDjNNCYM_^~nq2UYUnsq|;o=Hpu`yWD`?Kg|fuPtJuCep^6B!Hpi6ECq?{3{m*x ze{?iO5|p`J-`DgItS(N*+q;%gmv^o>e|}$e>kCPk(=it&c$~*sF-rJB@d4elkGu0f z-$5t!j)CA)0(Sqb!O0PJc*tWJtlE}k=BIibyCz>mT{?$ndD(;p^0@rET_p@{jwkgS zN9aDsQu@`+it7{NvO_e6A2U%2`v$k-!L2$_&vG99GKADpY4~2K3RQu{DBt{&_GV6n zf|Q4ZDKOxjKlq7Gb~49-?$dOm-fk4So=M!(r_#{07CK|p0&i7tnG>sPI74QPomlsl z^QQh`&s2%Crpq1a@s<@hqk-FJHJ<>({dd`g7Ky}H@fAJyG>-^0_hQxCL9@diM#x+3 zMh|^kPWMSgfjQ-~wR^rw;R0*F87i1IJ(i1kUr;;CdsL8-zpJV7EQAQKjIfCQiW3)`c5UmBWqf=~@HSL1CU?@fzrSAVqXfpQL+;EnGa@OeLT1Lv{0Dn0M1gAawaDvxSV% z{liybqLCs#UvUt(N;DGhJ+{;$K@v|+zsm3~C*y8yjuRBUh0Bi2#`&KupkRIw_8C9N zGxtuD_y|i(Tflin?o^Y53Ui6Y!Uj?-KM!i&v5`Ht}c#|(T%}!=k zF_9@dN&WX+6rF2A3@fE^xz9peQ7$Ezw+?8@U_0F19*0X>ojL#ZQVg4PjVSW0FioHU zpJ&yuLQA%jmQB)7DzO*ri-Wk{=H(>O{TF*AppHhhTH&EB=ix}^Ch(oPm+-Rg6Thl_ z=$ku_wAu9G1kFWsP6p?u;C7bh4!e?At;_h#T$t(&-6V6$%|STg2Gbn46m`BlhKMy> zkLZ;;lr706Py0RaVn`}=p1g)sNTovGpA?jHSP1TUEAT_@8}`t9RZTR^)NH!6v=o#9>T3ks%Nys z)5Y)gaARi`$=!DvK1lB%ugud(skJURyCjm$Hao%e-V-9UJ)9f=a-HlOfv)2isJ|L* zxX^ik#s`+6-4;72c{`rWTB${DRQ->k^N!1@4dZw_X-_IiduWLExvz(8NfA*hq0o|* ztk7OsN_(lKP$>#^?&~QcWR?^~ydg5PQ^tG#>d!uXo~Lu}`?`L=@An)DoSMk=H~Y|i z#qzL)V@~icq|rJjyf)O)?eC6btIApMdU27kTCbQ0 z{Q`)QmBiHUeY7p5j`6d0EP;KQQCJk}se^Y3Xp6 zOyCJ!_)KQ+$Y#t>P2wBL9l`L9xtJyE0>{^OqR`j|d^9dkyN|DB$FrK?%(n){Vq+pr z&CIda{~g2Bc*dfFkqD}Ck@&D{|54w6^`tzjmvg%cL37?+j7XG%8KGtv$}#UQ9vWnN zz5dWo4ZiqBDi|NEyhpEUx{@1z*MXjNBzl&#((wEksA@jL?bDW1*@z@uvwA6%?Qn-% z4;CKpOFLl|Iw}}L2NK_fj5Ks_{uyA%q&|`C0GYk^VC6( z>t+gUc|hEsHW9-E>%pf?k2iCT5U7f1q0P@69FF`!KFo2%h9`YwEyFQ9<;=J{>PL{2hLUE$qOsVr`=c4P@$(;y)F%|d7h=CTyOH7dowLDiYEq-at ztIHvj|A#&H^D7>%I|4#AM(m;C@6>eeBz$>v36w-zqkCjFj3}O9c5JT4R=-E|?D`}e z^R0lJyA}DH6}f(?(`5dN_ugQ0SQ~$AP$A!x-7vdp7BbxXkC`3_5tHUIA6MAHMDDp; zmEs72!_pY*c!XqbP~|Tk{7V(`*JJ0W3sO}DmUp47y%`bXY zAq@s=zEj~9lDL{Jhrfv$Aiu{N)H-*O-`qXn)us8=bc!7I3vlmf?Q59uCd~HoCd;o>ds*>4PiT14&;naGNAC-pTEc>i06T!+`-Zd4>-!`;fI& zBkX4`Yn}LJB1%>3fV&NsvsC5sZa28zZ&eXii`C)zVjtM>q?O&a?F(H@qp4X#8)SWm zggN{EqF?i3zU3)LRMRW~;RC^Z{v|bgh2x8;()%J1S@?@qTs}%GMU5b|ssW8tS787f zM;oT3k_3^z^yw!lO#R6D9v9h@MPl>Fq0x!t=)yiaV6*|U_SV5?OJ}H-Fhu_D4cPp$ zmR4{bA{S5}1 z??ATX4EkqMJJo;LOG7;$u+Lt_pm)Jt8WomLZZ5S%w;2ks(|;b{MPM?Woofw253b{H z-E=VZJ3$ANbXl#ZLC`Tj1>AhrLclK%e3UgCo6MJyw^@-G9rMRr17B+*Fh>t0PRa-Bvva6=;R=xA6$a%Yf52iv;}>3vWu*nQb)!owBx<@ z3iAGR2==6OQ{RZ|=Jv24UT@0u&0Z8+jjtxxvuB7hx1@MoIua<_t23XMgRTu z!GN20&}D%WUH6v-wyqf8xbGx|?q<9q3l)+dY`}!??V*zPZA`mQC;89p6We3=?Gs&WPfu8^8V3S6a3s4U*jrKtFGk^1T~~RObb{K-Zk-bK8_n&&{J< z)6c=b`=Y2M`5&DQuc*=0T})l>eXPr#Mr^&8&|LLkQm?Ln71tf1NY4tKeb1BMmj&_Y zf~O=a8BlZ0Lb70?D4F|P7lVRDa7!9@pD^);xl6RkHj@n)J=n@-y@`b$vr|mmm4#^P zEP@So)o`8Bq<^v=vaeG_$up*&#m+?L{hs#E4#K5!GlnrTg5| z$-Q^2gxg=i@z^%n`t=?tZ55)Yu$TJ&6oJ;}R8)Pu8qDNwW6^(Sur@XhnanmcIb4tR z(=$Nx;#|aj1ODB}Okmf> zHt^{Rb!pPxEe^*oW)a8j@?cSrPKv6Rpg*_w`n2#qt*=Rd{L(aBq4lOY^Y&Vd_GHN` zId|m$I1hSTeTlE232#ZN3H$866Y#iG-k8o7I;nCKZZ)-pJpIowwB|8A+^S5>Z_5+0 z&nk52M;-MkTu%S;rqK8ILr{EcF~%%Tviq=TBJCJyge`Ug^k|p}F&K#>>b2K6hR!4M z?`j<}7u^jTgx_)AwlYv!wS}(dxcVP#V=-fOJL=us1I}lRc(1)(u+QcyqrPn=tv>e& zdLHL9)sJ-fn{>F{;U^KS?ec^2_IR}4;t63#&k>(|BT{+s8TJ%Z5sz>yQW1LsL;@zF z=Ci3d!&(;}8B4-uKVMXJ<>B)wT3{#F4tdjbz~-Vllx_+Eo){l(y^D}FIssjU(J)6l zkRCst1HKI}sCt(e&wWM?@%WQR+XB^zx8Ym+FC6barDrqMsE&oQNf~(CEeY}iPot3e zB{t0A73=y+5{_=&1;XDZa2}0)kUJud2FK#*`xD2g!|DWXr+yS}?k!}^_SG{VMUw3} zUm&a)oJ-q=&eB_7T&U}#8Fi}NNrDyWWAGjCBfF&psV zIvR!}M&v1MMuz)d9=vmw8l)}2up@$`WB+Fyi+u%Ot0Z|ljVa6%kR&d5%5mE}AAI~% z89Rl%Nuq5o#}DTiQwPFPw$L#5CmL5g0?E}=(G&cvRy1&}aT0;k`X zK%GG@f7km0$$UptX*A+EC#&(2Dd)7a)W@o4BIIj)D>SZ>qbc4Fe7_|bG})|$%bNF) zi~vz8UsjBDWs`ZYKjmOY>?Z2Ia~3AX`cv-}55PKDgg@8eIMea37RTcBam;ffdMKCU z+b7GZ+zl%{qu+uTy)#MCrAn%_qlH%UbxD-gWqW7nwl!T60(Tw7@T;#gcAl<4h1gr< z%l?hfH_kFt#|k65qp0Pr#b9svk{ZeFvOiLkO|~9d4C6zx%_AE7AY#^O2$^q<sN;132Er8U(R~x3*gG;Blv0Q1UTvzLBr-9VdXD3(o3sSL3`F3$cZtfV`Tz# z>*#B;$3+}>$Vkv;^C*0|wVZjsw2i&T^;guqxZK7raR^={LYLIdqIUl!F|TzuL5*oF zoPW}ee3a&26}H9dU*qJ>v+I;BpUE4HY#>pZf*{}!hKE-yBt4^)602j>*-Rgly*Za} zpgB$0?*UhCmEy)gH%#^FCV_F6!0wwB`Q`Q<>@yX3innX1+7bo)HR%h@{WF(-xV#O* z-1_On-)kAK=pc-WKf%om;#dP6SJLI2iVcdhu%Ycaeh-jiO8J5yDwIN>y3Ggvj$%@< zSsn7)EQx34ISkh{hla1E&=Q|%|NF-nQC&>gBd3=@_F@NI(|(^=RyUJH;%VT2#G1Y3 zzZ~Cs>T#J)6+C_THMpL>(tI7n!5{jmF?TMQ{Vfjt8t$O{+Fp8lJPl`i zu^5-_idhoHIOh|Kk45Tmm&gU6A>z2JehxqW%QKh~m<;Qe`{TOC4uokl!Ny@fjC>iQ zQqnE#axQaR?h*sq$>u0^rIR!ab91UYrs$O_fhQCHFvaf<;E72W*dsz3B>(IkcsjL= zJ{+(h{)@hYX?GM%;8=rS=PbicQw_UQ`6*bdbcwRwI@9p*^Xi31eNA; zU6}{bu#nx0_tz*f*t(XaONzkxH^O`^gT)x-Qwbj@G@;5s6m#-94=xR#AYv&^#Q&ru zg!@jxy@w5G)Rn6Qbxy$2d^?y?c?`bi9U|iD<19Sc2Fb=cv?H+qU$y=tzByCC|8p8R z2ARM>XP%l{&z$UI-fd z#o>pb62EljO`6flk`2x)^Dr}_dPhJ7luNTqdYZtA46c0Cc>>#6& ziuCiQC-j=f8A#i5iEg-+K_;HQK?R>%(aoG2xISSM$__0ip2;3iC$B)fj}+huu1^ry zBu9q|Qs`%wcXW;NL7FeWkWW^3lfp(N-nPCLJSbfTad%Fj^3QSRh?^Sh-n$0w$eu>| zr>XF$(iyimeZVrIZzS`4IXY(7kdkV5o{P?1k{4}kAz*9WEcZ-wpG(`bbJ1R6l+Q^B%ru*&~BYCl;E3rZHz(P&|5W0c)1zN5b5&3=Dv^+xyaIXQp_s+*YmFaN5yBr5*SU|uEB*t#RwIK;@ z{yWVUy=(znQpc!=CsVBpzwxW!cl-NmVsVYO8_1U4gEkZ2<_@dZ%nn;2jA&D(>3-bI zFer+=?tc!i^<1#{E9cZ1vn0Qw?xQF7jx@szy1zUDgzuIj`BFeXH3yJ|SH!?KFOyvV zcZEFHR707wvms>P53s#+g!NzB$*3F;hEIcxpw(>oNOC<-rIZs5@T zzvPXVG;b0A00^2pz-KOVB4pKq2K(b7IXedOqTbstx3i>EPF{!H$=&ov>}uFBaT5Po zYX&UZt&4q*7P#@%SJpj)z&9OTBKU{Ptpx_*h9wCoT2qBTp{IFc%tYSppDpC{5(z4~ zCJ**{+wpuS<-y1BQ|O)Pj*mGewBeKGFrKc!&2eHu^}=Kvs?Y+po3*s0w}UQFn80ya zeBjq$1SxU9M&3_VhvJJf$c_A~RC!PZ7Ovr=Qh5zsdE0?IGv`vGdV>{i z0TO98Os32Dr6=N0!bgJFzTz?-h>EkHHMtzi-S^_{f5sS?qzB6uT((=esf7H}Tnl^Z z;;Xj)37dD z9|m?8lfjGLH0O9fQF7E^S3EsWW$Zoa=~;(Bv~Vj;UKmH^vpu2yI%UtkctRk54Q|z* zMx!Nflf53Y%?}(opXb>qjN|q|J4Y+YsPZy0CMMVHGo!*jY*rbYGbe#gpPkO`m9YmY zs{+y&7KW{M>BMxYF6%2IOa?|UZ|WgL4w6viLDAXbap>58Sv(33k#dh`YG*5YA$SoRiaS4o9#T1;kzwbR*d z4p{%hn%xvAjGP>3v8NNTX-O6RQ?rAKju<7SZQC$u{5-u7;e?BL zOGt*(ZS2|HM%PMPV}IW^jzO^z{#aMD1A0A>?Px$WuYZLb8BQQ0`j~FJ5J6WR7iH4R zec|YeFmQ^Ghb)V4RAFiv=~+<;B~A}G_m35xzM;;{-FOBX#C72S?+ba{@Rf>lHn|O^nVmym9QDe&?ZuSxus8RvFb%HBRYK>wZG4y1@rGoSn*q%Rgz zwol`l#B1>2%MScrYKzNvmDB6I)ue4G7k4k=!Sjd;I;h6gl=-yQXN!l}@m46@3ah~q^q4i`?!@Mf7}= z!1w!ShI)xZrGh>>1%9)evMLa_JzNRman?lo%sHaT2%vIVB@;Y8xjA!oHLzm(;LJH# z^z;Yp<_KrAir-G)zOhWQ{c#d}iC;-3dn z1-32n0q$#Bhkffu==5m{v>^Q%jkv1^*Jl64`;r@(MsZL0Xp@A^@3{GTUk)hvK4k|s zJt8j(NAc9R!!YVJ7XmU;Sns>RIAr6C(W3L4%1$rMd1oY9kjsYl+>Ls#=)f8Tp@3SD50qA-8*?ocvf91A}>_R~M_ zuF^H5Rp{h-i|PnT@oooywx4c3NSY3F=R@wUydM{YBoY|%$yBs_cx&YK}S^nZp8}| z+J+BKJ|`CQ7SiWjhtu!KS$0-eCaF6ago5V5Z20gO;^(akQj2_Gr2HS`I7_iPJ7*$O zYJz8fY=RBkXJ)t6pYa*7z@L^kVMW7v{5W@+y&`)C8avYA*5UQc$los5G35v`{CW{$ zd!ILJYu_RptnQJ4`4uSP&_w?9MxyR`A=>#I0gLfm=7LlfiQQ|4>v!5PpJpesU-w*S zRtlCRttI`aAsvs~VrLL=v%s2&XqFw>z~%q6P)=zDerb5aq|Uzx<+DSv;cFf`ByK~w z!xPDo@9uO-P7W$oB;%&3o@9dkOqx4g1am9SeLS6^8@K?w5UZ z?*}t5=a@PhzwBUY#P>5^L$c_xR2^@Z3Gzo&RGH4L=jer$20Rzdb@8j0!2V)&n7i8q zoA!m#mdS%q&JyzIpCHVadV&^HjA3oTa?tMMHj+B$2=x)b136p?O-P7ZIWNMwI^(u^ z+!;0?yMw*)U?n|m{elEq_yDSoGKCS+TvqfG$8##B@u7r<|Hx^wM>XOU+e!kGW+8i{ zj=5@iitIC&6rg_X2%_&x10=DG!)n%Ha9jY-S2?MkQxV<)!{ zg9OFM*QmLi`*(zfp%4k|H?fZkm1N4dn9`ZD9NYV447s#SiY`-Ahk0D@E#ZbM{kSLC zZf3wr}x{QwQ zo;2EICzhR1z?Wjq^xy#}_AZAPTlBOZ_qd*dYk`@>-)JM4h@FPuq!VyjUjfIk8l-%a zNN|h;ie8^iwZ2wDSpOaL&*b*0M25Cd&iTPuO38r8lWUNde4og~#3eNP$A5n_@ zfBn@ETUdw99>MU=s1Qtc2ojgjN{kpXB*)fV!qhFrU}C=xGrF(iUlmW>C}&PaG=?GR zQ4+hEUxaFhL?J@!4(xo^$Mlxzk%OW2nE&M@ebNzxA(u2zT9)(ijqBj8M19bYI|RiO z%xG!oIr6w7mo!MP1BptGOV}1iJOU+Pd5s0Ysadq;&`T8amB3`qu{M596hE&LBKOku z@P6o1{81&rd$hs=MyeO`vke>Q2kwquGb@4w-L}U$5&Q8C>A~@mYD|!E!iSFIOj3#m z*PRq#RgRv(DzTGTAfo|C(*(%PKyA9@%3XSIO&p|GX!Fg!7@)M`WzG#C$-kYyot!#m zgfq8H#IfuW5E)OvIp!g7{N`c28y^n!^#Qn6p@jzZ_TWaha`IW$4BDN~QH_^-xJ+aX zT5SDF7R5*M;_Bou_hTEqmophl+`@^G#ceox@&dErTOk~ll_9~00+6B>K8mq~`+ z9hI2N&Vbs|2y*VjF>JVX2c`-{6Jd^3e=guZMt7kd9vn;}^UAlA+{lTvzqAqKebk%x znCPO2N)xR+)B~~iO6h;^{IUCT9wYij4abgj!0urc)L9`+_ACp>Yb~MR5`Pz0w%XCR zzZPTUrew%$T}93}218QoPJF7cj!4<+Vs8Eb`X7Ri z9r6&i@hY3tGDgncKZRLz3p^fEfR3sZ_JQeR;`-tRHri|&Yk6(?_rrkQw5GTo- zR`rPPc~*io>OY9VqMu}V(GDb_#1{3F0)4YgtY)73iPH>$Jv!6v{ z%&9cum6Zy&@~5NrF9H6w_7+-sQ3tHXIj7B?gRmss4;_VG(r@`sC`9J6<@=|jz4>I2 z2`%HgKAmWIdIBtWU`hXd6Wkf02D;TN$yA|wrnqi^E_bzsuEVS0Eyw9{8F)?eJ1bbL zMtw$Tz>Bz@+K4`@bWtwO2p0<9AwfGf(?pd@GTZMWnsf&;4Xqb(#xU3CUb}#HFKD2F zmyK!1&q=u8)EhY8?m~^3gdY7FED&T6D+7(f#GLAllt8(d^&N9@i6#GTfMGQ)02%PI5me#!*xhx zzZ3iPP4t-fbQC$HMPjS0+4|6r_#(>%|L(AXV;$`nB`u2?UAJk(hgtCc0@pV#4a6Du zba;zo3$dsE9qs=hkE?#OOmwCU8tFJPmCEy}8}9~*3gcrcl z7NW6t3F%yvLW>w9+|}GbHtv*Qcb<%3Wuvn3$jBPFvbm0|&|5%vEU`u9p-c2Xg_mST zStcB_$fiAW7NKGF6qMrP5nGI|lK$NlIIT?|qqP*!+bxGZ6fOW=<#TY+)H&q8ocW}- z`YPMWu~zQiF~@%A1E{-R55uZlnZkSD*u9#uP^h+$8qckz{(?hj%;ndgu6@YOm$yTV zsS?~FP7qynS=OsTOU4Y5oLxR{=(}D z3+dRRSFr7~D~#_-!S^QZbmq#(pv294Xa0UmOb(nRx+&+O%e@{qWc5;&)0I%;xBwpv zG!rMSA`;qlpPWAuM;4bDF%gr$*rPz$`JseFyUF89_xrSR&IHs>?WLNF`^m7P2)g~y zqpRKmpL)N6Dc#G!V%bzaZ}2m%K0Jc2-OtgJ+mAASKeI@rG7N>ssdy`eM>tBs!%Il5X@ErQj4=}(t}MnyEqC8J}BUxKc|_v*m(Le zZ2~oaJ4T+>D?++#42_au*_p~gB(1&~WBGYl@TUev68_Pzy;q1+c_=1ian3uxOGMwq zALI7>Vx-Jkno2srZ9)QJ@?1&jmk-pu^e8>Lw2bScuVl7o4O4-e;`~Qe_UQZV9Nx?G zV*MJpx#R(1thI|E$UP^QmcAg0zFp*`)CW3U$O!*?D1%dXg~5USm+-J<41CfI!fqxL z-|aP^iXIoyPI5bq_1cYk^FI?c@q^&gxe^=ixHkDK{G}569#W5&VfOKtMB!ZdCiK;- z!I`s5aGIVG{c?1SI=6R$wZ{NC)t!T`vkM{0JCW!G`Eh;Q<79vE6MFphY~naPN~aI= zX7n zrZ4a5P_qo@TK-6Fn^s}4vK*|`jv`hf37~8mfM3o><6iF;V&ufa?x!-KVtcE(@zQ51 z6}TPW{+$bx!lm)$gudolvsG+q>?SA-G=eP|?KHE)gq>)|y{kM~I_X6g4cMyyCT_Dq zspC4GbCsJnaqM*iArVk4enMWIFb1!PG@O%v5QOI#;@!{~QW&qy5A~7ag*!0#RD#Q9 z508*9vtuwvMIGGo1bMD6CW9E)B@Em5hmELfrGD@7n@?F4;G4ohA~gFwqxJPbv*)x; zVA&Hv3{_hR{#e0E?Ni_tb@TWiw^~!SshRT+yW+u-I$G{~88;OUp<0hW3V5sIs>un^ zNA|+pYYFVpW8V1Oy9_)wWWa$68SIM9p?ghUNN_Y6AP;Ch1jY(dV*HW1mvR14n<*r0o;Yk>dkLMbMSxf3LB1;r z^0trNqly2Sg6&@ip8Hox5IZ}O=I~}PvwvUb`rpC$a69KzUiFM|E#Hck7N+oE$|9nF z@j9un8-$vtPP8dZ1O?87l53ytv)#uesj=~7*vBzBYc6e|)5Xh>>O7_`q7&$n;Mvse zg$^FRFl>LV?lX~?F2$Q)@`SEb380gH{)L{>Y&h>}%&c<{qekaB$LthU($C#{k6yY% zM2x0W%~k$5E!LWZ=Vil=;7B~Kl7pW1ub6X{mqC1fDO2lJNv!tnN69dE$P@_0MY1cY zL6;>CJ+mQSGIa3clyX#);O30CbjXVWYqHPk0X10tkfv!yg5fDon(#vrJ~kv_33csZO5(aD6Rhx2)|yRq%CWY5vSn2#5DCXGbVl#Dg!)$6!sExl?Pa# zcfC1cemdqoGvM88Fy{5`I)c-hC*X^>+IX%x2D|IBDI2Rz7A8Mp&aagq(p3#~v~@Ms zDD&yKOeX!$A+`CN;y)@|lY>>EYe}jo*H=G#7mh`TKzeI9G0lpF3_}3bhz=q)K_6~T z)8es?`p`d((gNEOVtHyJ`qga2_J$^EUcG|MtC&QzQ*Cf;c>)ctIA>pfwF6>~Y{tk} z=UG>;y(so5jgYxd!N~wHdSo6>8b3&lOhV`r-YHztu?mHHUy{Rrhe_G3>1g=n4E6cA zg9;HTIAJVH|Ba?o9q&u@y;vr)%1dEk%XX+;sE=P&MR=p@+UQ;CFC6T#b0j8Z6Mq zU#Amjs>6D$pL_xD7tBX*AwP8C`nf0W?zTVu=>jWoW)&@adx9_?W*D*fDc<;?%2yMK z!OyY7%+{7TD5<+l2P*bM=O#N$c+9alrYR9jl_B}kQ>k#QJ;#YxW)H^yC3bBZ_%?`z zQWut)6+289yzFW&?qsOFbqce$;1-?u;TJ6E+=E`r)wuor6GrpDLi8}WP3}(TQ}aEy zU{hZzNwG5(K z5SaS7`Q^@=9MDgKcY)g-+RCYMoE1g->0kysG3ya6{KsWCmY<~aqGe%nxF6InRBwLA zaT@NtZbLG23f2yYqmHvGD!aCTSg$-DbaO+8)1jR6{4M$8qJrDH8gcD%J5rZhiU;pU zfL+H;7`F31M`#N3mw;I0mRbWx(Onzx+8k-i9i7wrS zFr1PO+AGar`r>W83q3zb+3ZcMpiImPvsOl#8dV_c#AqZb^n^~?jD?Geg7r^`6j z&>j@ld`HJV*pgqO`LO8xA#$zt5mj)$j(MF$RA*u~czQpBw-E!hb&$)Pn1tZU+-TyL zza2%~j}ej6gLGX^8wxT%=>e1L@VnUus*|e#y)0=!ks2&|D2$Seui^P^9+*>?g;}%b z!9YnW*cSaq+P`YRxyXZXwkw5bKT+a`tj~heGX6LuR|8&O)ad5<$Iy&kA@wH<>SLQPOm}5*#dWT4xs~s5Hq+q|&tEQEmnNS*@gNuBJXyXla z`c<qpjvij=fBQf`!H8jA0jsys99!%zE-r%!;3DB*p(ZB8y>z2Us8RR$`}ENl(ev zz?=5h9HVk7w0&zu)px(KQRy$UDMuAVf8IthLjnHWA5*yu;>}{;S9ay-2c}tV)1Vin0(h_2A3Lu{2>+kXO#*~<~Ra7 z|K4LnGUu^|(E^xWdmMjU-iMo2PmrnCE3j6N6gC=j#^H&1O~cDZWce`3iXb3L8- zO|qm1l@`H`-RiKwMhM>?=lsd%+KKIsH)P(0d#D$BogClLMt$sx>EqNklJq2qG*dpA zCNT{%Dk@mph#ES3d@5x|v* z(LA-OVAlwHJcjqYk>3zqi2c=Ml8QdPwQwfQE`npal;*Ola6Nxtr#kE_#qyvYJn%V z@*vaGhlh6w!lq}bxFfWH)=r8e<0Dge<)scJbbUWmC9~uc=dHap(vMR^xbBd~DNvku zo<6vd0q$vmw4(eqZI$1Peb<$Vgh>^h8)8ipRRPK_&g5^Nr3T*&&N71{;^e2%FI@R+ zI_XTD#(&Yj6o2J^!7I1kgNun4_P=Mz)s|;q|0@G74(x;TRZckJWh&7&;)Cp8V;tG~ z5IdJO<5!#AM6yi}Z;6NEp8sCsml9#pnq5sX;4Lv;s>S<0K0s2qcaO-e9h`y77COG9 zQ5%(E)-UEC`)85{crmlEb^kt6#ofi6q&|an+;sB&=46<>8re7Jir`j*B0T39dZ)`B zQTW3jvhMg1>^&ApHvG+OzCYO(tG+vyq?QE-u;_|+We${w5(yyHgOb+l)+Q{PfY88CWOgPf!H%Y=nQ>^ zUeUdajA;gRTrdEM))k`3f_}m2A0e8P%Pv)-agFj zU2B_RUE3mNeuD=7m@f|-ET4kT$MyEdpT44dI42gVP{!0t2l3*{Y3Sx#0^JMhG3Ci+ z==k7?^G=O4mEP2aLHdR`@72X=ZVu4Q<))racu#77+@tTc&$1Dg8)&<061H_K;~cTA zsCTY~aH(5nOxF^N>(lMs6 zrH4qxsY+rJ<`4fIJ&8op1f0C=I&GHfCiRk((SFfP4_IEnTIVxZwB`WEtt`VGPVdP` zk3VGga1#O9(dL~+s^se<8<;SAHOXRhL3FY&oL2hK{KG^64jX%MImH-wc-$FsT_#{p zv@(>gmBLel(fHpiDc+NssHen6Uj*wec*_UQho0aotZMT<7Ar?T!!Xj;<>H_cAN0x53(oUen^RKDQ))IwH$ zMLB#=4#Z~>T&~5hk&0^0;GeG(!g%vYe6VgaOn>*5CXc)!mObGlbkQELajJo|SK9Q$ z>!4O6iJIKxPSR4?EA+L8i)8s|meVro;X%~JWqkos7n(jRCs20IajW&4g#M1o>50d0T zd72hij-I+DRKtP~w>YL>lIkR0i|S8ulXC%BiSBOx??^J_FWZB5AODh)+aF+mFURd1 z*@99!k(j@9D~&%e%7ooH3mZKz+Vi$V;bzx(O!+vBOH^ZFc;^~iWSNHHaS@=L9f9TQ z#l$+xpGdyeLzz2ENx>Bf^gJ<@+5K4s=8g$Nd!Dm>!--3@=3p|tmXeF)juYtDO@{G# z(yYzix76g-V@4|Y6!4ZIlR8Xm01SvbjssK=#!% z2wcc{Xyyyy9)}8S3^#%M@h8aq_G2(jtOzVryXeTwhqN_jEw(ecMDdUqjD;pJKdlZS z-j8NRL+Xg?Zd0%ZL-=LPt9PJa|XTV7f)j5 zXD}vq3g80z-{zRdWyXVWKs0e zG%l0=8Pl5_u|qJHepy{b{QdKAg{v5iU2ILQOe@&8L-OQ>`fWnF8Q)9u>1gAhOT-uR zaM8*@JoqXBXSbigwa-t{7ol8F{ha|>u*{gqHBQBbqf45vIoiNCnQnX=D@*$(pT!1U zG3?^4g9UC0Bt&M2nBzt$T^B``)Y^b+&jIS**hl#HT1x@C>}(^ziXlHm=er=lSG@wc0tvg5Af%WHkc;?s~VX_-aWO1ks)0O zRq()9_j4dM+>D>o0x-bKLf-38@DRU9YVJ0(xxdDkO71zJd+I&xI3x~(nj+Lnl226& zGRc9nTKv)bPiV&6YI@twm{;Jw4JuvwN#o9+^j=62EY*1kBbVl4(3uHPVn2u97%u_F zYH?6{_X(YAb{-uxg7NMpF5{7yXWx-~lyz6)p?;nuS`B}sa;M_3c4Vp9(;oXxZD0S1C4u?<1n7C1nw`&Cx>~+!f zdofjNWN4w+Ms(!7(3K_@tXD76r%j)*O8f!c+VB-rw@*U5hSSVNO%bw|JO56P{z%fe zJDbivZYCbHfLbcfgnz6C*B?%V8J8AEz!<>6b-e?ZoD*?(78!V_s)*oR-hw7{00sym6E zMKj5pf`>T%Xc&(+yAh$T3$!5RiM_g?8M)o02T_Xx=(-nPa4@A2&SoBETDWZA!tJ~1 zZ!<%%v#cYJvvSGCkv$lx^@n;4{K5&G4`Y$#Hu`wxF1WW;1zi1=p&}y_q(VlhK&$}X zG%o|6Iya&sJA~Cflj*y;A4&P2HzacNZ<6VdLDWCqqdx^Cuw6Tn9F%J!8?+?pHJXG= zB|k8Q*}+&l*M&AnbG^xOJ*qwZGJWW&fMzP4^byoDJ1rf^rNuAEoa^cMa=rwVOZw42 zp8DY8#^C7gW^nni7$fEjbGeZ!5^f;`Ue|=dccL>me@?|4b6?T$3xDYRRowT(brK4d zJ;N)e2T^tB1^Q6s4LNeO$$sjVVYGGf!6J8Wkkk)=OAp?VHOf6-k)X zClb`N36!@df=;vr$~=^2@29%p=~F+sToy9(xS4HQ?Ic{soymu-tyaWm2Vm$Mtagpo=qM^MQvL znJ2*Wbt%SM>xB4MwS3qmnu-us6oG}Btoi`AvA zT}m{3eu7L-yD`MSU5c&mVqwKTOVEDXL%$eRLR`u>DxSQ9rbaGCo#V%u zBkjUCXhj4JuB~I+SG{J;Vwa&ar;8eJ@i;9X_>zg-nNHIzMqyNE1SX4e>)`RH;E+%p zHorIsuE7?#RcSO8QYeH&8%N?TbxqjB>2zvpIiu&4ZrTa9v{BW7_;bw9L$~zM+4DIa zpvXoFBFrt)l*5c=tpv4@Duv;9gB5AiOi8yLtGp#K;b>3@$&O; z?CBUOW=Az=KO0m_Qqz3#$=8)QgwxFxUDwX2Z`(({stv^@g(Kk;huL~p^TF!-#Z6?& z{UCIEbc`C`K7vzA8*s6#0US7&gdWMS>5sX)F>Xo#=2+We!chUIz3Gn!+g_8|4ev?! z=DURB1;Zolry)VR3RZF${bMIME`f+F@DmomO^HhKAT|vIn^f=v7Q;<*arCQtfx=3M z(VNo}c6Q>h-p$-MtYwO{ii`odCVe8B(~Kuf+tE}17#gc>#!a(i1W5ziso=X9ZoGbk zJiWP>8qN>o<~t9L@14avp0e!qYnkZ(LlzEfD8tciEAckBrd+#U6d#66AWPgzNpS8B znyJR=G9)PQS{@2$x??I?QqxYu10wKLz$C~$xRm%n4Sg-`gztJxc{x>$ROrYZy2EfD zJzk=TJ3|-9 z;Xa+@wtgs_nlC0$<7`WhPPjwPMX!L@$_GgMgAJr>KrA7 z$`YxBRnRSS0HT>xHg^A9s0a~({ZeLlp!x}MSI!}mbXMUFkDUbU6=C+~4`dx@m-jSn z39gs$ge&Pk$V_)X=*W;4@Y_>R_Sko#AsuFO=1eF~%9NwJ-$GF|DH|u9`3?&j%U~Q; zhj4doGPUP1YhOQ6MMH=Fd3Rk%))gQKW!_;{_8?G=9uru$E0Q0rp6 zTfUWd^06O%y=Mzn%g(2B29z>uEfsLv-SOmYvIKdlzXuZp4mjh?J?wZhU7#B>0ng@! z)10y^U~$=iZvP?%xKjulOus_-h(eos?Mj;UD3fe#iK3GpU#C_Pc{EgcI=bnIqfD{{ zZ4GaxvrEFj9Iwz_@gHEbQUEM}eE^T&bjA%u1?2Hfioy#6!GhhyI##>Tk(V8?@X#_k zxnd-ISg?V9l+7d&Ge+Yh`7`_kjastg)gjstWJjuF-N1i*3>`VGj50-Y@T!J24r*Hg zrthwkmyQ5~l2`&+GqI}o43TTjAi;hIIqdZT^0Htv1{@bfd(ksCGOg>t$7&2*s2c=^ zJ*zQ&wF55GEQB$Z>&eR{SLjr3ZTBMmBW<5F9)}3$QQhl@I6I$6w7PegbQ_+gA=Sw? zYWqgx^lcG%QKp=#6q(@rBroaSl!-S`PIBoeFEK}l<_%$jn(KAHFHk)PyuyD7xFvf4#V~t(x7#9FFbx>0n1#S!Pa6Qd|z+~ zx653CYr45$(>WK_T$I77aV+}9oTI(w9Ivl4fx*{qK|C!Xsw+YX1cYL}RR-*~KN?f`3FOVH47e?4hXcffz`k@LoUykdvX67YEy|HTPteAdMeZOnKpA)K zP-S+giSm+9I1@2R6FO%t;Vs$NPCH(0CF)_;;AdGzA|8Z6ebqv`O<)eeYKuvNov9#c zOcfI#Rg4ACx*=#^F{s@!#YN)A=$yHirf$6gp4#!uQl(;?KDCTYdl!LoY9+8{_z7Gy zQxZHDdl7|AW6^$-7drkr2^E&Dptfumle@En$ULiHzYjZtJ6>etylr>*CXuF`O|Tk_ zd!!5YBkwZq3q&wp+7j3YT%V3i#QkMzMBn2k8gG^aQk=#gt0zh?$qC^@ zBLf(7K^D{UIBmOi7AWSu5X#M4$;7pJ^rK)GipQuk<7b{Bk?pI<#aksPy4n<%YTM(m z!FxE(ma%9yVkFM{YKxNl#9?d8Nh;DFPE;rFrE2wwRJ(T`eT^CT&YpXJ5|dH<>O(rU zavfh>XC*cAmH;h1HE!QxM0UmW(ka_6QU&)Mc$DZ(f`o2SvyJ=F@cT6M<7~l%k{*(r zWmb6Evw~z#d;-0z4#Q&YC>UUyP3Nv3jcpE`U7CIqYxF1&OVtH3@Ikr38OsJo;v@-GU?-1ZMP`j5&JXFnuq4{7^zOzfA<)U>AtfR1n!2Je06khU!$v+&8IT!ZeSP2iT=QM`*hk8JD*i`!Fl@W1# zE`kk-%|xjpgdaUSgqtUpqT5V0A|GRe=F)tsW*f$rK3B`eY@JMwu3CZ;-(~Slgg2bd z@?iYibz$Om2bi_~9PRpfge~v<#Tw4Kz^=M74TY2Z*^SGiG3c3575`%q4$HViPHB$9 zjTfG92FJD|l%%^^0PfQSI4?qUlSAUIkUK|7_w_0q{mdg-@4W@WvLlpT4V^Cl110Cy~ zfCERSQsvn5v?N~`)Z(IPcH0zkFw&o-olb_#ozc)zErQc_rQ*a3mV)43V_G?nP&LIo z;v%QcOI~t?i0H;bj#3F7%VGb{s3c_-d6P+`^Mb`bYT95(*>Gy3JS zCDS`T0?b?enBeDwd5*4cpvRcUoe{prwD0w-=~jE#wm+RQJq(VTUw{$!rKRlgkr5xDDxf)kkW?w-4+7v6bW8+XCvH9)fFgTd5T_pJp?l}BEagfCer)QsrPZZoQ#0$(FX*1cAJtA*1mt05g)GV)TV$xH)0E zP4;I#l~Y#1{18oY(=?vbRES4A+riXd$CDSdx)q{E*OTcVx$*98G^q8&(RK0zsbup& zh}X=e7qi3#12Si!-}ME!YMVT6x{wMoXSUqleHs%c??XXk99^cAk0#3{fIVUZUqglx|6AQO(Wi?1jy#>!W5t-SbgAMcO0Pa38ZtkSzu6wL)=h$m!R>Sie>J=-dx;Y+?8gc@ zecWTkqm?<6aP>V2R`z&2)A(Fckeql9^~ICfElmP^ydjj*`B$Mn-VQIxO~yxqDhThr zCCuMSXtG`c7>t~TyRHo*t)JK6pzBw`mn^pqR2oMve3*n@i^DMQKq709u7M@XXTz^* zZ5opJmb6)ohWR45IGrS}%@1$V5KLr8A*nOgYH;KD)mjW8wE``4C zC8%aEiO+R*!JTcUyz$a1uylhmshO5SyS@#Em;`UwCA<-zgxCn4MR9oS^lsX)NLb)A z+>gvJ*+~yQc}Y{}s6g7tVD!C}$GoliVe`@>%Vv*xDAvud!DX?dIbCzkhC{>%C8Z-s za%dRG0m|tGOg}*V=5n?vLOVGAn{_zUc^;$-|3ral7xU_}GWVhnuW27W&+#xJecJa5BZ*EFe5b# z?(Kcd^2SNPjWZI~VrjiLqHp!#WV#FgclEXi*l0}6UBtl0Ly#jZU9f$6Mo#=jgX}1|_Y`1{p@tySQlC3E3uS(Kn znn{A#Jx+()3_^FF!6H10a*zxmL(FhnHfKjPL_(0gQjOR0WhHGYNJZb~FEndGCq2#W zp-bOmKReD);7XTiF}(m^^H_Awv4VT3cv<_giW61Jv?*Ygx2eX zgZ$8kobEvo%=}o!-s_x3uQ8GAI=h*qKKe66a2j40qh>-_F^3J=u!}OWQG^b?L4ZfD=NY;%}l|>~u(W+k!p{Q}M$r6+AQ|8S=#U zu$NI5t52PVt6S%R%B3Wn3<>B^(#E)YhEgc+U{eodF;irg;60u?t$54X)^04aF*Pp4 zwY72r_8{V=If}4bp$RRduED#$DsqdPD(7eNBT=xr^xe zKvz_LnTMl}n9%h_$oeOnVUXJ~GAWp)@(TyEgS=0&2im8DL;W+7*L;tL9gwEe%4*4i zH+yKPcNDY1=PTRh?T=U8OG%uK8Jz1?!j&y%xSr#05dI}jZMM5p`SW{l^mI*7G**He z8+B;jYAX&T7)6`z%Fyd8rokTO6K#AS0H&S{Z9b7hkMtNZjMF!II8zaiU*3=A@=NIf zkI!U%K_j_-X$vU46Xk`)>ER`pcf{6R7(#x|f=AP|DjYk6@VTlE-0L34R4aCq5RSuP zQSV~BtRY0?9fRmhm;H3%+)}ux5k<#cdPah|?`6JUXRxsq6?FFtQz#f~LO(xArJszA zQ8g%@>OE3rPrB$4xij8Sv|u#GiWuWqnGo#hbj8KJRiyj zCdS!g*~@R#Uo#hB>|M$!ZR1H!1G06}5yqlRgNGwHRpL9sc->r)Waf-SpNx7K8z4-= z1}~xVFRG~Ko>KBvc?4WBDWMF^z<0rI7_>G8t_(4yZbN;McWVJ@J0=5*!tap+4y!Vu zTa7)@>I|Bp&QLDzMTRvlfwi1ogLTLr!mK!hnwE7~tCIz4Q9tPm+W|zVwV1;y%i!m& zg=CSZB(J3GD2>XgBl&}Bh)noublcrX>LvL!{$MUG?O4cR@w3>$A18CXs^`VTCk)oiQ1E zEk~1rRWGUkz+^mk$^jHw-2lcvBg%I)s5xizpFD9FjW-)Y7cKeBKQum(^ehg<_QPEy z*u#?fQ8W_7s1~_4(jFg43qk%nc1K#S>oM%8Ex#8^k;jX)80?tK+p?lz16)+La1tlo** z6+>~sbT5p{kB9ep`B?vv;{`Spw^=sHmo9tA@f7!Ryv=?WP%I}B@)gVJ0*zB(ui1z( zu99T7-)ZJ5wS&Pg5wzSD;lbEKZd?q;?BIj&evA+=O+<|2Adf^gOO{&?ZO1Z?To~gL ziL=L~!L3YA8_)eT;@cQpaaj@c)XuQSF^TfSv+-S%ENuJnnji2Xgo>VZsIt23i_z!h z5s%C#DeE5NG}W>2X@eGg;m-LIB*k#Tu^1xQ5rsQJ7KYq&hB32z=$?c~^a>I|*P%UB z#nl%dXiG6sUpT#w-iPFdoe8;JY>3t7=P*EKA&1FYh@nw2%)M=eP`9~(#%_5=-zqzx zX(p$qCR0eycx}PxHY@h$VO6;KXskeJ(|tOCAd_y>f(vxMfSv7;s`FM6obB>{GAF?f z(^5x~fEYj0b#4isP-v!Ggy+G66J8+Mbrx4H+(*8D`9LexB(Y%FRa$W|ls!JpmJCke zaopeU=!n1(knCTGbE_tk1BQF?!s4T(cT*-hsvn0s+so{7Q8UugxE8B7UM8|6gC5Br zM9RcUsqMOWQvJh)y61~P%9|=;GV?vC&Do2Kqtd~)Y&&y4A%q6MPi4*>nG3U`?}4Ri z5e->%71JBk>4Js|vioWtofuV2Qw%++L6k96`BYNg!NCwW{|5CNUxtz^yW!IfOL+Fm z5`)W^*?7JY#k3cqnW?jO*@pQ^&k`GD_eFr#3gTOxqsze9n6I;Q;QN>rNLk zy-^y{TlHY_uR~Z~UdptK`r_H5dJ?7?OU`Z{j$TS_^vxhGbQGO~$~Plv5>E;S9+GC- z68v${qG(LMxD$qSrPImk*5Fzbj4MUm;GFVOkkjpAW~;_P=_gO_T)z=5O*osd&|K=I z*i0hNdvJYaH7$wSLNi2iLDyy}HjK!^hz=`=sMA6-{lj$gOYSUgPa!$Z@g^uLucw11 zl+l;vc36K(6w1%uVEqcBus3En1SD~s4efEX*KIO9yEq6hG-ZMMMj2S@ssnSbx`J5g z225zW&6bb9K$n^6kYRflo(mb>bTg#u&>D)eZl%o+WHf*B9*XYt3aA7Wf-U!jk z)_Aa$po_5-T;uR$LVGI6{%d4z9zFp=bS*gDyXolid?~%s-O5g1JQur* z70E5d(~N=Q2fDA_16gg(Ce=g^y=o@|ukIk-!10Ml`B+2R%m|qHwSs)%w4al=2a<2W z#f;T%Z5*@d7Z@v!GDIn=#DT^On7?+h2^#(4qHtd&pzP3p~=8i&-pk$@ebQ; zU4*gkR)ONI!!~VR>Vjn@=b>U;7KgDAWqQYbq1KmJ>ZrYlEY;^UF*m;?{4*IUKH>$Ve%T8I&twHxyqn0Q`SslVd4XOzngJiT2(Ut_2yUzOf@^pY1YWvI zpyDjrPCY^jUYf(pN=`4#;2BLzYQf8gY>2;2AsDtcA|##wr8noP(Z?u={F#Un;;!`7 zg9~^lN{Dql_KW(Me#3x??zs4X3${!aBleEJh^&2CYcRaoxeN0e52E@04^TDMl*7wBq2caNVaE31^w|XoUdy=8BxY_sxhm00 zly6SJd$lI0F`=8R+w+ll!I9@@@v`=JG!IeYoqp$lds9b% zx@|g&)@I@1V(y#T_aaUU-U@sVixT(u2#V6e=((Z@n{F1eT^@4y{qsxm=A11qU80GM z6w7p(_p%?YmB|5F7wo|m#Ax~=JftYa-kFky96bPbWLx4nr)79{MCBa_keQ}Y5GK7J#;ns*3}8r`DFtACN9hootN zb|z}Lv=f8l+C*B>i*A#B2*uh{p*V61ICH$I?|AQVt$7UL-@M9BUp)_AWNKhfj28wN zbNtJhZYU?;0foPY2(-427x-l#h76$y)YdA&WplofPp|gi#+eVXd0h@$Q=$tiw**6v z`4Vi*Nh94RiCmtaHBiPwSdjd+@wm&oCb zPNS^pRk|{HFz<=X3f6b11df{*%WS$|POLaitdnaLv2~dguj5=c>G~;x1Gi-0-I^ot zWG=&ZXjS2CQ8mfRhjH*hOb;AHT!_Bj5!PjzFXCol=0))coH_0mE5Nut(2H;-m|e zRUeP;rW%H>XgYTc85WoUF-Od(_q368e!vHIjdUj4`#Ofq4y>iR&qImJ_y{6YsRrAd z2H`NTPgJ1)f~GCj=dC%LO4g9drl z?MB7d52Yg#o5-Syv9MCNfbGytBZt=Q#UZWv#Ix83{MR)=q^2gGoH!b{+^!}+k9)yG zVHR$ND3DPn30>&<0)>9sqU@?7*!hgp9ogefF6_}|-znEqxAF;mcgCFX(=DLu;1Ia5 zBOlFvn4^u9fR-Q11udyZ>^;3`Xt)@IEd?iVj{06$5H|@Vr3YeQfH6Ym7Utn~TeyT~ z;5hd+bdBEy85@(U_5|3Hgu< zjZ+VR(XX>K(EkAJQ<*|MhBCbA_t&Gk;wk7h9!2!hZrgk>m!T=glj%zi8}_+nDU@qa z>km4oagpO${+zTs{Lc}IRDQD|Vn8Y!|2h{2vqR{}CIhfgH)I!;a=4N9YVMq~7?%je zpeVbW^epY9lSf5hPn;o|ownvUGbG`K`$ZbQc_H`B=ngSHJDuom8wCoUu{Pm0ci5EL z5!iTnBgY*Qh=b%@*!Dpq=_J1(dPZx2;JV-jjbF{fe1{&|vdfP#6g#55(X*5i^XJbi-HK=gFI)vG_VcH#=Tr$w|mMn*$qXJS68@git4AH#Q2c!)uWUYMCdG_aDlz5lxjO@5ywWl^aDz zNjf22G673Pt;te*F-~u^g$kKCQJWDH(BbnfCg=Jcw(aRe+%_YZ!@8=Fse&XD?|6k= zbzMt&k&>vO`iLk7dXr~Lf#Ah`$7`K<0&@?IVwq3Kt_WLC4E+y6XU|GV*R@9%-3GjW zUylrtJwZCRdeMc!5#(OB0qz_;g2?oAuzGs|y%r52*Xsn($ziOA+0~-M72tg+@1(lc zp6C>n3S&wtP*eISoi^|V>22V&PR4Bm<hP0I-_9XC{PprVcy4xEFB#P8!b zyAV&xY3dKWo|Bkj4V{zI)oHmK97=bJ@DIiG0^SprBXkG z@qM8>y>{&*t?H3PE8Zdcee({=ml!8F?P^6s_S@5k;tu@C5k169C7FzwDTKb3d#Rc6 zCo*KT5sWeb-0@%_GV%|ZsY`3fsSOKB^uE2=3O& z7Bi>vpkS~)b=p-y1}?|~rvtLYWKAhup6Cg~gomJYjuzJXsS;=BR1|NHp?AOC!?y2p zaFha{YBbJ6*?C3~@->p242;8LCF3~mgh+Zic@Mlg(n?ECOT*pGt@Js^2d||)2a`s> zCz;DUsL;Vd0%89YYQO9=I{jG3%FjFmUE>U(!&#KRTl|Dxx!=a-(FN4<+)#Ah!EqkW z+m08nl|!R`Haf;;lXb|D1u< zX?FNMq!YwL+Q_GJKDcdPOD0}F#GF&`M`Aa?TH*BvrtW$aoU+PeUq73Qc}s_*_t+Np zkZS|CzPG^?yXTN&f08)u&Y+7Iyd{Ch@6zWc5%};~EQs%T##hXn0G}P^(F*-!a=mR4 zJc$X1?F)7?cMS&!?!^|u>Pg#Sn;-~3CRyOkpmtWtP=?Il@ET@sbK#|{J1W4^@%I~s zursS=fjOU!O(BUWw`>#`WxOSy@2;!doLf(q`3J!hV;%n4Qcim*PDS9At4`FHd7}8< z3E;RT0`sRtVw!~}+Vei++w9Q{|7`+X3fKn45vxG*=R17dOUNfF2guJ^fvSo}>32hY zfv1`rbk#+`6=QW^cSqv(oMmu3FNNmU8wy^GHAfipmD|v z;^;KG-lYKsUA{qOFT|t7nd>BTM=tFt9))jZ576OPXR+;hJBe~*9!y%Xg5wa6rfoNQ zP~#d3ReKLo&EOkk-}QKm*!3N!D4fQl2PQ*grvy}5WuWtG(Q}C>>p1`Wo-)4h`5I&fl4u^eASw*LC zs&FnG2Q}2u-i_(RH82K5H!sDpNt8a|G~lCKufvoxqUbnE8N-!@L3QFy>|!_`t!?hm z5=1~mqKBR>NhTtD71*kMb3tm>3S!lz!RfkO#5WiGp=#(w$mVeH^Hff=5529}2T8S{ zQ6Z21Ey8GN6@$fAZS+v^F=$XqC$-Oy(%Aj2IE{G^J_EcV;q@hA=CmANNj*jHdkv6^ zAE=R)6cPGf#B7|}Q}yGos=HZB`O1KRvn#$ zV#lY_eXV8WhC()89`C{`r>kQA>Udy6kAUBYZ*OjXndcF=F0ng7-JlRX*D=e5yKt(O1wAm!R$| zwBVxAW@7WYn+*8%9jn`Z5lO>hl5y%QM7KFY$FB++coJ}W>1mXHbd4SeT8ApN9&p1U z6t@PK(EZ!x(MRqlo`3ro22R~cG_um^wEGL#jgBX*!!HTJ*9dWtd_4gZx5VQ$WgWb^ zbpwV^pG$89o`IOstvGQ{6OgYDYz9*~!D@$05*<9A40$e$qO$SK>ZfiPzvU-cyLkwX z5}J&a(P1!3pa;TxTv6xnKHBkJnD3h5$!w}Fpao-Zq1w!&WQM_by8Mkah`o)25jUJc z#>I%4nM`D&Pjoy&)^8ZDZ5BQA+b_C8>a z44np_ZmHs-g{~xIp%e+9a2316KH}}@T-=tw4lg`=2W2aF!9a5ZP;Cz-hQBxsMxlIi zeOnrNu<0TzzPFw%Y5;uuN}6k5o9TF$Y*>-MjM-K;m>-qv$6gs+OqWy|Aaluxlx)$5 zVxtQ7wB(9X4AD!0U;eVH||L(usf0i0> znmp0%kFt9960B_xt`_ z_PhTupT^6*{r$adO#Urz|2WtZ-wl5k>K~Wd*niEYl>y5a`TKeY{EqV<$JQ5YllS_S z-T^+o{mK9Cr~j6f-@pDF$G5Qm8RMJq-;Hnm?Iof4_nSW5^4tB-#<#VPeuvZfYlZ*I z|4&f^e;wa!`%2x|*M9mdp?`$v9|Hc`$N!zq{I~J1e;)3S&wbi-`#)N6|Gc`Quif^K zmw#=?{r~S@?%&tI?|KyLn=OQdDj)Zc^nV|&-`8K?o=yL8xc>K5`{X|k*FSFDZ~KqK z^{4;;SNFehehL4dF~9t`?I$AsRUblsuI2vd8{GbC=l_iQ_{aOJcb&h-fzZB={(Jo) z^zZJk`hxw-`6sP`zpg*}=O?#ke?On}uM7U%jQzh*SHI^?NulVzh)raE_qzUcJp24x z2L8V9)YmD6eh&CE_5N@=eSRnI{N<19OJBIqBB{R%SJ3CLE&hGKQuNQqLY3yfXWIVw z9{2f$#{Is(qOTg<$~6BjzAb(Jl#1W?Q~JUUrGE+cpznF}Z&&?yvO#D^M~nWx-@osW@A#bolfL&RE9CUIeX8O=*ryIwpU}7VvlX(C z5wiHzS0DZR*1l~1FV4TWFZ{>jkjbmx`AO-E;Xm64rF8uc-{1cJmxTZI^Pivw{yGlz zuYd2q?CV&4b>OomV3XO>MW$wb{{DVp`+rzR{rxB9`R{Zp`_hvYTKu>E^Y5MWC~#@^ z_m}?Rso(uuK8;uVt`G3_voZO%J4;r22lk(~{Bbh+kFNiHJ?!*nFk!LZCGIbGziZnU zNob$jf4|@T>+}Ef^Jkq8eQ%^csXtTv-_M_a=eI9A|JTkRd(}V6(%&xn-rm z8$bTDapv*6-{Jo?&ir4$lK+tr{B@jB?<<9EU;F7VRDZAS_xJbN{{A$+|G|IJ{p)$l z{nx+SVSjvoZO8w`X#eSg{jNumzl{Sr>j(UYbYx~wC|6$;NqK6B4aqgg@<5zRIx5*{1qDCadi4-1wr(sYi# zyAa9gr$mAL_e=POf1g&louJyqE9r!Y893sz35K1LBR+9A*;2jp?2@jZMA?2DwI6YZ zx(u2HFNr+_h@B%QiX+J`jssx6Spob^)8LI;mjp#c3{kjYBv_&TjVw5?M2oVY(9fq{ zk{go4FgaIJptialr*K^75Yt09ObZ~7x2)pdZrH_!uU20;^gDdZQyz=sk}m*vQ>F5YHds_y+w4U7~&*vefScV zh@&3*k&I8VkaAER{AApjO%f(Ho4^WQYfIsJZyrqhpbiT^ms0hs$*}yA3{l;34}#Wb z&>SyW(y3R*`VSZa)`yGmg3&W3w|F^e^3Wqc)t8f4n`RPmHJrl&%kmZ+)#FuL-L=Vh zmIy=6N`aA@A3NuCEEF(Du&I+JK~k5<@z|}T=I$2ok^e>B?7Pd!z}3^(0#9<-d^~^F z_f6O|!=CQsxSt1Dhk?b?Om@GfCH-_N4X(?r!643#=9ySFTfMZAD&3fgm7yb1C?^&! z+GwJDxq$SH5RhFbez3ijM)a3@6T9PyE-9Y13aS?cLPcOHz4`Po&DpI2hZ~2(Jx@&- zuWJPQ2RRPuy%jjMtAI89VufA3G4#FlY`%0_EiqndiUlhP4y{?k&slkxj8@UW=L;!1 zot=!Dd&6zw*KWa8Uq3_5&U8?HdYPmi-wn|-I_T!I_q6syGyNQK4ihV8!FC;0%Bt4l z&s(iDnSYsjy>`W?HA4jk?lx4+={O^oI+jUWSxIK*n349BlT76xKeljoA<>qMAl0Kc zk{t_PF*VtXi0GR-QmY`u>76G4D|rA~8f9Razc}&jE}$nC-6BUsY>9f88>ncXCV{VF z_mNRXJI9N(&c%xj@e|1bbIZg@`CMaLYHvivuGFyRrs%gfD^Av4$wP zIskoJOR4|m4fy@+0=6si9(Zm^#tIGyU9 zPpRZAj*q%W4|HBn<1`0*Y=(Z{g9p|3;M^T`bX8k7^VT4gO<5pD3zxjIv8=z&E?w9{ zlSu){JXp>sytQUKX1-#zmPr8k9EB}$%W>b3pUfTIT+FYr;)iks;Ny+n(&(~uI@8vR z|A{{nGe+5V%r|9YjUB>C2QFaOdzQ^AxYJqJ|i_|Ep%N+IFc`3 zj3@6NlM=d#+RnGep*P0B)mvs9*wGm^WTmllY#P<)t-|Nwv(Ro>6O$v-#H={533or2 zg8+-Ius!TP&YzU$dD+~z3w$Bn;!=gL#B}7 zJA@#~*c}e)4ab_NYsi94v2emcl9V@Z#*udC$TJyJ{FQfxD*eg_U7rLPkd{F`nR3|j z(q4c=IX$8ICAi^ZBt6LKNk>~dW6A+@>|8n(Y*NLTwT>@|X3|?ya?hFmcyk<=eGI~# ztC2nzL^E^W8^VT<47#*&e7a39Y-$^f;dankEHEE}M)Pgp>4Qod-r7Ug-FeH_@r!Vz z!3r8@Jqm8U-h#91Oo)W#WfJB1gsclohaI917~RRv{i?_#319b9p9r|(Bf(wiUj$h;XUOqKX_(27_DJ)%CeX6ZnbmED8x$}`EZ zD+74rCRH<~!%o7<*OxIXdm&UdvMkz+V#PU4>>V#+akG62(acYVFAFwc;+qp3m*Ot6 zm$AgUOl>?~&0%{awQ%~1T~D{a_M;92uRS~<>zICyY&<1NS8z1t_?)raCF{bh}H&@^Sp z)pds(zbx@$1BZ{^Y(%PNM`6P>V@7>@22>o*BP%9`vA3SxCDe2w&ib_l-l^OsJlRh2 z>%&=Q*6>_%-CP8A7=@D2%sd=1LI(%0=aV&KddVl(L9Bs_DU56X&ISxXl+zW0`i|FR z{i#?^MB^uhLUrIL!eMP6uXKzZg)#94B9jW62~x5P7f2Qvt{&9 zk21BIrjEiT(a2D`aC`^`eBXz2^t*7r`!Q0s zHkg`LrQu4(4PU%=VQ1=wLK;t;bjeBxW@x>Jr8cE>#K=^r5UZoR&wt~%9rCdkK2h_z z!|?eyGj#mq&0mTGp=V|qc0DTqtE5}-NmCB|bC)r%eTA?_F%$PSeW7)_oC>JUNbqee zMc#)X;+q{z74nrxOZIiT`pFQh1*^GnE=8Jqb%XF{#*<+q z`80K=IcC@jp-j+PvLQ`}tli^avpMY&@jK^?-JSDc7O0bX8tUMBER(jVo`pve6KII^ zO(JhH7{f~slYHwevPNVZi3mTyNIZE#Oba)_@Hu5rX&gj$46DTQ#7xHa=_y#G_JSS@ z(qJA(BJ-9PMk3b6u&P$lB%om>>5v!#AI*Is(>rWR9 z7J>Ql>KsqCGO2ZtgylPoY=#BP<6YA|^qZ;<#*gOgbjMZGiW6ZRclLf(wDS<0C4=dO z1!1guMzxJ_ST^eOzS5eLG33~)Eoe4;G#Q%gji)Lu(o1N{PAwh<8=VHzNqOS*&Nm~x z&H)BC`5dEs;Q`dYFo-^XxRS- zGj41Qbq+Sg*NeHe)sRc9bJt_yg@R6?8Eh79I+RD&swOex+hkz>G0G^W24P2WA+x-B1)i{y#W6Yt_&6-Y z`pO+yc9B{&Ht1X;HAOe+(#_JOJ7gg@Cv0Xp^+0li6+^@FYm9^5N6M^iriaUTxG+ka zEcJcOj#gI2J9*|fYI7HD4?9QqEsvv1?SiqU`xtrkCZ3dESp_GPl`-;yBo@7VP9ATH zA|t-!X@qn zMmMB+7P8MN8zT%|a})5)=3=_6>j^E>vLRJ>?@$M)H_X;|N~F|45^T@eu%LOENIzOn zL^{KX&g(F+!F0Oc^AL59xyfOQ=fdGaWuELeS@a&E2>LhQk$e$HXkD|D6uRqi+#lg! z*y2etRjT2=R2IjB)kIyB1dL$M9P;CpJA6!zXB-asv-Z^&sos&@jNiCc*w0}p{N?sQ zvX34$k}D-bqE8r9i-EYklTc*LH9XD%dcv+-(eV$XXjY0a&ZthoaYxPB<%WTDm1O|Y z;-wPy$5_bk9fvQa&d`ne1O&skklK6JMEN&22(`1sJb*1a>Wqu0&Jlbw zE`c5T3*qg@DR@lr7JLwi#=-B$(7Ihe;hO0lqN43Vh({Jp$$m>(f*rxRi$Hzc30SI% zaEjxbJJp)RZgU}Y!o@Gts62}fnqvn^xvxpm-Uv9l<|HnkJObGI)pTB68PS+*%1D`d z)6*|+Q6;0v(4smKS`?Krf6{4kh~pOVy>g5goYDt&%|w8rQYObShs0-h+xUYVX4|?! zd+Bb{v2_eN_=!wmC3uf?*j-Q=(_#J# zsnGWvRPN&K8qoZhWNi^%67)jCx zbr5%s7jALz0*KOxAYb!V;;Yej$+(#rkgO>IAG^n(fnG9-7+9mqj$5ptek7&^AF%n7 zwx67q&Y&kmCX*4zgGq$?aE_m+mqz+26VI2CXnA`xUO#@2CYJ7ILJu6M+OLvDwcpLd zxjQc~i_UO*e{+^>n&QFnZm1N~{G25EseELh-G5rX+=p-Q-MEtKu2iiDPl* zoW11O9#fE*7)}b;CPD2|3Fz%wfa^Y7B?j~oIb**MkHke2wd}luh6tZS~>V=v5}y$ON!YetwpYs%b;eX73ht4jvAt2C-`^nO(hlIr_GXY3Hv z;y7=`y>zjzBo5g9S#Zjl}!XeXNQ^lwdb0$dnz9E+d1!EjwHEkCw`t%+bs z`A#2VBF?!JqXi^Av=QD-R}|PAMC0+3HjwcrnC$Q(&x-!*98Y(_?#hj`kKAsm0)g%lkchZ$kY z_|s-CPFPz6Ysco&>h*>6int-l+33S|yYDnCvJ8BhZqmKk1@zV`SrjDA0M|XrL~8kL zSa@{@#O1cq{7q%7eZj7@=E7H5ZcTL*@x0%UM7rBtU;-N)7id-|5&-?1(Y}5mo7T)PY-Hehn(NB zNcQEB(-Yh2{ihc(eWet%c;&JNJ~>z;(MG*~z*w9kJz{(B!! zp84^?P$!Pv8+Qpdt;xfb)<<+;mJ!|QBQDt2U4aGHqcGv06ds#V(?^-BFzqqkV) zy`AW7D4-OL_({9_=)aTByzX63$t2SOa>v-5dAMX9@?W&EdUOE#wARCyfibG>#lszo z2C@58Go~Ad!kkJYBDKB{6i<56&zb3@)#4S24%|ZgH|(Ed3@XW4T8k4+t5`Kc88l9SnSY#jaY+8par6^WDfPP)g{6_=Lf z(fiHwXm~;Z**8gx{w%1+y~lDvY114$k)OjBEVu+gi}VEh)7#i5FJejBr5E)%KgwWG zsR#Z@&*1xJ(fY@gsZ?l31CeAo$MCk*RL=Acc*XRxn#b=zUvwdyrO|LNkdpLY`$@Jp zSBH;`lAIhDJnSY57ZkqX<;SUX_aNsX5SVY?mQT6z@QXM7~9 zhQ^q|_9Q&^&zwf?o{v$U74T@eI2pc{M-*)qlU1TY(3~npzGPp-qmyK5##E#Z>TOsF zl|<1!73VBThMlR2Wb2oWXtunSn#*J{_DTg@(y-SRrAYENQ zQL&erH~^8;5CbavfQ@@i=W7vW6Nh5w?0r6`cpq!-C#RWRFlZZ1ed=SI*5M z!5riEqt-ce`WQt7*M6~u>p}!s>nh=KvIY9yQAfEONx0Zdj?V9YN49MLME=!^F`1!x zM3%gw{az_lSbPR9=Xmk0TU0SvMFHFX>;=0lJCd)$xfzQL*#8uY;c(!%x>xr~p=Zk$ z%nO=E>iu#+S}&0(3kk@%`OWNxp69fEEe~S7`{|d%5fHUtDSeZ3nLZelL}w>AXp(Y9 z)&Dku{FQKYnz4}UbttiF(>5b-wh=kqhBGNSTwn5g40*6n7d56D(5@Tb=rN;H zWZR1!;Ou3`c_1iF_)}Leb3U|getJRuwZaZMaHEpk?~Gx;4JdjJyw=$S*$n7JIMH|N(0I&jAaXKj{2r?21Gzco@I8&^ZWuUZUo zDa+7Ecsji?xv93VfnyfuB!eKViEdx?h$P*Y!p&A9^q-D2%@nF9F`hB(ly@fh{mVQi zrRO3YN>HGmukUA-%5p$Cx*5td+gR&cI@I*$MLHrbi=m=@bj)58Mus+kd`}c^i#f=2 zx>`ea=qjkLQ-g#LEmUi0CboUqLLTqk1+yDc=$w=nkh1FW@6kcowoi=5$~WZi zKsMwr_r~YwjHl|Xke?)tcis01KFLXun~r&OhD|MI-PIR7ofk#@Hae5Y#|u$LQ zuZZh`=YYbDMc^JJ38Ejf*-v}($drRZIDfE-*gcfSCqM5~iBBc0?o3x049tQH?j~fz ziq%9$)EFji&BqyO@vzHPm-7;Dgt53RI{C~f!@DlZR2ItfDU~6!)+)g76ln+uzQWX1 z++nTbE7|$N??~IJ?d+bVM)36cWEkvuLpS%#L*+HkSj#0k5ZdfdFLzv{fx0~C4$LC* zk+1OhyCTAjIKn9rNBqOalNGvK=&@&$Nt$Xnj*wiMeq4p zN6uaEoCEIk)S24@3R!T-hDm_7?@#rMO|EK>;EejW^ODf1ILUeJkA|; z5nO);q4Sn5B>%3E#kL>GF9R!DePtbrz5Y@E+Nq42cWS|zHfvsL*kVvV^o6Z3)unp3 zB;ciZ7F3xuld{MRnD2TPn%3Dtm6Ie^zPSfsJCCCG(fd@~v6A!zwL{FoYuJ3~Is6bc zr@XMWC{UbUzIEfn~l2Uye|86r1z6KVB?onXP88BcE*VbcJ|ncE!< z{YnXNwdg0k>+ytab0ruwtpxWRbigE+tz@-Q63o#A_;^nd4*nNLN@_%4k-&ieQC^!F zh;79)ySiX#Mm#jS?}YVkn%FJVMc4f)0A8sOzd^AJK5%pN%H4(J-Ebxm%yOlz=a(=p z1)JgUtQUlAP1`SLqL|oEu$()SG%bD1e9o1@otu_n_21=qp+^$+ z?jOPUzT5O4^Of2ZS8;6bRF0+BPUm~RCX)h6$w7mZ`g(_SsJ506xI8hWWNZ~qTIP#( zg&dnaD;N!$V#s5I+obfzewezUmMGZYBU`uj@|rUi;)C@GIBfU0{%>GEuz^M7h1o=i zEu0A66UE8-3^|lhKO-$PAl3L+ zGnz=>RY#qsoA|L=39S!4XJf>pF|U3cP0D&oWpf+Ir-o))cgdf*wLydIv`c}2Blb|= z?!<;VB;npLF$zHvv)2)#x{9+@MQq* zd?bpcjz5XzCK1>%&z`o|bhABHi%5X1BB}G*0-8Rh=)I$w#I1gh_lL9Ly-pQ~N?sw6 zpJqaq=QEER5Wdwbrp>#79=^VeRH;-_$?cr8UMH0~q%ua^lxCvZmQCb()xs)2O)9q98ZvjOGk?@%_;Z`P*;|jlGUjh=FmPTU#~qyq%jam|H>Wz{ zUT6XL9NNi~J878m)CX_viiMO7ewg{-DP#Hc53N0~j#HI2*~dW|xUFCtm?dohPP_*u zqkYW5=L;8hi@Kn)cRrr)>0{n|)RFtMBgm2m^;q(BCkl<54Kgk_m}OsD@uO89_NI;# z6u5k)OBTB^YR%)ZU7DL8w&fA_ze@P9+Y680Qo!2&ZU}}dR(0KYP}%6oIe6R1qSR3` zMKP34c4X<}L)%G*qd$pT5swRR&SyuuO3+C;nRKo!B(o!@(%IRqX6k;0vI zTlTNR@v}-H+98|n5xYRP&XmSO>MAhnQZrnsECtP_ujtlxEjp}e4Hcu`DAPfi$ESj+ z)?G>5@ozHz6iCr41)In~bv=%4AF3fB@r`EA(bvt7?9RU`%7a;=*SG7N=yZ9 zdZLJiNpVEPq!LS3d}l=kIyl|l5G4lHsqOqLRCDqr`g7I`sx%?9?(<`JgxOA1a7h8< zj}Oq3`a|GuX9zp*te{@sC-EAJYiODa$ExG{6blUciP5G}YW+Hy*PQA!>9fQ67A8fq|MJQ~W4qs9@MWV5ORM2VO% zZL*VTfR8SWH_oF_P|3cV>`yj?#?edB5;$?=c$BEygsIWDspP_4jH=H&^5JL`4gcf~ zHVxmYf4dT%CnZ$ES(oiyD@kYX(_qKHafS;I(%IKGyNQsn8GWvkj`KK=f;nbkV! zaPN*9+k53J>s4gMJZv_@2_YXT|G5_gwny^L$Goh+9I*!;@T18I%_(@Lfy?(Kd$HLQ ztLW(AFgn^$3HP`H0%%Y~_L@yEP{&lzM)4P0J-NresdQ{+IxgOcS%n4WLFMwlg zCivZ#!GDS0$&+0QN~Z6VREQOEHc{*aBs=7dZrL+_ARWQNKEx}U4tO8T|vgWr90 zpYb$&xDso$>0=O^rcGnsxS+e)UovSd4G;aQ4qk+!(_{^+gDFd&Rw5ZvqD#CEg&lSI|>HE7?AiK#DZ$B{-BrmNc zo#}c4X0j9=DwshQJU@Ur9)~#BR0-W$-bgP_oR3A<@=2FVGg-JZgNXK&@l=+rq-AG1 zV5Y?_a&vARj2xJSdsTeM(3(`_3sX}4u92Pd>>)`LO=bg-^L@7lfT#9!*k!SlJf3d` zF0%(2o9cL0dctiY^ivD=;WrG(3}^`C4z0r9r7Q4Eegl1Hca*yScvI*8Ljn&8O3?JfWOV!!3D^G) zk<>4-*zA4?{DioCVW&9jVG)hNht$Y<#dK0B9Y{W1?Sz!Q4;anO7NAjW4>7-UAUNbP zz1rbP8(SwrdW{&r^y5CNeqk><-k>LgA(5dtDgv%yc<4O({i(g$rfFlFu( z_FJ9~o2KZ%^U9pd@qdouP@z9{<8l~U(`9j>{ywyJoFds?&2+Y*0o~b9PwiDh$k`0qf1H5y<60CrxNM7hV<2FH&L4~lSndR^x7L^ z-k$AyVRS_?>AD+49xa_qE*m#7|BYnPhJsa;h$lvgE;SS=4|GZR4jd)c^(=cEx_%3F}h-H29&FET<&u& zcx!YVy4>xo`Y$pI?9vUqw-$ldp(z^>#4c5Kgt%icmplGBvd~C61Gn1=So6d#YqB@JCFs z)_)T0_K`qOM;n}UyoK&{Uti~MSxO%)ZiJfM7Pvs~AlvO*KqKxHQpa6qc$c}XV~sUK zZ>&5*1%M?fR9z9e2X)zzI#fzs#CRFy!t`x1H&r;$^g)qfgh3tYUt@ zd_u=py+_}AP24!Ao8Hp+&V(Fwz%31&$x6eP&>_^?F&%e5kmVoiT7oa` zUL^emD_}=-DfE8y0YSYx@6PHF5X$B95gFow8Old7^T=~h50ivNuVctGpL$4prvNK< zSHKNvIXM1$E#qtzhq;GT`Mawe;A2coy~3JudUrtx8Xgd@-!!p}Uf*4Z6E}91@JclySojlWOvwd_f&ZAX+CJF4rvv{T z2K=YLALD$JAgHyF?)E*6@8lU;!%9K=7Y0%#tF&YB_iv0fbDg9}7|<_a=#<5C*?&4`_7FTuGy z(F3XxgZVrkWc3Cu_HXC-$=`{r{0&9*a?;xtDlu zc}{I_$K#i|*$_8SNRtXZsh+npXfF>(<+^^j|N9$FT%pDf&ep|9Cl*TT5^!q-H*08d zr^{Ehk<)@3caQG+`B-3FHKhQhOwv1QR#Fg zdM4-7758-@v1c~?!iluQSb^SKGg^md^7J#LF8y8 zl*#2YO_65!$3+*9y4R4#ph%{3R~wPcyaL(#PGRfqA4H<8j5Z$3LC3f4=#*Fm8{Z|s zVu`6#xL^%!wi|;uePg`)vL5-@^D*;HJo_VhB9?KC<2$of^T(7=&{LB&`HtplbZ=%j zd+b&`XsqnQj;*ILY|1v$`{X5-Pg;iV64HVJdp!*K9)c304$OwT1TO~5GAkA52zbme zm{eM#?-zBrG}Ruf+CGBYAm@N8xJffa?xLo>tw1}Z1x>rtNv2XQjy#QLoStlFX6>)6 z)12J_&A(RgjemM#Poy%5(p`e%4vy!4l53+!*JnbYxDs?mJYwF7WP`2GPx?hwfqzV6 z4W_-? z@Qv3ADzo1W-j_V3bx$UN>TF+FVY(chA3nz3l{xr6r=IQ?Dx$VK`0$b@V&uZDf|vWb zp1Ivu(i~Te5qe633z6Dr^db!H^b3jCw9ly79fGBNIoJ{zLF4u32u^ePiRa%~@aT%h zU0y{*VL${0dJl-1^=Wc$)?spIkqqseEe|HfFIf^AP7a=^BAq6s%$ybPiF8p5;}+&g z7CoE69($yRx%H*&%Oh8zNNf*rmo_4v*Q?kglb6FXyR{&abs8=-r;?pl0H2C%#Q4?M ziG2JWj&u2#-sSqaLxT)?rNBMARoXa^;y{KaTO zej4a-IT#ZT52A|Bac1k>V-VA{5ij!%dHPL02o8#ZBEBMBvDyZ18;D?r+*W$+)*^6S za*0^C)Zp^9D>1-jJqRnVA(JY+aHD=Xamx?qO)j?L-ghZfp?xY;22KN2)qCuMs2bGB z6=i&aCHWF>BdF+;p8AgqjR8)-V_r1K;@UfNp`!ILRNJ+Xw*#Me17qiDNuDa}=e-z3 zeSgt_gkq9A$Ufug7_}@)^gOF;rKBhaMlNqPc1dE#dx#O${w{Q+_Fo zv*@A1rLHhy<%vTLvT$|Pby!K}L-4Z;04VA%RI=eBrHde`g*CdX9pJ<%B3%~>da z@D?oY_R&LkwsJnOwHnB_ z<<0yjsXs}d?+n5G)<~H7Z7UkstmTine@53DX~ByLT)*3S7c$3+aovJU*s$y@nmqnd zf98HEuDm@#&}4d^#K@S#I#R+mr1P_R`5C0 z0CUfe;-GOdo%rGit~(5%gkAVvCXyG2LVe|7=VLwJhBUfA%Y}L6+8p9ec-)tB9m9={RNo%*LR_ zCn30X4m|HoLu>tiH2Ogh-DPov)OVj_zpTDbR&~n4)HkIhV(tT0=36_X(JG18Jh&V| zRtkyX*r9exz2w?GN$?u$r%&KZy+&^s+ANKsvQ34!PyzY=SleLj)^JS{B5PlbZ=i6o;r999&SBO;e{n0;?BDQautS>j}qRM9GvR2 z2OT9!pht}RpPfjUE9I_eKmIXY@o@v2sp^X*!d$K8T8`%9#KAXYDaL<43ZvXCCo=5{ zR=yY`J>|B32n2lB&yir(-bEc|>p?2^OOk%f#(pO=c#&K9>$KKF-&i(#k|9G;e zk;?_Fvjk~*bvBk`oF1LL1#drduOGkk02ry{prM!z>D`@z->VMsI(A9XuxXO$RkV~Z zWAv9C-k=Z7CQ4}dEtYs0PXaj_D_Fc|8b3W}{9@(J;{-R&C&ImPd_E%<2}O$}1l8ZO z=;p^jbvP&JbQ59zo4R;3o$`sy{dE@F{1gPEAD@zoO#_g~IYES1p2vubH^5JF7AX)x zjQn~~pj!Wqo@H8T=h}8!*q@6YvYou|bz*{xH_niN4I*$LK1(o=)k5@&uCny}16En> z6`H6=!jXP!!N!qV+Gw~J6HJ|9m9QO(Jy2zRLImW{;~a>)*6$nx)~ zu495f#iOc57)~zD5G;{=js2bzm@235)ZMuNSIUZ_%h_1IbGHsGJm*08sa$SyX&W8P z^}#^mV1(e>5rHj7&;S;us%sf&8&MJ-gwQnjGU9Mq0%SB8Mm>{4`gRx zl}-{>7CFf*0#B2z<gH2)Qg9i@+c+?F?^9vUpA|5h#*&{F z%Gmt(4g39K57XgU2&X<=XJ+NE;uy~PjK)k`Y~K?}G%snBpyCP8eQqDQZ=-->C2qKL z)k&tJK@(jAzpw(^8F-7U{enz>)1z~Rpw&l@&8h6Amao^r6^rdO)+3r)RZJ$AU8G5s zjR@z+dPA72ZG>z7%)aKMJ2 zwPcVatIY(*^Y7{46D^Q;48jV93iLZ%3s!S8p(}hY3Ch>zZ}`jgqr@C=)w)X{UttZy z3adz9vMj0kpoh0SrAWe<2=;nRB1T;g;PL*Ccs7ZT0|VmVaI%I3X09bOdxDWSz}+Vc z_2|*G6i5|+Mg>!41@>Hq=>5Dwh%_39FJoo!?j|n7YUad!hJ*D#Tcn}Q?KIt%WGt|^ zyh^)|odlgLw<$CJ4CyGl4t;?gOu!KtCgZUSh_63{6MVD4E@>}53)%-8>n7pzrkT96 z?ZU*N#G!uN?L7K6;T~F@`n%ji0J zM{uv@X2=Jm@MniTS@9*7d_Fvjez#YKe^*!HfT0S}JQ9x)hg86N>;v`s=Y>B#2)DBv z$@CUw!GqZb`1OZ6$R0MJyar0F%FG>0~bV><7c-(>K9l>9>+zaW@SIwcyb<=3V+9jqwh%Oe-Tg|eFBs+x1sQ~F`n}@ z8xV`0KmzitQ1MzEnRj3@zEumt3*9@QYhDZ8Df$6gpVrank2jH5GLbp>y8_FdVnM4v zn6BE8L6(dcg57bs(ALQ1VHDNjb6YBAtq6sNWtT~rX(pcDHVGZ7UGPOf5Y9$L8v^!%QOuV#|>*Xhsf+O|Ve-y!Kks?-XHHDxF6vux&&q&nipxl>T>_fv# zjMwB{%mJf3;yK^}r(Lcd~W)#CyU zXgq=jI~4IUPYMd|Zo@FA5IW=5VtOaNiR>A^4;Gmx=~<)2^@oQ{Nx8WJqatZbvp83l zh3+;kf0aQpnJywzr44f~YjG0H^dO~i9T*CF*|2Jv3yh1KEF_)K03-?=7{j}A{T$%yL} zG$v!B&k-z%lM~GD*p2qV15{*t4i3+f!L5Hwaq3A?u!zZH%e5DBJ*^d>w!{)HbNk{O za|Y<^dnahVSPrdDO{QAjfHR++qR+QP;UVt%xRvEnE4|~?>Eti6JUj=|1AY=u&TXi7 zISv&L9zq@C_w?}8CX#X_iAH_srII^hh?>MSkk*wF?9}R@rQb@a?#%OG^?oNIdgI~P z&TT~Obr}1yaUy7!mDjI|^e1IS;kc{k7wNQGLM%hBL)CB%`2Ea*MyF(E-{c(f%qENO z>{!d{9()BK|BSJsM}_%&Op@7w(lsP}=@s}~eV;_gh(hES0v_)y&|a;V?B450=+$z_*Zt@rECX zg`*=L^N1pEze^$W(v5^SuS9;^1ZrJ)ot5fb%5!_f&3(?c(I>hppgMIw9m<#n3w~T7 z^JN^U-Lf)PH#Ce{6y8A$+@^E+P9xsjd9&+Q`^uBaXXioDXc=?II~EQX8e^KDK5XM@ zkvCpWm^;Ins`(}ni%Mte;hoOL2QuK55lPMMYIuyzEV@Z|2HhzxMB_Uf;c)5+`o}(m zS#YbJJ(+))RvX!qgKrnm7m+pO**Jicxx&P}H5fy+vd~@V2@_E&4ljR6;&oeN*z2?s zp4mL0CqqwBE|H1STQjNk@?5gObt8=ml*OFtyTp0dI-=8&P5)X&kgPd=^pxcy&M6}W z`}H1^nVZIu8%>qNcrvZiktS|KgY3Pf!Z=#$$;>?Zg*0@G5}l%R zv}-?)Xd(7nq3T(JS+W(4&qJjC^6SAk^bZ18Ha!bN+v@KRnd&2<054w!$YCp9a{ z+oCma%=HrebefWqv=nmw{SkPPn~VQ>RS@~SM7qzS8M2G9xx&1#!jNF-w>&*_3 z7gpu)=Uf(bGipTfO_NFRzT@Qg_d7&a>L4h2T_*)DCkQX}F2u^YF`MTVFiXH6J47X+ z)n60_AD*Sx(+v3UFEo(+^^=IqMGd?&KLMWKI7X!%tB~+QurA{aodzk~-a{YHX4+xi z?M?$swr0^}<8JcWvWcduekMD{xVvZbHn5#o&wji#1I~1r&=0?R;I^3xze--3uRF~W zSElEqtFgTxSumcaEpOo&#MM*xnG*!5{z6!0q=fokf01+RMo?ixJiClY(PzWQEy?iod`f(`9on9&ci@OoDfg$adZ>Vsrb zb$OTe-)sJ3wyAJW<#@OZ)Mx4yt=;rM?G~~4@ zxv=9ET;;y=pa;4TGfoWedvZ?fCjqqLi7nBx5yk4Hi;y#FLyo5e<3*qKq=D;!?TH_u zWPJ@ieQ6bu*yadLD)-5RL-FhkT^Yec;X5EB978AaRmkH3jvvweir5$BgM;{fTHybU zMk-E$<1r%qfh!{5YgR#jei4S9EidcC13h4O;01R7k9x4RI|5J6?O|X366L$5NI{Zs zsoC)&QM8#=MGn2zgT8Aaj8L@=jP>i0QgtuzNoir#4}798F&)Fgdg|v6xWPQd2o#+U zY=TB3V=wv(6%^00Z)Pt;-g`@8zhoKOE>Pxt^UCavv1W+Y-zW%Npf327a*Tw%sKML+ z)cK_sqw3%LM1c~=I>`M{PmhEJL06bBls>vc|4r~AhAF2hzqgOQ5X;T%_Jk6ZE9%VN zHI_u8_at@yR7`UX=Cef)?7=-&nHQarhks)fNy3K5B=2M^Wb){Y8MuyG-%`mdW*5Lu{r=>i1SolR z7ccxyq*;?=py#hQEL;AT-H~U2PFptN^Xhi2TT%rop4#+ka5kpzJq{wXEVZPIA+#Qn6*ONVcQb+^mojIxlZ;7 z^V8t-96ivVQp^rNw19xN-E^m6Ao}c`gsTpJCB79EB;MpGs`!bsMjm0PFu$3GyZHj+ ztw{4CU$HX;*T|kT_H?YmlvocdV>~xE_%2yZvNwgGlZ_YszPW%}cEzG@=^rAbkWLlP z=%AnZ67st$2Mmq7K_c-XQS&HdVzR}t?qD(|FZHJhr|saRz9op)MxtC{8ps{bf&990 zbk~R|PFfiX?&oilac!r-=5z%l%(R0^CeMkpLk6lpoeJ2^1D?%VJnrQL2T~)kv^yJ1 zU0d+$&RLj{p~Idm>|!ijg3&(dC`~V)0FK|Rz}rEHk@eaDohw7&mH00DcJu@DEa3|o z(K$^QA4(y&*QT*OJ10Z)?>$8S%4HaE^Pxrm?vXjeGHCwf6*;jug3fGI1^hFO{e6Bu zZa@ZQ$2sZg@!q01( z5N0%om68nt<+&N?GC!MlOEQFf%Gk?l9M>nWightYCLi7xej|U~Z;`RZ3J`E^HC@_U zL;Fr;vsDhr%^Z4ldpP~=w;C2%&ZJ!5?;Plf^S^_(jTRWLlXBpU1@-4+k7D}Y#QS`#g}-kx&Yd4d78vY-a|IJs3bn(I2|ntcj>s4T|0W#^w%plI(s_ zv_Jb0R=H|nm|ZU~-S-SypRfmIrkKS`ze|@x`tl=(!=`^ zAqN*F&r*T=IouJ=^+35iY}=>=anM|b4-ZX-a+$rT5}#h5|1b*Gxx3-Jsj)axJ`u{Y z%c0iLf{NHR)3FBu)Y>bK%xO-hNnVvSAax2=yfX!q?76IzXCIA!ErTX*W;lKBEIM{< z0W=$@Qu*%nbjR8za#}BkzVEt4HP^YK+nYVu&R-6X4Byl*KL3Pl9T!4HzlYP93*BUH z+A-Y2iz92DFO#?6!45BcPSsS!u>Qaeht5{wtzJj9CQidZjmKnEVjD9{ z>oU>*z{mLWK}^!%elqXzIeb6Q99;Krf~Fw6i)x|7IWlG zC%t>9n7m5OAyyZp=wmBxE_q-NQ@*vHZc=7==Ii^YENn=*VHZHu$&{#E}D*o76Ul- zsuBrUc7=Wa&XlSo$bk*F6BTyC3|{NIuwnl9$fLA)6iKY1%YSAvRt<9CJT_2ovFHs| z{;>ep*|@;LibSeyr-K*2{-8HJlG!ff7S6%>jrM-O%IJQ(&CFD9W)l>W$)x0S#9z!D zX5MziQ_rF?;m>bk`AigRJ?o%i^FjJf?lW!7E+SjYL%=dapWodnPr96h;Ce!Ly+*%) zU9)5#b9=ueM#gPnnjRcRRsR(BZmtHJ*}R0zLn`=j#Rz!VA(Ou$6%#x&v8QX4yeK|P ze=E%<&gO3+`rQ{yU6g{2es#p^)dYSA=g+7UN zi{n@9S=&lRi_SrS6SuSA8wzymWd640F7Wv71V&G7fZQDru!V<`h+3Kuzi@9W{eD^% zmk#i0)5DvfRDTdQ_0D3BzO-g*vT7mt<3+m1B@K-^%**N-Qgn&yOz4l!r?;L8;|IT| z=-Xn1f7<%UV9ipqeGfyRm`w+UNuc$sxc#cKXi}u%3L$r5nEtH2M9L@~KaGFJz6jv_ z)yHb+KY<+G*SnudKB5JlZWm~du`Fn3X~OvfR_wi_7fI^ZB-F?rL!0>p7*V&8h6jD4 zrk~ZY!s|9^*%VB}^?s526}8nq+^$(4U4Rh#o*MktX1oSfVN<3Rj9CBOxhf`;nQX`QL3EQn*d@ zbPb`Ppd3yW>%v*itC(-`i(IG#2mqigYMG98Av4)#myj zC#Y%ccz86bN@uKI0h^Md>KbldCvrE#@J3=SeJ#P&Wfx}?DYGOTv@fNqJFXHLZxtvG z$|BTfCj9W5#cQ0XA+}q9W$PvYH zvfEJnoiRiVdEnv$smyTRP)*Dm6R=A&z-v!ep=1TOek0RB(m9V6m%Y?cWv$v)d)BfKRY43${2*^&Oc9*V^3%hpXO{xG-3zySI z32P?C_YV0WrB80J(1*11VbohCl}7A(#5E8_|CEkBL~c1tOwkN!>wipL}@~)xIB1 zj2=Z(**Z-w|2<0OoxW1-LT5TNGnRf6;$a@t(=~3L#HU0Coa~mvfVm%x?@)m^mVkPt z51Fu|o0zMUWvIzFb2w(K%PzS#$ZX$r1p}J7-Dx*r&{NvZPM^e3SI=#5*7-1TIxvOt zJ(^G_Qxrm*sVaJJz6RWu89plb#cCTDVuR8Wx@^w_e0b~t$O}sm(YeY*TrLK5Ew%Zz z_p@O7WDf|O!{y=Lr{k|d3#<&}a{4tZ`3?tfGcFk%m*~PTB9t-#q>riMNc&wHmu!zR zb2&fq)FgN_nd`Ne-{AIY41phh29t+hK$}NAb3}B5z-u#?S65a6_Q4LY=rX0ObryA&NRYDh)`xC1h za|GIWlw{%@i^dC4~|~h6ZP^&sI`Og$AjVl1dY)lr*7aR;DCn zRy4^hXRpselQJ|Z%}PZgY1XK_zeB(0_4?h{eV+T=`^SAf&%MX%b(X#NI{WOk_gd?$ z^;z#BzLMDdJO*0AR#KJHOJ3Yv$Xr<7NpCLHq2Y5DP}kw1*u237u4tryk9HH87qSH$ z;=JITT`}x4*M(J0vh-FZlGigI!qx>I;83N*%IgF&9uv-CrtLm3dGv|*inix@nTya+ zpoMk)E%Z+066XFFPu!Vl1*5&}VYIO^c~rljj_o~9%dJev3e{8e+*?aLzc!E7d`uMW zO>d%8QoOO1*JG>Rb%uUAI2=#;wF@rJp3AmJIaeEORD>FRKh7&?y{No45Py!T2OsVP zq^g{U(x`9Ha8`^T^8YCOb$lj!xW@K{nm0z^<690y$q(bl!L#XQ^BQG3^GbH0vVM-6IX$ zVFx%Kn*`xg_EF~I6p``hTIQMYSM2?`7Um5eL=HC(XN7X#=z!DTX^Z_3_TiO2y1cI) zf(+NdsMj87tx=)Dd@ zk%Q2m8NE82T#cIuEgCP;*{>Y#iW*EjOs*OQBwZ!O&Mx*nIYk?_Dx zS#mcU6%W!R`Hh93`m673r)T&qbGrfOXy`b!@&zsr@-B&>}{ zu8e`5t4zVFdOx7cRrp?sig*^58;XB*KxgLHSLsZ#?ajhi6^g}d;h~~xz!Ct7C=FW=h{cmEE; z2!?`oM>mD#-hNg;>thriG*4!*_lRf2sGjz{*)0RWw6wr$vYDunJCypz_J)zNdmGjK@}Uk~T? zGkcl4)YbJ9z58?#)3`N>7!EDRgX*j4u8Mv5D%Kj$cEyvmtJXuh@FTpfNkj8XgTSV1 zJotBZ5!Ks~)GXpTb$40_u9@*@t#FivKc9;if6l?rk7c0oBH>oTBO;2p$DIvQf^vyI z(&avpFftp!+$j$$vZg}Iw?nXdfw&;+S~k~Q{RU!9EU}Z>3&ZV4lKEH4$U>XRG{$Qn zG(E~ji7RpB&F#0Sz*mE}gLn@4%64MF_YskcBGD;%5scrm7`J-P1G5*opszQUyt$qM zf*YB%Fl^)y8)O zkEhmyuSlps1yw`lzbJ-E8x9|}t>==|t@+B^3Y z)bN-ONB=2=>xjdx#&JX_HUJZBx6;OCn=$93iAXJoUuW^!hLS6CCL)$Oj2%4t2XjeBKweA$Qn5Cd&(p_?7s4-qGxrYS?+RSe*6La)W&|igXsPc

`isEhy9U&ta_tMKLU7%VKeVf!3>Ks;(Tj`%x>`f3W!jh|P7 zoZ~|lKVvq~25Cw)l&AdqWo)Hl1{EJQ1pb%`z08-ROA7&B+$+cE-44vcaS7Rn_F~E% zJ#fEp2C`cw3EU$MRH;m2*WzNBo2ewEghv8S`p#Jk-O-sBe~M;}m_wdrG3eG43Nt26 zV1BIw;9hMyx+~9xzt*Q&aG(@@4H!knGNzD+;WpLv%J(6H((4_4WF}`6gR< z@BCR5b7~YE)NNv(!-PFvhb;3vR$_l4VlXWU-j7nZd3qac0OpnrShwOOlk1Rz`zeud zwQ{R)w_OIZC)>d0=p%GGr$xV3{if81X@XPi1m;{#g-R9SU82{9`j@L%o7`TO(z1mn zJT_zhj<3Rrn-RRe?cw(h8VYsM7bvx{3DuWbQue@^EPiM_8Bd+V?hYCRYHg{k_N)_G z1uDRncfa`?hd$%&j@PW%Bc8Sfw@}-0FLW5@N5dNn@s~m(Nlm$g+b36|b-Mz!{d0m0 z)sOh==6>cW{g@t=9%tds(}@cDXh(lGEn(KMz#h1Xm=6HEp7)TApSE@6^67jxAPh8znPW@w5~BINEayzye8{yQLW znJV;tNhjm*zqrZcJiD{#KREsJEU4v;h4aI`$>H1(P?0NzVxezc_**!$ROHa1*3EQD z^D`b+|HhVVFagPtWz?iL6q3tU!tJ~g@%b;U>`1r3Jm2^LzMmY9Zd&^&smU8hSF2K9 z$^_Af$T+Sj;waM<4XL%u@f5u~m_^as-{7A;DXeTpHl-9-pFe84lm?aT7q8sdignSG zNNb1`xLQqs?VI9YUvNJ<`{ts?3>{iJ`UxwXJ_F1(UU6@aO{G4)c{y30N&gw-5O=ecYy5p4MQie4@wUBG-2aR3%h#cQuN6S|Yc|``E$48iM>ou;)Cy=&dF;uYy_& zqu_Ot8Nt29CBuGsO7qu_39Q3KQS`yxLJNSNdz`Mpy@Zp~Ved2^{to=p&?fC)@T%JL$E8Jjz$8pLt5VNC0 z7tzqwX5{cumnpkj2%L{PF7mJSwVF+GF%fK+;yZ|MjAWMkCNs-OMM~ux zXtlW^Z2F9F#A-GZZN1EUX!&8q-72Q|KA9fJ2D6U!H%VvMXFfe>5qooEIacM?L+YCG z)MsZ4Hx7)1s$096|9Cfnb-f=SZTW|0PbX9UdQH~<-vBUE|H8`x7&rxW03+I_}^T(`Obh$4$PwpxiZ{5XB}0)TL2q^&+y^`2a2Ot;um9I zGwm=RLEqVlI|g&qEin0aPZDNjVZWKC=Wf2pr%$xTb2KQrZy@oJV5aRMLgRtnc#IE) z;kpm(^%D&6*iSXe99+vbUWw#Q6c3S)d?d@iaD`>>eZbY6kin-L|MB4u%DC#B7i=B> zRpeMRhH4hc!-s4K+9B=0JNHasqvxqW_taeU-LjN5`YZDX?piv zos$W_%_ZK8;ycB+dHd^ixXHl?>KB;7?LR4yIk=oc>VIIPS2}$C@jR2A4%TX^wI zZM>>%2uJt#ar^SJxlikFVez(TGKke8rR#xAs@#cU*PLViA8grk+d+{eYzhq-UjHuVYqxnPBk+7@iI;TpC;Yb)Ar&}1rC zqtUi&1ph|Gp4OY};evu{D$xc;_qx3Bil#vb+?ZI^{99vo@65<%0^v z_3ZQ1<6`5g0@ir%I{1D&M{?U&uwU?=qC$K?@>T)qq%5bJi38bymENM*GGR}4z6Sf9 zbZCX)2~MBOp?zM{Ah$1vNoxyvlcSm7u=5_49FrxVkAf>!;Kt|$9_Bue@P}6&<7oNs z#k@t|J_v~q5WGf{$s~2K!&uQCP*5x&%UUaZ5m!iA=X_@*!p*V;2$+)>Z!wx@z-R{*ItT*R>H<6&O8JYa?=HF=uRoM3Q&k}FM9^kIH|HBW*(_yz#AvaOx3%@_9hAnyQNnfJ}z*Tiy_^(nA zch?!=OVI>)yF{7hojJr#9UMUKmJ4pu@E@$_ZZB7I#SrdX{Ecfilw#Ik6^LmlvG?o# zh+g9w(e_d^`%?0qvA3^9w~w??Ny1p>;ZnjkTODC9k1Ns~*#;OixCwWj`N^LO91Lb- zMRfVnOFSNPnR^oXk!`XZ3*w2pDJX9=|4uKSrJjmr-NPy=dcz|OfKXvxu@1W~I#O0< z7C3uG@ZesFs@^H&8({)33|8Zc&s(r6Q_&$Za1S3QUID&LwIhk5hu>xrm*m;{PqN@RG8#M=syJ+M z8!akvBypO%6Pakg;PwgUK&{5NxFIKpUq5Cbs?Ipfj>tS>f7ZA$+Y{0>N!psWm#$?; z`*z_`S38paYJ!0!M$~ZIo+Kt;#B*)|ut`&z%R2Xlx$if0cr9T7b%8Tzy|CB$Hm-pT z3V898g44L^#${f4fRGjA_ORgstHyHIEK2@t2Q&B#YO0(;D;CDH$|7NhF#kGRVdF3K zn}^XAcQrCm$$@rv+;|E`JUSZh%DQs}eJX}<@7+-CiLN1Vp50)6v z_)KfqD0ZaE#u*g0*MtnN@pxseFAcJj6m3zLpvAlAlIp4T!n@)YR>}w?pGgiBJ;IQD zCx*fk)qki^^M#!)w4=jkLg?Io_weWQLy)3;8VcTK3*3vPyh*+T_j3PScE`Aw9`JKP ze(nKyu-Fw;yUi)x>L)t=G65x{v+QWp0cxT;zS=&U{XO#@|4fhL4qQ-$1>AmmeLx9b z3eWY@MMB>5@K$l`wM@GBp^=p92S890QY9R*_Yi7F->E1AMt~x~k;PO3#$j#r0B@tx(7OHDg)dr5-#R>jpQ62g0S< zO62Qwj+}JNVA!BmX#8~=x5h<7-wZeMR?825|D$Q1ui#?W66(Fw z#a4G6fuILN#VG-yw5;GQwph3ECE7OBX+MX;lmpQtdJ1QyVMX%WOWC&fHtf$~8#>rD z3_|!Gkp1a|VU;4hz2djv{!IeQvVEYj>N1X-^G9U*!Cr90oAO1v{cO}Df%hF3NUzVk z(w1F;uuYxa*w2 zsL+t(S7_AZy?|1XdcBMy?vD~{HE+WPwQ4rGunWDXMsX4r)$}nuje?du=?+2sIh_*O2iD0+*zotOCUSBFyH(gC$~o#AYg zsywHEuY=`|RiXn0Tfitz2^LO8KKU|-XTDBD&xaLs>)~GB?V}bOZ)IG2ebo(IW7-ad zt^b(5-+eq7`v#XETaC#-)`Ccl zblg!y8 z7&-C@yX`4t^-9;!uzM%*ywnN4PxpsNYt>|YFyOM_Z1bk(h6OO{gbS$iIrMCxG1dha z5dMmxdD~s+p^_(?^JzK-AAW_a+(fjnD~?mOQUxDK&wB3i#~T6N1n3+Khq^#ko5|D^{Rl5ot?vs3_Dp*+G_T}U=6c0w&Lo47{Ktw zMX1{+M$Zm+ELbxP*w0b0Z@NC@jlO~jIvTK`=_2$TPU5C_&J<$7MPRkh3P#>LN!pPS zWDp|-m+!}6h|gX+C47!K<;ggYdxCZSvJ{?@3@1hngF5Lz93?w}+Z?9>Ph~7|>7Bn^ zU1^NCc}N!jq(BEXpDR(vu^jwmG@j`h8Ibnk%NU!R%L1M2F~>)Nl$I~%ljj70;ec%Z z$cyKq4I{&-a@$MPU1JT7E;;O;$Q~>Q4gweH7tygev`0uy3O_{1rNe`Db+LMS?)iVHI3nd*957#UZJ&*P(@a&!PmjXTeNUs-`S|1PDQ zqs{rT3x460Y0KD|jS(=(JVun7_^j*&00iJUc+c%doyHJ&qa^%nvgj8kT@cI0#52Jqe$}!WDsso%Ll~bx6*F= zh0pY0{J-Vw>)9F9roMu{-`vV)ZFi)e5EYzaAxY;o?D6&dIZPxOPn*O2aL9$d0)tNq zeEy4sr~0b6bzZ2<$a87*|u$--Wr9~YJtmvSr92GgJ zka2k=%(jdavcw<7BKays_l%^Xn6Yj3BMES5PYB*K_;MJ&f@G@J8#CY?#x150)$ zZUSrmCj-x#YQW({4U0WFh61iFhm9%+aF}X3TP)1CgT0@k`RG^>O-v<4x6j<5Z~F8_ z#{%^1#B7xC%odu3k+g~m)?aminoOZjS*C~&S2u!l;!)Q9eJN!Kkc+Uy?Yw{P9~@g& z&+V?sL5cgRbj4#88#JPdbv;z3S&xUpc*7=Kc6S*W3Jlz>>QZcG;1ISUyPQ?sSjq;h zpA1)4Dd5xfvpJWv2-e=}1wS9}V-E%1dCePr81e8ABbNY_aB9JczBNpFwj~_>TuA31 z8_-oDzyFVmW5F5*4&oQjS?Hs+F#C==JahKvc611R^)+=UnKqYGd!q&+`Ttl(=yVtu zUP31K%t@=jl0LyyVj}pRL>v~A1){T zuM1%QrU&flygRJ%=zaW~l+AqpMA6kBhp?ixj27GT!k+gqWR7~r^b{Ae^YiqvYW^pj zGhG?h-_Ancsw{ChHxxYj=dvzK3$Eg8DkSVKr;4E6oQC2<{!FhE8|FTO2Ai1h^CY5i z-p_;LfL0B``R#}ykp|S2w2W7FPoc)9qx{<)1&ch$8 z_l@I)Y{>{^6-8DkWt{t>q=k0U5LqSK5tR^`;hWj8M^cC)@to_D(vpVKpgmPenzZ|! z-@ov@&U2spT-WFGemB2jvr1i9T6HYDKX*Sn(;LSn6dJO|J$blfwJA2wjDm6bV`=lt z_gFk76l^0TNNo5?OnO_%FZfo2{z67+K*!jBe?6|%J$gZ19&#$`E>r6t4KjTQ*Wj?5?SK_IsdoXMHcy_m2 zk*apN3Y~;p>Rlf}Wt=*KI>TO@ku>k63pr~UL2Ac!+&)QzMz8Yb z%ibG8i)|eX+jAO|XXId$K^{Kb`kH%xWH=SPtK^!iF2MO!1*H0;5hg@8aD%^b^dMi3 zLQMqDuEBFYw)haPx6VSdKN;X^_=a8Cx)Og2;$(wrPr*@5l3P@Cji2{q?!{Qu2&9#Tm z?t8)_S_YH)ihbz%Zn$Vv`(SW=u#5_Z)$jpw=6K*jF$=3KBgK2NbT)7eg`G2J?-xdq zbFwt6cTu4S9XDazovkd_+#B8%f5EYk7p94ynr zR@xk3fxY4IBB?fK*Ff+yi<_K=b(k;bIZ{BQnNH{0$=AI(``g#1d8{XX^4UM!h3zgl!ebJQJRu3ewx79=ViC+i`#6*Q zo5I}i1Z-AT0PpMqu5!pG_@-tE)h|9{d3qpKJ~_AtV*mkN!3f*vBn4=yRS!-^h_vJM%g-8+8)D7Aw%+ ziBV({beYMI+eWLyd?|CG3+`R^oCR+(VOJOVLg9e$_F6Ur&s<)B%6&6w!Gpp44c>`M zOO~?FN-N^WFO@|x>*HV*z7+->>>++_EhR^^vPEtRAl{!sMy6J1YWAJ!y&g$DEsl8d zpRt&`(fSF#MHa0Z-D)-dpKNP_+fEt1SmCbxhJ z6fN^0<4di~Hq4wI?9iZq7sP%&pUj#nE1+U-6K>dblHiCN)Lgm7Jsd0Kfrp)7Q945e z2JdOmF`5aUej_mFPZ~t*ILZ~t?V)K?O7Qd4Tg=^U2HfpPWoF`&Aun{CunXAP*tJO& zJG6UPqjfUv^f7=#R*PW&Q7yLM^I0zSqdS%*3H?KRRr`Q)C7O9`6xnAuq1ys$m~!$K zcf(nQEq(SAr>*j34zoPi*f}$~+KMzTe7XU%8Cbxbo8?BEe;%fcqlsL;>>?~)@dgze z)WGo73nnjKh1Gjanfu!Dfi)0dcO_}yAI>pE=4}ZIgY!dk^DpN;+xJAFBMSwX+1Wz?+$x2N{4zDisSL7 zKJMMp;pC-$fPHAY3hjEvbTTj&GBVq6+c+g``XWot3*B&R-Fj?M)W(yS9>Jx|Uu<*q zIGE796LmIAKtz%%xOiA|-yKKOG0!1v!R@2i>M{i11b9mxV;^gu=uet>-0$`2O%%`&Qiz%7umDLGRB}PbYcG1yg-oWxW%8l zxvv)#$!dNvdwSaj8#b-N*omV_=SGUa2Ne2rG25A9M;z$HsL}Hw$Jq5ngILaAM~Hv& zm7n`9nl0pRvaF!dv?MVFhrJG@rn`zw>YL(#dvFRbisw?ty$-0EC~q&PlgNkkX~C`? zM)zuZ8?Ch!mRxJCu`U~awb1)ZkK4*US~9YRZEgyO>E_{d}#IG zM6OHJ=(?m7%^us2yH3cmw}0+q=%5&S-PVorTMxkZCpOr+WDH5PkD$#vpQ6&)U(9RE z4;G)S0e5B&1NDR|+Gt~qdE`R(pJ?Nzoz{3QPRhRTKYys!En$Zbr0`AbH|v_Ug7t}K z(Jxgk>g*SGSD$X6;VN15aqi<*)u%8pf==_#*+=^3gq56shjZRRd zo5uY(@^TneNFyc6meN=IWGZPNPWOL2;=+#z=J2VXQA6nx43H{Y)SoH8*JbrH+-RZBS$-jA_vo2(} zdLFWIgWdU2ac_I7Rw@z2M2{u6H zgHT2k0BTdj`Rx+7P}gxM9ejEj6U>2X54{%rXQ7;Z$1u1(;{enD;|4b@1|TA}gq`=k zMhfqa;Nb}}tTb~kujILhw6cc4xRyEWMv@&F9})62*}m+;@A)X_w-B!T1+yJ8EA4j~ zmV)(>O%&EqC~|brqSo(7q35$mL%b9BIX>cimipsbJrRg4t+1PTOK?rLNi#nEEQ_6C z!Llr$vkj^L!OeOVS}T^xMwWhJu|G!8%7}khvf&kzagbn}L(<_`@Fe&Oclg?a$JqDi z1n&EiB$P<5#Z21C?~8VaB?5=)SKL*$X~G`bUH%x&?ry`xDSEX0>Rn(vehRYbi&%fU1k+DN=AmY_I8HTSgydZC;C**OCQzWlAp0Icy7^a|ie? z?`0&CH=qLft5~=#m`WdLQk?HOl)v02nkMZ?8kVv!@6Ba4^X)>GRaS-(e=;fIr6;v( zb)$u=A6N6@E%#Ec5ra1dW7J0@Ixr;&n^)8eJMwGzm`$WT=12KQy(`er#FJh;eaXEw z)quSsAM6P`hwqN)K+}I$(4%z~{vKXT#%jrI+pbg`w)Gso4w}Veo_h1*n~!rHj)$ms z*c1vjZR5h0-Ghf3GH_&4Bh#Mq1Q*{ve>!sXMXp2fH0`(9MEr3_k$Avy+_FakEr#pU zAfwS#q0`J;?GK|}ha0IN*Ov`0djY{#u59-B9Jc(g33qUqE~l~oCYtF>(6hR|nP4#DEuU7T(KPy$B8IQN03FF6j1eCZ1f) zeHnGnZgF%RoAoE3bWGMUB}l;xg-`hArUOgbxB&}S{$K^t<)~w1i?LJIz>8jeJQbh{ zk@lzPN$^QFetC}21!uG+SCejRA5WIkrc-=%BKZ7#LsP3(P}1+;AmybCt_qv^2&D^r z&W8K^z1m=^%do{L%_g+!n1#MSwlOaYUYH@>Y}8yclKdp3Y1SAEQa>$+7QZIZGtXMm zvN-}1Wt7?DPE{<>*~S*D>0;*17WO1@1br86rs*klEI>6}*jT8tTS=e5_=`JtReLy9 z85+>?ZLTydj4)tfAGY`_u+KYkvE}}G^wi!+cg-X)!tn=An%K$Tb2`jjH8EvLK`${g z(Ml!CpEUwK!=`W=Z4cO~DB(N#=SPI~PE5C5ih4t9 zS(;}oZW-&zrXA8j6X^k5|0Y>r{OxArq2M>zjOmjrGZ(t8U}$ zYHVG}?43I|aYP_nS8*E;Jf6T6-nd8e%@&cI$OzkZCfir7bD~*ae{$k0Tk)fvz#yDF z99$edz}!lP6aTS;o$=1&lPlih4Jjbf16-#d@tXuX%C)?x4COH2|-sP{B_)_}k=fqrR z!{3w7Snt?J5So@Rco2i=N>?jemlh$+$j;)%N_Xa5*gz78tzqFf7y9y2jk+rrK$&y{ zi`bHYdHTz_x>7Ow&f7J3e&>WU?;NEG?cd2IDQExFHmiIx1$1c>$PB9;R*;dD#tJH&!J77Cs~(pV7<}Y zu3&gF`R{guKXZkRY{780w3X39VQ2Ghjw{Ta>Pd$`9cQKfdJvW>l$VPJ@Fj)V#YgRD z%KiVbfQ4f8Ts%g|U&dhMhCQrNLW3$j9SSrWyJ9E| zt$NG)!~b!$kB`FW(|cL(3TL?Dav3#Ns3iqF2p zEeW#(9!3#!EezxLW!$&xdvSz4)=y$K*ZfFbVkfAco6c2cY{Gdxzt}nbS|-|c5=MU5 zL#qZhQqz--Y|q%49CfXyyk;qQx6>S>mnPuOem8dfSP`_n)`o8{mg4uoscd;lC>Ulu z#=q-TXyK;QZ1R8t>{zvwoM&#pQy1iERPGmkMVuayd>vNL6GPWnX`EfR#7_R=VhGn- zjBTkUFmBF7wjnZ<)@evUsbLGfnEa1d5o_QEP8G435kt64;TfwgT7XM3U$BJ4|4>os zA1|6eA9wcjFpH*Ej;REL#IZFLJV_N_+K(Y~dkK5R(@SxPMIB$&bAUa2vJYHy$FYYa z29rUw7Y$b2f|fU==zirkeETvDGBo6xhD>pxpU0D+>iZG4JW|NG*h#Y431a-Av^aWW ztWRkkUEE}?I!5Y%8gJiMecmGXW8`~mxJ|B zBcaex669v2Q`U1++*j|3eP5MezeG7J2(gA?5<U5M6_$pVtqiCJ|6a4*^gM(QQ z(a`@YET8p>*?R2ft%tk7U=;p`AvFeZf)PpQCLfzxQs`V_dg@f~k0 zZwcQYd!m7XJ@cu|VdhOk>4Bp@3;Q&{zK%$vl-f1>;N z4^;N|1gc0B!4a2a>d01rEs7oNN&f&Va#}-YYNvyP(k6Cr?NM45@{4@|O>#4l#>5Y5 zSUfkCGfsHH72cmi$250PS(-JA{+5qn8RDQSks$C7wvzI^TP#hg8aFn6FatG5%(HfdyPp8n7t_=k&B=>|T^gwGu^3TJ=Z#fHaA2{V_K zu(!rZ;KYxjbVm((;kggrrZsYxmt91!PYSf7w}3x>N)=utzh~dnX2R|HX;{2_5WSD= zW35W5cxaR@s@2tyU(0ni)FObH7nM=ye}QP5ufQ}DdG?^mjS6xuL*Wi(=pECFZ57gh z|9)`g=cCx7j2!mer~nljQc!32P}n%q61G2@CzMs&>FvOO^lSM}7+fM`eZI_qVJ~&b z?fOXiZmP!(2^h)eW$h!Y+#u{*ImEtxgAPWy{e%zU_wkNGh3&OvKRKLL#nL15F;vvS zK0RGY2lKzOG2bje3Vvg5s4YAfeCtM91Kg1pF_7MLjf;4f#9SB5qP-^f@oP8We@mme zyu5Q{`uPg(tP{LA^Aj5)dNiq3*OTTnN#l9PpExdLDfm@eQ-1^pkG%HaA$;S(dwE)9(+ijD6tB}E8A&1%)1Q+Dik&UYkY|rsPl~$h1IjBQ*2epCo zN@1b8c1-_YK1=;Au$a!83v=aA_?>c(d9P9jE3I6-dO_CyazQsLEwyA{>!w1$@ZoH} zp+E7KQOy`3%(AOr!w~t7GzmPt(NMvc>Xnf zf8LqtHN4@E&T7SOhYYkhvt3m6_zXsOEQblP8Cd;#J@)I2g)`O-y!tI=8rk4UB9%B& zcrc4*&3}uB&B8%GuKl$34hg&^>|>V1nDKc(!_ZpbHup|Zra`5{?LE9F2)Wrh&hd-j z6dKWr3;3ae7k4AInjeMazbPoW>kA!SzZ~SkTv^KqKQIzFPqS^;<3M#07B>q%&8aCQ zZ2|B~4x5Q{hO$AeycuW#_Q(C70mp%SOEQWrmmEvH7wm`Gk}) z;Q1y5Mt!Oj_$%6sD_+J@uH40>SZNA7(GJ~?&)5Z9JzhWWC%QwbQ5l$dw^a3*uwbPiHx7M7B-7A&~KC%olIZG3hG@^ zPJJnj{Q8a`?rhD9@eb>KSBniJCV^b@75?2NNt*lUD|0<>$@i(<=N|UPQPG=T&OF=% z#rhmkcXm4SIB}76$%e7cV`-@K#GSC@BX=-t78kz2nU0U2&(c?p5IsLL4b)c8q;i=) zY=2kCZwSc-F~1rvdw3h(=n!_z%C@j(nvlV-cfnDwClMBog5}P8(QacFR;^nF`U|yL zlbQ*vI<^eA9q46>gMOkxY!Jws#=y(b0t2uzoF>RfgSF8KbZ%XViU%IzWqmt3e>_c; z9x;hluYF6qN1WhZ#yL`e<2-oN{1Lr=yTSHr7x1=}ENRF4!@6`;x7}Z)h7w zSC0lzSEU42ZWPWKnNJu37WA~ti`&_@50|`GAqQbzX`pw?rhcajjIG*-IS*B+TYnuy zbVj4GN;y05csFKmnM2~-Ud-+J#8uYq0rgg2bXK^@4`|kK1rdR)eZmZIEUMw^=Z}XU z*^_Kz)}F<4I{mDtG6zjAp5TX`IwO+!q(y%mletjyW6Yt!oMi~LNT<}pD3Qe{4?!SS%l*_RG$18qB)ISV6R*ySueJS@tK6;38d~WePnmEw}=bb2EaUQo>@=|U3 zvKx7$FE6n5lmlPVHwlI;?%^fYOr@g-=hBGwR{Zb#DyGZLrG}~)KDBKMgm^t-uDT!j zyuFj?wrVm(?^fsiz0$cv9U&Vn^sw5erP3+Ii!iwG0RQ&u92|Su57|ufOfonR9ZWk-uCncK4)c#A+^OoeCPglIXzSOPixWck>BAzD-*MD zXL20B=GYRt`*tGxvf?^T`M!gZ(Dlp=ihM_heu9~ zswP9sN1>`OE&OQ}ci; z^-==+*lUzw$_tElCpMv_jW(a!irv8qu*iH)lkv|iPvlK;RnBm@#PTwvmhG)M{;BR6R` zvKDutCudJkX43`M7N$&`(1)uURn7K@nUlt%IC$)#PL1Dg)0cKVa9dMtcfB-*DUMa( zH)=&ed4xIp6Yj#YvhLIM1@HJRJ_(%a#0=)8eSy?E?Z~osC-DNmc0~JooPX{RHQDSU zmrXrbxYZPNm+4aUuo>h%bPKg;`apY+ft|R9pRn`(#=Hi1FoQfJRBt)L3yJs!tt0(V z+Ig92Se3!0)|F5v@Ca*vZbOfg8SI*4HA`>4gIf)?3A=4UBlZmE|0SEkpLBC;OvV8Y z7g%4v)8KRR0p8sy3Tl-Npl^j8w@iK-$s0(*9UULK@xBt;^GZ0m;U+ZQ@i6|&&g8u0 z=HTQdb<~qBNs6_%nXk@GAy0pT>JOq$Q4q}^k6DV zqr}`y(b7yUn)uL+cKU@+Xm_roS)+2bE&W`(eBXt zr(DIF3?{cGk8LvUWroZ3=$x-3`{!N+i@$y3460=@cUVQEwBc#c8$FY*B}q`CkS{;; zv`^HyR>*jp$I)+MIciJ!~Fj~DBi$LC$J z*xHBx8z-=qh6q`nt$r*$J(xb48w!5=nc%+QElzZ@!I_V(pmDXpV5tAWF1uae+GqDN z>(HO9_u)k_Z|-4Vy*fG1voUz^YaXaIonxA{=9KkJ9i46rr{>s$5Nx533KOo-q}_GA z_YqGF{JVkX3-hOy*Lyg{o9h67%Ryn61`XVLz-0FbzoWzo6s|EOCq9HPK`Hw8p^dqH zYG>=iPqD&(x|A4cL7%2%5Z9cEeUY~@|e`T zQb;}4if+O4*zWt{)RujM`y=F;7biZ)RKdF-ha2D!uSEk>#^L^7Rj|ay3@Y04`H}76 z_$9!HNuO50^IP8WFML+fSKIg8otQ1?S}~J+L6yY&WY{O=4CY&GOWtNYzlRC)wz4XI za>zj}(I{XRk5)19_a{Za8^x&RTL^aTKgljt`LYPvhiuRxO_GzS0{NjG!aen5W8f7v z%5VRHL9zE(@hlnoY@tF&H^kF?!|7a<{bTOW`6saCY#BP{y3q2}xhUN^5*BVQ17+=p z)SajbVczH9W}+m7UyY)KA%X1mwJdi1Vm5cDri!Up2z}2TzSt`^PRMpTfQxPdjCF~E zy2!)q$jyA-MNx{{76=T7534Xa|25MZcNp3O{^Mp9_7^j0;oU&!5uF2^B*IzlCn;O(DSq7GKsq}um{Lx&-4zLay0Ygh8{w6Ok|En+ z;mPY1b=Zr=B~HTL;3z(1b`|y=m`^uWy}^U$lel4*^lcTm zUa`ZtF})KvOz&WuE#j%fCX4&pQ^84{RHW!-D^T4t7tBqxDBa!<(>5kk>z8b3s~*kE z=03sI1+%aq>_5TFCycB%Bw~c$1FUOnrlU?_RMfbQjak6hFsC-$n>mt|o}G)iYlW`C z^euE!d@z1fxy0KkZf7P3Y^mWv3IFIqiztfoqmmDvFh$Im=fvz`@8TU~sb)rDUha^( zcpuEU;UaKf{rUQ@Wg@dTGWOpW1jF|3@#Oqs5?gX*|+Gt`7vIpG6QAxDU4fviK&i_6?%s^@TVI`F%wJJ zx|}FnF;X9mW6QB?krE9q+%51Y-{PO&iR^l_G~>=Z!sS`6>~hC0_VR5k9%vD`oL7&r zt&z3hC}m9XCKiM;BOs$eigitiqtEk)!<*l3oX$*1u!>aTI)7%ekL9j{&q{~pYO8|x z*ijIbVNcn=h0JJ0EI1FO&^PW9%ULSyWvqTYhiS}M0g*b zMCL5@ovnMmnmnqtn9=1)y!a=(#vNtJXlQYPkC-+Yif@h}hsAafVf+&R#iYWz)&SnI zHMLRd-!**hGlT5wSVJY`wR4*yCrQ@)M@4Wftc=}$t6kb&6P}=Ks40QX*Hpu3IQT=}2Zkq`tuBZZw zpDXa$mlYuYW-%-tqQvk}3LLSo?rZ|qE@ml*K`gb<29IehDSxZFLMdb7N4*G7t&N>e)CBI?%^xxq+Hu%Fb z?qj_0P12_fdMfF-Xtxu})&=3N&&y!psyP($cnAIKv!vLA#DMv(_W| z5Ib!NZ50(#ufTM&x$8y#Y&d;dVFg=nZe^_E9(LaMgqoUnT-Dn-)bTxyOi$*}zfZdO z(C(1Pes~=S%_cCH6K{N;tp>3^+O*Pn3M4!dx;NJ*LPl5-gpYj)dpxJ}hc>qJP8+7u z{zZl~{kZ|X4}8e>osI=>lRRa+WIVhmfv=GJ7fXlYCRwaPC{& zXz8cB%xU`_c2!Ocqiz?H>kVT#YWE3>H^wvVx?p$_XF;O!O#HdhoYvg?fG?#7PR%>;)!ygM0VBh?Ek8AwEZV zk3Z7|wIdB&+~CtJN%aF7$WDVksmXk+(4Vhce2ER+>uuNmN8Um659TB)FN>jlP| zZw2iy_Qf&Q*BQsVorTMAw#NC@lW%RL?*o5C^CeZf@ zXW7Nu=fS#qyKQ~^FQzNIcmzr4inH5+i z`h?fl`Ov2B-Apa)B^xXG8dWk%ScH)-cQ{Z9p8v~6wM(nu-6x@gRk{cTV-0sltqn@A z-sN3xFUOJ+74q~s!e;xs!sh#nU|%z_XAvf}rahldZyiZvhsoMot+pT=Jq;{~m11Mq zTSmjwnSP5iIV#KAUspH^C%osQ=N%8Y{Pr5&o_(78>mvqD+1d0bD3?u3GJ$Jz$I$!m z-^}1~1ne2Lgo&TZ2YR))Fq=p!kFWU#>KRQ6LkRkk(Is|M*Hsl)E2&-N$ zrh~=%AVlXs7G%4Pj*WcCEm4&x8($UCs!U^yNNT~yQ4VZRVF`AB3!wH@+QOF+LH{8` z5=G`RJCE655EKQf&ga;_fq3#;Z7t-AIWXS!0n_p>V(O~Ff^*NGG)vFWuQSH%`|1O@ z_KYHn8&N`)%Ti(W@~8ACZ96XHnna5_9rz@lK@gH#jJj#c)S8#X$XH+u|F@d*!y81i z8m5Dp3`4_dk8qq@BK=n=MMFbAGV8D!Xd2SYE-3EDmh1i8y#F}3QQ$+fj*o$ZueM>m zydus%dYVmqeT40qtwtGA+2nt?P~_zOk+r|+!!eCE~}>ss^yh{!dE>~UgeFOvd++C32oX| znFbxMs@y8~F~pW<(iZhr_T=3RJTa&kDh1}logI02y~2+&WL+setB#h2mB5ib`vq?2 zDQ=mGGX$xBWW2Zz{Qjsng#i9cEY5 zgITXM;j`Kx8Y*XRw?pVws|FyuVfv9BvrGmr??gJS{~zDKE}m@8s?dGm9O?Oa3awW% z>@1l8&T8>+?1#WKFkDF)%Z|frtu$(y>I97+3@QJ9Fpc>82JPF&!I1CvnA^XWfBhH4nqadqG2&0`ZDou(;VBj)zZzfP3rVQl;SbxL3#3d>cnEj#;wR zjltA2DGt5IApY3&3^jL~gQw|q(EV$H=X26|-4n9}E^q>`zeAX(EQ!XF9A7GNe}@5g z%J_=IXW+)8->gn6o?kI<2~{l#0F8eK!K~~)FZbDzdEJY~w9qR49POZur{3X@Rv9R` zvxed~WTDsCI4BPM&h<{RqV$UfWNA>zM%afzPmd1SW{<>28t>ru(nZj+bOMFvB#`sV zaTIjm5+48Sh4;ajvZ@N$qMnKD^rJ1f=a45lmCDhGPDeWF*uvbWUt?7^>&fBWQaFEV z7>o?6Mz?7OwDa-}wxrpQMptej`2~BJxiA+lb~u2`B9FkG0cH9!q!w2Xn1ZQl0bO0V zn+_(w!JLwvlzm|*=DE+O>6f#ug#k{E(viOe&nfxtH(V$_T;H?ovWxf5- zbNCU?mz_@j#}^6tvS65{?8M#d48y&(+O)}S2%9nc6{{G1g_Q*a;A6W1=EO|_@9z?z zb}9#Kr)Sb@qjpp*zQBe?Cg2+V!C)ioe#A8l(Ql^-t}Eoo{>ND^Z;B^9QY$6-B6ToV zR-yf0i=b$YE_q*=L{$l2aet~A70oQ;?^l}hFA8Hpce^36qXjrRa%gjuoL2=)D zj4S$y&tA)bsk0??uB_xYn#Zv~-G%gGiYn;U~T;~YkU9rBE-y&s-Wk0f*!&Y6Eb2W(l zIar9Z-Bfsmpkn^@FKc@FL>~4W&>CywpQ*_dSG$42++-FXE(x2HC*!~#fir$Lio&iu#nG2z$mfqNOV!k)xmSj; z6}tQI<28A@F!2;)69Vwg&ot(o(2Jj4qUcz&IOWJVK={O${M71Xk{5R7w^DDyR9=KZ zT_T+EBa}rdoX5>w%`~_74yP9*BkZsfpnK6m`g*Y#mS)#8W+9L3Jp^9r%>ZUIeLkvf zT}ys;w^-av6X6~Wz;<3>Su#%&&I&;1zMOE_#djAE$25K zf6BtGp0kpF6HzSfGvCm)P~g$3+TUHM&vI2tXw|Go1v`xTFD7TRO4)sTD375Hc07 zglEI8ndIBApx?ijwnNV~p~PojP|iP22~Sl~DN2i-Sbq;iZUTQ>(Tq+XzryaEYhk}; z?8B>%g)`t~GiMVajt5=c+2YHJ^eQHw`94h(88^&@N-agyl<2^l)!hs1-p1%;6ssFC zs7Yq|d!`?Q>~K^r&o`Ck6yXlh89&XzrBWh?D@dtz7*xi}+5T8w&N&;k!EDm|` ztD}=Cw`wEpdTz&gi%+K|U&QFm+y5YV!fwdeLHylSxA>Uw3{H0JI(lnznCx$-z{WAx z+2!^en!jcR)q2Lz3HNT!RbUN9UebXVC&#ky%O`?t!7ldkU<_4i_>tl^U)ZbJKq94u zBz{|k#FixDjxQHTYmgCLt)2tzv*swSZ$ zJQzNgMZ&9#cSKW#|H_#|owlBZa_D@_7M-scQ1iAs;O@X^(Sqd^ykIhI4h-Pk+6J@N zGjnibSUpqi7RU4NwNR_EfxUZo4Wr5d)-@#wxSr2H=o_Y9GRmJ43s94G_g^_ARoUpu%c zCG>*sxpB2^YeA*O1Pl+qVpT3j*-fcBPRjAT?Ts29W!IhOwr`JxvB}nO)qNwCXnf)R zP0l5=^+I1Dx0=RY5$BG#CBl+P%egpC=t#8+e5v+S#-^5g8uSd^jv=iX&7GN{R}K`haL($Xe9u_2GSwE1^`+RjNGiK>K$oqP|2rlS|Si zC*`k9`T0Sp{9}wNX`{(mbuE8(&v3drGl>?g=;t1!4}*VkHT=nu1?05uJo~fN5GMOG z3i#Vg!(uPe`(G9eb)`7(E^|_UwG1+UZ3fxp`RttF6D!CtrL*%dGe^6jOy{o%^DF)X z>jz5o!(%$B*VVDzu?BSMODO(cFpA&i837%O^{8LJ+-~@$(>QKR7FNGp2n*+Av)+{n zAcWK4$L<0C>BY+ov$a9EZnD7sPBL7x5ZxumWB(E_NEN(%pT-N0L9y?g&8yv@67Pdm z<>u7JBZ?o;qT*!*Y*4lYZB@F$+gvZ=f9lT>nKr36rKmY$sii*uv7rXH-5+3&&hD{& zG^jwdC{LRXO$o)VmDUiUFh@A6UW+=*ztU}m0yZP;CfmKoAMvs^=sM}LhO|L&-NlqN zR7}{b5Gxw@cOiT%JIh)3&ccM5nee(Uo(j%OQIf!Gh%Rdt$-P|1xlg~tS@|u747FJN zaA_!v8GM56UZg>{$^;+K^B|IQ+lME^ zOM~p$iE9}wXhti)L|!H(-^GDqlIWmCdRTpd?X>?A*5IU-)`Yt&o$iV&C!`IhLP_d#nVrlUE!&{H&h+6xc^U zyBy){BH^8Fs)O6t_F>1iL)@RY(U5rG36p~(F>JUDh?XI|MHAbwQg>TfYsC<+?MageQrv)K+ zCUFHgsD`1B_Dq)AYXR{CO*rAh0G7pfvnQD*)U$FQ)Vz3x4TJt*@Y;vGl$Hmdul|N< z9UXxu?+-g)9zn<4%)o~@#I(G_tBFoWv@?Sg42bIj! z?+j;CSxrHznN+>_Al6U2O=j;uvnRrL&qmkhXz@*i!-t*3`AuviO-k{ z7_(?yxu$YGHGa9z8?JP@Ez~QWgIKfa%uebyI+R9W>5vHwd3PGVZVTB-eBBDw#p~Y zbQBl6dBM>`J78Ph4<@!r4BWf**mZwD!87PaADgyAwAeY?Ae@EPd94i0)M&M^2MRhD z!*U-9*|i3B`^xG4e7m6xcst&N0~hP)ps^2|GkP;KS=!AuXjS1er6ykQ?{J7aSj0}x zina5MO#`jQ@67G^T>j{Ap-eF5N#oeAYJN(BDWt_dV)pSfxuSl-t*Wz;;%}~H7Fj*4 z-MxTs$ob4xOH_*HNX~#US4|))^cjBHS;$2ipWtn>?b+4A#-fCUmhkrMe#{EI!LBJd?B+q?&R764e@gHf+0x5>pSZ5>SkdaBr?_6a+0L#zi(jCt z35}s5?k(-7SCcpv@+}6pKR%6{=8S{D2vZ-nDW-WIiENterhJXXwjmtt+jN4N+1WtLpgwe*J_q_+tKjqvp{w%wEY=vG!fDfH zz{5-zyUkk^AaQ!5NN#f}TP83a4bN@_jXxhS>El1PfAdmye7ylRD44PX&%?No{r^Np zrN!9zcNHV+e0Vc+ChHox14Fh;lcCfMn7Kld`HtNLoxjI(fo=2o>h)9cKz1wKPAMcW zb9>x6c@?#*%%jsKmb7<;Iel(J3UBOVuV&p8-Pv-Ib&VYfVHX}z?GI(x^*)eo%bNmI z5){z;@Lw|T_>7USNAVN;ZD~Q1z-*py3=a#r#we3R7&+~ps6yaCgwR~LQTYa;t(ZMI zk$|K9^dM2f7N5n90flqV@z}5HEd8t!G`THrb%&+urFJQJ=AZ&36k0D?-nnn=k<*$Tt?$s&Eepjl7RuPi)clnKK-?f zhT|Hx6yGX12j`r|T@MH0s0fa1(w4#PjW5}nG%@buA9uF>TOUr_-G-JPyXcVR0PD!# zMEm3}^P0-hSg}7G7C$tC1VUYDr`9Xl(wy zh4OeuG?xC3T%7|QHPvD+eX~IFw9uOqIvsZ^=1_NTrQOVF0uS@hBJlTGPiwOSVfQ*g z$$HHN3;Y|I;)>SBjgd+?esT&u%AWz&nldzD`CRO_TnHwPW^`}L8ForbT$nW*a3x36 z>HDnpEV=awYpBu{{PE?Wy?qXzF_a=2`WI^pH_{R-!Mhj4n3%o^8~M))(r#AZzRU@9 zC}t<>hJV7=C{Hdy!WgIB>EM>U%B7K6K6tJgsR(ciUfW6e*d80<=F z|F&_>`|J7Ef$8Ai70>GRC1EQ|r^ycvg8fH1ieJ=^wU1=r{^l2We%t|+P*$W4-vJCA z@ss^oYXygPwD3>!fL%Da4dB@u`j>PZ-&q^bgL+x!U!F#CW2H&cGMdgOWy7GHGPd_q z1z3Do&)e4wV2ZaU_y&ovVXrLMU({udxxFk@XAd5z`NCb8IvI1l)o`&!C8nJ$!l7d` zaR16dDWjppt3fiOQc)V7 zdya}|NPAF9O9}10-}`6&3Xgk#zjMCd&&R45rX`JImj`;>`O72zx+ND5r#xo&x(}#( zBwZ{%I}3KX_mr)>w4C)f2IIj4;bOR_wvhI`TyWKzM%72s=y^sc&i3EMIgJNsPQMW0 znrSdC2{#ip4`}nwmTxdgcP@tR&BMtN(!QrtUuv|}=XXbbl5=xcr;@`Cocgf`7ms%5 z(Zvo<`_m4o3QqEEF=z)(U&=0`RmaKl>Z@>k98bRp5u*qO>8`W zv#u2PA2Mgx(avH=13zBd?>K+HmcT}je^Bo;ot@HqcjsvrZ-~9uPQ~SonY8)b9oqo)?L)VN1oSow;NKk$@bvvzu-o7kOz5_YZvFvS@S#cc zx$1>gJHAm*1G)I0jnp^q5lF$#+i}R`SkmpEJA7e-2Kx9Mf_1AE_iDqrB3HHKLQRf2_AEJ!x1|1B_vUI|iVN^jr7Fzt zBK>TSDWm$Z-kf1%i8YIhV13Dcq5AdwWOFP8~@rMkk|glev`N z$$}BP#^R116D0SzHFmjNCp7HrBlx*?Lm@SX`+j%gkkSF<6Oh0*=Q=t)I(tj(XmeR` z?cLz;r#hOgYK(=&r@w&K&#mBjF@cVJFok`wjTDv>LeDyefaTUyQjAFDQ)U}kt~Et$ z$xa1*1or%O6!b5JlI}b$cwV?2;Ll&lsq04?Us~xy2XDS9lQ;u&^s!Gu7wXhW zIuoDIq{I*1v2M~__;g`5*WS87TgEA2z#BQ(#;CCK!iA!WpCMm3*e;AQdnMeoROMWa zX1Xn0r!%M0V8`y?kXhsi`GPq(RZCgPZbqOsD1lSvPi2pD`yp#c9-errfoh||`9>hq z*ShieZls9x)C$$3ev8328gM1b0*t;S<6F;Zlp1>iet$ASm1HxRXAzm#cN zh_7S2QF;4tY*AayHRnU{bet29_%E0CT1uS%N6GZ3<18L-K9)|Hj^e~2vxRNC-LOzM zh1;9TdF%*N964;dqwS-eR5&|cP`wughO~nO^8_(nN1AiQHVH<}L#3=|0D7hU6Ag6y zpytIBKj`N&^ty8A5m5t>43ThYgLnVgWgY(dBZME?5Q#@x&{@U>) zt!Ukug`)d1GYlHOgWoG8;qe>&J*F+)!F!> zP#aq#A*VI8OMf55bY^6-P>`*Pjz>qc)#o*0eAs39SQf!!lh@XVBO4IrBX(`+3W!`uA{@4T(=19HF zxqT0Bei6e zfzrgCIJ-@oe@zYH(;nI=o@H7PHVMYfzet}AO2riIB0O+q44F0FgCCVr553X7{Oq7v zchEPI)c5^i()6xY1qP=lSlD{C6j>*N`!Bv-7&>@6`d-pfK~AW%f3wLi-CDE zzUlOZcGu=WM2QZc-WLaWbQ>CG*NfkK#;~=A3hDYR$Ep(nc&u?F$gi&fgIaB_53uEPPdz|w z^B>~!z=|;w9@6@WMUEvgw&Es}oh)Rn64srlgUycyBP;C|_Dh*D(|C7KI(>)K{#v5K zyv}&y$aa{$MGf!j+rmZdS$Hw8A1(;{Lk?~}y#6z?&J1VizLG)NXTo6d{ew_BxgJ~` z9to@GMp4R^2G~%$nS)=Aq0#em;8yb@4BGf!9{aAD%%)tXf5V=@xU0kXi2pjdOXE{& z4e5k9C=$lHZiFMFl=$O^Ssm#Jd(7d4i5I7Br+|06YRC)WO=22ZZ{k=?WX4Q`3ZgI`I`iHx^o^KlglZ=29Y z>gxZs@us9IF85Bb_ry*xwy7Bonm?!b zo2rz&xSn>6Oye;P8^I_vi-p4@IW9pNZEl?ALAl=?m!EjZX9Y#RX*-(74y>ZdIEin? zc#~0Gu9$Sj8J4(6e$cyx@FKY@?$5bNb9zVcm*9Q0Z@4NCwci@65 zGw$O$oTug0!$a;57o?t<+Q0uK4~PQGma1Xmz2)%S-B2)Ed!Mg+nzPa%Q_hhc7w6?= zvdW@fnC3bbdrO~pS?(R`r~MfW43}YyRzE&8@C`UcR6{;>#Ej9|(0Q(%c-APG4-J@s zreE?nr_>LY`*nsG>pdJiRF&;gE%@HeA9THL4m3mv)c=7wJ&pCGSF`sEKm0Fa%tI;1 z(z7Q|nOZ0GHvd68Z$`16{4Z{bH-;^9_p#-v+oWJ}jx;)brK0*n^mR_5+(p$8rzUvw z!?cfdyj-2P9Q0$8Yd$dQ$p9X+rWNE z@rE;#*gp9UZS;F6DoH-~OC1l=)?o=WU|bw`($nVt($4g~>l1o7`?aiX*#W+#aGHIS zXV5j5qm&e3NNF#+;gk3Rn$hYl-h#du*;(Qm+cnT$-6^#6qZS`(3Fl&`QEbu!xcbsa zHd1XUEyGRV*7eOizrb>fxe+gTJ`I{x;y!e@e2}aO9vrdAKQTCHx#21x=nKIJH=sb$JD0f_pq| zth1+*%4D!F9LSPQ0Wzsx9Fq`?aY}krcWVhmy>h{vxykskGLR=|4x$M+{it@-QEW1i zxNc#RJG|ZjP8LXA^jXXBN?lJLP=1Fh=S|>9sekEsQ(yMF|3FG8ZlL5@>(M{%0caH5 zhS6h>VCU=sc>TH}CT)2{p-Z>nmrv6CcH~f@tF{ij&sofEj)jnOu%pDwRp7gQyJD6@ zs{DcRX*NFa10q6m1kdI5!l;ft;o7Pycb4`HpEc&CA=B;&I}cOeY7#kV|Mwc zhyP$iSiJZlMRJgpjG=^Knex?ZX5!M{t03`Y7px!DQJ7u%4DLTg?zKY^<84gQOfQoX zvf`O1{1kdMD&vkAbz0e10X4LLy z_DL~p$OmEAwgTC(GmSK+?*lsdI|rN+zt9Jv1NU5+4tHXt9pi}gkh#1H4joc~X-{l; z*Mm|Tl4{JqEn6t*bvsmtnbVICePDi99UPY1k-b8Ov4^WYKQ0XxZyT==-g(M!)!%3M zQn`$4!?K`{<$B!Q=ESqVTeD`xdI|rl&dGZk;jd+Z(C@Y;SC#d`ISB*V|K~vLU#|qA z18Qi*yzYEqqY~Wg+@0goB=@} zmCqD9m3@Qv9agZ2{|7c6%Z5IQWiqdJYq2b=Gat8G2svH0f_nY}=(+P9Y;2C;Pm(*J+f;wp ztCP<)+EXgRp7eo$C4Z@H!#uVzjAaW`W!Y&<9o(@*m2wSK@R7{0x2j=IyO&zf@6234LVF;*U%u7`1Xxm*)6ja*XJi!$Y(Qa*R3#OO2TOVb9S zVmBFPoX?VXiF2p4omsFWU1D_pyD9(sFPtJ0Oj!Lz2i(x0!IgnVkax?Mn**jIYy<3!nW>@Whow$lhQj zW=*>Ry8A3xW8WjbK4l-8Qu`CXagdVZ!%A8WGswv+XC_T#MHuCy`5Pn?r?s(g`hGz<0CoMtjy zavg@zir0hb=2>^KF*ktf-s$t79^Yu_xpQzRzg;veyb3kj5=pyJnLdrW16jTsNmokW zo|?G=-(9&w(fhB_i7q#2&+=kWDhd^EI4u?aH24XpJ|sYT>ttSM)PY(jZY2J5kE{y6 z$k$J96b~*dq<`Wr)a-kh?$1w#D5;ZS=N7{krud3BTdu>)ke9MoE!&{kzXRUTYLIs^ zxe1FZr{RIDAjlYsl7k@{ZHsEDWX3nyDy300{+$+1bqNHI^pl{xyh#Mfcjo1v3#m5` z(dNG!xoFTi+PyMgJle|~J+=PBTm4-5)Am?AS9nN1Tq_samMF8KT{4ZSjRE%^k6>Zn zGc;M%nRb1T#3ME%$u@Y4)UhIX>Y{@GNnPo;o8v`owGDjpbT-{t(HSpp86?VjFr>M#2ujCmY zCw^U21Pkr&3KbVl!26~3MNsLc*r-{~ef_0iS zoEsmF#=6G%c8m^QJZH?W4{5;u{P&b}Y7whU?uaw>Pr;?*3DQ~E9tJsCQlErrmJ?4N{EEi*NTJF8QMgzAi`-}BH8}P|;!C(`LPPC4Q0o>fxtE3s((Y7Z zjjf?Y8=`qtl?hLrl22m|-%^xu7v9&dfPWlRsB6p!{&8uPpnmlfEb(|ruOFVJ#}md- zi{l_ryt7`&xM9f0b4Kv9wl4hEx{jXCET`nkPoN%M2_9F=;O6l}P`sTAyJHH=%O*5K zUzdLH^ME?re+(n#ul88BFc20Dy-UmO8ez4~ONiWKE^Lxt6IZX4(Z?uPcBw8E$CzJ6 zxo-({9Ad#ALiO0>aXI#GD4?B@Osn>VlTX3}aysM4{k2PIPkTA1Pu1k|el>J>L=q`X zP>}9xN>p_9km%4B%z=gJvV;NGs7YZ2ER!+`2Q3wOR4h5#myhD`MR`J?@e=C#@B&%1 zMZlb#?yRw1h04PGsOPo|LWXw{yX^w$|C~cts;0 zns5btW>5(GcGQWsOP9d)pdqaPSH^l41+;m&@y zKEKawqlo@dv}i#B*_;ib+HS-7$n<;E>)S+l_huwzSg7G`n?)dW591%;Cxl$rhObVY z;nL$JcrNsg(DA}A`fBk?TwmtND|$?&R}C)o*zTKP(V<@0F=rQtcKJpdw&{XSNWRd0 z|4E7(HC3D>aTyyclzG?R4cMuVKRnWVC2E&0K&2&jLF=2LFm}mJJ~VwYj`tcYW{xw0 zr04e}kBb?+o!%yEZ%~5`e>!sJIf(_)OPU#n2`t*3q+ZEq>06i&dsY##b5hhf8Ox81jbQEuW1jCRb%nRg;lUsOfX9&_eAhD>(xD}18j%OOKdQ#%XZ3bFMtPTMbLP(h{xUb5!=0clH(~Sej4>aa-yR&r)m`P zIveood#_3TzJ^nKgC?&YR|=|&!=cW$3tF5jmak1)jynww;`0HLm#}ynO!-hHcIy_y zC23t~_5O7J`BdVl_c=)&y(E|VtC_I;eu@~^){l3u@xa8eQg~~Y2$LeLsNwp0c6*uu z-utACebf-1_izr@Dd?hgXb=ESR0ueI2s6 zJm!I1QNIZco_EDxIX!sVu{d$te`g@nPe$o3*$}3=g9q(&z_$M`!b;8ExcmKLne$>3 z3L0351#UyY{pnCt{(?VV-Lr zuxs7L^>w8b`$1xv+1lZ(=xIF5B#aeVc^7YslRX;z7NlX=8OxFCU&NfZrcg`O2k3a+u)krJbvxG6PLHD!tY&wg>IKp zDfnlQC<}T84tMr*`P>)azu=WHO@0m@7@6~>$$D(I{1}ErO~cex$5}1dhPtawl#Dz4qkxLe_g?2QxZ?;v<2@xeoYf) zS1JD37Iew|A=_@71YoMo({=0RwvDh&L*JTHe-hk&%hPNVPR<-#1lv4V{l z2dZ`%;fGS4#O|ORDwq?_qZ+B_vp3j2v&@3)q>d#wynBlG^7e!mydba5|3b=#h zc0Sk}eZ%WufTtPvzuW@j1E-W9NO~oxHI0OvwZkZ-DG#h$o{-PqMKJbX9(kDo_IPFM zcq6}EzB=nY>1{tJZf=)mX`Qt2U}A}QE!&I3rF_gG{VP;CcYx4i_g}blr4`~FMXveJ z31&wGlh^$M3LkL_E!))S*Pn^JeC}vzzMIYb^p|L`a2)7%D~EAW%iw;D8~dK}m(Ep* zu;ckn;Yo!lM|@t)jyF@FQ`G?s*lUE_wg+?a4G%FS+6A>Ad=zy~_v7O!PGp;|$0bwe z;+BJNX-?!MG90PFagVa`j_qjr6}y*uoKAwu1>2}k_$#=(=@w2B`?JTG#o&=20>gfe z6CO!!fV`c>F!f|QrK&biW5^Nkj}oD}`7dRp*}(4l5%_%j0oJ^KMZCPnM{FwlMK$Xr z#`~k~!kJk`^u#}t=G~6v>re;vk?DM*?=1E`o5SiphJ3>=g~w}5kk5T^hP3D2=3~Y~ z`9(&vG}Cp$Q__rh`nw8Y(vUV#o6f??d#+sZ+YW4MQ^=|Kf~eSflAkP}N1O7Lz%^+P zP3aZ~>d&sw=B>*q>_MPtd^v|=6IzAe($A=J`C~D5R~LMeIYa#6I9%*e+Crn0_sHa5 zHi{DyuAr^candcXhH)fd&Bp%eItA13Zx&ex7SL3F^ z|4F`GUHHOfG=E4mu3WB`+PxD_f z#@(1F=atf`o@T<(We>0}SOIRRo&Yn8>tJU-2opRVgeNsigvj;~m@;ZSMh0txQgI5% zr5TQP

^#{VdP>a8lfvV#JfY)2ZyaFB`_z2@7;4;?93{<;{Kn!?`V+v)dwpe ze2XcM8u*Nc+TDhm2a6=0*d0f8^GxV)#$D=#Sz*^Ee@LI9$d8AH(k=HBeCp&1YP3s+ zxSFX@lDPz|ZwBDcggE?Bc#OImC{S%>BHmrQNxZUfJUdM*!uN9=*(Jt+7K~{TOKVqB z1|>S+z9^Q>TnKLOR`WA0BhK;YDT})r4=;i*qt}IK)}Glcr-YjC_ z_yHc`6pzV< z$+tU9;DDFwG2+iDa9?B3E*4=tsQn}i%$m*1SMS8o(-+}Mh$r7Fx_}24N-mryU%+MY z1)A3TJ#{x6!0YDhq`Z%Wad$?jrOczvk)&z8N0^4 zikzM^o5#r##ml3zVTA)=?``X$P;I`%*Xz!qU$05ok1R2|PJ{c7PM7U_TL)q{S3E3g zvDrl#U(Sdp{e3I&Mc+m2-Mj~0xo3+#z3<|u-G#8?;TVYX4(1Hm7m0DK1n(>qvCc@J z4|g3#=DkvdQio=E5a=dsT%tx#cUExTw~2VD?<`zwlOj3?4C2JWnK1rrM>bc}=WRw~F-FJfI&6^Dw2k6KbjG!vdi%rYH{)pk$J4j8i<{ znWa>*Q`(FE0%g>UyomLQdH8UwFE)4{f)y|F%U~6RScW zejmoUU0PtlFbm4LHJ!iaC4x;)Y340)(H9#{hmD#A$c{%a@txF%?wK!^^)jb;M{Q_M zT|q8h}%`zTmjOMO+bbohG*0lhRsk>3xt1uYQceUkjw?GP%j@Sz?j?@MQ?GHUl%#kz8Har}8Ne7WY7V0ZpB7)zb3xvJa9 z<7-!5xy%tvKDLn3(j(w;r5{`57l}3T3h;cL#2|S!mhOMPCPt0W1;cCce5s`?zx$j9 z;gPlQd~ht4|10FS4!>a9^*r%S#9P|_%7=H}C=_B&J{R=mq4f4&seHo7P_fWf@)>(? z7e8;E$9mmV>HNhpsPaHsJ0<+1`IEARN9u>Fu=jXyDmh+CgsM#p`Tv)5;4Jd8i%66h+dwJzM$M*xS^)u?+Kzj)Ov8 z969ePgN7_6ar(mr6gxi}e-_@OwWB}FuO)j@;@o9iG)G5J*glXn5=LS0i0+b?ESL0} zE(>Y0|6tN!Gkomyo)Xl5iJgDGgt(s1V5MUMYbw>!deh^i7rcO7yUszD7PbEDPx)U0T>PU(sprO@*$N} zWl8V8#4~E2i)BswJh13`zQljmrS4BQi6$>>x$x#BNM2|}9#X$b)jWpR2d!b{FgbPe zxdgda_3>A4TU=xE6qa4xLiYOcRJ8A$>{7MAV0`C{ylU|`*_)`Hus+%rwcaK1(;jEa z9|t^!bSd|^?$AOoYq(F>pZ$it23J63P$srzD)ND@Ip{J+6Nj|#hV&nsXzR02v}<(} z>+~?^eiyuC3vR8W$w~pxeD4*!bx#K0d;Rc2z9rwvI4&+ZSSmYvO%dNK41~1j^{{u) zR0y`V29Eh5^mW?~f!8nKzoK&T-qH>J<@CqXpXy~%t9SBVDT9>jwt&;`YUA$f3H19& z9JKB-7gqdOMg6B1a-P<2%5M&noJu#qZT>XA-f1HTKiWqJoNm!A<*vf2yZh08LJ=Ht z9sq3*OwsCOC{M~d&M(!KS<68g9=>lCukJMzKfcfB`TMl-!|Cs!nEQ(=7pTyQpLT3^ zqQ7uA>?Az8v!9HfMxv{A8h-rZhhcs5s4AfttGmTwW~ec*dza1u8SS#e4kv{BqobkL zXFED{isc=dyFgsFk^}a+V>qS4=|Su1P3L4<|NQ`4x?IA6)0R>9)Bg#RU7f*mT{e%= zS`2BAJyE-t8x%B-2b^btUpi&cFuOSZ@ansG-A)^m{7!SDXK#X!`TSA71*fVM&_0Q) zxykf}uv|9)J$9wymI^7atu`9>N9mw*4?~F2amDyGYxw?siM`O&!fW~ur=PAZ!b6i4 zWNm#D#(THW-=yJm@KioVT)ZuS#0!Z*Z}@z52Dtx`c5#m%fO3k0)8~cT=+@;DlvM-^ zJ}rUN$>t=4TFl12Yul*J>zwd$+i!82c7LFveALLzl#i1>*Fipd!hxk``04LxoSoZ) zEu>xaqVQV!F7XVoQj;t`kHKw&Q*h^6TQ>O{#2GKkpv--rBZa#1psfRVoXJq>*(sxD zhqJ=1Zd<7LtYMOCE?fMNaha2I>)2xYJ|6qS8+s1vN*W*MVqA$YU9K5Py7zww<}KO~ z*J=vh8ryL6SVfFA9R__zrHUzE{rO3R7R6{-LDjM>Ub|-;J-0arEz4W5@%4CUGwerw zehXghfp)Cr^B%tvEsUhyPc4&#EtVRF?8;m?6@ zqSjnzsO=kq;AkoJvescrsweqA?ZOMv!{K_WK6V`Xdie0VGs6CbXZX+I*Rb{DW+_{s z&W)u4tAE;yFGB8%M*g!nVnsh58Zw7Zw${*ln@yOKr^&@Lw@dp@6*~9s94MN*LFc!N zc*DLtnwFwYu_XbRzq&~b4^zV&2M;hGJDjb49Hr@9E(u%B3u%bBkEeQHhR20ZNPGQX zS_mIS-Lyo(Pq--YhtqlHszMq(LE6uISJLV9T6%43LUF}1wtQdAUIChHd!jdgH1wja zZ+G#o+XcAyT?@?*SEc-V6}uAz%CdxT8b zer-K2`?*xqbunk#)Rhn$132N z3kOKCg9B=N^l?zP-GcAx>LF{2Gfz}0K+FB_1fD&Ub^hKEJ(QQi&{g?dXQIQed*o1e zrA#o{p~X{mccWXD2Xzs>#1TF|7+O|9nsEZ^S=P|jL@9Ifd=tsGnZkODu5j1$Cusq8U}HB<~>R)^+LVJ2ACi*jh1M2WBb-85Z2vE*8AjQcpDZYZg}S^*FL#} z!n=GF$3(t|^MCT8zd@SM-7cSskFuif~*)HPdeuZ+<@#`B;L#d6aD zu3X(3AYAKd!WC2Zl5+Rkblt%pY;2_2%1TH6@4#_-vCjbO6u;7k7Xx_ZDObK>_KTtt z1PZ&?h?J{{=}bJeE69v@$*>fcQ1zkUj3S8tJx%0BSDyA__6 znen^?FI@T6kBoh?Si^8O+PUw-yT>$njb0^m-hM*Lq?w5+(^Q?##wdz%l>`{HI)bl` zkXVP#v!#6CKj;*e!ByV*ln}CqZ!c~UA9e|+K}#Reo$=?%u%aU-^bZk!nErw%mLDB8 zKbfP>{_Wz~C#Le+jrYOuPZ?gA-w2ae4<((N-Z*fXG8Q_=;g~Jb*QYt@9o>(@ zH@|i4K4&WbTo}%75#yYU-!wtyFlkrbuRp5Bqzk9b0_baD2mTot&I>O(vF=_I{Nq~+ zSH5LI+J{Gi#e&zuS=VZM@%Jp7FLB4w7FFEV)e21#`tmr1;}knugD1V;DEdi$ixJHy z$W}qRpRCGYi&wt5D0&F4@tqAeRm^kh&I(8?n-%1@-KW zG5^M4h>SAe{!UjxbH+*j{Ui_)mCcC=e598D+1 z;S^_8(R*}%Haud<17e4AZvH^*A5aQY-;eAJEop8LS$tX=q7=>+|{?nT-k3weEric?>kL^`n{g0nBZCcaY1k)<-M9n=XX z9vJ~!B1fWsl@3?g{Rg84ti^?I{P5ZI6kc1b$YT@_@VkGp9L9EBu{0i)mF)P@z^Ov_ z8#$ETAe|d_$?0s9x-d+)f}O**iXL!Q__=BXO`l&V^cuHAu6|p^X+o!B*!?RGCTsZc z&_ISeI?gb2Odz#-hQf%UXE?^l16Ov@fh&hXS^0zqOm%(<6<&d8RcgkqtmdTJ^ckL9 zPDEpu`=D>VTe#469Nt(Pa-YXRyn4wp`FXAF9JwQrd(OHkF*gQFSg3MXo|X!+TeE}< z(m8PIxe^#-H4_?K643j37Kmquib)qHvD@+e2E`)Q*QO>lH*#D zBHi`RcTwQh{Rvp$w1^{KT!!DCo{-rwL_E4=6#PD)D!kr(N6fDN#@CDrxYlGjs`Xb# z?Q#0zmshq>aBm13OptnAgD=s8H74-Vr~@BQ{v%A7nuV3sWqd?*Chb$zQnzapdk;N` zbC;x$(!diu&|U@ae%y)GQP)u4O#xpS%;MV>196CtKbv-*0FSqI!K>12@#?F|bZt~e z_Rc$os{8-L3)&6nmz%=6F$x@cD~gs$Y(2d`OJMtZEp}4hPnLO4NzKQMw^kQGXTvnM z9k_#j`k&(BT~pC&zX>kiWW|abvN=+z0@C6=Q5L(4?Tb>mp;;B@-FX2MwcddLQUz=u zvWnWHj$x7!g2(A7$v5|$*M1713fI-J2RGpGugCe+qM@v#RRKoFYlRJWy5jXO>YV3& z40dcgK<{ex(0HUB_c!?jzg&MKUDM}1$Bshvy=nZ!%79CLb-|2P=J3q@0Vq7}d#3%< zae3^?%fi*HJ+SqaBYt&Hz;SbfkcS$gx|bGj4e7(*2K9wOwI<|x>LRrLHg;N}?9WRI zC2!u|(R}i40bXsG$Ms#>sJ+k~?|pqwLDzP2m-v5zUG-MV9qq^ROFhVfBd~PU5FQ(0 z3HFzbY1qIte52eCuY}JLS7~YBn5uI)V{aU0A2sEWPO99+vJXA4xx*C`05|Sh$W_;Z zxudK*wXfd{A2kp2xvb83H}o_;JvI(y`ct5-Bne~BJ)xE*uSCmOAO3SxPb^4Ch0?!| z=t0F1y7X=UFIn49a!=&w-YE>u@5o6##)<9= zH2K@40@Bu*NK%WDJRkU?oq9d*|E7;l7cKeSF_E4KTPeg_MOM^oPF-*W`#w&BgCB3v zU*R_F$|O>ezWVCGd6@h;nk#N+(b_G8xI$^H7@Y~wcxw!tJU#@5sci?%;0tuC7(Jph|C_0g^Svs?eFkUg;!tP$A-ti2nVGWUMb3EP z%zCNYu<`;Adp#K4p3mdC86CLYa4fDZ zi$tTQ>pY=Mk!wD^Am#Iah5zy!W6No_ znKQa{v*cg-*&Ht@aj(ypu0?<;e{xQ6D>}%VvOMYb%zAmR zRcFNWzDJ;VpCevV36kggZ4w>?reH>6IbMmDyopsO;bFi$T-UE!wzhsFpE4TH&sJ{+ zGlh4;e@i!U*(3!zx7Cdm(+dSVi&4UnbW85>HG@X)*vBR`^}Q!F^|m`mZbL z!;?@xU5z~a!zjF{aEium&l4NdvMBOvHZKa%#E6ONeEUQos2*F$f2AC!kdaS?%{w_V zdJpM_S#!;r4ESQ-N*h)_M8oRMpjt8vUo0L()%nFVbzL+?dEcNsYelI3IERk-zZ8cy zBuZR{&9ak^CvxDtH?(i3CwF~$6nc6Z@b0<`FtofQhda6UOE;8t zxME#D4)H4z#~(dUYl>{(di`4bXfXq;@}#`N9fpcO#jxs#H^6}BVuo3N*`?qu7*!vR?sJqd zLi+>kSoj3i4R}W8buJKKo{b3`@4)FH32fdy2EYHlj5WCrsYhKhPjtIVo(5X<`chxn zh1|}3c}ai1tM~z?b$ubeEE>l54qg>Y5+})aMoi}Z`AL)^b@eo-J%jgW29f5+47#}X zDE_{tOiOLzQLgBLueG;9@vIthOnF3CbxsQl5B7o5v;d6z{9D-bOAq(IUcuXrzZ9&p zGGLPQcW!vE2o{8^h;uI6(Kyc<`nSauBAqgLfA8rKJ##P*rBodBVhZirIN!B*LWY+t#(6HAKUfy{vj{FowE7DTA-+f{meNzk=6~nd?N7Lt8 z7Fk;rL0JbKR-V0r?rPMap6eYLIc+Mux*spbI0k~{62*#?z!kVu;|SQjJ4!$0Gceh( zM7%J}i*xqn@TC4{@WLf8zMM6Kw@zQcWxpnnrs^OkT``L%e3STZ7fj&m>&>FtmVH!O zu#FdJTT!H@1+~Oor-ued=+n~@`OtxCeEUl)Z1}f8Sn8cdsh6J;m0Gf+dNTZ2cA5q# z*t6BmW}F3Z}{PVRH=bzh8oqD@t?(DnRB=x+f zdaUHu2Tjy}f;8vup3h4!iNcBrN$7ND7j`O{g&tEH_~t)*XdN`nX|j6}3;Xd`Yl&yvdjZ?_KQD9rZ!UE32!;dim-3BEsn~7K3UXDJ zyl-z-32hVR(GN!9r}f`b zMcOk**(uEFzRJmvE;q1}29RGB@3` z=kK5)wcDlsb(7fnK^eRqoxvlP>(L<73hezlN$kGPLYRH#e7XA+f6~}+6zaBjXH&JM zFnO*uR*g-DOQXAUp0gZZe>;Yw51Zo+7{MRB6~OecFF(Jm!lB)VVaL8-qz+Ygw(ZlI z)-IO%YEGwVT#y4c{PN+&6Ebr zgR4%>CwQF14+F0V-4(Uv_uc1`x=X3t|H3OVYF#W|u4URM?YY-kkHPG@Iv9Cr4)<=$ zz$En{pl7;`w~pM4YgJ~@pV3!&X`(CV>*w$b(-JyqB=rMiTiN?wE?>XD9(}vIv+L5q z5FFPB&;4t~)D3C4XtzVfk>Bq*?dUTqUxCQ3@1gQi2u&UDf)mOI^YeRtob$X&V%@Fg z+8<*<4y$NHdM;Y;*$BsiyU+#;8J>RH4Kl?e9Q0v1rj{Dv!m0HVM=pc+L^aS7^+mk$ zZ2;&^OoThL>|m>NjF{j12;J8BLiaW-WBH4btgd?*t}HnMR~}^1sAc=GS3@QB^U;Nv zpEqE`<^X(TKS93a!vc1D-3{MPI3?v1W?|j5ujM*#%5eIdFzD{`PrSI`F$8tZ!=ryZ zDagPK2dpYUkEdJ3z$!ygEyogq?B~F&d_$Vn7DFe7x>L-hOJH3QOIIfxq9?af;c59m z9J7Cu*uSQfi>=3VnsU3KE#%R;y8Y}tw5vG7PaU)hj>*z)tH8Zq4y<}>DaXGZC@6JG z;y=cp#dTj!PObPin20;xw&1-PBDmop5b zdC96{Lj0BiV17i}pKmvTT!UqjtMRV5B-xKzdkmzv1u`h~e<&Vv`b}}U12{FgRy-ek zgvNHNf%(rpSUpl#0!|sCZeSyIf(i;M9SOR3{c-6tQ{3*A2PXfe(AF)Fgq>;o@$1*u z6nNIDQAM?!BbDf9<&Z(qTHKZH7kUjd60PSvadL z3bNj{(W(;OkOPS{Ny(w|%eWZNB3KBbB z1ovsBygGgzK8$@zc}D~J+(|mroKhON5qpys(XR{X%Df$ieo0s#Vwb$^F#P(b)KMVWX`%0V;JKR5d8SnLX zlNo$cz4#`tnfgkhp^4+ucO=jAUL$A_G!JlnW33tq{+pXySa+R5HnNgDt6}Aj;he;?~#G zs1#?>{_hTc^IXOjL%Q&Z?T2ux^e$|R)aA+BlBm;+1h7~60#BMW=$YqKOlT!>l6n~h z9LPc4yW6;{e_xp1uEudiwoY9-o08!m5nha!l`J8n;eO_XP z8=tDP{(duI_PeRU$%M2#{$%Cfo?sE6lsyKh?1YY|14x83#Iw_0)(XW(G z;+g~1cx%BMNHLS{>qoty)Gn4=EXSeQj}xNl&Hm&uGlxEP_mTzoUd>vgYr$hqGi_Ag zAY!|gctSb{8JNEk%ZDp)ablr-&-kT0biO|u{CqC%&Nkr>kEipj=nmY}txW#mc_*&c z`b1Smtu(UA5~t1VD*o)8N(FnfaK?`f(C*vC$?5(bVbj(5basg^&T8F3J!1m#&7CXU zSIS~9xW=ULCl?QnSuejcY%ERwlE9i1U2Rq4RqlK0PPvp4_oI*k7NcEiNOMYQ;DXNr2dlx%Ko;{Pc+?|3ZV zFODM=Av;7;DkD@9p8Gl~ql74F84X&ZT}aE0j1o!6$c$1F^4#Y%Rnj6#g9eobZS`&c z?%&`3@r>7VU)MRG&-cSYYBrmC-~48Zb*-#W=vp3Wvc^KEG&&-^o3bAahN?^ZvCPT?C#vm% zi*-9|4KcPccGp0#82_OSYEpaoZSOu0vW8q|9pgZx^!J zmlbL7vv3SuikXQMHv^j?Gn$_~$CrIqS^;4y$=vVbb7;4L37(lS94-_-;|`1S*y*Ki zoXLJu7P`BEf9Bc7oxF8kH8QhtB zmPv3nRMA#K4)I_3x>d4xWZn(7SYb5`SlEa=<<04PxIGQLyAyOzI779e7#;}h3EfX# z6q8rU$}h&Tk~As!6&a6P+#ZP}-*MualtB3W-Vt79bn}O&B92SnPw90tkjWpzCnv_S z28$ZxK4j6Hlv|wXc>~-l9fu*ij$!Y14vN=EF^7>SSmnA%uu%}4^`#N4WO@#iFF8eX zs)s;uktdxQ>%sz0y2G+rwv;$9&o&5VL+hp$oX_VWAR3uYr>|tgYWr!7=dD0br<7g) zb%$+H83PL^e`9U+dg!=*9I##~uo-q4;?6(C(SxP!nx5#K`+iUolyk;_byEuJMF((^ zPRDS|%3?6KNkpmIQ*cCa9BeKc$OcUE6uWF{#9qZ%c3tBN-@87FMt!@?G=^GI;;Rgt zalfA#Tlv7Og!y1{X$7f%*akmGDzkHc^PonGf$SA8m@{uSecJbm<~uad$=2tr+vN;d z=`JU2pHXzvx)NB1&F06~u+LY^dcPUiIB&c3rp&)+(KbslRMc?Swlz z$N1uR9c%D~8A^m*Hq75}c-Z+IBkIO*$Tga#FH@0i8HzLKuE!bZ( z0u{A}(8u*-am=trirun^YSPPD+?E}D@VC7{S2|I}vJwtLARW~VK@Yz`rfW42mLz|| z*>+#CeR?s*jCqDHUWT(i`OEbKZdyX|Ivu;hq&@8T+LiR{;}!PX?gZ_B^%l(^-W5kv z0y8Tvhws-^D9$dEi^<=NgS@xV+v$DWj+r;u(4NJhAAOCo@(N)6kV<^^=Mq)F5J9*6 zNhWRZ0pmg*vpF3#_`x~=7d=R2SK5R5>$Qqh#^mg>qx>miNj7cEF@)EDO5mH!eoD&P zLkFz2Y1afhIG4PP&R3wV*L)#?T2zlAF*|XX*?q$_@)UMB>JpWi6y4HYJT`&>N>pRNx?-M|}EgptfTal{pe=J?E zMN=P2;Ga87*qaTWY;H&<8>JA7wvX3VjZc*{ua)K;T* zT?>%8wFUM5Uc$tLRP11Ri9W+#&9;Js*)o;3%@IK+Tl z`bW%s-UWBIT|uLhu2kNzj^8xg7$bfUrLS8p$!g?#^eiJ>IQ<|iQXYs+cgm>xwgK!s zJq6mDjOdrYE1uoi!t7d#u)g>g%e!m_T0TWoeQhS2!A0U*emAwq22o~CCan!{#)t!D zXdUxUq#9vQ%!DD-2fcI0;&fZzDT6~cOx>?YzB~!^g(U@HilBSB(Ue2=HmX4Z? zA>)$QXg^Nr+`gc>kT(cut-!ii6K4wnttJ8&H=pUeibofnZgxjW9*QD5`48t0!Uxr% z>`2A|O51rGEp{Oet+<5h4NXj=ObJ3Q!YFCn5vbW}%!~?($YD}D8NU=*w

IRf`3 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⪚Qqw?qB#wEra4PF2WC;xD#w&vsI=n0g+Wi<4> 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 l(6ctEjF&!VtVsTAxFg$XQvhlCSxdPT^@ul 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%0Dydtr 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

CksbGqJ- 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�>`%iMTMcq@yMlqq7p-TEv85noVQ!WL{_?~KYM73l%sruUbh z;N?Jv5~N_->t_(YSexDOnZce~=ZP2pr##KXViJ?~6Ij2&hggO}0)M)+1`CXe1y5lX zENB{MeeZT2%~ak4oeB3re$-?ZcG!xgasnIX;7q!xt_0%aH|ds_CQ12!fX@rfF<)m1 zn$OLn%!?0Q6|>UTi=^0lUdTmwVgGH!A#$f^_TtB=S~8pcJ_EE~ z+K~O?qTske4Ne&S3Z;riQ^uYxH0MnOZC$sOsdrBy^Glt$SXq%|2DjoUCsS&VmZf9g z#&Ox6C$TYKm9|9AfNe#(oSLl;eKA`te&-N~NmFh>?~Bn8;_pJzN9Ad2t-!_?vQOfG zJL1-N>Y^)$n&762;EG+K4`wQ15b%9Hc}$dNzcwC#Ywuq34HaYH&DJ7#)~}C!({pi4 z)@HV^@j1`0eax@!aR!I`x4804i`mFtKrQnK7_~W(Yjn=%%g?=qIL}d}TcSxUVHK_# zG@Aa*yC!6n!$GUF31@Yw)1F5+(K^WkMgCJ*&$nMNKkh!HB5VXZ*If63yzSoN)i8R(IR%{vd~}fO9Y)h72z}3L0^6tZh4?dR)LJfx(`J+ z)Tgisx}R{P^$*}C>cC`yWoKis9iA-A!I+lOeK?IyKa0UdT84Xhdjwp* z-O8WOpTV|z#$bkwpuJ4{!x+~UTDo-~o zP2hc{8XYhQ!!@}>N$W^I>b=zh_wVueUs)RGvAh$L-df?I0g~Jo(}B=lK8k{jCF$?u zGI&Ile5m1H^qS$rJRZzLZP_NS^-(J6pKxYM+Upqz-}6#+vHV4=b@XYDJ=mSq=L&BM z4)-6aY>K3*m@LoY)8Ff0{N(_=d8D1|o)^z%H0)uyefxPAZ$tX z9r5Hzf1u;fM7Gta9Gpw#ne-G5>Td{yO)h)zwALJ^E1L}?=ikH9dHwtf=~rm>@&N8W zCxbV(y?_^0>*#sGL|X2fPo^H3xX0rs)^GXn`dfTfaDdkf z5IS-TpP~G66Y>rJEb4bqpn1_pd3)L4IQ`T)y1OMG<^Y`n$P%-NFRFO zK8gF$Hi@|}TTZeW1ku9}W0TOcmb|9IPR{#@Yg|G=W%>%{DBP`jzpdjORjNnRujniO|nh=vYDD5DkFUGnjPa%7`v$jhmFfm=#N%sVt)@=7L(5S? zTu6)ja$x!L94wk@!xwM~XmWfc{+4|}*ElC};JyRwr^#EqF1Lzg3O2GbkEgh_W;;D= z97zk3i*hf5@%0^c2^ zMFp|UOvjCWoIXNE1?D7kH4*;EBnr1cd9saMOE0eDfb^5l9Eg;JH17XY`+(R|CJZ4PrsCtv9H1Y z<%LkC6hpU7Z{Y~`8Rk09VG3*a@!o0M*|XR6s3SQT7ui*a+tUAnO`;Tg;(i_XN!ek) zpB_wqKNXkG*umasKI13mmcjYaew@YN{S;GCNQ=Mqu>&hc(IP2-^nK|Enm3BEd)H>1 zesVu-omE2Gch0h7f|oQky$x*Env>d$76_3|LxWFZ$XWN2WX#JD^d#w@D3&Gn9>nyF)|8x~|jw=l!keB1~>IzPbhI}I%P>R`%ojHUzg zHK{!OBzqS;NIdL~HYPYMpzAZl!hPlme)_nc#&+khPwEe#{7(xUtr25T%P3y0eh_oE zx=!nSbZNG35Hs64nwGtdX7Z)!+@kNH>`SvOOW6MgD?Pe#)N@OE6g8Gz?Hx$$mK}nV;nRk^O`yLxdGI!g=+Dr{j*9(k3odp~V+Di7V zBT0GDLtf5IibA9Y;`W;+_cU8d)m-vK8G-2x=We z5ORP7L?lU!-o{VA^ByG&RcYhHE*QE(l`VV~#jkyqz)X(aK?lEDD9%2NTJa(@9}-Vh zf0Oa@&IQahqZaR!tYvTh2%gOd2`XPyOs565X!V70xlpD z8;ES)CZ<-piu#-6>6tQ*_vCB2&01q9SeTtnZ$0DT|L;d(-$c2?_JQ8jSSHRt!0s)~ z!1MR#(ftj#!19#|$sKvd^q0-2A%(&%QTZdcsacjrwtBM3eW9!`ei4=a0%jiK%e5VE zMPn94;{`v!_y9(GeTH*a8jg}rzaGuCLQXS!GH>1%ia|n$N8|iOynbOIjoLRB)Mc*V zgY%ooO|llX8?>pVYb<*%)yBQ#Pa)4Ku_IQ7tUSDoBt1W&exd?n4!?NkWxK=|r2oTN zEh!i`$DFmdT;&&A+Oye0m+AP8MA&-IoB8dF=PguDla~5pykzkMk8kLt`CT8e<@G8$ zC6&v%WzXPJ*X`_n%S9}zOyMp`J%%VBBaD}+W|Lb~(P8{-8f|9B8OrA2iHAqP#W56J z1KaS{=EKarNr^AqvWhY12L86xSV*rc!SAEv`58J7x#%Z3(02P&Rnn#>qSen1ql)h( z7^NRhPh)1Y$15#FO;1*#c4;|#zi2!8I$ALOK_5ll52mux6k8goFGVq3t1!p$9=qfv zM;9L23Qk%hEYSGC6}&g49}NdlbDR=F#$XCe(h|AnIMYzO2~5#P=;2pg;R}`o)0O=b z$=>@lIDE(@m-&X6bh`|Wr%U6LKbq7$;SWDk!%ie2cq(JU*R#iK0DcR1poxDxp-wdn zo`#g*{Q5#zb$ALa{W+2bWwb+pe+nr%zl2Km16slkut`q@X7ZdtkoaB9S|16|0;?_H zdag-aHY*kPjUK>aG7Y(;o*ep5DU`V%45er7L&(4FDViB};FhLL{+z-Tn*X8@&P5jS zPmP|#nx6~NTiOYN^PKSQ26@)8ZQ!(+b;5W1#=|tlkWu??b)u0d+~$wNLtZzgl??40*RUvNL*in>f)22 z^>8FA^+d8U+ml#vMikrhaV*camI~K*;K%owu)0;YYS4w{uzR>JrPi;6XUoE<)Ac3ia&0*1Y_Mco0#b1A!%L`f zU;}DRjl$7p1Udml_$nbCwhQ^`DJQG&(Bn8t?_4B)bWOx^dJ8eoy9&FvhTt8iZ8Rl3 z9OOkiQTOz6mLgurs#ZP3Q{U5Ad7dPBe0BiX9Z#z^9S`|E##Stixi-ge+J!Yb`y@`ow2G@&p;#4&K9hg}}KR4VSB( zS!+VSxOku*JELRCqITXFc!gg@)#07I;z(22uRDxybT@@)sJ^3OT&G) zAuwl4AI^NKPN@r>!Qk=*ZqDdZmh*EEEm@^Ur>-co(D)K=Zl)gI=@r`fhtAN{*Qa6o z#a~cSv=#RJ>4j!GO-p2lv;3JV?7?ASmb$)|@$SZbJb7rGqdz(?T_s;rz%k%#tk2M)EM+^UJ>uDyf)?I^&R zX+wDaf;#KoScpo^r}$L&n*#6b9gcN9k0UQdGG0!KEaz_^QN2287#~9AXhj?(IRhR9 zH$daUdTbt9f*xT5N#ybx(v=%Q|DYwF+hNE246K=!MI)5H;hosHE5rV6;nRiitBb>#oaGA(ZD#Nck?BR z@ssw`qJCL?yA<){!-Hh8N{l8??(pOOWpJ^(B~Z&uh8=k+PeJNBFv6ix{AZ`&kn&Sz zP%H4G9aKPKaW^V$l_Fi8gY@{2iQxM>i(wHJT-G;znl$+#-=8Rg&aOdNDP+sU_v27o zuM|c^PiCDf)Y!*lb@pes414N7f$?+lFh0c%O7d=@RLX3&bJTIZ{EGv0KQU(&b?tm` zbTF8&napl1Phw8Tfk^}`W`(nU;OYK3T>h0LT)XWGj+Sx9$-$dg_|HU|r6|FQyav(x zo^Q~$RGz)N;0OAz3ptmI_M{m$n6=)D6=&y9VwFNKsyXBPUhun%vY3QAF);eT5+oEs;k6FxP7ynz%cF4@d)w}!{ zzv~I}Q7VQ*^Nral-Sc7z>GQ1LRLIi*C*Lda-dG7*`uhNrx|BpK!fl}DtQ2MYFQmfPdQ7g!geq@KvWBn@ zwr`Fz%l&p6Z`~PBs%0(sO7#hhkqD(lf3CyR0$21IDY%~|*^uwt#kBCzWZd#dij6%J zAi8oyOdu(OT<*ZtmZcE zb)+n7b$WFmADTv~VMB&8X%8BK>XXXh<*jCM&F>L4k3Q_CmpK{ikh{R&|EfWrY4<_% zsw*Wge#E`1jo>f3=YsTF12!{kDm|;1N*3zRn00Xj>+;?$@Ruf$Lkn8jCvSk-%5?JS zt%P^0ohaOfz%R&@2B(~2QF{CF{OnlBo-4))TX)mRZcpsLwT$M~l`*r)Lnt>T2Hp=G z&WhHnlJnKi=)a){M%}LG!`p|mk<|_~OfC%V^?#w)$hB@yepTv=mR6@!puF8pm`ii;(EDJvIo#^+bTYFY8zyK6S|eE_1vZ_H$=N^ z(qO%`B_yt#&6f1(&|MElI^}g94=%bRl5%{&#SPJA3Zv(>O^*9y7etcnCF}J7MX=q2xNqn=>#j#`66c;+-E|vGd9!yvK%8{p(uc zdv6`L=k`JzvPzZRo*B-kIvGz@^O}w(gZb9R?0lVb$1Wr5JziLzn*}edkzb;YZ2YL^aXGF{lv^Bd92u~M%^z%`M-^Kv7$_H zEl*xRYgc)YQd1S?uO3BTx*O3-W`fwa`6n#QGqP@a(+%&d49UvBkjoIdL775kenZtd zT*-H%{vKawdEh6S@_0DDO6=w42ekuVoXzHXEa%+a4cYh0?>MtvL&4HU|B%VC@Zf_&wqOMNcQY1dxDCYX=Am>u)r@*|eDTw4H;j5MdP275#yS3bwZWW)# zz%Ub1T&_!{FCE0sCGWzZ$5+Hz+i$?l^a#;%sTCl;r^^1u6~eFaj=+D+#l)W-aKU3R z#Rj%>u_=~pL~Rkj=idV6shZ0#G5X06FmLd1|}OmKz@iJ zFV?()>U$5eb4K@}+hH?Q*QTO_!)-{1Qf_~~6w?g*fb5MJUJ5_U#0WeL7z=?72gNM| zK8lX+{tu-KM0~PEG%OhX+q%VT9h~fc4%de)hm{Ri@a6YRcJ&_6e>oGt*DVrezX-?M zkz0g5iwxCu?7=5%)3`q*3H{UBvHj=_(agAi=yh9+DRcTbxk*#$Z_rn;9iPs*H)TWh zs5*S=EDas|Ml-FpKcXRCO6=@REetrf6$XDQ1fw!b@*HNz=Z%fSby=nOV3Xjyd@`2n z(k>!TjZ}W@mw9Y~>l(i2K|N|3M&q*bNmQjZkfkmP#rMAg@Wt`dTxW$Eyi#uGm!5r( zZ&nY-RlQ-Pqbl&6-UTrOpJUvlFQL#LqR(u5eOUY4;bdm8lO3)x7xwvT+{K)Fh)mDK zf}7R&%3u=vtPl=QBdzGivNY`XiR5N1RDuDnh4^N&2o*JyS*4!|dv-YtlTWtwL%%okFk*ig-QMv8D+JeEx8iwvSJj8w zcTU4F;cneh`wW)|-A<`i9ieklLO~6uz;@quR#TbBi;H%#=C*h2zlrW_;K673Av%iv zK6H^WUriP^juq!`4#Z;$R&=e}j8y-{fbG|DEaYDSjToNJyUJ*i|BZ0= z`=1&$-qmKsOa8;Sx-|OuC4nw{)TZg{bZ~HwK$TCi+-n5SoEOgO&Eu!Aoe& z{;pK8{}=;wq*U@Rbdd7%?HN6)>m<$Z+Mvt6C-9kK}|{qn)bZw}u5>$yIv*^!Qlr~8!?(Yagk01YX8v&-u5g}2(>$8lytd0QXpJNo$ctc`?*jg+ z=Rk59a1~yjn@qlWy3EJA8SifDfyvW<^J>SR;6~p)g6pT1OVbP|+j2D;y)Bq~e(F0! z3>IP9DtYL6UeAAAw~uPF4cOV`58=q_m*}(a5HAkou*k7c+@!1n_1@R6}zp>XT(0B+pIKs=ZA1N8-7YvbBj+#U4;1~w^@+!|$0 zwR;@~5Bq}F9eMb5?ICE&`i*Ao5h&C23icf6;D4&$heHEq(feDWbZdM%jndl7d&`@# zEX{Rjb7mK;t(uIVyFO$7pJTAhXDR=D-&Nd^?FX?gi}0F<6Pa0lg4wZ=ocehe7L;(4 z%N{))@p>bo|S>cbf?GZmyxS1>^9fLWa<-Nn=JPLO=E6FJz5Vu|8G+E z^R;&2Hc>G9xItIQ(LccC7&*wd-A?Bg*WrWHU63Vv2E^O?_!~_Eqw&=d%ns70xucYr z?WV85jj3Wwryk{h>^jB248H(+(#Ke){T5o(u>jLjmqB!|8aed3U{u*Ip1u16fBSEs zUHUxAT2hHa*GFPjbtbs<&W7oGt0?WRh)G-y6Fe}LFyo~$cu$g{0S31)qwI+IaMfL| zyKn-&yO9#K@A^LIn)3nkdoJN* z?SJg~!0+H+yOG9T{{YD$dX#GTn_V5%$o)8U3tSdPk`*O!m-jTm^9p}D`DYGiFg*&C z4AoFDfTv3&uVP*q$mkMF?y8G3xK1WI6 zh&t;`euN7?T*jB@%2+`ELCEV3*Ea5a#9}T#rWBqltDy6%Hz-~;QP?5vVFN9uQFg;%wxdghAAQAwDq1vXwa^dD z^1lI3XHH>hXY~2W0pD@?0t;3&$(ucySinMCu94xfT`=>)YI+tui}}lZMuj)BB*4<> zSY;euUD(TO3BTjc`V&k-Y=;^b)xhmz1G;t$Lc=Z|4d(_h@pb@{FjDhieDDh;+c&-uu1v*2x?dQhRn=_8om+S%? zyA|<(Wg;ZYE76q+Uhp$>_(kQ`FurAaB9>hgW`hnbsC_jB9=z@WslC!a&8<)R56>G)!DoRdRXe%|TFRHw$Ety>+59kO zFI|a#cSk{!Q4|eZiF~%MI(z@s9B%bSb6YMOaf%YAH$gQ|PHy#HWZZ3$wK3^CW8d z)5eMUom@$$8jbVOAq&e(SXggDjS322;F>KSHrfhq9uji31LC1sGEZ=!Jx1qk=6Fuc zk{12Dgr9ai#G|>Ev|#8Mh%dLJDKkdk-LGfx(yX_jGb@O8_y5Pe-D<$B1{dSY871K4 zbePP~qyjIVOA+r)NR-+FCq9m4obz)&>{KpP8Z_dgp>sf2Ba2p|{48v(-!3IByS?>ZDX3mRMqaQX-uzT>XjXqg~mipGwx}#!e@` z{hQcB#sXw!DY7|t8{pBYY^=F?of~W{Y!ZGy<^}T$%a~`$ZjZf$HhIbvXmgW~bW#TI zkXL-(u|J~waz+?;&VathOR$HX(`lW@ORPS*8h1|ag`r!w(ze-toT`QdGincnC*##% zqgfprlA_ISe^a0pl2TN_CBp=l2XNcnhjnafMz^DHU}r3YE$Q=c_mNoa@fnFZ)*<+= zC5j}9z3H1<6@S^f9yjg^LZ5G^n7yI7I91wB*jt~0FsDFV-6k_FTgWiqPdP@_WlPBH zvkdEZNv8?U0i2`2H%%ybi|OtMaeJ8|1%Lm7=IZaco-3a4v~GmZ`CbCrO?vEa&SLN% zybR|JG6I``1AJFeB38yHg3}UhQsav`t%(M7UHv-Fv(>^MZgy5Fx0IlEhA}(+NuCw% zkHY(P>xnO$2p@i(#FEE*Q1XW>ytO1$xg<|pR*WI59|M@&{FAKvN;It+G63(7TS;{@ z4`b=MJa}a2CG6Qh;fmq4+>Nj1TxtCYt`B~L;mZ-w;#bV+Pu9i-Eeo0N(NLIbZ!CIp zA_rH*iXimc3+QT_N>d85VZM-Cbh0bJ!3i@^!?_eaZrl<3wYI=8RVNA>S&z#e3?-j* z8?4uugU9}LqkD=nuX)>uO#32nMCTxg3m8v}hlTSY15?m$&P~|nx{EJrAH`l>?}s~v zC*kTyH>|V!0ZjKbXW^-eZn%`B&MxMY=MZk!`VWg2r}9~+CLj9%xrX9@P@w`2U=D$a(DV9}mGxU3mBu;ZY(lp*RiGnfD9OgA33b7X*!pA@6i*$1um1k64v9Yns^`Tp zAUg}Ry!FuOtQ6Y_M_9D4;FOngAcd;SkZz}mwUEiSYlZSfGv>qCwo7OMHW*~Ll9i{v z0(p&oIH}bPtJ?p-N8ftuvzuq)_{dsll70$m>ub23_l}{2yfR(6Eh34VYe~uCAO=Sd zgCp09A!nw*Vo8apW;|Hvv>K2~r9K=Fw9^>P;>TG(%1oDwB zf}JCdL)i8JcBLf}Ol-c1vgiHA>zkLbcORoL@QWL>HMFI>+qKEGqL1Gy_^7koh8!xycAheE%8-qtj1)zV};h5Ly2<7)nrMHUx!ehIWB zwK30~#&AHmpBfx?Vk?V6_@4P`T+9Y7QW_nFAte`4cBm1XC-7B^l_I(E`+Py|=ujwH z`5RY#`VRApOwd{B1AlbKObk^#M6tgvVC9fVOxQA%LQ+nU)w?{wf#iptM`y4flBXd* zA`f29O~uq5)@*(EE&2y_8+WxJ6B}?!;2-4S|+ln zevjWj?_zSkDy*w9AI%=T#gUmNxb|Ma08^D;3Iwftcz#WatXh=d8x<$;x^%cFi&g~m#_vtGPR9HurAr~;;@4cw`MIU?$ zGG=*~C*yd{GJNN*DDWyGV0J~7@UA+623eQja5+^tbT1B`Z>Z(s)slp)f+79*{#%@H zG8W$d*iPo9QS55)aH_d|4JA}Hn01{r3)`a0&YrdfY3r3(aB(=>tN;{JZHyt2llX1R zr=aVN&$vt)P+GqfErc7O%>~8k;0aCq{%9v^dh3VR{;tKj&yBfuGQ*-C`DuMy&qJtZ z9qzxCf)i}b$uw~o`3HXIv$~(50HkJ_FEp{F@BkTCN#W`-D%{TkCk(k#jZ4M}j`^)l z!aep3t*}4DR*#k@Pwf$OLqm!b{W?+a4oYp5_ZROF@A zj|v-0;6-2^jyRhHS!W7y-hnZw5^Tl?FSI4>(WS7dasa|JYf$!8R{x)?_-OlRIC8Sz zI(x7l)AG&X_cwH1jLY$2+3Wv`FP(n_*Z!*morQ@QIrKJfY7`1}_lC330(&+{O$P5( zmh)|o`e1bHe$lXIJs2>CTh=dy1pzhOxn1K~$x8!j+S`SyUD2FIn;ABn-Ge-vN8H-$Y1SGi z7NY&ZIk-@G7P0yjaBRLm^_)oLotzw*lkl7}e194Bu4&;(HEpykl4St`qyM%^x`>^s zMSGupbYI6Bh96kXN-S<*NsBskYg^EKH6!-P@dcl{z6@@x%7bakJ!nwO2qptZ@$!Ej zOx5c#@2D69_HFlgzdJs3yy+PzRV`^fGNN|MApDm>3X&x)mPeHgh%8GU;R*L1(DxQmUwCX)b@U;}%{p zjHC|_rLpIYLs@m6>ncTrWbfIsLMde= z-sdl<&pGE_*Kd4fgBw6IB^<31m(iRNQQSa5PrTKs%=|;{vkCPd(B2{v5=BS&g9Bq6 z@|yRs>&yOPT~H+V_{;~fwSN~@q;TxN-c9VDtv^4fZ!W}*X=Srt>_Kel!R^Y%Z04#^ zHdfS!&H-6?%CA81(%SNw;gfKH?-EEHp3EfUeDL-KL)usW6RdxKz;ho&Lf4i8B`iy- zJaYa#r(k}VU9u0Rw+bU^xK=uzusX#*RaEA;MrPr~0aM6n?FssJOyCC%D&~%>E3#`n z%JgYrf$*Evhhh^GFnpv(9yUfKb7%wGH(SV&jg02pOLEZU(`LLhES813q`{9vO}IO# z0VYYT!k4#F0y*CX#=X9IM;! z3P0P*;GL+3>zw;SC^@sjFEKZ8WZ4vo{4k#x{FlrbAA7+ciCKlV>sN^W_5Z^g(^J`h zd(>FavOSQnFNy7ZJcR4LypqnWc|27(XpV5bBHeO|}) zMqB`;0p9%)k{~zu*Ncof`!e zB{#tQWRH-^a9~Rg%Ckp-403j5;PpF);a|ob?lc!fuQksj%uEB-I%TF&FZfDN?&A&a z>B7GeU7T`U41StB8q0oY)4DuuT;KTvno~zn?df!M{m=k|g0*l*S|)t=n9a&szCwFM zD3i#GW^00<^IMBga~Y!*8TaEpH|wD! zKaxGE)MO(q%-Pko#mqOnnSZYS5#LQLLeHiM@VL8;M!Xb*c+E~us`WU0>^g)iaY^yV@TyD>pi73|NCVq~KJ<;V!ihGqWP4l^BU(M!-?%t3 zw=CveWiNB_W`fS=ZpfOxo??YN4r1Vz;WVy2A5VS?;O$==$4O1i4i1vDsOv@_zty4< zZ<^$VGS9$eni8}9?o3mKj^Xk<6_62diQY>mvVJXj@dDQi;O;1#2__Ht zf^Eyt!Y!CvHbaGuQ#kCJZ-z^6z5%B%hjCW18HNAUhkL73&|T2L-hbHxwzu5zu}L(Q zUwRJ#u^zZC)|k9)AAr1lEXACWWsWn{ncG}%c%m(Vkx7Ljv*@90rxl~R$JX@m<1|`Y zxSS?G_=ZKFCh!;ek67yO!AdXfrd`pooRWAy-i>i(*#tjbAr7rMHKd>O`Mws~QZml_>-l|e4Y3UFlR zQZjSjhw(yZ)!Xg{$Z8kEx5ZE3mXjEzt+jCRkq$KK+|Tt0dhstG9o%d>mAx4-n02}f z9*E{|*xsW~x6Ur3=%M*Ex&8(;pEY6C7vAECa9vt5<}>uwCPGNaOMGu4N!wo^XL+(Q z+=BjAwCH+|jaTJR^42D@ksoUKGCpNOa`z`;CVG;$zLi74>%L*k(BJ&l!;Sp0 z*(YF>&15`i&<7K`wdq{nGTNKC19eA8(l3Pr;c{=sXZXCvY!Yg1}JIGw+H9o}X;t+UMeO#D%Pe&PP zSJD*D>b$Tx__w+NJHom+{gsW_)b<^>_s&6`{v`ZW@EARZI zAIgDX=Ku|DCbm)**7hMuN;vl)x1?)4sh-I}rQc_zxYApO#}_*wMZpvBRM|xz?NU>+{x>c zxfjk~VfX53r0+Nly%P?Jbq@c-~PAwR=}RLUqCCR za!hmHBwjS&3_PA_%-CxV549b{F@7EpEO@vZ+%LiShyI{M3N&+p1xa1<;N_e&;MhG4 zdb?#W=Kr?gek~K2#_O%PeNiDe@}fRtotdz5i5Br1sx)A~HXoK6z_=H=Y<&rj|8C4@ zzJu1We{1Ff1TUoO#eeXqo+fMda)gG8)wup=7OwmF1kb#(CzmT{Ims#&RwQ_km%X^n zIk-+?i*D`YuTHmPuFK`|XNNnTaW`i_=0;$i^?r73cPl1M6?!-BnKE~cL}uKvho&`_ z;+*}_T+ByHOn>ab49DB@VwD}VK2HW#-JXrQ)!}T-hZ49g5zQ(`8sne#QFOm4fV86{ zxmg+KaI>;LDTE|(k)svhz|sUTm}*F7<92ZiyfxXc2ig3-fMNWv@+rJl#4^fN)FZDO zi*drh;k5E_J~V1fVF7<-#pAsb;Gh2@m>ge*?+Xi|=j18gQ?ENzISJaYNP@RlFF(Sj4d>K0!?`M5`uHpfhpen)d&cF6|3wRH zyloPz&xoft-uK{|j2}#1E5XIM%F`N?xdOxVJB%+Y;3msRQOk}(mZrK8jX|AhsTx6d zy*}xMx}ikjFW4izkN*0f!KXDsAIpYb@ryGC(5v?sGL5G zNzkGDYRVX>YfbN{9u}nC!u5{Hm65 zyPJ)%OCH0?@csPndE>D+txA0P;V?8eIs}_%q(H~HpBT45pHjZQ0EvY;4!>Je_?;dZ zmFMnBR%U)*!L|K6!l?~hPm-=ZU{r1hw&jmNaoHGhu=E5ho#e8<}VFnhxJCD+7l3YuXE8bAAfjR|aoFDU%JN_yk zYFAm&-4|QQ*y9qDiBw^;-gyiD*gib)I~7!CZen}RTov}kk#PQ=KR@%)Aw1(?$@IqG zf%(1GB#o}@ZlpB(DG?68R9C{xe>yZ_(G%#bvcf<8lZhMm3U9}-MF%O`3i}v90xMJau8%Jy8JNe^N9y0H99h|wc zpjj08ayBTiW85Oer`~GffZ}{+Gv603O1#0g&KFpJ^d@+;>(CF`5`I*gDV56Q!>bMM z(e^8*rA8;`erlwQ!*2Njn2aQvi?NaXoAHEjhIqP3dsWrUh8Xn)m%_slh;D!uZm6*+(tD>P|Y9FqROyqmC|jaWNvzmCo7!%j;wwafV(p^S zsGayrobWuAE&MDJa*wkq;ou?`dRKuxo9qEM;{AC3@l-zI))2BdzL{mIhO)@fcj4Lm zLu~i4VzAn=lFeQf$ys~tWmEE}Ql|P)=KrD(rZf(vu)bWh6Hn*Oc8{aE^9I#LDs(xf|GUDSFde|6uA8zgQYY}*luWEhOo1Gc zJthA1q7TF3ptoQE&7Gmi5|$4`jjz^hW`i()Ec=SOi?blEbu|<>@8D%)7Gsm_2Bt6c zs>-FP(tk_$!WWtMprHbyw3s1mWY`Y=)3MV`s`?2o5WGtU2In~UHJLCudOVYVwvj#E zdjKZ46vCIYif|`8l)X3C0rQ=b)T<}>zqRyf?kYLj#ZRN54@*Qk_I_kHe=F79Z-J_) zWu#l4N{7vMqWO(wXe_WXS|?7V)=z{d5|6{$h(8eEvw;&UxAKXl>nkU$y$rp*@@(&x zSZ=%Vc63x2MBdX6(2%Y&*iq_Ask{;?=bDo4>lpm@eFD3GO%vuA&1LGdcamR~DjOPg z3EaDH3H=lyEPnApRJO6>6`}@$Jwx31m1Y!J{qd4~b6S%w1pQYENao=OQ(Lb;BY;H9ynfgM!e|az3hA2>&TnBf1@n0CSybZs$O@agO^Z9_u(X`e) z2nVi^X1d-h$ak9;C2f@;#jQe*l*Ck0_0nLIC39KuJSF-)u@t{gtD~?{zNG)`DLm?k zrZ+loxPwnhg)R#PT5Xn1ow=^iZqv)V8kU2W|;umbR)WHciCebC9&$a*IabVsf zF4G_p*0jf9%E%%3bf3T+dv#XuUdXU-$C6R=&n(uNm4FX&n#GswHCeG^05e>5)**J) zaGD_H4Th1`xX;WGr4`)3?_dnGyW&JI9_KK{K?&d$k_GOwtFhyg0V%4)13yLyYk!|X zg@;}2*YW8>PPh(pA1JUdKW$01L!Udb#fw?g3}Q|4qexV`ovm(n<9+L8NwlYc3rZ_s zn&G>sqkkpq9Gxd#cg+ENE+j)(uO0nKx8-DJa+Im5$|8Mbsl0IqZBX1y<=ZuR7nvlg zs5PX$=hHDsx`|DUd4#G@d*O)i-dY+~02xk-0{a2zWB4%~HOdL9eRSxB+h=@M!Qp^s z&oN%c3HoIBv)@yS>3eoE#=l~Mm7yMo4zm!vm9v;%ObpZ=nL`hcJmRB;J;1rQ8(QO5 z^0S{-fwayGm>wI-8NKD`-I|eDv`zx}4+gAkzgOb-*I&UHEk2cr=vkfX@6z za1!=;pV^~p3elRb;@EQaioXW><`h^WP z$+RS2k%s@uhU&$64tHe^;PG`Y_<5mg=+6y~hDr*I_$glm57{fe^6f3|OHw$9CM(h5 zB!sS)_RRJDXFh$u6Dz$s5oG@fnS2|Kr|suDB=)<(kM+^? z?fzi)W?3$?_$8v1e~S74#telUQ))4=VK3+K-&c%QRKY(D#^kfwi8%%s3Eb5KXr2*D zhsE(^xaTJ4xPQCABOgpwRT>P6%qw4Ok7oUEkHC8C?G)#rLWu&;_~^bdjMEM$okMTX z*-fARHY>0SlL>6yZEqIuo=x80FENwLLty>3bGX<_6aLwm!n7H-2)Tb?$nS72)X#># zitoZX11ETSP8A+JwPOxRcI4H3on_n;m`j(|QJG^qULI(K+Tk9wexog%KV?WIlcr&O zi8ChJ4Wr#r+BCmwB0L@5j_Eh*xJk{L{0n6R2-YyCS&LQZp-&~|s>kER%bqw+&5W%$ zFq@WU_|O~kKb+*!7|N~Ipkka2OERyc+`v_|FzYLPb5?|>rwZ`d%udkg)nRoX^FZU= zK3Mwd3U?{n5;AR)+4IWhprfP@wJ}#geZoFg6Ql|IMk&FXpHA$|buWn3hz1w`G5jO% zVw_Up$%coIt~~wBj~^o~NoSU4ae-ki;5t#42D#-ySDYH=EaBMN@q^i&%E|12=|Ap? z%uOu0aUFlRzrlrZKOtSJfGIwE#`T-*V8hykUi=w;g1^X=wahiA()w5Eu=*jg-T%Sc z)cXRDo}pQ*E!`D-0pE{YL9cRCJ}XBVuO?pw$5(NX_HUBFKswGJ?tYJx?0hhxcpm;3 zoI%%LtY?F-eZfBmwAhABOIC1r7A{gsfGzua_`y5%sCmaK%m5oGUN6B4HP2w}zqgQR zT?1;e+T`Rm6oxyDq>WY4sJT3tDm)*GC21~|)+jT}E`gI<7Ds)prL^#Pv+$XAU{TX( z%#1q67B*i4*PWNJI90?3Re4a>19{RKW6D%!7^3@-+kC)VFBbYkhMZ!%@wMA8zWdJ; z?#_ZzG*7=F@>>)^SxvX#!lrDtGuHw_{-}tQyBsK{_c52gJqPJ+2%MajA$okqhPDNM z#n~sCq=8D>N2%;2l!Rx zKH@PW8 z3}MzG)gqsRZ^eVelZdXg@OFujc)I)>CM(_Czto8P%*J5%&87S(-<_Cs zA_iPfN>jJ>I8xjHMSQxV6OYfGEbz1#`};BsiXXoRtHMlfmV`R|oL+(p{j@1zK__R> zAj}gqv@u-h#~hZxVeK7#oLDj*#g;`}^xZ<75j+YagAQ_M)xB}_opYcnu>@{Ed4X-y zucBcE4;jx}u=Q#wlRkDY;L;iDaajZF& z3*O97!8h2f?!XRJX;PfHR&++egZ9j?!uJ72pp$(@oO!hxZ#TZNKiwq3p7?~*2Izqm zf2G(}qa&UQXedjbSL8_dprGiGNsM5I4wC!6qA1#Ca4($DcXKv()Fo*Oa=x^@i$HQg>e zF*#4rI#+Y95>1@KqpK`I$QVub$s(7)GteWvIm7l%C$r~1Y)ZmRw*SO@suk|Uj8tSdxjyj@$Oa@hXsWZy#+88BBRv3utJqBY6mWvX-A4`&TKV z!GBe$)2$j_xEC?6F|#nrDhBSa?7+701r+H24ehvKjIP@vl8lqXr?-XQ)`KUcS`<$& zW0sPlo=rl;B z9H-0ABG}QhXW3dCk!Y{wF_fTrWV>Q7%p3O(Lez%P5$_--YbNw9{4hri-IJ&=DHYso zPce7cEHrNljCe;0=I{0kL&~n>2XQN_5BSDk_4$ z=xTj8cU?x71nK~;S?fWjnj=`PjllmaGD6jdo_u@eK$6W=!&My<;bf{T+bQ26jwsv( zuWf30zXhJmI7yN|PdSVW_Uz)n?fu9XYb&rFgM!fVp&=#PM`6O9I?xOZCr>c5iYuhd)0}39Xx~!C{FA zayygA)7yepsXI_a?OE>mwL#qGn?mS#%`BR+WP)-C)>W?PL zFBi~6;S(M=HN%e`X*luY2)eXK8*9v5VCQ*%*tYH*rA@YHwlOkn;R`QJTd6>Ydp_Xx zPitsab{@^LlA+6jmN++QEiaq1hUOn|r$cX+klw_DeDnP{I&rg(AMu|y+oN(;$gC*Q zFWWn!y-!oQ%~FB}du%HE^yvq;cvTFB9NNq8ow5fM)-R{Nogq+R<;uRSG=!pA8dT~U zLs$InL(_9rdc3s--1e$5=r%x4rxo1Py%*u@&t?|(;1Cq69VXL#TUd?L4v5%RhvPq( zq5Jekex~Y9a2+z8ZgoY`OK&^2%SxNR>~f%^v28;BLr3Un;NTs7Yrpx88@@`4UuNw~cnXO0wWn+Nd)5Ew)wP!`@Hd z;PtaUC|_v7_U3yRiJEEv^Mf46PlhMQAlq!w+b61@XKIK4YA{t(~Ef1(KbvWP60W$!PIm; zUc4_ri}FW!lU-*J=i=`~hh`>VYDNKU{yT;CpD2LZaK?<%V@0R89YzZ!G5yh&gvSGO zVTfBc`NiC4a>F$+Sl~O~w6zjC3?kT*j}oj}Lko3B1)xq@I#=~Hf=c~=@O{>wFf;Qx zuC)0Jw({l}89ESRTMbAlQjsEuM6eyxcf)~f4@Uk!u+~hEAMs!Y_WH-L{trSQ*Pjwp zdbNxmNvD!ZBV(fkRzg_IDt_&vgCM#55xg>xCDY~A{4c|)=sj*a8O(HG{wCo#DSZi} z*b;oV(v~vTmGI-=`fv>be|$l8E>_7e!KlJ#*t_EtNLL5KQ=LE-tsjr=rZ>>HHxqPH z_oB<+P5h5hDr901%thuJQ`Fcc6z)2Td?&m{8ND-jV&il=mK#h)ODC|Hliih;;z}4G z9|Zop(wT!oCkQTAv>9N-0#ge}(e*y}%2J&j-FOF}`8{VDRn7;be?`eG7g5WHotRb; zgKc^iG$yKxdu+H<Ml((^w&kXZMcJt~bS{*KUg9OfHL0)YO4VYXP2H zq6W#ry1uh7ni?Kg(DGZr-o6@z*F-1brSDQ!Ht{4j{&HlyH9|R;%WZh5bQE`Jiyx$K zSD^MM?V@$tcCqlPb=2jo#7@huq)B-Z*qnL}-~0Q5vF|RXUFt$TH3%yjPl3Hf7HP|x*i)p(ue11xGQ)Ho1CF?os&6Hq zsNslNtx9ZA=3VT)H-fy49^uIEdN}Y|8k~+C%VkgsOg(0fr=1tz=VSG_qumP6-CWQA z6!h<0hf6r_Y!z<#Po1iomatIiO8jFKLDFJ9kosEye}2q|yyauq@913msI9|}RqTh% zL0{mRUbJYOwmh?+F@%|vM=-7WEV@>9mRDCj1mDK5WV%OP>Cr|{YL_rVY7tcrc zNMYVR(;4#Cmx5-Z(0{(u3a>Akg{SW5(FQ*U+-@-$J_w$i4*{d;cJMNa%o@p7ZHg8? zQyoDY+Dxx>R)eJUdER}f*x~w;)og}ZI7*hJqWJtbIMF4BTN~raDeV(>9bhc1n(&T; z6>ZYu`Ox@*u&cuZH{Fn>G}9!wwjcx&1YYpEC!;C6$c=I$RM@p6XYtBGD|Yti4qP}{ z7Q9Vva#7Jun0ap#YyTOGd8?gZ$osWy?9`8VRnT3>3g>;aLJeBY9Dp(Nf<3K^^}3bCg+U z{=t17sr-dIC(yITo8Hu}WIEysv>Ck>%^a;MEp8g_l*>&iYv?BATe%#pL zR=o5)ksP|$F&+J4Fi%eb)q7DCw01tb7L!LJt70y6$|3TMzbNRDub|*uD61Ls3o^u` zNlSV?*?n(=9k#0IwcCPsy?X$2y_fUTgwDgLN4H?)k`*lAQ6^YKrHFjH4vLJsg?#A! zF4(x%9^BN#xT@ZVO+NV!UOznpJ8xccc>hP4v}bv-j(3k+ znpm-+lu}$OapgZ{V&zVt5h{(Z{66unr*p|i`z*O|pEe8R7M69l_G1L3CMX6(-m!g>Bz?8hwq z2_rnVv4W&1ae!kJ{&6o7`~m6gZLAmbC>zHT-mHSc;R{6BV`p=Fue(D~!!+`C%V9BDbVf8iP~QqserduwJ%x9)uJW1Vl5uZ+ z3*6WiF04fvmQuPN3o3>RGsGgil(vc{o%@Qdx~(AB?jx`{rNPF2Ch4@9z++ua9P7T0 zxo>X}JmXRL{-H2;T)xI3^V$IJ_Qev&Sg%hX)o4q$QAj{QKIv&$KWOxU3UCs zFU(s$8gy1CFso)6R(MnB0WW(77GJlM_26(A^EMjC1@EIr9};14&tlsBpbu=jPw>qy z(ITmfIh6fUhi0>Mq0wi zA)}$EO&2G;9E`JrwAs4uEL@W2Mcw_<^uD(c| zIE{l*x(%Ylv{3HPh$%wmcp=>{a;1;4)A``&@uc(ZmXHO}r0Da*(ZFL4lnuJg+qeJ0 z)qb<^_ZSykoOK6BM&`osq29dZVxfOBg|O`&Cv>{I(735~OebYzz;V);=d>-pnoiT6vSPGrIi<3Fl%56Gr%XLnEB9c1QkJ~#2iXU5T zgF1O5xU}&mcC9JG@ykBoAFqX|ao8E*r2$+1I+8A&)drg%uc7OA9bDD45Z=@xCRa8@ zlvSOA6HXg2S)tp0%r_ooCCXv>nQ;8WE0TY}Em4w|H;CU`@Jp-<(Eqs})urvldiz?e z*y76kqo&dQgVUifWhhJOXy-CBU&D)aJ8+Z!S8nUe>FmU^eZt-35oQmJr7g>{IE$8U zeqUia&d$FHMpx^^Yl`zB$uo@a8XSSUFaLwFwTYB@CKaVTOW|k61lA&X6-T+;1gYaX z;H&crD~k?si@v?$XY4+YGlzbG#S50>tTS5pWz-v-JdnYAflKKVzX+@KlR5PaIc}?r zHaLx0#G6<<^H=wTap4-S%&F0kx^6E4i-2@!;^pYGmkF;dL0Emnf~IcS!rdN`f}w?l z+)uaF+_|ig+_MWsn0Yk~$3HC)dkx=ksp{1M{*Bo$e&5Gh@q?yeG;B}?x97F+jyY|DyJ8qS zq+&)|?~PIJWhT0@sq|<09@Jhjk2YBjBFp=A@NBLxULN_LOS`NJ^GpwO(|wM^^KK2+ z8;}dv`_I|;N*sZ=Pqb;)l@9LP?V(g$a)=h(wxh=9@-%AI4dLzj15Vx1VjdfF@k>Sp zY}0**s#i|q!KXLTa?1!*Z~bIH`p+W_I5>%w*9YQ*H>P;-wmJ)%<-mT_j^W~u4rC?a zqnU3`2dc(Iqf_l*%J9CAM;=6Tv!&zsoN;CN%VZx^nyb@i)e7<7WMw*BItKm3e_&o< zAzczprJ~*nJm$NBCA(h5slsfgwAlsE?=OeYdn&A@aX$IwGHS_MhAYh^S$J(B&~QSGItpYAt@=CQtX)E3s}>34DBe1WXVKb6uyASozpP#0K1k zcyA+;v#Q_?pQ{Ug$dBmu^nsw$Y{!S|rm&Pt`*FU&bq;E4=h9v%Vx`tEG3S?nN5*di z>-*biLhDG7cybXNZEv8vWCnk0{z87rjc?G@;*UGmCJ2l}3tlq(J&ew7<^LRe%#S&6 z20OfjJE}q|l#4IGb=w#?m@Y;0megQcWF{6}ujI~J$%DZuDIBugiOp@-gqvk0+?$wC zu}k(Aj98e;#kCiM^0qnn*E?XsHO~p)-a&l+y@fdG!9B=n`plP%9YM`fOIb|wAsD&7 zhWof&0{hJ7;P$@DTx#7(n0n_UfAGsgvGE`!ni}^NuKTBmW{gT?h4R_d91sHoJTmZT ziNK|=%SP4rGx@&28Sr$sA+E5OCADp-ATd~$Ezx|z@m{O>?+rHm&4OUA#{MsSmiK@q z&SCU)y*ryVOOIwe*iR;T&v-LE4|X*_3-f*~f|xny1rEe?CTo5a+luPQ(#w-xHHy)5 zNI2E+lY@By%@}hpmsc78A6d>?js-qOP_@m7-CosHneo0FA5N~I(wrzJo?uILbxHi; zCpDrb>m#sqm>F-lc>!he(ov*5h&?z%RE6S(Q?nPafGkc)O;f6|@#TfOzL zUeke9OLd7Itm@FXE1I2>5c=5^d~xZ@0qC!o2d3$F`4mB~`_Y(0A$Be_aGxxj^GKGx z)gH>%AGKqX*T>M2ljWH2U&!yVUdY-PsIr0mxEfPQVkBi z4%F+sgr?876FvT}PEF2VP~Jrowhxtt(nv*?*DAr)Chld8!B26@6?LhT_i37jhapX1XBY0TJ!OCjJ zbS*3RomOXY>aTp%?XQB-qxZ1(c@lVdl^)J8NM&ZuHCXXrBRE9mV9Dlts43ZrQA)Y^ zaK9%%<7){{jm^i6wXrz&)=@a(mO_sgE5rUt{FgoTLV9=$A~I23y?Rz%b9Exx?UG0Q9)0Nc=vw;*o0A0cr3pf*U}nv8z-=) zFQ#(gp^0E#CG_YiZ4|%Wr6>68u3*^5lhE^SHW@DMfeuFz6OHGvP%05~U%!K7gGm07 z%|c2ke~O2r#$sN23HSTfbY7>`k*`uXh5Zu8ggN?9a&2xzk!cP-P%DFco9|E}&ZG>7 z7krS}a9C3?fy;kT4PN`CnC^!Jw4S*K7KhB^mj8BPTviqiXd6N=+kc4OJj?+@GfDdS z+?_<)?{S(ir`26K2sTw?aahm_*jTrfZLcUoy??T7a8e%_?~UiwKm8WheklY)wR@cVKN01hlI7+(72xrz zZcaw}BgAKRq0d@=nZwV4a?I_OknIxmN3#v_w9P4-VgiP;>kbZlvHKPLDl0I}{`^LV{z|B+ zTLE)^DB$@Cs!TDqh|9}&!UWL}{Ma`I_GT|*cx)EDiGIx=xGD zas;unBa2Oqq|1`SY0^j;=w0=wa)RJrS+e;pY%uKMdTtdnPFCmv^E7}7j(uF3y%aa! zst@O#%Y`Z0wWu#G#dcVH;_s+EhRwbJCF`8&h?G7-`gC5UYc`lR?x*ZK!`V(+&-QOQ z$9p_Df{$LjhOv@1lqOfqG`*$BXyQqJ(m!7aJl(JfC!yAmofxJz}V`aR7_0 z&|n*7s&P-{9@yn3K{D5@X`qjg!FCxz8cw6>C=J3jcC%r^tkW2{bnmW8Dvaokj0BiW5H{U0b4jGoHga- zVBqo#-1vKWP&zu2Hl4Z(hnE(CwR9DC_W681eBLx}6thLO{esr zP3u!2;`KP1;TwT!^Cjutz6+?NR4FcN=izY81{OR&nMy96f~hmLD&3j|kGbX@+&nW6 zU)w#$(X%31@;7ZN(3git8&dH=kKon#Z!bo73lz(k_OC^B5A5XxBNJPHV1vaSa zQSklqqIZE>Fx=fq;8v$&Vc2_q)AjWf{Br{?bC@FZg+Ana&qj0U2X0}l<3rT{^osLu z{vx(neGZMnE`hzn6+YYbCY~DRNe`0t!|vd^GQm;Ki<=^+f zHsuU=wOnE%vWmmFr(cy0|fzvpX{YyT?1@gt^19PV|N=+8Tvi-&3^vp^D?K zrLp&K((uFR2panS4c_{dfU?(Pu}oeKw+)nG2J$tq&c6^!&hBH0J{P&SDb{c@>_3RN zSV-4T*YY-7e~VLSZ)*cW+m4ZgA z__`cRALR?|!x8MGz6Hkn3mzrk0~nVmFr(v-;GDVl#4)KEv|UjSUe~Ors=NQVNf!sQ zp8O;VFuusox;%mXI>AAev@Kgk^T4ZCeUMpUE-o}0UK8)KiWD*MzI>W&2Ej*f~07nZBGV|eb6j~e2uKG8D zonJA9CJ0<_n?^8-e1zW(6-c$mm>LyanAW(9+#rhKze|`i`OmxI>z5qd8zIjIJMV=J z$C9|$H=E$cj4fo@`mi$Sk_2RUPJ`lq ztS_$`5~A;-@sn+|=A}SnE#47iDO| z`dj#PXB4@n%_TeAQH0Ag*vT9@Din0PzrRaGvu*Z6k3=XNDq~A)&C=QCvwCb#_d)iq zVIdnOUCxe2uP0B>gS2R31{qv^#obSlqx5O|G^Aa~p&!g4W((TJY8{ zGz`Tv^7C+6W*%;^7Pul4h*eadg;f%V;7ikTyu5ob{aid9{8}f{^`-UP8f^()`s6TS zpSa7`y)LQAilyJ25$%PMYYAp2V0#?&6oRj9+^w#?rd$(29ah3E~NHqRHK3K#a z&g|h$aXwi3nv1*~Bj`)lW1OdY2XA(EA+1THYvmPe$ zb+j>HE{!zOBD-KzayHN;-lQNpRme>GEgn_y;fF?k0&g2H z%G^JPBnJxbmqrLFdwE|9qoq&USb+GvOP}rFG4IkeVSPy!dbn}uc6^5sa=4b^|Q1e>o z7!?KY_2qEhqI|kP@1{upn}~fbA4M%I&f<_DR&FIqPZj`U& zzHe|OvsYfYZfh>o(Ii?n{XP1fpU;$pj`Ig@L(o^~_dNGsA-;U_9IsUmX3p)YFv)VH z@J4oIBcC0DmOC@Ba!m)PW3nG|CPuR>IXwF&Fbo6xX0f}!Y~WJsP8@#zI;ggXp=MnR z92zgn{4SM(al=vGC)9>M*Co*{uU(wn;u&~<)?H zjQ#Q;rY#bTN)FQIhJjG~Dh$b}mv3QK{Bg;ZpcvH4DMi{buPc{e;B8&#cG9J}x8|~m zLN=T7&Wj!gJcn1KOfW#vm%E{Q5fy6EQFT=xJgJtU_3jQRN>XJdPV3=heF|st&Cn+H z)DY0UY(m}Z+VR2ATvV!_1B(s`{)o#ju%xm_oSU%+2CAszrL$d}e{e1SD%>QxYB7Z= zC><2X&aOe39|x`VOxEI_%0aek4t~aDfp2_p>~XC8^N)8B_)U`)v-w+=2C(_06|M10 zvyu3)mx|9?W6H}A=IG{0AB|1X?~DwbFtRJ($-RL^78l{mB{R&le1ymR2J^SmGNC`) zfD_N@#hb&CKd1B(M_s>zONNgGkK_XMD@ess!4=T)M~9qhWJqVvSFv5Wz({bLjOSYv z;ixE;U-f*4_`WuSrkNRh`+g-HSMq^ZGb{lw`;+)zLlJ}&sppSfB+s_`13{`_W5&#-?Ok zH`^1%zIu4O%9Zk#J%fg11##^rCHCMY!Pl%v_8GP~qvIJDVyeqRZC>K; zRr_$`+R>zJ+YR0|T3EC`4Te{B@Z~D0XrSXuTZh?_r@)ihS*>o96*x{{GF-*LsY8f2 ze1dM2(0ePq+-0_1qh-i_4fxv{z;$;h@ z(DsBE@Bj7`OgQ7uC50K1=7aSJ`&3xAc^#MXQiomsDG8d5@woYh0~hPDlXZU=bMdFL zG5Pv?xV@>9Pv0NStc!Pv;}%APm<-F#-(}Z|A7kb7QS`WVJ&kW)$^ysv zz@+tGxy9#(kgmr@>KzC?ub@P_g z?~($q?cE`~QXIn-MFeB@_@Oxc#SHFVS3D;%)LE1pk%)JVo{66)T)}N+pT*~ePG0VX zD{yxFP7-fc9^T`?JcN}lIEudig5;(Hi=xrl1!9f6~HQIvY~I-Z>1&Q@og$N7#O7$~)X zG6%gz`+>2vZ=Er{wUcL&GF#zDYZCbX3gc3F;*33Gm{h;O-`d><%jPVAR&gm}lO6Zp z&E0VFwa|qbJq2~QJ>oAcy+#jWTOcr9;Ein!q^98^z>l87(sx=w-{2Z%wEn%&DKln+ zG9=jV`BAXFPL>VOZ^2R@Rc0RL3da__66uM3crz6PS}z^MY&wp!Au)Ztv!@s3PW7e2 zfdg3ZtY)aYLEMm$Mr`Bh3AFs6F&q9|iYBHWXUQW5E?jV@3CFVO zW6=;6uRn=j_1hme-xZ@pvf#&izXv=uyKvT+aj>iQCZBd|0%@PTkLSmJfZSsfF*Ll3 zTfJ&6CcSfl=0gMN=B!0{p`a1QpK3v^Cyy{dxS#h-T7)$hr?S4F{Upz)L(cPhoHFk! ztFTO@l`fUAKPQRy$#BH$KgZ?AUHDU(y5xC%5zAG|gkvFMbQR9v>3@CL%V;&WIp#Vn zv{#4VI|rD{Jx%5izJQi~ImISUl@>Lrdqes{75H|ykheON#O~fO!f!o0G5bk7?)u&% zGX9kS%?|&;N2R@3Zh9AYe%-{s^AIHa=FJt(;AmV0kK^a9gmVRD| zb>|ErpQpL-A>IMOzJpJb*ae*?h3u(CCR^m4#huG=rppFy?0K`mW3m9Yas5$rT=WIK zg*)TjWJTsBI~=FxX^VH}PUWK3MMLJtIxH?WMYH9_;OZTUc2;{~=>3gs_P>wlQY!^z zp5tlbYgd?_?#yYIT}7RL2l*+Qt=QSO5myT#nXi`$tbT35KDF@t)w;i!H+T&D>${zg z)z&4op&Z`J8O?5seel!90T9e9z_;c|k{obOw8U>L1pYI{mzo=eZrnDmyX`*++_V_h z{ue~oZ8RWc%@@%KIYuK55u$87V84q5-3th#?8FCrqTwJG^z;#EO^)Qn4;r{5t&_ygEICv26RURNWo)eF_S}U@%_h31` zl9cf{AEd%<;m2DevO2*mP*hP^9LuT5x*R6I2Tb!`Kvo-L(0f(7OwOGd8l!{)8!8TYC{D=gnqC zg(jRtTMGWRwa1u-MeI&X4%5gQf|smxxf%ZzpnH*Uo=J2fi^g;OqV1|+T%ya?J1WrK zALHSny%aIA88daC2_JGhz<1AnKHsAXD;A!HrEh1^nKSkv*KUYG!=|!PnPG6VU?Ss9 zmDsk-@R^kz#2s*oL8Z(r!Wd?7C z)0}ml@L5*|fBo);tMOo9*n0%tkh0wk4aSW=?O0=(6jz znYd$cJ%4ar3U=;Hq2x1ZFvxE?9j&~9FRhM{q>BWLH+f5AZ%xEP!PDX%t-u{^o-XXZ zUV^W&Idox*p6K`WFf`n+#V=HNgIC`pz6ebw_P82N7ZCm0>_JzIXTvqWwKUMS9-E!7 z(e;NP_^xrc@lIz6GxJU$N;yhD0tDBHc?P#UV5l%(Xk-&FT)^&)TS5NUCXD=h78*pe znc>%2G|Ewy+CHCP9!isF%0YkbyYdpcSDj4XLfq-pjemI0#GH(7ZU)!6b}X#L8)YUR z;~dW#rpDVt?>~oJE}&Ly3%R+fC$zR zJy@i-Shj5NmAwRWPJ`vSBxa|mO)q6XmL@esus1L@7RXZr^VokJOE)_%vIL*_aR#>J=#iD+BUcWMMCr8}eBu>le%m4!Jb!o_ zyYyM`TP&MGJO5cxWK$fy&)mnhnw4^g^OC9S?>!hDY>Ae-d3tmqqTaJ*YZ9vVR zGubAQI;UeKXB##u6G}$6;O*2vY&7vBFx^O@4*K9R_A^T@T+Xz0=F*w-Vz#en7WaG4 z2!6v?-&6HoYVob()Jos4}21a=c=i>}~YFxx5?fk*|sTHd*IgSzEUD?{Nm3+~E zI#f{Yz--O3_zgQxF>~u5aC52wJM`C-iZu(k@nekHgTv#fD_om(F@ev$&7EB}eJbSN zB88hg4DIy>s|)*C=6{EvxM?2KA1TH@iNO>$X&Zf&m_%i(M!?YZ z8Qi`ySr&M70=o%;Y|+^SmLvO>k2>j1gNF!YoF&2R+|v#?;5Ud~o}NP)2eZi4DHX?Q z`;)ihemb!KCp=vBh;M0A#bC=Fr01tg`hiU#YLtgJW>OForA3yBh{t+$sW6eGvZeSZyf1uWmXgaEn^I4qzRg8QdX$J#8#DO1U`vr> z|AQs1>U7>P4k!1zFbiR4adT)cS2?~EUYxh2G@&>16?lC8YX&r}i-X@%kE`q4l>Bzwy;O_cEBT1svqGr}e?n!` zdg{~r50=i=WGb@R_+=_k#WHt1^)dqthaBNgG!3N4!-1^unI7y>mt(Ijv{`($7jv#s zK~effzM_0AX|CD}4@avr>4TFgKy4F=@9lu5l@9c_{T<(bt{tv_ohZB$&f@~>9Qbtd zIUI{#&i#wmA-h5QFz=57jtDM;onXZj6`mYPgljH_Tmr8` z=}L2%#h@YVdf#N`CmPFK?+MI%tyfIbHy5RD*wgqsz#5Opawj{CS*YVMRQaL9mfhPU z8X1s}DZYPErP`JJrwW|zS${yIvLx{UUh#xZP@;yf)kLWG0@9lBDSxGiU>^z$uLCz_cUe}v#|KlESlmvltypUfttY&@xOE9m>WCJM`0n(K7LF* z{=-?eE%Oy`F7AcL{zlkgZp}wo)xvGJ?|gZ-B#S#G?9z&6$J7wis|&PB$}U;Eo6Tmby@x6yRhT85^mczhhMq)7&hy# z5&8k9^we?`MV}f=pRa6z7;O>JW^bs!26R!emS@xciZsWBk&RX*{5W%#Z5$p=i%m}A zyE@{|SIrd%R-D42CGT<8_KTS2dJunaupst)6Z^7VAFEb&GQ-0k;Er68aKG)s&fH4O z$ohz<)XHdAvo~p1nUkzqJx%;LhPu^TML#A36+J$~?<|s`y}vBkqR*?uFB*Een)MSX z_r(itwETVww;Dui-ru4tPD@G0MH7v!H6hgA8!~GL*lL(7LG7YsZhO zV{BLNJUZVdmV|Li(4;C#oqEE(U(0cqLExw%11v;3s+59b9{AnxwCo!G= zj(do&6#U5}(wU7~P>1!8hO;Cu6Bd)N!qQqM5%*V`Hn$7RVLKWA^wutP|9XT1XV>tS z8Cv+hBZ&@8+ChKWbgcMU%94I9Wj%Y{X@*}VER$y}PDhGddJ}*~rE&$PA>eW1GRvPc zk@=|zJ(cupB>E{!gFSBGK>f2!)i{)G@xO`P3Bpxa^(hVWx&s&C545HIft~oC+b|&s zj#>E9yO1>c)nmm%oAcPgRtenE`I}#p*N;a$BiOq=M^J5zCggiNlEqL9X1qxamiERo zeQOUEdpCgJb2$q9UVQ=cm3DN(au22DYLSn>0+z~5EpmkRWqY_zeQ)rvnqo+ha;AHX=i4MV04qf@QNnNOs);2V3-U&ym%&gC;Hs^KLx z?~Lct)?5}iJ!))J^*}N(`z7QSv#6;rfxWD?Ap40?a8G_3Uf$#YTw4;WetHa}bnVG4 zUY!lhy9EnU^WpnNIl5pZLFt{zG_Un0JXj#d?q}Jt1K}a!tX-OI-OJO;>)q*GgWY3-Hc@ zIkcfl;KC>b(K)=$WJ^!d;!6{#^?M5Yvcr&ebj-nyb;HSSEYbJ{dN}rr6>YxaNG{_K zaKG=&!J*Yo^g{VIJgAiTt~hc@gVIqh&>D!m=zNBaQ=%7 z3^$V?Rg)09t~iq97aQ^E4O#4HxdD4}Qj27$7I%Yqi4$f$N@TyC zH`8(16_oa`3cm*?WAO@CTyWtst50#|tKKKl)sR$v+U->FY)enJS~-M0m_LJ}4UXf1 zKkp!;uNuOKE8{K~XQuYu5hHAdae*V2kj;Zhx%DiKS; z>AeMM0c8)+6HiE@7rqULE07W_p__YdaBi-1mo(fRgEdinl5~3rGQT#0xRdhGDrLl+W!8ALQZ{PM%G}TvK$l`_H zmB6L4QuAk9qymMm%s^P^B1O5{6>O)L6hqz@cghywisB*U6%Y@4vumN{Zxk1=a9i-Y zq(NN30s0lkSQIV5kz4BUM(I0r5BVr=JUtMNe3nt#&Zpq=YB+O|XhIk35tuemo+-4} z;l%rg=rvoP*oMilqXP>p@6>*jA%hA@TxKREEM z9?!jc(=X%cC&=&;nv_q}Zhc z4Sdbg#caW<&nQfeV8M-dxVGspjO0z&V7LbT%0n?Db}tq-72ph2qN2$MVNLuJwm-g$ zx6N8f5eJXsq$AGMowSI)2DJ0pil3o6uN!L&^~fnvi&lpiGVL_Mh zZ>l`mEn0>#(}v=&_8^jPvLYXyY1DI4ku9!W!PG`-;e%Qw($aUQ;D;Zu)#D8&)LKBD z*A3j&SqGJprWF1v8_rHO7ta|N1(@>`~@bXR$rd%%JhcDm9@K=1|a6UH*-padj79;f`zpV)}#bW-`d|x;hz6a%Gw&PcOf2!#| z0gc9c*!kAwG`V}Uct}PYSWmCv_Dza`^VLQCf(BJqSr-GUH$PyINEf8f6k)%Vakm!qT`n zb~DD38#=BB|2p&deM&Yf74CIDoww29nKWGMxealqojA7Njt-BGWD|rvE%&G#a?>%R zR*N<`;8cfN@l$ZgvOa#w6FXY$euTEz%m*xpflvP_L85as^!SvM_aG_C(KKVXD?ag# zYR851eXh+-|Ams95kESKY0r8jV++tFRxl zJ->+J^G`BWrSU@EpkQlu+h->WytpWFRYN4)P3WiEUx8TPl8109fW^MeV*YuOu<_;((VNL) z==vr4|Fd0wh%$6mrsCNbrCj%&Wpw(9kahq34!(AIFG^+-Q~4*8!PudR;nGaRrl z*dDZHc{Dov1kwksW^uw)77q_c`Ue-%)u>zs;LcIW+PeEDyIKhmLJn zzFmQ$txt1h^$LO)p@*M&OOh7FoP!lbm)NB{(kL$0V6Of?Bz^HFr*bL<<$H8_y_I*N zAmu!450FIh^Elq1K5DY(O%RFM^K_(50Yp|M^4mQs&@p^2Ug@4j8A9H&c%Tw9nz);7Iv$2j zfl|yZFp~9r{{=4!{BY2e=j=k92G!pj$Gd&IFPi1Kf!^7x(6Lw_QK*S2^RFX_yz>C3 z>Q=$h_gQ>>fg@?{naY-}$b~mvE7&Z7!7#gG1!RnT&91M=K~Gf;+BxJaR>!Kdm{aR% z&*wLswr4+N6gx44KUKIk!5zMQJd5&O|M%>15=r)Dat#R$@Mx_8`K9fKWVc7C-#3Up z%}eH0^i)~*H6t*(s|=>{;k4jk8G~9k=Hkk%Yvg?FGkZ zZr{ldJk|=IVl~*;eGUB98?QjJb(!Gz*eaehRgT#RT`+Zx4!E(-h`#1)v6iAT92ap9 zJ|z6cl_?5zc~Fed9lHa=WX938Rf_aw@+fBBaE;Gt74rtiQ>aURDwGB$g8Ry1+*7d| z4ALE`P~`&5{pJS}590W=WBL5?rqldSI~DF!eU{*DzXb;z-g4J+9mzLh5iL+!$=0!E zCK?*cl*er3tj^qE8{DU1@0do+S-uU8H+Dm*&L&8nT#bj#vf1)KS~$6)0KC4XaG80g z`0#ZlxXu|U^3Ohpc~%!m^=%Sgx3>d3G~?NcbL-GO&j|V)!^qUn7kpk7;#rB`;Avw9 ztCX8adB-Vk(%mqwc=9WDb;$)b-o}%3;=Xai{>kzEWBu5vo&eS}^fg3V?Yt+F5%@dje}5AjS02OnvQ?Z-x-nMqxA4p>XLd!)7pu1V zlie&`mOe0!rH!+r?S~fQh`~*;*uji1jCuw=exB4O%!E3}1(By_0L%n&U84lW;BZT+~E$HtJB?HWpdhNOl>v2&~abjT`WAy+$Y_| zL8Xcmb?6(~p1H*>7NnX^Jr8;1J(0|Rq8BUq@`fAl^ale9RcO7Wz!|99z?YxARDSt* z4=4y{9?4g#%ch z(2>Yr+s!>Y@fnhv2Q$s;`?yZaA9kkmm~mk}R#=tca0?-uk!XgBnj@kOE!x~}{T*!Z zMO|_luZzn=nsMu36)KU~Ytwm6X~-ZzJx5e=AM^b)(vM)GQf8_*>85zY(L zVre4{*?xnkc>7{3KgHS+uO>wC24NpjeGKwi*`M)5Ml8H5In5o)RRpb3)7YMRL+U&f z46_6m%HIlEmbX-nW?2iIi&QPa9XXo)Ti8gp$Cl#8GYe_cD>=6G>H~=TB1vCD{V63U zhR)1z!lEo$np?DjmIxWsE?;3Ttf0xqb!x&aO$ADNu7~qa8i*!-DZxU^HtxXVX)N=? z2)3+mG47vk3SNHiApgp3ToYl1izg2J8*r5&}ip)||`AITk|A1D8CL6cRe>iT4O7H!5B zwsqRQ9=tl{^Ia20GKB^QadPZ5dcEs1v<0S);qEi#fNsLUWI=T81s`WU7o?1-yg;ndYxw5c30zykJm+?-iOh&o2M~Cu9WvPs(?jBlK6L{Go*T} zB>XdL)w4V`0WA#3^_^c|7TkAHSTe5EmyQr=I+ z>ygTA+t5MO{m-8AI~=%zfB`JGM20&d^u~Uz`vk7iBKkIZDuY=mus^bi&pUep`)fL} zUf0_Cr>hC%mE7Zkgua>O-By_3KaD1&j}f1i=m)7IXHl#E3}}7d10(Zo*wa8WI+yPb zr%q0w%Vol|ZH>T6=(j0v>QbVjiJ$m4n`*G_Wgcrd{vSO4aTxU zVbzT!@z113;ANwYd}2BiwRQ6XE)XJ2i?~|q*y95>d zN(hnvh?yk?RG=%(Vn0@JyxJl9sgX$1eK&Djo)cwsA7sy!2-@!Vuz7XE(8}W?$;rpC z56>@f)4s04s)fb4rA8J)rkTJ}iIwCbxJ*T|?RZ-)o_E)l1_~TX(+m}%Z-5(0OjqT9 zJC5K#Y?MOv@^1c&xf1h``HDCDqrm3oeKzvRPrR#~jbqcXB?JJJB#)KLDZx>l#SPsqU^Uu;PpnH z#;sh4l}BZnyPhv_S!(>H0k$mC*q)uLUPRsgkN8m%isiN%9r!u%C7iO2=F4|mll-#; z(5x8G7S^`e9PrOThf9ZH$-I*!SI+Z;jb+LH?Pii4H;q0AzY_TlF2+b>p)<60B6@7! zOhzR|7@C-X+pXKMUZ)DnSu-AdGLb5mmZH~)HMA=~0?P)ZQmcj~rD~Nx_?BG!c49U4 zh8a=soelJz)|Ti9--upq%y2>BG*JH-gJH1)d&W$0w?G;PNpeSQnX*T=)`vY7_>a z#_pqkT`gSW1rxT$^BccZOPGZTXOlN+_rPuMJL@siUcrV6p%<{!0ks!V!ICsUZ4HfLPZeb99>HUM#Zl8dhLl@}HYCC8uGA1)WVKz8)HpPs{H*2#mF(=^J?>KrHa0#`Bp2gc+{-K|nK3nIr6&G2^qnm6d3!ZiX<=k6QB7Zn# zu587y)weLp+Zu1%Orz`X9mTm7tAMwi4@fpX<-ZFZpJ9p@V2=4yu4S>9e>JY3%Tx#;YguKM zsig*P0&`4epAKhJv={6upYo4QcEc2jWV9-fVA?aAxnrXb;puOw?34$iqqZ@ecDf8! zC+dh})y16J{Smz6!xi{lA^?`>ABFj*V=%%~l_}afK-rwh>{01S-W#jn$G$>V*^kabSP)*1wE}Bf;v%E2h>zTy z+JiQmZ*0T5c@9kHzwg|~Gg7=)z88N_CWD_YbRM_p8^e#KRS+ZY!plJf!IA-BsV7U_ z`|Q}=7w!D)CDQbKzVM%WQI6Tw=RxQ00Cv)D5_OtCb|(o62yvx3D`mON~`Yhof|I3RCL}AXS}#ENu1@Y&<+2qz_cX z!x39q-=P%d(|Qm4?R%m1s5@mB7zxfKOa9^Oc3d>Wm%CUqhepNP;QB2AY_sA8Uei+% zhW8A@kPr#_HN%s&eQyV?1~)c$ejV&`JPQ4n17XAWaCYvH40`TZ4fjZJ-3>9rTThgz z`mGF&XvpL42%OKmuaoh@u@S6)kO$G)7^;fXhxP}J@GNQpZnt;^Kd;`V$r5o`EI3fN zs%Ek^d$ee|lmeZszsi}v-i9qM1DKPP7QOiO4Hfl*xxz!Yp+d3{_RBp-sSBZ0E1|(F zG+)Nf**f&+mpSMxuY`z2cBuI^4u42Z!ZRtC*{07EaKsz~cCy2OY-iP%$8$;G&=4mu zjSb22(_b*raO2vi2(IXrYuOkrC-!>4DriuDfH@~^xbzqL*ze@S?cV$a`-?}?$V@42 zowhpJlntW9w>HRb9D=5hPu%f@r?hBOETr$SrXSkJMSBik#-m$ zY*zH3$B8l6lY9sDj~Aetbt=6Oo{Q?Y!ttTzCD`li%N(W6NUf}s8(Ch;W~~Ls0*O=x^m+S)QX^$Uxe2FHF4QX^~ zcnN=CiXV1cKj))QkG0KFIKx(txIrs|>_}`ekFqtI@xPNAlrrToH#1(1#>xnU!J=ux z4oWjtj`_@0jNZ)NPC3MX5q8}^pWBI*CF?o;!2@9LpKR>anMn@gHn4&7G@0nj4yqWr z9|IItp#IXiutatuNyVj7#H0O~wWSq=(KxE+CSb#r`$E4{8e=WP=lF5J(xm2QYA8t=NY}0eU9;TlP6z&p}sHN%{cGgEQ2lG!5Bxk~E58dQF9EHRE zcTGNMW;LFjq(?0yD!E0C3u)}c>--_-4ZPy4Ni3_`2Iu9kN83S8Y)pXgTv+}Mp2|AG z%t^Xb^;ZK%z7K^G0XA28shm@bPGfiFQUpGO8|G{pD=zYXhOtwUiC4eR-8l6I?s^9D zp%Nl8QreIAe;U!f=6twOFR&?Xe__bCMQFcF8Y_i&w#ghFSk&9Y-P@wih7?U>!wQti z=+-^ZYTE{x(r?j3KZYCb63J#wz613ulxgtkU-6$`?1UQI#k{|2s?YT1$})PJu;VKMOLw#v}qeY*H*&s`pZS3^S0uy zzoF>B+*xqhFbvafMA5v#IKXE=91`3Lm1ky(WbbZaNss>HSIn2C7w`VzmiLzBQw;87 zO8j0N)|iiB++NA)kbPwOC!ykE<7nhI!M=xMSGwgU5L8@4=Tqu9G?53_FEi;3?-NGW18{u%R!KcAw` zo@f-1R_{H`k93Ekzr*S5CULH$RUdBPUjwcPVXb11}!{OHNJPJ(6r;HyG*k5=9 zM8f`ZZ%76AJv;(c_R7-Z-wH(OBGLB~(d>s$6YnEB%`2ZRK=pc4Y6@7!Odo~8SOXVU z7UfHlC3i$8%Er>4tIm9x@o!9i7s{IBb@4%WCpPn^*_1?e*7a`@_ti9*7KOyHk3!x# zYe@sUD7hF%X9!+{#h#!XEeHFz9>w2|>eNw`48y*wa`5dAD5$o;)Ayx#`_~N!`>8+& z7YE@TbpuqgNT8nCN?fbdEBLM*g0qF5e_e10g+1HOO}LhUc9(A9qIqsCe7O=0UM=kH z|2+s6KTe{@;$cj0{&z0Etd0v4@-gF?x-2Yl30uCZ6aG_BW_5wv@QsfGURuxw`mYW{ zlB_x#ao3dE-=@R#b{7m7bWSv|I)PQ5`@&rp9H)Z}W$3ElPHoQ{LzkBQgp{c=bfzMo zzt?5QHU%2Mo6;11_RtEJv~WCF=4^+B!`0atM=@V_D-w$a&F3fi3Vx83SkRP+Vecda zj%m<(k&n?4bYdNR%j1?feT*wxnIHamjyLmtOKok$H1U8h($;q zhwZcK_*DIkXmr|$jYwPumo90M>983zp|*u* zk-5o^rX4d3+1{74%iFHx^ZTQsxFxUw?oWHex9(Nrw{=(G7K?3A6#Yb`;;xMDYj$8n z;$$2Ue1J5P-=Mpz7zTdO5V)Oh$~|)rurXW!c^P`K753_M^wK>nK0lT_{4ts98N65E z;&yV|{tjZ%lO*__lCRw0jTWpfO_}|xEu}>^1E^@uQm#T%hrUM?prJ9r$a`AU_sx=m z=TzC`C-%XiV0EUm@1Xdq`h9fEuY<8EH{rT%C-1*x9P7C^2TBfCp;<^3d|4@j@7{fY zv?1~Q(8nn_yL%u`^hkvZTd#?VH#UpE97_SEU(tM)>jsn?YXS3b$ij;kBgkFZ3`<7+ z#3wDPAhEUcDz((UfxoFO5Usic zrxxnqN1x|hWcN2XwelziUQ%Lp7pAjoed(Ng?)_z!H*U99@Rf> z#_)|t(4Km6_`j(zEq)}`{H(^QuasF^aWggtrQ(4)dwM)*CF0fB5TUaNEk0_~6y3d4 zxgsBaf8Qf^UcQWrI(80G8-F+x&)#lv~ShJU=XPIdFb^M|j$S&pWVkR?2p=aP!dVS9YtG*nC@Pcgd zyrYdU%r;VB^_GISnI~_MnSeS1Prl@18lJlLoIfB_j7~Q9xU)7Itf(E)cgHdq6S0)` zj?57l8Pf1&uqiPUYt~||21jLIa=)98h(qP;@a_?g_YW!OtK6Dcf$0lwMeu11m?uk; z8r7nlQFXlIbKx@x?z_oEfUx# z|C9?&ji#_3Q#y2V0rQOL#w|$~QC##M0<_X$RJ}eu5kJFaTh?&DLkgkgs0#ksX)m6j zXU#@^iiB$YY3ym640|DXL$+H99sc)o*n0Oz+=|;8jCZhM&-CoLsW+o|rT$(z{U!*- zPh(-jm3c5O=onaRT10-kT*=!{7Xy=?WsT; z<}o}6v}X;5=-CfYMe;IOsXWF3L!H=U#T6v=C=XggOWBs+5-fX7ID2~~iTO)PlIzJj zu|-ZZpFXvlo33obd*mi!Lfi@Jakr;|hmWuUv-KhG-vxZym_iNSvg99Biv87JIg>2` zG{-rdjbA*9O`JTa(!Ki++&h>;MpOH_o@355Km0DZL@VLxjCivBC`+x>gq*H5UTqo9 zwnVx?@uo{K9t-8lzjr)Xn<(D zc4i6UN<7RAmvbNxKP$6@tL+JXY4);urMk{F*-mQEv<(?h^IN}`y zXef}Kyfu5TEWuu>xpGTK%%LSF8{uo`Bpj7{4qI|fAj|GP{Ps16+^u)voy#uTH+(x) zKJ}z;Cf%ZC)d%UwsAbSK+KsfQDluDGf4Uuio+M0bMM@@W;N53Oiayt%(PuXKTvvnD z*}}}pX%5NMEXO~|rL3kelo~oN@%-(VF#FIRtP$?ivx@RiUPb8IZ2yi1zl%|8vMqhJ zJPaEG4^W7-DYZZHp~Zf$arZqfd|YmUD*Ja=)_wN?_itlxIiEyT&C0lOyb^USNx=vC zLf2^4Q`9UIdckj&(4dAK*rBP%oTW6`kAWt%C-oDwOs)rcHwE@NN)gX4{J^ybX2SAP zNs#_s!yWbg2>0y&z=p^U?q8%Ksjt#t=lg=-#TZGxaqUfZq-r>2FM5my$xlJlY|5#Y zyW!}IW}<#kx8M*R1-@OvxwVARJ)NUiG%B9i)(UK>zk-K0=OM@}b-?S>Ug0?X9Jc*< zmiV#5IavBu0rxvMz=*04s`umBxkm+}*i}yS{Nyas(~aRZZ+<|rz)P%MafE)ny#jf4 zYM`$61?$CQz*S!03H0WPE*Fhqj$0kUe(X>DJIx4h?D)lh*?W|4cyB?cL4t)IdIBGP zvKfSFGP?vnGIL2{{ol-a%}Ywu93{iWG&9esLv|2($rxPjk?bi=Dl()8%bMEZ7Y z9e1Y0N$Bf_;}4Z{TwBw0IwpORJKi;u($j@ZZ;T~PH`FEdMTa2Z>@ogJ>S4%kG=^dF z#*}V;6t>0|R!X$Tb4$hzViUG~fmxecu`MDVWdFs&2^zv?99~3y3Tmv-Q3jrFRbW4# zoyDe?ZscWEgvXNAsB7{|K4Vk}3-G)!cJV~1jroqRoxeWh8%4YkpFuj^LG8=svXf-s*3tlb37v7rdz#A(~#0kTs zXiDS?atn@u$`J|JsP0d5LX6<+?0?Y1XF;<4aqza+Vy4P!G}zaSty=I9Z<`BFg=MQ? zkEYz3LaB5Sp5jmJU;iFgR+%wHe{Fg!)Gc4@ z0vyd9Pael^!Kv~%`rWGv&tGd$;BgZu?i|K;cu0w??+*~|8(7Gx3*DXOD=VSy;$l?! zFpc#j8M04FnOK>)ffjph#;CHbtWaQI{hfMR$Oo;V!l7mhdN8LW^v1^1g$Iny{dn%*`Kmb&|J)7S{wh9 zV?aMVdsvIVGUfmEIA} zDj&;h50ny#cC4f`$-b4AEzh~P5uf2jd2;1_BUvhcugKgYtXa<0%@nKf5&Mpr(DuMQ z9A&kHden5NQ`cH_%18#frY2(dve!`FY0BQW2B6woOZGO)h>xom*vehM_=4=uyh?$P z(|xd0$k!^8mHJgoJr&8!wvAx(f+N7WLY=J`sg5mI7qWeYO8oX=2~1_LFZpIz2>!w) zV7prAP3%1hWwKg0R>y={cdC&=CQ@4PW7G}MV20C6X}Z@A$}_O}K)bdu6h9nN6_Ju#Vi~Yj>>m@0v?Ps;{BO zti8f{dIuZu_ z#*f#cL9eX^-={VEQk}tW`qi^rsms~Pg2C+P=R*F~?VI>^ixr>DX_Lf+Tb!T84)E=1 zfk-_YRQ=Jyef098b^gJ;(x)uWG*d@7r+KmV@yg7^v4YQ8wSfwRK4Wk4H56&jprd6x z1XqNR`)uJH;Cw^;_`pcY=pVt(+D~S2wI49?t_54zyqTJ%k@S7Zety{U5?ZZ)0akGtqQ%Q& zsdkC1^Z{L8hg$!e1hr4E&$ zeRs?GQJV&dA8tOw=c`&%-mp)w>A#EMR_#hf?Il>|lR##d!)bKd5{$?(7AYT&fUF30 z9H6Plj+N=a*L_C9ZsIR5vAvr$ZSkYG`!)!jY>k z(P{VjvLF>2^r9ceRbOLWuGgXLY6I7Os~g9E_QeOGi($&QtJqi*$6_vCg|qqRX@A{Y z_~RSL%wyWXSkadqSXIbx5PSwSe-3FG-r?jOBzZ1t0sCC4KnfZLENkXxbXuLnijVm) zwJ;Tm@O#Z|daOr5otZcwW4yraZpMVbG+O_>P&BS}7oE00g+tcAKwg*$CVx7>77VE5 z;$^MH;&dyF4@!X>reRDyW<7j+-#7is{CRNH{2 z(sva+=MpPe(iNd6R3S9L(IsT z{K+HD+&gL}YE0&;tLCxYr%c(+p1s%>cMzSwcc5MI8aiSrL)R`;!WO~RT%LdYY3fky5aO#(`%ytk09)<<59eO@<4^9dGZzyj-uzZs+)e zvB-cu`L+h;Mg~Cnft^%ia1f&I*g$E^6DU$k;NBlPPI-?M@%3FrveQx(-0%A-?0Xao za~aHTHqM6P3kG!O-8$4;lMZt)22rBHH=Ob3E2o`3lPZ1W#k&XTqS@{<=qq@_#<|E+ zh4>FnytWCXvitGffWa*9m?T)$ECA2<8kE`94k_)X-10L&F?su8SiEE*+TI54;H+4b z>lPfEM)M&2z;G(A8Hb9WU8udU6<)^*`>bF3)a_jiwN8il+BeG36SR@r)=&Xw3_9S3 zeL1*)KSe(`G{TN~fbPv2*k@PC?aKX!i`vro@Vb6($8+Q9pTjv7` zbP`0YmAkGV#!hGd;c{Mtk@dw~mOfg6y;-waJjuQXGPl(*-3@Zgxnc-eUAO~%R)NrK zIS6j%__M29tZ}Q}LJT{96Lf`{z{^ER|F!Vfw1O{HIbKHdAoN&D%eL{-5E@_!uLw zGX`@rc7+OIsh3=~_8_#;7vrOGf`8;QkF6Fe^e#gevrevOPRYZ#1(L6DU%23!osfX8 znd{l0jd3ix_#~`Pso~ugp90PIe{hv$I&Qikcw8T3a7QQn=2M^D<6m_SVwa9Dr!mn- zxSvOBMZf$%pte;qeAb92`>n4QY% zC*_=I;Wy5fqk|D*d>$)DTW>w&hrDoQw|iFNPELlBt?R`WW#-H!K#mn}jl{;#7s9it zz~>0h?8?3?;+z9Y5HayC7d2u6j4v`{Lz2!^THck#@YUAX^tXd|4pra=%v{9gUv)$C zkt3(mPHRZmRt=}GEduvfExhW56xJPSOv|k5g?+XZl&aq4%RC>##!-2E!)HQOeQoA{ zVF+x=Q>KWd*EsfIJoNkbgSb%0yqr;`oTPTBOX?PpeJ8_(Rl93 zesW0BrBW#yke!x~@x4{xnX-m*D=NhDk_emr#j$Iais-j=9=NF9;8%x-a>=KU;wfRi zWO1mQ_q?abc3v3=>Y3SSbAJe}lbwY#A9Zn)&sc&|^f^9!^;bCTI|9Z8$&=iFlUR%} z7a2QtDs5Si0wpWfaEgxw#?46uDm6KY&pu7#jhC+GywCmQo?Lv0jRqf4s-7{6*IPg~ zzmjFY3St@lnzYFw9X9)`(0{u_;q20ZbmgoTjj;0)_<6M;_hJKr^8v=j@5dEpi8%MZ z3_Yxz%Vw_ig|dDLftxUoyJg%y?N{7#n!VGL5;i2_@YQy3uCQF>AR$dj6{Fy9^=$g` zb1cmIr%ubl>!J3Eu-nc0%S~(Q;%Uo1>=H8I+s<2xpSMb~Jx+~~FBVun-8*sOI%O;O z#x=O{j{)2J$P>7PaX3HeBvuP&$kbp3x*B)_V#`V}Vw}K04t5u9b6(;D;TgTqSq@Sk%mfaXI=k61jr4E)fD;2E=#Fn1 zcn-*cUDd`kXIDF%%?g3Y;QQ>!<^rK(oMj2WjUFvCoX-I!+6a2k6|U>I-2Q6|SiY2^AE{??jJX(|1m~iUR5qTu(Sq*BRoR&r`^n37 zKT~LOgzOC^xOBB}pFT5zT7QmVgNMxqb^CQ(+xSOdu(cNk&r#sZhR9IDnnV`0B7%#H zpU>)S)oI%dS#(_~K_56}eBqSLX?YK#3HR-BT~HTSGAs;wqbAeO=ChSrhpO>&%PI;z zGJ~>|Mli|9Ei^V~GM#a0!g;=7AbCBKZujSNUe^Q{oex5AsVzx9xQ%~L4B(u~exPw+ z9pIIMIUME)2{?VepYq5lxu{%8nW@~elBQTc~;Ir*5`&ErFv=Wuh=D4bZ= z0#)_8@M*9Mt?bwbn)}YMfV>v)Tznr_R~K>-Lq3CJWCqS(=RtlJv3O(sQhL!i89sMS zLHnxn_@ph2%`Q8J%T}hLWzI=Rh%E!r?`$ZzkuUf%Ct!q!$seKuhKD?d&I!F;YFnR4};um2KSNgn-|8`;ke8_C(r+E3X zu4(CbM(ZYSQW-(R9%?b=%2Kk@T!sF|kx=%)guM`aeG9sZU|gFdGji_+)&6ikNIn%B zUuV$eHNWtml^lEfC79cJ&669lQyK7ADtoJJiw1wvakkS$D!?Rqam|-A6>@^c9?77s zUnS&w1Nc~MfX8j8;mE4hXd`${TXYLBGOZDl9IffgxA70Ntr@xJM{6@&?4-ZRmANHzb)jT zHJHjANul?Z$4@pp&+LaS!-b>T(Js>%uI`G0Hwqi*gJdm{Yz}9>y`9^hyoq0+I1FM+ zU19CEz1;V4cLf%#ES@|PNRC@iGMzj_%-EO#`@#*dFt{0JNr}kR;66Ng@`?LBHXTpdIM%BB5gy4a)8>yIh|Z(2#OV^PeY}TFi;$!D)vr-*(P0*S zAG3@vfShZwXt?wRKAEwC85I}uDOUo)ZRZ+%7#a(P>Lt)1=|Nlf9-$OfF&5V-kdo(B z7^-lY*RBtx=`vnyM*1~46}nK!6J&$pmZOlG8VA)|9-~R0BH6|-hLVy5IFb9DB1{HS z$oUK?&=K6mMKN@xgMrb`SoBU=ML8OZgwLmPdC3->C+4u_9?mdN;TM$b?gZC>Xf}4% zbGCOEKyqS{XwKWmD4Knh^UgmF->yYLOI#5eXno__j;_ZyCDFM4tZ+|Okmo8TO7P}l zd0c6hOV8YjF=Z0MnIa7#*J{PoN7++Uq&l6rbREyyl;GBu0CH+!yes`D`Z4u2w)RI; z@%I#3F;{r59*&@X_eFGL>jb)fSdF!AIRM{V!dczq1~gNS!Z`0hu&)ckisOrLyv=4h z)82zl2gUeq>@uuOn}-H!&3wjIMK-Qff>SXWh4Jf^xun4>Nxya@Z9c2TFM3;qpRQcN zeYqcDjJ-TQ6}*zO-K?3%22SiPcyMPP_Gb@eY}s9tK$>bHLtSQT$@b<2T>f_sSxmlA z8Ck8$4s>OphxJXdxplg*FMY*gw~b*JWLCnuOaZ??cN2F{hi%eyhgZ{PQRiM0eB06vgVcI3 zG-)cu)k@NVYo0{aI@I&yltcBs{Gr8e{=j!&4P_FW=Eqgp{5!P18 zvDr?)_*0fjs1~q*MwF!Bv{4c;#37U4b7eoTWHFiZ-<`^P$cFI7CuZ~4l=Y@!rgbL5-zC9g_6Qlv^~0nO$v6zZL`jSQ?e0N><*=$um?hfefia- z0L&2_Gpj1ySoY9ZbS=)u-0K>&weJ>Qf8l@G$@x1zaaW;Ng=$p$qmNgSR-h}+{;+eU z2GtFeqvsFjps$@1+i<{%Gj;S4EodD~o0e6kP#v1SpTd{@RyuYBVN zZcd_v*kCAqmJ4}zhvS^TMKtF7BQ!8rLDjjEB;REKYyXU-9PvcqcS4F-vL>JHz89iS z%Zo;uWq{kqc@$*j1V^mTg5fY{COJ5Omwe-k8HY3ZxhLOnRw3Txd~+MmFTDu-{biI^ z5`lJ)_wnPFhr&7IRPNi0OnRC*g>F6+_L-)IA}KWmHt}&Pe|ybG&V8gi?OgK+3m#3Q z!4ayop{$E5j~q^)2mXgW)0tQdpvWKKftX&u*Lga*AKK z%ays`>a0*YS(_ME(nm@-ufWkvzuJ8e@hk4Qd8XJ6jeh%7Rb;bWy zKZc*0OR;u`8;g3DB~o7X2cNwhP2SJsVn6~K|1sJo^KU`Tks55-k8T- zT1o=iQR{boCKH2yZ6n!OUQnjeKmoW)g@9x&^7*Q^DR+LdMMZ)jt3db zdHCQ)Fof9lg4sH0IQ)4JZq%N`7g+gmu4|^zH7`ke@%}s)fQ2Y2zZ>jT!lCG$HYsd$ z#ZIe@+>@OhxIysh7zQXqNMjw0{I!y=c|8?NeA)ytvI?yK@(}u7wzKcHitNlCF*kOr z30oL&6+BKmp^>*D`Ta5{y^dJ?c{&Qbj>=QWF$2TT1JAnWFy|Ugx^T%|*e#vrJAEqfk+Ju*Rd4HY>8UAv{NtA>>fb}!4ncVE_-Sr( zyesjJYbdg06nl5>Hq44Y$oG}+;PqoVFna8Fobq8N9Db?HPPtyjy(`0@Q25Sta*Tr) z;rYC6R6NNIoI+B;k6DXX6aLd*h53dnVDmJ4rhd^AjSsazQTsaB_5C0#3OxZ47tPt* z)nD-iH-X)Irpk13CQ*TMBCc?M3g-v9VsXS7F1SLShFA)n%%E1-Q8AUR75@V32SM=f z$8oq2C_&%b%PXtKec`f|F7evOlfe7=6jtr^fEyik3p5_8;Kvghf`2d*XTR7XJ{i1} ziiYjR_x_nQx~(4{cZem=$P2YAd!mTY_pmiBC;+C9T)#>~I?Enb~nKUB#sZ+wL% zayG2#_iW;ZweVvP&V*MlKTw!%IOg@<;*?u>Z2DJ9>%4O5cG(4e~=JY1{!DS|)Qr;6~He;3{N!KwMRa5ebB^g}cCDR8B^Rk6(w-1_D(E|{xLN3QjW-e^dW-irp9vuhIF zyZ3^>lB~gE=a|vu31i7R`WkQKV~Ph}WW#)s7k&6Q7u7@FV~l7pTUH)QHn*zCad$r+ zQQF7)@BD`sPP*|5a*8mzNs1LMnTz@Bvp_8T-akm&hPD$2Q^2{8kRWsqcGoLli^K?e z)g%L|N4upbCMuirk!y|Vm%vA{__Tl?wJU-9g=#qC z8i{tbiS%f%JXH@X;PcnV(2l*SWRq{l@{AVnG-?7~S8Njnj*oyjLp@lc8uC(>%J?-U zjMvnTE*XQsI2rYlOuvraB z%=%pMaJ*}H=pxaAJm|C<_WRity}0( z=>x`=;bgI19i>*h#Qq`@zp^)DKQ3qTD|EV`FxiUsw&=sHkn=3FwModO7tzz6b(F)=nnUi&d}Aq0`_%) z2b0!x=B6%Cz^T)|!;kiZ^m}ZNC`L!0QQs%NNyvZt=N@E^eqvDA;Y2%+n3AnRDPEd+ zKs0anK=#vo7X|)agmD{nX!XAk&>gavcUhr@GJ0!3_S|j00`hRnn*=OcoIq6*O1Ob~nE0gYV-S9pBCAM!W zU={A`aC}2Hn(&v{BvuS5eqW%?a4=SHQQ+q#Nio^%MYN|zo!?l|$3Hd=1E1u<`7yv`F;5XT~OE0COofV1HZYv+Gr8#7ImU zp+WcNRq?S)Y;opeDid!@cVQPmXC|WvwK5v-H{@682p62IJA>DT6i5N zZp@>l73EPjHFqdW^4e4A6@ z?I`kn8_3L2CHvvtu=<${vuy~Y1%c^kro9M@=UsvYL6MdBr3bLGsy|@2It271Tlspm zB)qShPrgIeu}KR%kW@k`@7-TCbe3aZt_-;}dh#`)>otIMJimd#uRN|VKNV_zAEKk` zM&iFGwy?q_PkF6*+bM6J1uf8Y0Yir%DwBN8o2>i}gN|*5QF+R6?~6Iz4B1X^H+w+r zvRH1;8yOlQx}H z)piW28Ak3~$6!Oi7T6M>gSyKGQk9QBOPN{*dc!aAldmsjXDyBqhAASA4BP~FvGZdxmVP; zc{o-U2zM;G!`Koz3t#M3qWFyqQRQ3>+TJK9tu-@6w$I;y>YsWHexFTd4)f@%gcK z7tRkCOz5OcxJY%33#OQdQtypr?1t4%cIS^i`=jL!`uT>ma!DnQ{5Y4Kzl>*DKT0a) zCq0FjgW>4&Ns(oiH`8R{Z(M8tNK{ze4Hs`;LUSnveDbmp8vgb`@Je8OO^hh;-Fo^V zyzYl*Bv4?zGka8{45m3U?0~fg1*JXa;}7%V`qC@>oiTBw5S|Dte+9G4bNletFc0v* z=>ypF0oHh~VX6JP?3Kw~Tyd61y=XfY{OS-nmqwAo3I#l`eh=f0+=FMMqTyJ`7%td1 zmMy#z&E^Fi6J}Ig6ZRY5DLKNz3(ge*JKAcCQE?g4HP^-2Potp9;l^=Y= zuBX40%7J8A0{v|*2am_SUTosR*9fKo*eHT6Ie|CRPQdqGP2gO)J;B=I&uI?8rGq~ z?kjjhDHM0Id0<@pmec5k}f4G41@}v?kyNb_#j!dr$VV|EAh9xfoZ<8F&GvJnMy;_i4h;w~}|w z_ZRN?YUDQV19wzSf+?5|pu*_K7_dYEGL22xh(B^Hkp}U{Mm~Uk!Cl790%BRsuz8|1 zcYc*iEaFX2~;K2_SLUSx&Cj?yjXu{iwHK$4v-0jkSv zp;KWjJ9SY5rt$`V)`SI%R^OJSZ8J{~V}KFqvhI`gtU2W3XX ziQhf|_uoyxpFi?g(=}N#IKL8#aUTrbJd(8Q2CyrdmZ0P0PRd51%=M}kXik~T`wYvX zuyq1sZ`@{B{eBj^@F9s^IxI~yH)XT(h4y5)dltRAPoh^zL)e_L6M2)PTI95ek*UN! zmT&q2J~0u#v-`&sN599MgRWhhjp!9=bRP7iB zv$!|7zilS7v}@qBd^5@Rt-!L8kt3ULhalm%uDGftmKHXmka==P4YxJS?)PSr+9bl2 z)#c!Es2^>MEn!}#9$jA}oOuNAc+p}LG%HhQKIvD`bL}qbIeV42UGNQ7FE^t5!ajDq zrVm}S6S{HB>bMh^deG&?JnT2V0%z9AvxBO-Xy@#O?!wGl-+8F0{oNAW9iPH1+=f!6 z#Uu(W*JEbaLfEm7q1=>XU-7c1Iye|q;ZvVZu#o-_<340z&R!|@%Jd>0HmHFmItwTv z{1PX9B!*wy-hpAGvatP`C7oNh0CVl1vM$SJIJUnTTDM;!{^B)0CUy+F(qjkXGBw%g z-OE|m)X}ub$_LX0pWW+IGe~0F51@Won(DEDCZ0OM)%uNLPD?H5WNf#P7qleK3Xo4iE zY6x`4x8smS5lOhwfEpWrOmn#F9!6{7N-JRC0M zXk@)7(R_vZD5{NT?=LpOPqh`KB?KY;#imSk`2n)}qDmt++rbs#9Oizn9RrV@L${?F z;1l1&)%1zzz^~(MgkvGLNoM0uhb`i{6LzD6!!PLCAb|X{7*$T6g=kQr6?sRr>92S%c}MZuJ?m?#Jl66#LOGk@u1;5mHo$|N8Fa0?mA4P)C|Wrd6nC!R(#A{+nrI-~l$m-kJPcTzzFzRXdfm8Vw_T{fB-gpwuy`GZ5wsl+r zVU|f(A~V7jy8XVo{C?beOW)In@$JWaavTlp$J3=qF9NFIZka)r-vTH(67=7qMYZ^ z;QClR?4!<3ZjNDRO3ava-e2^cR*!!1GZ}a#qRpBHSg~g)7OxWSX#v8WYMKt&-Y&tf z%Q|_@moMS)f9JWyW|Cx-IgviF$?WM+Ti#Po9=t{^=Y!IOo^sPz_HvcLP}7L#Ez){; zIw_nD{HEZ00W@Yj`DA_4#4i55I*i>6x{wb7boUwvdX7U`~kbK+=Es% z8uF}<6NZv}?~OV>2SPzr$Qe5{)$;KsT|1fK$z}MTY!2=Kdm6l0mS%rV!IHf^J`%WxhoTX?m#$$`fA(?l0hi%v zK{wP!bmIPw6pUJO5XQGI6ZWN{cvfehy!jd;%XmAQn(yu&pOz1S-s%4E$WncU==Z2Zcz;(HYjK|}Tc9UnIvMs*Ct8^;!c z&*Lhb(d$ijeIjU~pARcZkYdw*n3DDjSMk`oA*_FF85if(0LhLVe|V=Qw|CcB*sX4k zEiTQlMBu9qUA>(>&wGveCgZvC{}gCy?NglapA8&2u@8Iim9ohjjmJR z%x;{aNzBt+<@GvH1&Y*oVPesP(Qo(+20e?br4h86jGufxt;qB{v?DlCU zaKZ?t4(>qd(?V8Q;wSWWpP=5rT$Xa=B0F3d!!p_yf|;`9RNJce==*sysQj~|3iHL# zzPuDBoxQ*uEQCWq<0wwOsgWO87Rr5D{F{BABb=rC+qe=@FX%2C$&Mvl!%u7h3s`WM z-#JH`StzyP(LV>-(gqtAb^RzhicBE=mC!|Q9nT7cbClZjGk8hwAC9XP_|p*s!Tk4f zex%%H=&g5z&V933>||kQvh5xYY3~8iK2>@!Y#HqQ<-tPM-1zS+u*rNA zi#+`R&KuvrI}hKnQB`wswjiaMvT+qA|EZ+7bJtm+QWzVrtI8?V#nZGWb)t;}cQEe9 z0@z&Q!(ifHevnTU?)C^{+s508#CgKr-8-L+ej^3ZNAzGuUkfj@a~=I!uft`Q>O*w! z6>ep=EH`&s0*r97!p%hzsB0t54Z2_gJ}*7_$KoXvelr=wJyG0{Lp2z9=n+42{6frl zB1@O{G;^zj-|J&O!MuUO1A(J)3vQ1H!Qj(r(0Ja00yH|oh{`Ja*O;=T*$e1iOsDuG zor5)b0=xg-cYb$49G|Fd1wPK|@YVM?Iiw#KoKg1yorOJc1jmvBK0@AvP54S+0o;0W z0KzT1(Ea36^gSzNBcD`)^F}Sa+?I{kJO#Jx>SYveEJ-Hcbl~MHFKEwrjxs$C>~i5m ztPnf})53ni*@;R&3TTVv0I3;Cbr| zMC|3DGtht{{tr4X-qcmvoBC6CKaSW;|3Cnl_>h2+CeJvW2C+(@MYnf<`@ z;-GcyZLyDc4AXib@X8GZ{(i(L3OgE#vSBM>&evN)&&7~}s_fxGT|JKa@dagNbm?P4 zE=xNSfd?KQ;%#GAVnx*izRhqA9o{wyT3b&sm%Upn4uh;cJPK758i#Z0Z72iZgn=I&kAHakQ zH@Ut0Ye3u81SWnPPLgx;aenkAZkka%r2b47d+bnQZ+<9Yv;9q|iXM%}R*e=-IUO%J zbrVsE67k{-Yckk-6$~ZrLWVHYtQJ_RFF#KKmCm4$ZLUgC%Y!+Ft!m*BEThN;!x!_=PjY>a9TCppy)*ZcJHEB1xKGcBHjP$Nlil zg-ouXc^2`4xu>Ay6R-#8@QjTGWvQ*B84BAm>x?^^U^OYE4w#;gyP*K7dMAWPg+BaNe7dRXSO6U200W6h$!=y_oUD;+-v zdp|$Nt^ymVmyBl#!kzW=yAk}&3Tg7#dJoe#45S`WH|*Vf1onPx;37jRIHTre5YsdR zXa7^cYR^(!Wtxe#)#3c@=7;!Qbe7jTugs3SX;71*DQrmT72RK}CG5cN!2GM5P;0mr zHNJ0w>%Bqr+PVe18qLWgAqDTVSYUJZK+&uP5G`rXTIZFMX`+|7a=#uI_e!6s4{ygg zpC*ugYB}VdipDPMZgEIZ85m2&^NvP8!Cq`d+mGC3kAB;dXW$boI$a3ibG?|Uy%Ou) z*T84|i-Dpg>aa^rVCp{2!MnZZ;l=H{P(3Q3aANrEt}t8@Zi*VOh}i7(-s`ntqc`D3*GqLaTU3*ynzv^ z1P_L1W14<5rljjKXvz}uCF<<)$j`8{aRJ@A*UGD#`;u5jjQ6ZN_|a!xz|}nqsG-Xj z0#6B9(vTDu@>dl`eQ;uHaxZcVW!KVw=jG^rdlEZVUCJfw9?wpOiSg%JX}Z2R2W5SA zC~B4=vl)|2sg}pkVBt`xYZ9`GAx^Y(j0P;4y`Hm_Dr)N!LO=wr@PX=VW4I3}Z= zclfdg!>SD7%o}OkoukXVKaR%t_wr!#s{Q=0z5}SW={$e-;0u0>yEiU5)y*BalZMqo z6|qJZIEC{Mu=wOiSle&O8s0uZsSh2{JA6Ah>kPvtyUFaqt_Y})nuZg8RrBehI`nj3 z!ZMc$Eb;eeMB`_t$QrN?JEQbjNTVg!uwp!I>YdL1hTZ0$dMIFAWgyD>2QmJZ zIySXEx;*7-F9t8~!KX)L$RuC|#a;Q!ZG80t{@z~Aq#kzhD+k)hD?dT|KvC|j$ z*OTdbKn7ErL$LFLyjag_G>e#>!tXfonp<=H3rKf;MeSx!su0dH&mH5KVfIAkW0*)k zw}oVU?{UAzK5Hk}{riT}2ui+DRk{rH|E=hWeiGAHWYh z&pG#fUGMkn#qyHAfx#0eIMJrjT)-9+;0cW0~8cKwseid~iKN z;)TEQ^haTSelm@d{gqAEw_buR-nOLGYfX_)+bDU0G+VX)0~9(1ljfz*xcYVqmv=A~ z-t7pdE=^xn6c$9W!K)Y(&xh?5j%EM&POnB zxfgTrd5;;Jm$Kr)F_d-mK0imaoxIzfd7FeJEOPPTo^14?5S=ItPPU*G!i=Xq?KS7M zIh1V}<^&ePWv}JkN&eX%a~2_)&ZkaNfK^?M5MvjLr&=%LI(HScJ0T%_1)}Q z@&fkOa|_*iah9X6k+l7C5!8Fkz;{{MAopz|d}{B-$1jWV)N=`%zrLLu12%F>IZyDx zk~t_BcZr`?e-pZ0wWwv_A%1wdkHU``@Ns63VBy;iWV|*c%savq-Cj;Ml^4lA7D%e+O3enCJ zgV>0r9uSwE2wmn@)X3Lb&3wBE73eRPZQ4eMRuy58$q$gu^W)#2zXhWuc2R^=H^x=3 zWT$idG3$FUnvFjSQ@@$hz>l95&Xb4Hr<%LLU6J=>L+WDj%DE!ctaTQ6aA&~pZZ_O(41mgYsjRc)5sRu3hpvZr zVT^7G#QPk^W+NNuRQbaWeAU3Jl0{6j?FovWETb|d6HJ*fpFOKn!H>TMruOte7C+)1 z9+@PDEscWjQpTK>7AJFImu%V3`jt3QU_-1LKZ(UowPKO18yCy9!|GAu6kxd*tc3ih z?3R6Oz#AYcD4ec@tFhW2$9cVZzfiHc8H_uUK*pj6oNE+u*VA{R9m>OLW9mm<&UOg> ztZ9UA0oS;nKfiG^a|bvFfvKj_9DpX@a*#r&;2)oQ7-SvI+>T8GJE;TIRQL%t>^Y9b zzs~W6m$M=LQz~qF_6&`LEOOyuU?#3^+~MdU0$tLarfCmh&HhHTKl>B6i<_`D zG3WS|k*ml}UKS69{oub$(WGkwZIH8j6&$K8;PtMhVBSY}RIN~D5jH;XpyeFq2K~dO zi!RW@z_&1?n{6*C#gsulss8Z zcpiL>sK#xR2t#!gNMq$BmMGPLkg$vThfC5ktCiLk-}P{K`7?O%OPaqN@rP^lsKM|4 zMO>EHHZ=52<;zRz;jGaO?vZjdilxkh2ODhIEalhyJxM(-dgm7|Hn|AmW_`e?C*MFU z^MRXFj{#GxhdpuA*h%Ft+@kj3)>jS+=b?Z1@X4mXSXWvDYDM!&pDE!jWr2O(bpUTJ zYT{00)}n#a5I(H)34HDE#bmpqobjd%l9qQv106?fZWzJB59)Itj2byM@i>!L6ZT=l z&*8b2N!0thJL9=*2T(<{5#k_#bwAOS4B0?ttIMax_s?fFhbT^Av={`9eS>iWI$YP2Xm;VT z0mTml(a5KsEKNdSF1YQ6M@v6~gS`ivA`{PgHNNue?q8!#cUr8wqFrg|c`;^}*8mx} zCbD1UKd{-KM>(->?&Jk;lxbT{N20U^#>hBQOo?Ij`VYC%aUtlXexAkjE~2A`r@133 zDoiHC5FB3nG5Hid8j=1Qru+>M}U=8f6W_aXuCSLbL5%QDna?uAEOYw_AwBkO6CD*0Q5 z8q9g+C|2JlWJl^(!K)emsQCz3e{L?E%2b2X5i6)@d<;v=5}y0=I$-E6kE%gNtnShY zPU2EK-_mEuUlrH{U6)5giHZ(vvwZ}q$%mNsrgEk_Lx##T`pR7czVHV5j4y5=mFtp5XcrQ@i!a5n}i&LRJUG1!?}fy(vk>D$#weAleu=)2L6?i?)V z3|^{`UdVG)nq|gSX0NBA6}M=3`w$3Ket{MeM`&wl52p>4w7Pmcm-luegc&u$yGO^^ za_<)+DcPZP?_ zO-O%?yqWzM4Ed;vOVcB``s^W)x^6nwZy!chvYSxq)Dc#0myTjlLVm1389hc!AcZGK z*!I7NVc{ox%riYfk4j>&?WF}iEi8f#pDeg(DaKwWR`LTgeIY|?FgI^u1n!Cs#D8jY zpyAa?TqyW-hIgiN&mW$F)`c6%?N=Urx;L7BwHo5o7ggwLT+1WVqM>0?@Ue3;cR*q? z9iQh1>z z%D3xtTf}=fRyb8Qv0pk6!f{Qjg8YNma`1$aigFzF|NYWS$C+_B5D0 z@B!lQ2zHX4^I3D_9%eGUg`a-h4Bxah@+Y>AVLF{Hn6O@iX_kI$pYc7u_C`6CWhLVs zm9;4Ay_=PV4T0Haifov04{vzz6QdK1XjkDounv778X?T0^*;VY)jtEGkB(F6xi`nV zKVAhRRDWaXKsJ-Q(SY_o&+&fO8`$$`2UU5NkncYO8&&^tOf35uy#Ke3En6k{OU8_$ zfp8g8zh=fhUzp79SE$Du zeX=XfnmiP}W-Oq_?Emn@@bl=eW5?)i0(aWXoK4J+5$;+dX3v0qSSUq32DMp4v@4JC?8PDQ z+4dVhs4@*}Z~98ytRMVcu;bXU=`KR0n{X!ipCetShbm}8F~k^gwNm0e~Q;apYKC4Z7sHL z#(#X1qTotPs=*DM2KAftBOA1umy!9y4>bwIbQKQ84<`xy)kLh2Oyg#GMpBpAHT<|h zg6flm+)ITVq@_jR)hr!$uxdK>84Env_Y!nZ{4Sg_&c+_5Kw+n4*_@3+SFc5#J$Cyo zu!dc!U~4(|sr(L<{n}z}J#7&Ug%6k7s=@)N$q608x_LK@txW zht!^PgxtiGydH{dhV)6I|bL45d|aK_1OJ8di=QEPX*5IW$s?a91Pr_iQfC91YW{y<}m6YQ<3+? zo{V=q3i+$g>@qjZJQ#EGqi~?kjOms+(*D4e>`v%f9Hy>~a~%-st_ZYaJxBi4{bmro zjAA2(gwW2rnh@R@%e~pG1>*Ku=sBkvlM)SpD|?MM5_yooCQ#sJpo`8q$Xa4RZ?q0T zq_qjT54L1CPsu?LVl${Y`GUjc^I&L z9cQ^T3oBHKJxKe%-r{0)5soes81x@z;6JhUisDW?A@5iOH`h+Y4I9qE!44-BF?a4h z_ZBVqDXg$p4+mWAxwraS>_M&)I<<>icRy`F9aSsfclxufNou@}&<|D0+Ju4Wzc>T$ zbl%6?8{38`kYw5+@QAjiRc|^_^}$kT()Ogn9-(i(QXltTP2^`g45RPe5}e?EXX&o8 z?E2AAwuSHGckTQSi|$yGmCPw_lfNMaJfB3rl9e&@vlPzP$b_Ts&cpDU&p5eo94m>8 zBtwlCps9GBrrz7cpmqg$jV-I%V`FVVD-h}sgXGwOS2Dq7{6s)gY@8`{) zb)ehN6LjILIja^Nyo+7DmA=$!?oj7i07_7?ajq>~F){RO|QrLppz z3ws!nOdiHh_;0>j*^H)f?D@u0_%iqu`=dA(YNq>Rcg;-b`5p$&%ad_=+({f`{1Lq4 zZ}Yw`=^!>=j13Fd#O0$~u$TmPx3B}){C6+K>8!@qtVmQ*_GX?g9KA8V3}&XEv0e2% zTHZFmJx;!lRoPp+40fyFDCC}!qvtuv zI8RTRZD{)j>)Y$_xwIYAk8i*t{gL>6m*Bhb@uDey-XN_d&sGlgh1cbKG2Cqvl|R(x zzs(QCh%KW@Uflo>Eb`%x8^!#UXrH+DJLoVP#}HNszPy1!u;e*SmHU9yu5AszT3a7Tl>G` zmYPh^-kAX_%j0Q5v~QooWbJue*uJ5LvJPBU_Os{%=zn@=zC_s345<&(7Wp==gh@hauz%tw-X zWdZ$rx|;v?N|AJSD6t*U9JAMb&;42~gLga5@%yuM>EHfk)L?1EG9tqv<76luj_>1= zdN#4g)$bubBmq9wJPW*~v`qmg3;tuB9Wd1P_36Bj%KiAV)5o^0b2a+c&b1O&<@} zW{08W`&_hM9giGEIhgQO8({-FUWabUJx26SG-hqY7iQhLOsgg?QQfKE~CIBwg#X z(3)}?o?idOdB~2Xj1$HD_b!F9)(d%)x3#co^I+^he~NwO4dBd)6qIN&rfH@*qPkW$ z&U(K%?GVl5M}J+%3_iT!_%nB)bJ+j{o?gq(xP2bCMeW8K>3;ma{{^lO*@F#-%`tke zG_%ZAW;HJrS(E4+4k_`aPZ<|6^^!H)b7wT2a*#rg8I6GZ!!K8GKZV#r6vh~_;X%Y22tQu8(& zC>)+v;k{NJE;bLPI}6p>lU=hgcGn?1`N+_wWmz`e)t6>cVLaxqj^^6h26I)0ZZvw| zO>{XJj=oEpxrwv1Sn#jCbmw>wjB&SMOG1PWiRnx>YwHL~E<8e2dSP@w$Cd&kR&c4` zPxIazBLwf|{}}`_822CyUF-V6%O;9s_k`ox2eU{k@;;mky#RGLHqtMaM~_M`lB{?D z+jQnCw=N>XdS~D^k~$;gh*lh@ch3j2bEHD58wU&g@%_x>iyHHp{}h`Io#{lFIH7TYEPDQ1KYG9t^|eEd$V`c0tJWEMaw` z4a{FD5bajIqcu|vaoL)UAUWd_OLLkE4r>(Xu$luYZ_NeY;xvBI{nOZKAxjRk7qXed zTF~L?VDj-l%a-ZOQO_$W+Me4bsygq$jK>ABOOHSBr-yThLI?S_)&^QIwF2WcORN(= zS!1oL2YME`bCoB{am|Z%?pDHY@@WlbYL4fbrMuvo&KASK#fRuiMI>x2h-bS?l_=OM zhd&dNjUP%@a)#m2%wy;ZHg&=un7Av7#=l<1`z=tUkl1J7JJ11AE0ma3^e1@QHIq$` zKg+UmN$~d=!dUl36gp}w$@RAKV}_r`?T41Kq4~PRoR8wnhsx~Gb$34RRxI+nPf)OY z7<#YT4Eve3z{|UXX@T~XxmX#-Cs_$>F*%zNLkuaJO5sd$5k9t30CH~+61%}I1T|>OWByQ+Nkv?)7p5y3S3Y1T<*`^!$QxjkxePv029n-i$YdLz>c!xa3imY(+W$& z?zb)IdQqFPxXa+MSd7xXd66)6v+h4og5M0Xp=n$do-EX)3Y|sl-kRy;`8S{4c(VgD zwrFq$2PQKo3}gvs!`NguNm{GFm&usA;3MBOA)gi^xD5MnRlhEc$(R5;#h;%6g0`N5-pM*tW2*yqK~Q#mZPw`?{HI^&dGpwuUjm@r}ki-;0jV&BVqx z%1oneF1svvh1Aysv!quiKw)PzyL#9NXWV;$mWxEtSh|>o$uz)^1CeOz62~XqUkM?7 zHB51oCzfk$7J9OKVPg19u(|3CX5|lYtmZ@rDy+fut1|;|I0K!By|ru6>0SUuyiLJ$)lp#oGKGDA9ZB7j{Dn?zvX#%T?^x1iMh7O_ z!-nIjU=db^m5#gN<4;5S_H!?tUMBRlZk`~Mr|ZFKwUEmZujY5ZaipLVRd`q6wb;f# zM42b1?13>42^p`zN?DaVY#&9B$9s^ZIuH5G=*y z%O;?+XcP|1)I_@jiL}G>8J-y*%T~YsfQ5l!+`W6H;A%aF$uIr|BRbna=lKEay%lbx z((1)*B-5ZGS@2H>N3mb+NAXXJERJf^7P#D}QNd1=tqvK&-lcUz(M@fpqprgKyBQ!b zM()EC-kMDwqeK-ClHuZrP#8DqA=jDo9ml_435)iGz}CzrF!KKnt$iZVo^QwTfVwkW z?%Kv*&^06tDPvMOYe42R+-aF>2EI0VTGs17gw8D!qmlNds5v4U_r0h@*|EAJzhC+A z>ZAfat$2a&67AsQfp%#0sKoyEQ|J=Eg{%`YnD_lNynpdID83mB3Q`p?IlzKyW52?+ z9D%Job|D?hh-0U9MFMYkBsgxm1$Fb+gP6?_@ZG%6TA#}Sj|J`ckDzA}f~WPaBwc=6hKi5nsIR~Xw}mLNkDq*zHeObl1boYE5~uIR{XM4op7eojNXgp5I3lf)Y+LVY%$ZXudbr&krB=!_iE%@$&h*6y`{fGw z7oOCHS{r)vLccea^^Rx!NCS`K6ya+DOJn+1040@WhVARUa zijn^fWjERi$!=yC``0f|E`LpM*UjztBl+EP)&>lgfAKTK>35F!UxeLaA5pn^U(yY5q+geh1 zSG?)6rvKPs=4h+S?kFsQrt3wJc-9sqWXia8uGiRd-)PnvEp#1Cm0{MxHLy>Cv-+8L zm;d@SpLE+J1TN5MUc?1}c1t%I250h>Nvbqq=YEn&RG{E=2{tC`H>UK~k^j65GRtbl zw(p@L`N5i0FWgyP?hePibqdfgIfLp~mr#zf6Z`gODD?`>@v|@FDDCTAZf#dA*L6!^ zSQ#CKG`VEa)uuV{D#41(1qa=@JLll|e`DB=V;0zaZZ<{E5?n0L)##M{AXd^wd|}8$ z>MvTw#hEMFTs!Bv3~aKFlj zI^X+4)d-=R)EdXEM%==cz9VVp)`c`bRB&7Uw8ZXl2e4637l&D#AW7vQij=8_qxtsi z=ByW(#}>0E2XoPMu?F-x>oJW2OUg=Vf+>6nZr9um1Hno(+g!w1^*(0HPraovv)o8t zZUrSXMaZ4~6Ee<);*TpO=n$}tU43GPe-~ZCsn#jDk4wPpRRQGFAVE)4m(o|gJm5~x zU^;sW;qBei+)MsHY&3ezO4EkIiy^y7XYf5V6wdu#YrNQ8Ef4-c?@(B*y@TI+I+2}q zx25abdhus^FFvz+30B%Jw8~ABRe!BVj520d{`K?vRZ+~&av|$pycw34uB9M>ZK#(# z67x6qK;o%|e9}`5^c0xa10KF|HfZ0{K(zT^XINt zD=}?fKj#122faRzsfadL;y36mBTr>D8sEH@t^MjiM$f)+L!?hw=Y819R&TS!V}ThM zq+d@TMTt;+xEiub6~N8e7MeE|qmoJ}`OTeYoe_8h)y`XDM*J6%vEYACb3MiF*^`Z* z63QXkK{(ef)4~3AP55z?D#n~P#k?H|c2zG${!7w0<#}JZVjTsHe<9C$8cO(>DTs-| z-fWXm9{7xV4(r}{@uwVJa2~71>2s!2=`wll`%H1R1^N5(I|6aJ=H!&6lBP z@(ncqqlx|c?&v5JiF&^CxX@ujfAZZL%65%}`ZH_T#pq1t6QP5~*+ZGX>pZYe8Nn5< zl%(sIkC0@jBpts$jMx!nm^6J6oA@^zJs-rg>38#J=Z0?l=r)7GCdk2p2Qp}+H3|Z} zk5MFA@ooX~?CPLoY!TQ1*G;eR&(9`Os+Pbkgd}eG>vLS8_c;D{uh2I#F2r50-0Aiy zaTfJZ=m!m#!0wPv{9Mq3k3w$1A zJWlhTro-?ZAz=465Z-AUVd&*Y$ZZRSSLK6|FaL?&RfaToO^#@C265)o!r}6nQB>RQ z&nAc-!1nkn;HUf_?iKf<6fpt1<+J-|Zo|3%T*%cq!)m=K z9WN~YgS+;)(##=C;C-DO-2Ci-AMS;~%exvZMgJNb?LCt9uboFazFS6WY59RvJaqaHT+r5fwea|D|YO>pm7 z0t*~B1MqeSbSX>GvvPTEQ&KAq6+9>>Jqtl*APie%53}%Db4a1|2!Aj3I?Ck~!rYWZkVta*jup|UhPHxtAo=CTSQ@4oM%I!R^Q!@xOLcJb{}I{wsI+N zjM@#74YS#oQ>yf1-4s5=B^vr}8gMEue$4Y{OU|F5 zb+>!1jhi;cxLpcP1*_`+!p{f1=!y;lj9iJe$&S z3}xMx7o=iP6ST2?%HNHl@w=S#e!*lMoIqh9ntax5LHF$2B2 zC3vHHBm0*UKr>F>0DJ!x^GAjdkQf1;C5~2x7p0iZ?l9&*`Ye8Q zDuugcBT41596Z(EiH{ENVuhWRH1g3daKJ+}Z_FSveXY%JKJCm|G%RN7sSeB*#!=YD zByM8fb1vfQFNoy4*vpT0n7Jny$|iT<-{X(rNUaS$I4-cx_LpO%>{W~s^38SUQaSFJ z8jj4=uy!i3Ch5i{AQj^cvbp-?v?m1Lm6?;={2#o$(lNmuW($T|d)U@F^ZB4^6F3lf z2!EZDBx~(uc;mlW?8nSetjjiqUA;P%&a4^Cq^CGi!}!qr-|WOP%ce8k{5kCI^3ej*Y$dgQ(Sz!RUU+Vr z2Fp?~pf!t2*k<*IIJo{acl634;q%l0>W!lyvsHLL$wlzCexGsQLnE^9xDQwD5?E`* zSgf4l%;w+x3|bI~PIl#-NzqiC@Z>y~CEQ&u2zjFP_ZLC0VE{fxs6hCOO?Ygg9*IfC zp!(#g)G=9uHmDuKmu;8$Co6=#X@@e~QEVf$T{Z}FAamxuC5y_N-a>cJdYWBUgX&d5 z5I6rHEI#fGVZKS!5p{j%v#rdA;l7z&CLg zjc*%E(|6jl^tXTTUsfBuidR6D!WiuKie~8}b!kSWD{UznLrrqm`N^+R(fD@-W_7w# z&9*H#VTlJ<+z^BbH=bZra0q0`$75jrbfzAz1HlGfi@u%@uB~d%G z4e!MI!Bp7-(S7}?{MgC&px4!zocjv#^Wl3?WFp7!OIDx@9mA;QNhEp?QJ+2|b6!fmfRgV$1rW9}6Ndf}c{UVkVT%nvMKsnZgNjfIg4fgw5Ru97g6?9!LO*imbZK%bTTIMTzN+V{Nl^FSL@HA zREQJp+4+}SRpY{H!!+1i^Dy2#tBKXftw4|Gxz^dfH8{=btM!g`Mf~dp4c7AeG}*Mm z&nUG<9@BQMM>j(|*r2t9{aG=Il81=%k`Ma%O`ps8^(GZ)IwpeT=FPyfvx>0(xZq)W z`x!n;>Co-3*Z41YO2Fa08@)R=iY@dKqwDH}paP?74uy}AM1b+Le-An1}#N%M}D+qHJ4Z?YL z)o9r%MIrGQ_+q~xJaG3Vm!hb|*1cIphIM*yQ7fKK@QVD3zqc^ca)4L={+`d=8$&9U zgD76!f@LqsB(K?8)GKix1Nl#I+UYv%d|f5#eHX*leBQ(Da+`t!TZ5q|YBHSTzo4$P zID1e2B6h|M569;udF~a|Y`4Z*aaJrjdNm{)&f!D`fZWGAjDj4qEa<$#lIQ zMZRqz2cgHIW7mpmjR{cNaGpD*;($$QVK`%%B1~3W3>2ISYi!rjyj!c8n6=;-du0Lt z1O`CGW*ffl#VtT+U5-)QrOxx# zFZ`luROJPs%Nxe`tW-g9HG4Q)cMRh;|G?)m>d^Gl@u-)USZRfyGg zlTmM&Jsfm7hjHPX(Xag?ewkwhBRi*~+SUfH>dhXI-TataI{FDSnSK<%?Z1j|gMgB* zyn);IBB*|eBaOdTPmeMJxcRQrXnNEKG=9GxsG>7t-|TG zSWsWu0cdKQ#0Kl$m4~pu zRvPc#KZ>4d2CS`H3`7STV8w$F;Cl|yXZy{#z_*1D8Z(qW+dPK#(!SisL}3QkQppw0 zx{DhRULv`AO>&uJOE>QQVqL4hqw}^ZP7*J2!`jY3LhBS(Y!gDs7K~k0w5F-LV(jZ? zZINB;HFhX32yT9=Vx>m?qUGOi!8zj_aPO1~Q_>j1PSmEdUP~)N!Et%(t#B?^)~BlC z5Lma+l^udOkZHL{m%O#{bo)KHTiOS1b9-PQW*_X0;OOFp5U&2n1h#qiGcKiG@bL|o z<(S1+KJ-@>295Fuvsr7{l%XoD=Z!PEOpRqWO`0gR+?`9jb|1!hlwy`g7QA(xisM`M z!i<3+oSh@iey;4b+FjWXzr{lNi}BJF+SQGNYRB?hyG-$vK{5{d9>Q(ReS;dO_VZn? zSrzs-hB5Q62H4y}*Ze<8eQ2mIX7GD6Bkwa0hGfbrS?g7ev zZos*-4#I-wEHFI083W#b;+;=VB>hK+1@8SHYp+}PQM@Le{Wt3;P7$9#TVxhdah4jH z%DC{($EMJz+c)?@miOV9moBCJ`Nl`*YJtp^K729GkF7TwLcduwI`llUzP6)?&mSYj zzmX`$7L(=tP_-^7So0RnTmX1-cr9vdH6xef_Wa+zv+!Ez3jSUe$*fbR(TJ&os3rS0 z*I^`lZgYfZ`pyIJ$5DjUW3?#6$e7Hl4RDv2KbETB1BFcm_`9Z*Tc*;8onp^mp1K&f zSlf~1+<3(oY{($?Uv{EZt-tXftC=0x73qNc<{leMW5hl3L|U}w~0 z><_8K%{pB;F*S!zbWUUVSJt?@Yo7v3VQ zY#+uR|J%)fGz-Ji7RGG&PT;*?@BuZrmba2# zgq~#cB`;!&(`CM+;0;W9G8pfc9p?VX+463eN3-QR3f!IT&$#_dq^K+)1_wDGVZB#^ zgxq8jjNDZq8*!Z# zV+Vhq<*TRM#4?NFe8jwbHu<`cP3RgbB|7^K=26HHl>&!r56}`k(d7 zeTr5sb8c{k9^<*?spgRVS(ZlGpM%u=0QN57Emxc)%m4gs4|&QL`QrCuscESp)BQM@ z)?E=CG%H?#@;P;pv0^j#O_YgpGP&qyTrHfZHc`rsMd19W5cLY&Nm?cdzi-cA?N*7X zx8H)=R-HxL!?*c|?ys?GrYs$8RDtt0_JVKx9Fu?ZnfEo!0q_41JA5s}d57+;02><5D)l z`V+m}loTl{79SIopofBCvi>1`Be_(?8Pp&?FBlTbRp#PSb(QzA9erlkwZ=M&A zSKgaa$;S)$^V_Fnv z;P(Im7XRYEkBh{Eq05-F{5sGauPu^19ZcCvdO_Ur5^gZRfx5pdneoAo@XMr%3vtN= ze)%dkWXDvzHSYy?!TSLJV%%%d#nwEOdtU$vgHxHg{w!P+V#th6Yq4Q%!K|k{Uf5?J zz%e&(SvP)G;Vy12z<=&Dxqz?6Bp0hmT=pW~slgQ8lyh*C>qt@%)$n>745-uf4E*}| z4UbM(2GyYwY(ma7*je$AYi(A*fnqIE6W%c;+1}8pv>g|k{lo&X#cX)MEKrk}!d^b= z!8-Sip!MhyGvn%c#YMWLq+LLUo#WVDFaL!FBdpmO(L4CMrh(fiFwGKlrLn-WogI4l2TT_J zgijv9xW?k8XpDv}Ri9R2qvv-(?5!^DQvGH&tY$54AAJo9_H0Dv?t*h=PO*};el6n%duq|lQIAO zM60*rHZbZ@BVM{Vj&{s6A^S(G+1~V%&~ZTp<95ff>0j$`Z_5olW~a_78H=9ST8=l7V^d`bYvIl63B zh$+RW$Z%ypdeF#q30!<;L_hm{xg4?cAg?Hn-s3djlo9du1Iw)yhpCZ@WI7BI3H&fx zK?)f|X>qbTb2^#{b@%SVc{dNXa{hIC(kmpC&4vE&gV(%2SH~|6cV}vnGthLJ;ISo}5q+f2%Rs7nQckME(00e&63innSm=J&-+W%uuWui=LZDzA^#`&JIuP{i$=3QVf7bfs4I!( zK>+>!v{y_$Vj@Q_^-au`=| zl!633o~TV};!pTZ4|=dat{aV3`s1}S!gah2`}EMWV$=!~cGvO`e3&c7>W&{GjaUiF zU2_D3CRM}DcENRYXe{-r<**4SUvamee8V>h&Dg$PmmW!tpvY|_*>|1SoN7lLC928V zJpKI_rbRI5GhYu2Cv2mQi!woe6~lkObLe$nZFCTP*mSiAQQcIJ5+uYUO?EVjxa&9$Xq zWZS`c)aYW#Ct1NUYDt^pO6cXHhY&JpKX`^67y22(-uU=%N=g%0({F6R+)mi5u8R@n zx~j87ZYS8+`vul~hNHkqJjSWqk!8=c2D49jwy@F7nTZQ`D20u)xq+wQY`8t+m-hAI zX5kF6NcAUwF{T*2lGdZnr(g_SK7l!m;Xo%Ml@$)!Os_gKIUjd<_WMIT|9+AK7hV=4 zJX188-)=dI49lRlu@QJ>-g63HI*c7$SB5FF3gkC*1amUBXW3e1yu^+sc(>*pKjz?1 zXqTM=A>s-wc5R}tpC82~Ue2V^rimc7YA}m?kWBN7hSS_u4{V-pL0Pg9WWRe2Ke{1- z-pJ_KEQmS>KF)n8%q#?s^js<&FGkMsDcBKiNv0C*P;zf894Y?^UXSy!?VUS!*=;j8 zK0O2}-_y|l@<{H5z`8Y+9ZizKsVri&EA;LQq;OwbsB3bgdpA3I?Zsj6PPnsQ-ckoQ zQ{>>b#}KBYT!Xsf18Cj5ade@25Unyf%}=P$C!fU=abV;J=&Kn-?~7h?jw|}{@zB@2 zNYj#4ofT#o?{v|iSPHyi=W}5jUZdZ>L8MimP3gL$QJYWXMo!toTfTpZ;zHlr%C-%r z=v)H5)f4Dz-x8`iIfzO#V<2{u8r#3+2y^dW!#uwVXRh<6EO=QG+v$_QWv(fqA=2ga zXY@R*_`QIY7pYO{c~`;TC5yM8*W#rErMRZaj1*18S)lexc-J|DZrS?Lf41ZC;EJ`J z@8BkgeprcRPG@=5t3%lKK|^VqR5Zmb`z*j2h51U_ON=r-LnDX%0f&k%lzKfM8~g{; zW}y!{yz(KGJoAA6a<0RPyIE*4=L~mH;2e%>NyP0Ax7d+~2hj2EZ_&}kA@nS50P4h7 zK##H`p6ZO_#s)v5Nq;?Y+mjO3V;sk;1g*1@8yLz|T#EPrtI3!&%9Ja-a0CkX{^MtT z5QE-0O@5xlN72E+mC#&x%i8eH40b0q6gD(21h-d`Z|B#b`D!Hb2M{5979opBSPh|z>EyJiVrpqp^#OlgdC;_W(a%S__OKgvsedb zPrJjJ-OaYg4Y{tCQZaQcs($ty7`T6Etj^)u*y$HVL8}6*GEh9?HuK%#S;* z&muWv=NlTx;fP)J+GbDyK4qDgy6qJcuGl$PK9`va13zpm%H&-r}b zZ`}vDAfpm2=Z=R!!AEma9D}i`f3bZ>101g&NnYdc;(%dkRJw7QXseP9>R(nBc)TtY z^?enQ-Zl!Wdw^e_PNg~_J95?FA=Ety#uZx*vVXfjyh!#a$~n3y0=uFwfFhDv39whuZ&PZC4?r^eRxRn>8v1 zxw8ot`LIPXK^&LO8 z?ZuI6CSyua0^6|H3%`z6CQ0+_v?5aQbw9V_>fcSr5p9=fN`{TFTg=BjO=_a&FL;ZP0F~OK%byxujGr_A_@k zo^llCIEM9LxFHE04+v-0uGwI+OkgFptR%lPYsk)uBdK{Y)YL1@LJE%HfU{EMqc9cg zf39Kcr3zr2cC^60J&)QfojH46W^~4hRi@nnvAzl2ly*k(1yg2tQj$d{9V3IE%5*C0 zAfK)=hCR!x6-|DJ(3Dq?wF&mLCE5*Yy+2jv4X(wm<3U&)Y(Ph9vM{%PAKNraiQRUP zW$M2|d6|oILBh;IP>0`vgzdGcB0ecr%1p;woefZ-TM8GS7=fap0)8E{9&G*?(vYc+ zEO?@nIB|tB=Q!jtyb$TIBa@=Q)NU_YU;ltYRuAS3;ZQHS8C3HI)4vtBu&;X_f9?1e zIC5Zw;6>0AI6{;7i|;;=VNh<%9+KdKBWT?pkze z)T8hvJK%dz9KG*rgF8Yt`sC+VoYEp|S~GYLXZaB*qf!>idRw@gCW<&fZV@C*I|;$} z#?Y#4705ZYwsPo~`%GkUm49)29W1vv${o_$joC}oQQiuWrS@U`LK*gZ?J~i8Ye9Ro z$Fi{_99c@&RBEwk;BU6ZaksCAlhweX)GJA%+?EXPsQ4$BeE5yHv1$N)mj8p#m*#W6 z53Q)8;XcOO@8nanSVY*97BV`m_u7JKH74DSssbt*5sV3aCsob9_>d?NmRi$dai=f6W>sC z)LzWDR%MHRO=9{}R47sF1J0~@i+ddZaAUQ1kezUTM_#LfWPv~Myg&j+jj6{6leH<) zK_I3qm4tUQGKD$)QnPVCoHZ_qu7$OVK$+plH@e86I^?6h6 zlX&pLEY>fuI9&cDVB?ZJcKuZf6!m?;@-z12kf6&t4XZgj3u|VmWe-XmiA#2wu<~!a zapsccE6r3T-tng8>o~Jr((r!rei-w@ z5N1{ho+J0c%tzUSJ_+ugQwHh$u`DN&_k1tv-Ioe_%#I@0&46XD#2=V)0K&#C6wbOL z`ls5%Zk23iuPxo!gYDsT_nth|iWF#LZWdcw6@iQ1X_0Ps9-ZF!84tGPVO_=z$gFw6% zcyRLsxHWGdo4aU;(0#X{rmGWSob(ime&3Bg-N0T%3-^h~bx>$^oDcjj2!77%UB|X8~h(&p<|v54&{yHoRzeN{wein-{++Q93sp%kB3c$V41W?nqT#x|8; z_q`)DO>zJmr+*wIgk6Z*+&J-yuJ52i6WOMo@$@2p04qE!!9EzZlY@UKgA#Z4(0(1M zM$VCsbxpOG8@(z!BkQ$pl$wIwtu*gqrcyS{mGGngVca>PPJh!S4s}Mw$jqk z0)yc~4?Z08f${ss;|(t*q4R#1KR(F;Jua%VxU~z|xDV3g9Qv4*_DrcP`7cgr&x}I(t;deS-r{K|($G4qrdd zfUjQDf_0OW@juT1Dmib4UnZqM!<<8ur?3dCzaS0sp2l8Jox_64IXXUYn80zKNbWg> zbY|;gzNVo7W(`bcuZ}jOM6?}6eEN?3(97)QCn?u{-1M= z=uU4uF4Mn;9`B#yUk#z>RzHr6eyZ{%wkBjCWD}FNy8!k5hE3&BxO}z1YgbJsfrA6s z#_;KFGjc!G28I1&ai32Bd;jVbYnI(llLYwLvwLHy$!9M#4PDEMmfq*-K|S|*!+jjP z!-am#n@q)nXH%t2B1;_{z?{2c=|oEjz8oYAp|1wf5MyI@t?evZ^(>S;PTxS~kPsO7 zZ!m7V>V}K9e#I4g&afLLPho-A0BSv+go-Pp=}&e%YBcBD#yVwy=c*jMg5l%cfr443&Vo82-SN>1*=*BB#knENex zt6{S2)venw^~C@*8fr`L`SomayTF&dGZjCcECPwtV%F;$MeUTx`E=BS<6>I~=*$LB zsX)B!8_T3d+rYkUU&IE%BH?pNi+xpA1^qF0bV*B|lv3Y|0|)Knv&tCz#x|nsvCPVS z9#&kJ=}B&cTNS>&bw^0=0~iV!rf+TgY0L6{l-*&4GNUi>V(BMXbRwSf`1c4l!9LOG z-G|wdy;1zb@0%GHF_+p_4uLO!qDb;ch{n8EOeR&S=kq#kW#acA=Q#W`89!tXCv@X-%n+R3nFp5U4D z57v?p&C2HZl2uj!C7lby8Al4Zw0|Sm;&ZyBR~*9sa&}__!$(t#Np`v3yGuyNqk^M&DWwWsy{c&Qql5Hr zxR6=waE1GQf53H15MJ-mVO775GL_6eP{qm6oVyn@WTi;`_H4mFvx`-X_G2-2>D*z> z|G;ndX`cHff@@!QqrdR^)#km4yQ7@TUuf9IHt!VnKH4V)@7M%(Wp5Z=*!mDhuLU&9vcQSYhoNzG!!xjUQKB`1NyA4SBhZM8oquG8( zIr7-)i^^qPDDg9&iX;#n?hAKjyZLO| zjc|JEx{%^T`&md#Ctm7Yi34NvSZ4cKPz(GjGEay?g&lIt|E>c)o&5o4jbB3}e<>6D z62OKUI&;^RYPs>Nov_u~9*-0p=3-oh8MVY{&`)=CuL zdy1zFm1+8o2!5pY82T2w8ayvpLG9^$STxj(l@%RCpCl%-cW4E_w;J3BzfOK!pCy^? z9>jt#o}%K^BcfYQk9bKrj_E~7vSPoRu)2C79`7}0**5XfIIy29VITM9o; zP$sWTMGBo4jW3T|;O@6qaQpFL7~EV3{Zqmq{KR4I?$jJSJky&x8l^ELg!olkjj7xw z3dA1Yp?K3m+u@Uja1R4715*MF37t%#8a$NN?&kQVs+E(6=5Y(52y6D5z|JShm=raD z>3+)P0+Zs{`8!eEjmSV+uAPF7SU@RxY2dc#BzE^rq5S>%c)zid+jU^4sQBh9OrJd$ zubjM59&8!K%Qc+t^wZjZqk_Xh$N|XCSX+N_o9n@M>5!eB0TAvg15( z%OOMhVWq|PoVSF^3}Mf5t{y6v?l=CGY8k0wVh^3(eEvFs#QSo^C4l|G(j%LV3= zkF5&bp8XSFAHT(1L}z$+7aQv6tK}5BVj<+qXx!8h0ee?F3g4U1bqp<~<0Y9a?u7$c zlq8DhAA1Z|6}ABBtKfa2EFEuI1L1m4~EAPGC($cE;h?YhJWCtB5=!9>BZ%E;M#j6ry7aNpF9^ z9e9@s9^UiNSZ4$sU9*!Jc};@%=hm~F_s-~ZJ_@^@y0Tw?58~2g=UJ|67<=*T4*V4E zrJD~tK?MQcb;325c`n`uYnN`oM-q3zanmF=Vbne*SE!;gb{ zv@kbO zg~}{vSNtn*%J(_&U+7_!DPD(%bd~8yyR2Q6dmTGHFoth6$)iRguc3Wa#PowS=>Crd zY>SIO75u6qmrtqW!!#IYI)M#&FUAhRIU06)8_DNSBwD$Y5B@)MS$ZRAez}8>C04Qz zuIsQYm$Co0=`)|s4m>}>o4wK>bsNGta8C&{NsC$@3{bSXBcRRbue# z)nPglg!d3{H_qJFN9Y-aLRa1i);zio!Z+Bl!-`>aT3(v8JU7G2$E9e-xv?IZ)AadA zAvAeE;WwTB3C-?mIQ8Tkc)9o$&Tm$x{}zwqO049VxcmcC^>Pq7)V#!dl^@! zeu9&4-|=(29GHRARMz*lkVZ(J=H~m>iQ^o*`6l&XxXMO|BLzmF|BIvOaQ-@K%B{xD ztJGP6+fl&ZRpazT}&x=F%(_1vhe30CEFJpx15PTBWq#Styq9bq?p~q`$8TK20?Sa|-l+u5_uS$`22|l6 z^U>^cRy03$coS~Fr@*$Kzslm01wLzGCD=5yWAg1Ea4y?{MuvYz?}j1pIrtn78nvEP zzi#BDB}~|4wQ211w|0~n8N=LXn&YFBVeqV1mMw5A!_s~cQ%9*3J8zreCa5i3@S#zg`j_D8WWPdB#3 ztN${w!^s%z9HLR_W)HqE93)yYwGaYr)3DVm1{Zz?3QCC}?&nn~aQlj82F9G$*>z0A zFALIb&w=#B9H`F-6MY(c2vy$A7xuWLFy=-poV_YvY1rM%E+x&PWiN-&5Z6Kq`V-AG z1Xk%y&70$uPLio53I@P$<>%xcdgXwZznsSj7NGs4bl(T~k^YHR~U z{Vm7v*a$e2&BKLrU%9Kj_H3HhdKNOtl!D`1@p$Y4n35Gl`j5A;^1wcfFihukygx!x zX*ibrQpD$8FJO;U6q{=K3R$_yHzT*5_1Xg8>g2*@CPQ1K-AAQ&w!p212;V)>Y2n*}07@S^) zy-P+j&pRi;?ZCu^LhdMA7oR>JjY!I*>iKDZ}MD+i_ULX>i}J z&pvFd=XFh5Ic}VA&+Mv!<>oG|Fw0ADiZ8$`E_dN!+-jz5i?A|KflDx(&xfil#gVxc zkT)V(*mY{N$k=)8kT99PBEq)Mu>}=x_te2wuaxv(gaiqxp8hrN6~-bWiE8XZEQ@h z!yzknz`n`TX=R`VKP9}E&ofEnFWXs>Lr=PB^G_M3wngAK>SxokC8xMai@t!KTtwxC zx=t9&&!?>yoC&9C($kx-;D`Pf)YO%xaGx!3clHLhBHEV%c@4HqVJTDEZA8kg1K9Z$ zXQ3mbkqh5o!~K!`iA$`Wa~B=|;jScvaJ&1Q%6V6k`c@{IyLB4NF`7eqM{AH9Q^0RZ zXalK(JNX8Y0Zcop!sgrG!PbUm2uQJGCc6t+Uj@U5(T(s;q6XEw0$}_AeUuDQ;JF1A z!u$UjtgiA9cDw@9a@7%>6gM9>4wGUpo?i#!t;n6SFrpcg=kpR$p|ItlE-i_VNAv1p zSon7qs14i)*|(hG@FhcXZ#{?4t*n{a7&|^-+Auorf0>KR@55PhUqemQ2$mBQz`kXu zvstYVaHOc1+c#+(U-(K(gbk(8ooz{@5*qNIc`&S6{E5#TW+jiQOX?OU* z8?|jPea~?>g zp#MAW%zT2?!ta(}63Jh&n!*;-PL`Se0-FPq@#&i#cstytlAV-iFL--D=+Hk>J)=)))Bo9COW= zW-EdPuE}c;*1q;LW{n!p)V0zo&GyF7<#qMUd&hBHU}uNF{%qmr*dL^(1}~IcG7<*Y ztbr8)iqJDgktU75A#VMlK|7mFXnCd!RjiPrLmp;0^Y3Y>KC};e;vT{jqfpxXV+Jap zK8{JB{=%T&LeB5UNHV!2#a`E565qY*3|;PPXz!v=oY&1ZE^CM;w6>=r_cj%u4o}A1 zv#QL0?nxm#)eEEabhx5FTGYPjFIozmjJK0t!p#|>?84Y3)Z%gq?2ie280m?0$|RUS zUR;O)@8&Trix^I2nJ$fVo`mB=)M?c?1^Rtgp2b|2qdh9wl)Kx2Dt6q*>v#u$o}IxR zx5&X9txYuk);NmQn@BfRJt5P=UC951)6j?_)bvke@5jUeb8dix(#l+jRw--<^T2oK zcjNESf4p}Ep%JG+dOn&oMoZ``n|P2+@nFguw-fsN*F!>p4K!XU0Ml6uxLXd>DYmHt zvzHmLIb%v-#OOtAiTV!EdFH@o=XK$-dIRp$p$#xv)7$oYw=&BwzXZ3c^6ASxU7Bz2 zLJ?B|YZ}6E!1!dWu=t0su9v{EUp3t4Lj*{ zddA)pf2+PJma*I`3gn$&q9tQr$G+wzu0~_c%+I`>-T~M%Cm%Mv(_!&fWk7$>8=O~c zM9p8U(ENNED9FfTP3$2q_n#kh1~59;uLr|b9*Lhk9m(dLUWm~bZD@-3LonUy12;$M zvN!InqPicqV3Us~v#S=)3W~<+9}DoF)FE5>_kZDd*Hs+;Oc6>-ZTVGCO`&zW8neor zg_CS*ptI~fu4}%*zpK=!tQi?cL8=Wf(E1F%yb=m6LLd2h>LEIRL!QDctHouUu#Q|m znPs%^rcYDe@LnzR=$Bd%vwZRbSh_5GJ299oOIBoWehdYv1EayO4I0LznXh| zumJ7(VS~oDA(wA89()}gdY=aS>$+u1&`_wGVK9!EwZF|EerA{_24IC zDQM6V{OC&+VD7yne(j!8G#N$QxiVp9@GXiZcznQ9MG-iz=qT!jts%!rA$0XdB4_fR zaP9VW*ur0gbvOKZkEAEPfr(>FF1h{cSquod@tCa6NdrrPdW7+BPf4KE%*eL zz)Qaj2!umWpL~#OkGX~Wwl~6|*p>Xr$#PWIHj|=rR>Mq(7r18R09rfa4LA2yw@Afw z9zJmN7Q41OLYYG;IBiaWJ6*N#K)eS2TFs`N{wicBupngSEknbVIk4-G4ICKj#CjnP zbu1c?o|K{4N+bH1V9&|6Dbh26J)m$>mf}X)Gnv!?ytA$u$`4GZyN4rSwB05!eLN6e z7t4~Q7t$gTe+g%3Ci@Ywp~`f(_46 z>ic5$X`?C*+dhvwKTnB5gSF|y-KpugxdKfHJmd(kz5 zqSYVbqt!qqw-#W%kr#eRnT=-C7}J&?#VR`H!nv1&@o&2qE~~tTx`Q_G-%nb>>KZc` z_4groUO|vu(+M-8g?FRM0PKpHN=+eY%=C;i=fP4SWez~$tS-(&>mSN2m4Lq2%h{t* zizz#DJumfaC(BtI1U&~`G5y*J2 zgJDaCKFyAqNgE=hnDm$Bv{T-k%`#P`8wU0U82mj#1KSieNT#VYS5BPy!HqpG}|F{zZ zN4dY}AuLzy^XHu?uYonr8dY zG6IJ??IiIJ;r#Ly@<=<{_;Xtukw1_{vuAX{VCkW3qFOuGWBY@1xOa-Low<^ok9TK^ z(;evL%|mdI#?y82d(79p)UK6#2gc8&PXe|?q4E`(>0b`L|50&t_f zG*iw!N}4kO)A#I$)vF(&#gs^zyTuQFY#m1qcgM4nmuFzl%y+o`avyIV;*5{R&u5R^ z6j_k`3DQr^*dO{OnND#F-p?94lYv zYEr+D1zPq{9>xp(Z{>6;)?|JZR|ZJXv-?|d^zVV#yw^oI`=&sN)K>PNrXrd0Z*b!D zcxEEZntz`)V(V}E(ukMNFe2?W=k5O+A9$+LM(gLC$-*#p?uHW0bDa&}zCVQ*UmnA< z)k3E{IGMc(Im#z@Er&HT?S&5gUA(FJ1wXHgho!51=%ac&-ZxcdTZ%6*S><+gbD0iv zBntVN+eEzR<|_CryMi_AO+dY%6#j|)OmY}Mme#GA%MP}hav{?VSgid%{&86~r>_=^ zMrtk4I^Y0sM>S|>U;;(A>Vt#O$JloM0-m^43{IB|+2H{(7`|;iz8_T0-;+JeD$j~o zz2yY}MSZRudPX+D@$Nm5{91r6&>1k1(M+`2)@ z+^X|o^m4B{4JbQAVw(=`VTv)7)h>ohzCO62;h{)ve;&lYPsF`V`k>O|LqA;PD5~o| zR9&AAOlL5exc$UKK7Zh=ycm_9tf9o}d$?=#6Eu)Gf~hA9v0E%dIZ={W?3@YtCz9Fv zM}lKoNrIIm6tfa7UpDD-9q+HQmR57h^i6Lfi!)wE3u@w+jhi2aU!Tj)%4tz&r!|B) znX-kiN^nMw3BR%X9yeX~2$im};WwEsrGak0c%?BR?CI6>Y=F&LN}5rPpQSZmUgrl~ zF+g2hd9xZq?`NV~2Vt4&J~kpPkd43govR&X0xnI5*_K1H@Z;tQc5RfRz}ff#=~I5d zbv+TogN_g!@ecgF+C}RvUu&+51td1R}g~=!2;)!pZ@fj03clI=Y zh2MZy;l{Y=%qQG?N}XB)e zK1K4Hx(D!F;XulGC%D2cbs(3}1Fq5YXp7LF>bn~auGan=Pd1`iJB%Q3PbjWPJwkBi0)D@{0u~$_%sKl$hL&4pZ0z)LXk0D@ho332oL_Dv z*$}|43jgk`yAuduLM>ErBiyReh13h|(5$Wcz&EpCzuX9HQwOBYF#^KM=2Gsm< zAJ@B0on;>gro8y$pl%}uPWuXu?fH-I%WT2{e>G{!I$fB1Tb&)4od|cLzvEM>QSfT^ z5q`d?1I*$kGnz1U~e#$Jx$6Y+=hdNDO-_A989>KB?w|I|@ zKB#(X3HSKzLRft{1xGFNWGjmouzSas!4Y8(@mPG9+afElx3~Z1s%-=5e1R;R9o`ID z3%a1o?<|!iiFs?~aM(KMC-*m34|m2D@t+fKFW0%Ij8JJmlqanMxP({`H#fwze>s$YYDv* ztLuE^UtzARcAYzWIvqyLUV?hT(`oR;NKl)&5VR%tu!aBq;ZFUjA>B{LG&Vw$i5-^U z-8oNq^@z2UL~1_hrFCgY*2p(?`$?p&Ke&b0&B z9>p+bEbO4}y_w7}-4O@1sXs6?xEN|5Rbi1$Id|c12`F9o_P``Yht;d(?|>hZh$0n4;OkkA2pPeJhRG_Ud9z zS~QX!StZZ=Td9GLzZ||SKZ7P7MKot*8x{+D*rcHwS>zoLn)~!3A3x8Yk}@yD)FA`| z*XH7=@g*Q}$CB+^odVlmj%W6N8kw5F$86p62N&qX)3-%kc%)(<|DV=AHZo~AyTfUt z;jnnPQf7(`N4J0}X|Wl360{>#m+T(M(zU~vIj&oRwTIrp?3!#^xLC|zdA%3|nhT*y zz&{zt9pF`K)ld_wsoqH+@c2`_wRbFUBi${E|5d<#{m91T2REQr+m8yy7_fVP-{7Cf zbuh!_JzwgoPRiSN2s_W;e9ZQ@?8Jls!SQ>WL}v@ZC$R@@vOHM0eVSOhQ*h|a$>Mee zXrV#xZSX3O5OVAF*l}+ZyJdP4f)DJc^9OG6cO>#yQTb?klrxK#xLeb*F4xL~YJPYv zCkhXJ+{Nts-9Ycx0(8Ey3}fo1;pw_W-b<x-h_V`foY;XL-LZUa>+ z1Tc^Of1vv2F0Zu3f=-RO018u$>Ef{)cso^&8jgY<2T!w^N8~bi2lFh8%nrZUHv*?W&-OR& z%vmG!zV)fWem{A|dXmNPv9$Ey1M#h7HMTd)3yXdClUla{ypb8rbma>m$bBjs|8D|| z&=KzLE2f~T>J*&0P2hX|)Byi#c^utO2 zE02HZJc}GI-vwOg%=|UN$nxSBP_;~Cbw=MXbfy+d+;#`9xy7)nA064`I2}q!na)~P zJ21s5M`_&oR2XP445myn*)vDwiUa*Gz+c*o1~DN^8s(}|^ z|0Z8#k1yi>32$I$QXajke#mKCe5NByj-cm)aN4}jpWW~XqJYl%Eahr1l^A3sd7T*K*NiIHoMBFN!}~c~@DMMU@d6AMI}15m zJA5rOk=L;fhK6q(>oG9JVHQisIddu-en<=S*Xl8i)Cf_&S|5anBDr7o$GEd*78LN- z4=4ZE!j8tj#<1MEBE!Z})MzQDaqVZ&blnnq<2jk82>XezbB3{jPN%Vw*I~=_Jy_*O zO{OWh5fTLNN>T1sZk~h^EZtm(SKSeJnCPI)vlgt@u7UB1)2X~Mp4YsgOb+^=;P7ra z){$okkt?<6SMXx--H;Zr*yjzU=M>Rw*kz2>=x2g%9oK^H->vE!rXP|Ph2HhKc4p#P5;K#B)ZkxD- ze4qO;8$~@__vkC0knHDNe;->=@zbg%r+r2I+?E> zeu`HWU4p(IThzR8p1<-$niABLu;SEu_Gh_-U7)nEPkdE}6SXawo3uGKTYu*t7_C6# zkBV%Z^FQ&fo@t~!B$nCV>g6}b2pra5rO>)wletVNVcn*JpUX7^OT^nKNveXYI48>_ zc3uN>^${>Jwt@C6*P&b$6|gy80)O6zuz%J@Oe5(!9Mw<5OKhTE*aCWt%4W9Ne=6l*TE0@UeP4&51gr% z2`DeW1gS$OQmx8nyt_%tF5mGu4yi(Cy_=->xn=WVdm(lg|o#$SL?><0xqL7)7RQicwT3!B#f@!+wvM_<~c1 z@wG*`XTBz7IDHcpK0Al5%RL}<>kJ&S{s@GfTu)kd-2(POq zp-F)$*mWnvAbT~GsTj*Vbc{&*YA1g_EnDEEPvLS8r$SacV{>0Fz`^@gvBIhM&{Nlp zYj>*PZl4-~xwiLsk67W^?Mx1DUAIv;B6wam3z{jtBaLkBL z=n&eBJ`&DsM8I)o`a^g=hZVw?qeI!p0bjr);uV}LdW7kFC-VkF)>7tbZE|c&qe$t& z@Q@Y5?x00%^ZN-nHvJY{sjlU!Po05rnoC*rX$gwZKfza9I*NC`U@X5coTi4PlS8E$ zj_}+;@t>AZK*~Ejv@?@*n@wR!cpPa5nA6J@g(xYtp3-OLbDwyjm;2fWPOzacK24eW zO~fEovP1A(4TH_6%E+xrOmi>m(Y@HsbVhk2^#_DA`>W&dbEq2W+>T}*^_pa^A;&Hb z65Q#o8PdClyfs#;*F2EWz9=0)pewKuSd|GH)2Hh^LXHk2Xi+6 z1*?kJkZ0sr+G_k9Op4suHN9k32AReOJ;N1w})ba4Dm`mRp{w43m!EJu83bV zp-WMfdM{nWU(tdi?!P4VW}O)=ThxhGBXw<83(T6Ak;d@E&XZf*S&j_{t?BGc36}71 zEa=MF<8?U`=+l+w8m7&lD>*^%Okn4(Qc)Awxrg~{HrKdCAEq(6fdc30=QC_QdQ0R} zZpJR8#E6#L-^BOzEsz=ifvdmp7Q|O9NP51Ez?ct0r!PNH;Yp!r%v!|G#V!2%4Xx;^ zdls#hMhf4nHr+0d#*Y7f;DPQ5bTQ%rw7N{Cw0-8{(2e8BKZA$EgO`BXqZp9*qt6}t zDrsBO(+v}T55aavZ{`yt$v0ig;Kv_6iTYVXslxCKN_ISjizDx2=?G`q89fl?cQ@nB zR9AL?5{LIfbFk;}LV;U!504p{u&FMIG;F^*1r=yeUch4H6wBDa_(ND;Z-Z%F#b6aC zuz4(Iz=_xLWT{fmH$0X^GsOoOn>QJr;wx^gj_}?g_bfb4~8jjd@8{G74Nv3r# z$PBk*dJb}=`oy2>h%%=dxd;kAmL#4Ya07;@3}(ekR^U%x23u}#6&Y4%z-ntb@rD!D zAh~KPCncMKXZF0nKR2Qv^il;>X_cT~;d@lSb6G53vk5jdHKImd6RcM9;EDnovFO@F z;x1={&(4!L@Vhz-5?_LKVUqB4`!}?ISB%|W+t|;&A~s5x3Du?t;fyuID7(cQyoc66 z)V_&q8Xpap9a06a<07=%cpU;hti>Q@Id=7@zy?`w2p8_YLYctBg8N373_B|Eewz$M zZjHg2uk*?C?>$TiHgPF7~SuD6#hmwO`1w?;Nfjy~ROu5+$V};yoTe}epGZtnV z+a*|7*e854tdwh;7YGUS!_hoO1JdKNMSj+Um}mTJTa8=^@|IiAmM?AKi@OprY|j~P z^6$^+{BI%i`?m)^H|Mc8$unqW=moJ-iqN44WnQ)B0hW|a!)D0W|^_$d;`3{_8qd0HE=7&#o(3(;r|<) zgP*Kg@vl<|ceQI6g&N$!rHbWDUmVZO-?gEB;}KkzE6l2uKEk@L%lK={AM9BxMG0Z% zv{rl$Gp-AcmhJ_(gB!)-J8K{#--2RH71_JB4DLUwgvfhdaBfmNZVeN|pVj&B#rz;y zeOM$?v>%U_uGaWK6pOQaIhuLToYnUOIj<|jt(nW%&kYyRYw{vyU{%XJ1;&YY;AbHh z>J05G%OR&{HCy~2kL!bNG4HTE);$*X-Zsy%yq*>G( z4QjhQot@|Bv%%v6X+~KNHA%;!lD;uJ5ip+hlt$ox{{)`%)D#%A$PTi7 zjnGq7;8J!=v0nm5Iz;2E=%d|jTyQLqY-&|leU>fh4>u+=lZhl+bs0bE7}Cz$N1=As za4v4B6m`}&z@#i6ct6Jl)j~+A<`a3HW`JoNeU%eco*MLbLwbieJ^bqrwB>oEQRpV;%*!``2x4QO+=G-R$Ou@E4uxSxNTqJ;Od45)@tDgg6snV zN~ST>naV6hricswz_F_SVpRA232{xMSxvq&Y>7`7H%y)hw?j=xVpcDzfA9m(GZ#=| za+U*_*J(at*c^hH<@?mRzl{ldI=fVg6(ZdKGjWiaN&9r1y#V^=mr> zIs3qmsh@a>lG)JwOgNuik!L~0E%-Nb2EHFt2=d7v@KhtitzC;b_tso)=UhFSaK?fE zV1I(|T3L!wGq1p&QXY-&4I}S8$8kngCp?#QW|!w`LCKn>P&~dE)0EeeiQh%AHQUXv zF8B=<-cR6RVGm?ksj^3_?Z9$g0c;p^6h~hkK<6GgGqd%I0xvj%Km5T!?CvM@3WqD> zZ*3PaFq%p?ZFjNP9xj-4{1BO#*Q5V>Pwr^&F+SyRGVcRp=+WE;d^gCJwwyC(p9OEO zufR!ZPkT~3pllEucn@K=vLyDMTf$8&4g}XRk$BFxmuv8C=C=(x!J_-lA8 zWcc;KV8Lx4{-6SStUjUR!NKhE7&Y3ed>b!xbz=5(H98U*O7;Se=woLSzoV>#Mx1>L z`tg@=0JZQ*%ObfKi#3Hawq`*_vn&R&Z zK2i;DI6vq;{2twboAL#J?=W4O?)Dg-ZI@=L`hv$*c`V!dAhu?^n=Lo3zM3!Z+DG@w zVwt(}V0PHt9Wxi$k<&vnR{p4n56hEe%3t=11}z(^kB5V#F{1ARPI z1xBOXh7HU#_zt*Ta>h^Q%Ixcd+j!2d9uKu|;2t*VFhwCNs&cZFOa-p+Ij2Q1B;_AJ z`uY)eqF_FoqqG5w?29?amgOu|@XKF5uPhD>ZNj#XhAe-Y1lhOoIG{ZYpZ|6t!~cfB z0@=Gzk+BVm^4sy+Bw5n9uSWsBq|(cnApF;jB|zj)4G8kj8f*6UxO z(V}e3n#W+gM<$Jvs^hC~s51o#pyr6XVnusd*1IVU&djgn|2p~5%ui1IwAZt+-8+a> z^iE-T*c7(^QU%T%;2~tp6~L`pfxB$=mLIvZhfAt%g@n~{G%esDzjViOZl%={I(2y# zF6ui>g{|{(gwHH&ma3zkkG|YwZV_ko?iP9(e}zSxuJ9V=7fE?fB1_jD!(E(PMv*r* z)8*;f^zzIgHabj+?4s+rqT~nMqr6tqzCVoJ(fbGTN8UoJ?R37SC64_z-^s2%mY~Oy zXV?j0H|)W_bFu5aSg*MQ>>PO%6<$ive1$*!?yUWyJ&(3C-{*1sXh#{Gvqys-{B&ZM zHot(njZ>=rwv|C8k%?B_C%sffHrYq1N@Lh;b0Lg=`sLyEP+4klxO-Av8T zyn*}@w9OUHHVN6a6$x5&Y;HA8tc&Ab<~|nKa1BD%)PnmhbQgTZ#@Mj!4=jk*rp|C* zrZ_Z&!mrlz*S`Hg2R0w)#JJNAlT#>PF^&xr*n%G(xd=@2H+ZXL5w7xU#}A*p@xEa> zSG+YJ3s>3G!G;Eu7kB{r+xl?a(6@MLZ3pVvJb{-nJ$CVJMoemXE9owL2RHU7qu-CK zq8)kzXn6l2+?^-OjeGF4Ut)~{ z5sle&`qElq&tEV|pQhZ?WO_-m%&sjHCWpM>l~&lokhib#>fSQ3$%2DaSzdNgxh`j1y~&!%AD^iQR^sAu5MMejkRSoS{F_cy04LT z9m8wz?8;F1_5KHXEWd%jb1vX_&*9AEttEG9Tp!*Ld2)|~71bK#zuq6Qg=nO;AlByJ24nB}=7dGkXPW!cT`p_I2_D19^$ z&W=qM_)Xy*W)7&wx>Z|P=K_vSSG{C5gICbi%x*q+O9^~mXo(q7wP4lRCd^y1;9rZX z@a)xKrl$>I_0Uh?Y1NM6tuxu`pYL(|wG&+6i+{N9dMPd%u%DAXeidgK7*OD37n~BO z#-9?H8rI`t*uG`|;J%_d2H5iaIqR{w!2A!+3(n#rhV_9#c|5vnIKY(sn$%b~mR_tk z!cp6Vd&|cXoWx~{Ctm0AQhFlOJ|7OUJAUGsv^hBGi3>i=ydY%AB6-t!hOFo9Sa#>| zA56`*Vm32u>Dy<4M>)xWPKFO*_7fdocjR9*{k)p?KT(7gt+yd+x(O{3b~Ea(t8w_W zb!4>ZB3?f_ju}q=4;vRV)N{Xuc^loB?VJ?+vhOj@Ezu`c_h>43e1P2j+Q_munMO=a z!1{hAHpeL!ZM7Vs27BRGnkmj}T*1uGBva#vU~a+!T_)+^%qq+0Gphn4mT5JLPmFlQ z*{{qNO?)d)R(FI9l}L&i`a00%z;2K`_?^+aVpH6sXI8-xXyYr#CJwre`pz0G zylw^e)JNC_$QR*z*}XKgb0az(|Hs>2&4e}EIJ*4l8#MkAy4tS6SkM(uk95U2Ehr76 zJV($*^9OvB&K4Hc=!)rPt<3M*8(#Ua44?TrktUSZu?YtR{>^<=dxJOU$ix8H^OB`} zr(Qg`-N>ckk4|DXjuwBYP^Ir%bIVQ;^PKEf*Kl zp6x13KJErin&1n)kuTtDsIj8py^IQOlnRM`Y-BW z^E{&IL*KCTM;eu>QGiy-nEd2S{33X%D1VBm^9S9Op=4@o#!fC>P40J>i(g9vo4YrG zW;A4wx^x{BL@Cm^_1<(^aQN)`^hxYFVH0I!PGH%NjTm)u6n%KL5BkB3_BF1jgtl?4 zVsAI^w(Y6d`TR{tUiA$$ukRo|iQ}YkvlgIo4*xnqo22#xkcrKH+^SoQUmWl883Etm z+0+{Doz^t=`S^0mUsjCb=~n!odf_{=vl_}Y&T&C$-i%WV=Lh}?rn#Tw(DGasyLRCV z*R=_ls*d1N^IeI0d0)VC$OwFD`i+m#Xs=b;G!S0ar{a264^5u3jLk`;Q4@PG&H5VK zE^v|eHI0TOA4js7=)*3*&u8=eQaDMIUtlHV3JjO#ay9>T@h6LI>B(jbN*TJ5ouBW6 zua5}l`19@jc;1RdzA$vci{J2?is1ZtScNUgX&4Y^&*Uonahj+SzO7;0j(#T^7_LNz3>J#qE!$C| ze!pmN&ufUQ8Vs@R%A~V32CA%U;cM&*Sob5C+buYPEL;+?O*)>Nb-4_e&ex*{RYO6Y zrlaMCnatax6;5|aK$f#K#=TpL**m^K>VrLKC!Wmqewj<>Mfu#WZ>{Y34rMC+7EALT zd!gba!kLFzs5RJ_W=xxpx!w1aLMl%693|47{t}8!CorSF4{-mC z8uQjH#g6&*xJ9cFdf#oNR&5!Yt91z%nXKVH4Q%HnA&XakB}K~OzoOK2(?$Okbc1C@ zBR4|ms2*sk#5Z66L*sK@kf0FD1%60i-K~3Q%bNW{%HyrL>CPn4BJ=sA`q+t{JS#x^ zYz>eTP8ByB1-AL(Byww!AE@XYLOL%kV(Ij=PjoVmw2HvKZ)8Q2s*mckut%dwlgZmEle8zWvsv=zRN~fq(f#@n~FkK7_pwGvRcdx^Zs08Ts)DnFOuk0{mQLS6pjW8Y7H|j9X zpYevD^t=NO9X^DaPrR|Ir3z-t+e5{gMeykIPn;|>nq4>DMvGO};^Lmikb@7oNqfe! zTP^=_+ZKL?ny_W$_+}M8oLNXO$DD!XaFZF{rmXl2!JMB)zg9Fgh!Q z1q@GQZ^LbQx!~P=Y4jM;^qYb=p?V}{^ak;=H{@uqjtAYz_TwrB#**VDMRxycIlp3M zG1w`-fC4*1RuTtrd$yY;SKX&!CCEX7B z&Nq!&1dc=h@=5~7;O~bm?AFUNbSNTxqf7_xn;{RK z_lMK#-(zvtO;fnMtBQLaJb|*C*MWNZFgn>M$(jxvV+(#vW}p8VqdEaw1j?*NzMmhg zwvpvjR-j^OEvnxh&ipgS)6$b#q&!5HMc*vK5FwYqHHG7`*l%3t9#gg>ES9&T1i`=b z4A%V}Pdf_=gbbG+SMuj*NLz2B})NK*XrT6B0DZNc0DOCS&Y2D3dt`of#0rDY;W@mGzci> z9|=43{#ZE*yP1UJH;~>gZ$K0C*fV49&BD|EVwhi;=sWdxu~_? z*bp5}UH*a_ORFC$9@vpeWe&)`c+Blg(#J8))j09tI{xIMR6a;ym5{kT!IiY#$5ZPM za1ZipFtTB%;LUplQAxM(@LpM_^kyjXzeCy7E8(c<-HSW#4rI?qX274VKhgT~Ke4DP z0wYv@!Pws?!Fp~57VLB7r^yRG)k+c9bL|fvFxgKJiz=XG`9@Y4p~}Yzne@|B>Ty@@ z6725T%N{p=yzkgeb&>@9z!;&ywSE$QOK#iSOZth=fL}Z3v88~CVI1E zAT3MTOsO=T?TQJfZ9-OZ&*y>YIo(bCYHBoHdOaEUzFJGK4F99HttFz!_d8&DXsYOC zgg<+J;yP?S(TvI;&yt(hMlxHH&Dzg);JC@MOwM{JBxej^cQum8C&-5)23B!C{7Fc# zm4&kVQw0C)9Ykh>@+KC-y~>xyPg14sYg5p2pcPK(bY#4C8h<${kQ%S;#l5SX;Y!f~ zNYmHEMH{6^bagVb`K(ED!O1xO!&ts~)Zt^*3@TdaLK5l~~9c}84ID=c$CrTygUZmp;9Bj#X4ojH4-ZUtS=NxXbpyigUm z!!FbkZqRq6S0>Tem>y5!QX95m)KW|yJb+Do)FNkt4A_Yo0(-$oO5nQ$^2Pq8tb2hP`?6Y=HGQoBgObOb zTe{m$J2i4{7){=O9T4JK5Bf(`xKHT?Y?0kV$US1ruJx&b!J)H!Q3~=4 zT$`aw`y9@#v}YIR%F#iWc&c6%3FA7VVeN4-c2>RTHT(p2kJJ%7eZ7XWP7(6{6Xon} zI~~}f>jJByatBQhiQsHAFGEHXVRXWNO!zT|?-pj#vBiHdcuy4m3G%|D7b57A6r=ea z2IQCc8rtX-xXu5M->&-vPU<4RYoa+BHYxItqAtRZ@MTc)A`+je=-^$)X*ev(L;Pq( zGi;c<0TUe7(cAZG)OJ_kOY0%LijC(_c$(r{qi`zU-;I-epP+>L1WJi6#W^ylMnh*7Wj195L&fi6)zik9p+fArwpaxcpPkC-;ZZBJM02> z&sHP7$Z%YDD-<|b(#n!C_`O4l#gLHK2;0mr6G)8mo|2@lmBX)D z_!On5?&U1T3aq93E7+N>_PDk5A4W&=FsHFfWT5gAR!;iL(?or|-SHdC&kKEuEno1u z?q`(PR|9JwA48mIDD(v3JhQH(HA1cC8`0Ta8=xbm6*{cb@zVFV{IG9lpxr2z)FoEaogJe^N%pn; zxuega@y>a!W>_+*h-L9_-YKk;@Mez>mEqL$pLmlyjO#e~jQewDEzEo`Vi{W}fOO6@ zrYSX=#Wkr=%n>_M6Z}H@I;wPHviesv~ z`RtmmbcWpe)cFtfF8FU^tq>f+<4u@gK?h*8-={-I_lZKkESuDFX zo7$Jv;Kh0!926AKeyv^0o=nq&nT=_9D^2iT3U}2J&wufHy_3lDhcTHI9)crUF!Y4cmRjA%W~f+NZB->c0i=Qf1KKF{a;)3fPPY6bXz z^`(KUR$TF+QqZk8qBCYL%v3_V6)Oe=R`csSWO6e5(=(vX8^maFQs###r z%}&CJ>FHFn<^s3$f)BKOUIBSW1Hg398hUWpj(x8GBYyhP6`EBz@{(FX6%B#noTbt@ z(ZilCe02||%vuE|>mT8uawm2`X*aC7s6-*x5Tm1PIKAs-5ZzOV>IuLb4RvHQRFa^r zI+`U6U%^+m%)tN$9~ie&iiYUk1@FMKxO_9?vu_=MpPd6(+k*=Je5f5K)l&$A?rNat zknyCMs6%-%+3+Neqa+EAp6cin!#T+w{izx5!?{uqx<{0W%m^bMu0-{R#xdGG<^ zSpLz+aG1X$fCpX! z=<;tRafiJgYFxLXB+XxZ)+8TzT6%$Byu1}=h6Llz6VoYBGg$Dq%dy`wjiSfFWmwkt zioYCJ&Ii{`U|YXl<)hqRpl|n5+|zap_a8jMpBNoa9?}MwcS8ehjvrwDrQe|p)V93=1cz6B{*R!sWY|~@d%4LbbKKQb^T{`%7%r1Q1SA#c8 z?&4dolazDN2}aUQ_-|zjK6&*Jp1D^eH&GMEPP4|)9~be}w*6dKMJT((2GZtrXAjrw?S<>cY-cjgWiUlxJCtlZ z$ny(KsdLgTtXxhBkjo#i~II@ytQmd&QTbq8S6wi=w;5KVY13=~Cua6oPZ z6uyv$Va^v&ZRG@hCkNG-BHyPDfAvw`N9{DF@9U(iM1t4o-j*VF_Q{5)RU0Wo8t=q}uk%SbUc81LKC>;>>fiFsWb;-YPSLO_$z~$`wy; zw5cYIQ7NNNM`OC=K9p%DT2e_$KCNn$W%qo3VbugP)~S3BtUtujX_aUEw-syY;(|Tc zvLR9EdTt@xyQlHq`ylep` zdig~qJUeW86j@ylpZsU1qrg9ZvonyLRalQEV~g?5X2R1x@6l5|o6Q*Q%mPfF zW9eB(HuU}k7&>?u^KiP0PFZJ!?o%8T_8+9Rde`_FbBl3@g#tTeX@Gq)2KK}HKl5Ys z$1oq=1vJHP9*G_6Y5O67JETW{mxkh^)2nI5vCn*2%`ZImGf@aKT@+pInnPBjQgG{+ zR9^OeFW)RHD=?gr*#7?ARPVQ)9?km0IRvQV)ole#(kuwC4caOAQNME$%Y!j>_CE-y zosWOjXG2Jl41JkuPU<@QV9m1-P%|IMj;-Cxyq28iweHU&^XVF_ygrQr9}T3us1nw+ zC001stOXOd;Vh^B0Gs%A9{KJ(g(r>tX#Ij*kK*8 zN>^}{R0wu23+Bz<%Ce36CYYh5W`A7hSk&d4lBDxgIzD174R)|&u*zZD*QQ%A5 zjge(%)~jRQ{kgn;#6B2O7D=O@31^kILHKB-!1Yy}jUDp;>`wnmr@(qQ+MaV87q0On zogq4OvQi8Svuj}F)I4x*xJ)iyAK}KH*?il(3eM8FmGkphjfc+(ds^0sg93Z`ubU(3 zO3WLu6L_V2$0Rci-6)ouuMcNmCqs0+I?R|d9G@Od5=*Zc0XIhLF{$-o5PTv6A2=_g zq*uk4~XRGpqlx?;CQJNNJTIa*lv z1k`XjZgnwXSK}g~_N)Spk+{e=W=pYic?ZZ_avJ=YtOPBcu{7oHe0cw6D9KhNVE>UL zT&&R)dRM8+Hy#?thg{Odra|+`Iy;7)jNQ+gCBEQDVP5hj<2-kJ^A!C3BNgtS)}nQT zM`3&GMmnUQ4S5L?qI*u)*yg&Q&~R!CPFX0+P%uq~U<97D_!mo86H;E?QLe z305on@s(YJsYwpSe|PlTjeP4&#?8xEPS9eYd6oR3T@{#S)Py!xYw4wg2Rr>lm7U_^ z*@`EV@Z-D(T<2&nuD@G`UCZ6i*G^Hv^K(+DS75BvZ5~V-J{)(*zOcs4&7Gpa z*5Ss2A~L!YN%i{j5Po|d#cFAhSA7G2`NUxy;`fgiEq=|d9xE`Ac5<-f#{xVO-NFAW z-zu^URHIeSqv(FGEzRE&Nf9z%VREcCwXBXqzn>?@ShNoBvyZlQj=K(PDXgp&3;LWER~DaD)vC5cm9%i9qHfB~SWKX@kC}u_>a~HU}atR`8>F=eCYzLCC$v~@sERYU9 z20OGh(L!}HZoz82_vjq#Z4_8hLbhVB)@{CY$ssU*6w7a(i_B@_Q8st@M0#Wpf&cX9 zGoR@>HaK7j|q zC; zTi#(u7PDC72AX5ENo#=~?D=&Jep@%QsJdV(YF$KilELieW;;IdMl1EF%5m=-2aws1 z52CLd(lMj<3f?@H$ObLGgl1azgfssNXdF2L_}_BmJ$e*H8tIZl;zfAUeS=kBlBVN) z85;lE4UcA)u%kQM!D&JnWUa8nMQv`>IoSsvh^ukyS7Wwlrwbht^dH}1<=B#)?o3(j zAQTDzBk4ogu-lF21R{x$QK(?%J7QSeP#d=IAfuM<`!GBrAGBQq@VWjiP?13Hl0^r% z(lihsHr&GZt13lWnG1z^>rb$KdmLr5pJDrTX&Q5@N<30qjrC`rw)JYI7_!P@kpd?q_;Zb{iwz2K3%0t=ra@avBc#nOr> zra5`Bcx3w-PNiB!+`3>Z-cfIakQch*_Cx-#ZQN0u;cm`sKGwkUV@7;`x(6FP_%Ao# z^fCC{RG^x*jj-v<87NnJigJSs;C{#q`s4{P%qEd-k4PbZpWmR;bsxG;KjVsX5=HXM zZA9(ud1y3yD%<#XGJ5WM0Ud6iaN;c`a;QAOt6Xt|RkAg>VZ0l6;ae_Br77ck{aIY? zqABpcZK!ZZvq1Im+Yntkixoe~f@4vxqHARzz(sI_%9@$5JH;UklWf`d9i!OzQ4_iT zsq3Nfog$BmL%9Wx=5$wY4Q%x=WL*~u`H1D!{Qi3Z+z9V%Or3ET0{b-Kd(w1Vc*GLT z&u_v6YX^#Va1|9lP-7O3Q`q=9!u}$t9Q_;&*s&XbaN5GVm^)%9DNbwv;b#CU2|~B} zL^N(I4#HJm&vCyBCeX9#K5+MW29`H>!|AQJ@nG*C)E|=rhd0;S>5Ph-aE6O5Dg@%f-zjM~h9pL-@W>J<;QGT{2174ij%{u#x<3N<3IC(hAaq3!mI6 z$*PUp@N+f$ccm33P&;!~Baq|qvFF}In; zc4olu&JR%K7)@?jJJ?qhgkOOYIP6-nIPCKd8t*p?<34PnG!J=}DIUS7v*cN`RD!`%y~utYpxzcMGtde|LK8{aAy#T4Th5Au~I6SRVz}JjbJ)+tB{Ja*b6rw zoMRpUYZB#Xisa{-6^As~mff+eex(e`T{*?Ff6bwVyHcR*=uC7NFoJdlen$CxQ@lL* z3U9+(vjgtSL0$NMZ#^YuFhrC(~n_Px<5JRzd;|l zJou%xpZ{>;CjJ)KMjf*P*m`|gwj#xb`gxC;~&-|WM==hl!?7}K7q~t z@~E#gn8}YbrV*42nk&z6KO#m`j#CNUKAg&0%*V4D{d`>fd>DMRo{C+!&!XkzRQh0) zhQY6^@ojhoW8CP+O9zt4I7_ZE-Pm*|9qThcfS>;%%9EGH+?jgxIP5m8 zJLg0TAoeav=riZP28k*U9B#dt6yIusd$}vHu(-^@~fW+-RN(8OS}!Ir96n-4t}>S`J&0TgaS2$S=Q$Y&TIVIN6B|{~FEn?r~EZ*p*8vila3RL<3P+f2n zp6j2&GSkoEs{IF9;SPaoBk*{FZAN8&2XMT$6l`#9hpiT#)S17S=5G%o%W(O|(aMH%fn*!Mv`` z!UmQ_75(|>mL7(S#E(JxVIj8U4J1#cW1LkwV*X}`d=GySs9R3ie$@~&a zj449hy@Tk)nE~+P)?~KkR~(CTcdS((_!hGgwy=oDrEv6GA9P)O#5vwR3Z=8hGx<5u z{58g4@&;K9`BqI8ms7#%)mY(otHT<9q@%3FJ?y;l9G9eb@V=TIFv>mNwngs~U+FA! zK3sV*8?{EBt@wmuiRFUKE7y3I??!cY$03e7%xvhr&wdy%;j-BFSU<8uS8&&7ITCP^_~F(szHgl-m6*v27By#cI$qD3l`y5{s>PCwfK7+y=K~&S1Nt+k@lW6q@wlVTFKKu8M ze{6h(cK^}E0}_2`;r|zlR&M5WH%5{1@l&EF+xFow%Sq_FsR->fvoS0n7qiSZ33ELW zlYbKl<8Aiw|IR$MTNMPPZy67F9c7ues}f5zF2c~UZD>0?jg4YbCK^i2s>+?(fA*ku z`2uvUh@!aV9D5o1SA64-C9RFmz{ax;d`aIJI;CmL{1!Wq@AHxLeRB`i`bp3N*JQAb ziXqt}mNe>i6(%TEL$l*Jisf|J$!pVb!i#23FYXW=N`1@CSB%2#!k%MN)?j)v+Y9BA zZ&H(s9ZB`Z(^6-3X2i`Uv3o2fyI5~u!LM1iwM!5o1nmqNujVW|uGdJDPH zxI}b!dr}XN&xZ1>e{(dh`W0|S*!F?ayYL-)lYUo>wlqaap*uWa6`TzVios3 z`UIIyNMjc>;zT!Np4aNEtHL_z2zaHFFMd<(2iC4HS?ldE&VSA`uC`VldRG^qwVf9~ z@KOM}PK^^y{8Ej&>kMga=xaOy8T99hE5F^v7oV%mV)yR7LsR8j%stkMwV0&QgEl3| zJaPb{%vIs)eJgVBx&$L{D~n9+lle)7Ygq2mMO@^$N9b}&@Gh6d)6c!;wB|-JDqpyd z0jBeqVQD9Z3cUgMF^s}~YQkg39dszHnWb)1V6Lw};kf)~n7&V*{ajpt8t>QA!nf;S z^=841J-W;8$g_T~^jZlWs2f1v7gpfmnt@c-F@fEEG?GdG8NoJo>C>!q397O7ps$`& znbyfvk{$nrGwB~jUg3{n`Q0!!I_L@vkxD?{XWOYmB8k2v_ki`RmE7~a;V5OTL|5vJ zso-}doci{OyCL-Qn2{#fo{Yi?#ZURF91qG_89>f^KJyiOWd#QBFgkV4gVqZ3tLQzO z>4v^FTjSCXQ3{H5afJbCAKS`3>bIx7ENAjAXydCVB;k}pyP&{#h;ZJS%2q6m$iGV=hj=Y^%;6b?2#lc(s>j*F(?MkZCV@uJP-O?_+tAG8alDUVB)Io~#X-7C z?96r_R+=*%-j9l62KqJPwM%&af`XT1;=E!PTsA{CZ0(we3{yu@in%2WUEE z3jec`wA*6f*n2nTQEA$LCauRNP-@*M09?8OQzT}btPF88IyfEh@v#LeX# z$;AA{l>+PVV)R~!6kL0w&9sDbeiXiP)CTv7dvTtSe^S0WjcWH_A3>IL4eZpN4Zoggbx4 zYc)EjQw%9m+Vrn_Htx?`j2>H7^0)R3=VGUyprPyRSooKfbbHbOdV7OM!1*X|Zb&)% z+v!N!K7Pf=EpYmjG}XElb9x(8nZ+*)!C@!~;Rk%5hnbOASKF zRLFbpxipaFDEqSn|Fbx0g(_`1Bt@@&?_{C6qbTU0vxG2D1_z@HQHV3qq6W;bLi8IKL%leoQTwO#N8e7ue8OoHgzy_2~5fHH}Vw1qi< zA=qtSiE>KEsXSo`x2SU^?VG!Unc`3UpchQ4O5fNG)c}xs`VyPXNj%Kvt>IxUY^DE$h%>VjtJFPjbMX! zt|m|4f!tH+DHQ5G%T79S7By%%(S;6wvg*FT?-bk|b?#~W#`lKw_E0YFX{o~i^Uai! zH-p_acm)U2ZZgd$LqzE-!{L7vorfb=?-$3-D3MiGimdDg#pj-k{V{SV`|YhJ$C63r?%>!d<7va}$SM#jb+UTxhT?wJrJy z<6k_7{NRPS_RUMq?(lBP9C#5M3SYo|nIdjT=O&chK8uE|w!u%koN!0NLGI@{OQ!gn z!}lN5F>UP{nxAdV25@Nd852644+?s@mH;2%#<9QGc=a;R%d|yyLoJiTn>Ga25R!_!J=$67(f0P(4;}^ z%}FOA!5=|)!|vfzS9J<#lcKV|ZxfdJNw5I7dRUX9NVM>?*f!Y+dPgtCjYgX>!0j9E z@?S0RQ+(*4PBf+5kOtqQO59G7Ig^Oo%ecJPd|mWj4P;s`e0K!9n^?IA()>N zql%Mu{ea+dA9Qhyhj7^_S~uXExLe`|wk$}Zh(dQvnfDXihgPA5O%l4uL~!f)PP};G zJS2{t!uGD320I>SvnS;<*|BHk?6w_ZmFy&L<+tH9wP+gq9va8Idf(yvV=GZrU>T&2 z*~b?eC$X0o0$I7>w)7PLhpzDx$vxYd`CAG7?hmJVn`mJUm#7Hark$gpC|8jDltF># zRxtP9Tj68*d+xdP9_ArEfp!hf;x^?@BFV=B`O9oND;co>pJ%0zZG)-k48NClYX#zw z^d}f2QN=A+sG#^=a@28x;hVGBlxVmVXJ<5{cBLc<*VX`b{C&{-zSE;(qi+;vH)tSfA8)SvMNi5uYJ&wjGc;J5*QgOzlPEIbZm}xH0 zVKP0pAYSkt&29~)^FkLqImce$$rZy+uibovYJt6O^#~fX%8mLvWN3KUDyFl^nsxg) z!4?(anUr@Sd5d>sYQ3M`Ts4)n8l=hI@e04kOMyMe8bHpH>Zp2T7O8t5V$ZDnuqI+Z z+MXX&+ka>pTsfP_mMne*Z{qrKi$*(yPwqiF;6Uo5N0F}Z+?j`u1|@eL+MOiicd9k{ zg@(j!9~uXNsTL%cuSuVka#>V+4qY#d*CeFygjaQt*NZwT`q$Gun~#yN%h;P*8JZloQ;4I3AL(a}gSvQlNwB5OGr zO$n-z)@Q4FkK>L1)Yt-HwsEJYpO*!ufe-1~p4Whw#)p9h=GQY=9=_uvyWyNB*^>Z|BjfRvH zKah)6pg-w^2Q#|(F;D-&_Lc-tkiLWaYmeY;-(hI|dln8EDBOYm?jVJBX;yIBPBiU6 z8?Rea4M9gvbHd)4oh(kngQ3AJWW{x)BmMkfuLLev6PRxJK6nt`0G*izIBk#wD!&-Z zGH+Gj#2-cc%0-L7R+y*Vbxr_3=}30|k|y)!hS9F)b5L8y2Hz#8@+#j~(5Dn1R9ChF zO>PjhduQ+q6WyRSPmM)+CW^*IcyMjIYPl|L6-x7U$FqtHk(<7m4=@Wu`2%vi_qg9! zRclJO^%CuO9bZoWmFElR3@;P#k_4s*l|PBh``A-2WA_mJY&7 z^~?B^{S<#UjKs_iRWh@V!%zKJ`5l(``Q+eev3gJ?H#K}825Qg82aRUj@YZ4WGinQ1 zc;a%_JHe1tL#N{AsD89DlVUIC4&<%!#4zW>aMGD_h?)7_!1x~)VH4ilW+@6~I0 z{_;iK_&X9iv`_H!_Liek#BhGo22HYWn?#wCf#CLVCl<>a!>a|(^dT^tJKOsMWvq;` z$XxIiHl$#Bzr2vk{ml;RELCo@7xbL(*Nvw@wbET%R zjkC`3ht2dLB<2`64)29~1GCuXHWBEKDiUVMtO^++lPh)k#F2EZJZEk@0;~sX({_&p)b%QV^_XjX z&UquMPuz|7H{XQ3#=kIPM;24?Frf>T4>{F!7I-c4IPYWmjr*+s2#h=y;s&YlG&Slr zq)lz%r;jdWmmS<#ZkUicE|Fjt)831>Prb&knHhz0bKZkNgf2a?%E!|yHsdJsuMjcf z4jOX-IP1wcF1J#dE{M;fiqL6W)jNgdgr62%bKRVd`$FzSTNKm@J>b`$F5>0TpRlFg z9|G#$p~Jz!BsXg$`B%@S&4JVSld%O{m)&{D=vsvn{7%8;ly1TMtVA~a2rBw@9&SHP z6`yz|2f)b(20dqE`fB(*YPWE%cY^4ac>J9#O^&NmL`Tw`h2Ewf9x@Spe-BgH zg8`|)d5#xc40h~I-*=JSY=qwSC*YLP24PF$Y1UnR$o})%{zCUG-ZbwT`0Xggd&WA6}w;e1FzJ%KNgO8XT9?{PvSDdD&Em`IUhky^$~~b`{If z8x4_CL)nwO^SoU{23t7u5=>DWM&3hX;7!9p&gq6Ldzd7gapULnSQ*DDxE$jTr?q4J zTN!r0VwI@f^e)`FZABI4-|(q)CSO*VgArjf`2TW5umPsfiYdCNRT)lot;Vp;JDeE= zzJw@MHS)0iBCtIwgg%=j6~AwSrwWWIeoPKg@xUM@BZRu zPPSEwUQAL2pVV|T>CvEh`oh`EIhei}M?#wA7q0iGf~fq)2r6)Rg5iR<{^a$=?AIkv z-t(1-=!3!-S|@ZUa@vCM?Fw0%_InFwc7GZS7rO5|bn5s#Dj_x438n%Mrr)s@d>@#w z;NHm)nAXe~FT(0(F*soa?KW}ZN;?|x#Cv;O zqpnV;b#I@^GChyNncvO$ zY20?PN69B}zvRRm1xAJK`*rwj%tfI`_=(dTR)G(%9R}6p;ke+eKW<6g0@Fa7B96~t zOYOp0QJE<^u5CiciZWC&mV>-$&*ANeV*F3P2#h3uVzas#>~A|N`BlGhV|F8d zbdDLWoG8b_9Fs_6jVyZ%@DTVzSjX36d0DK(Mhzt7Op@m&OWLUBOm)SshC!7bEz}mtviD}-Zil?Mz=9=)qO5b z-8;9euQdzT&>M7C6Pipw@WO&`hA;zlV^|Y@y$DU^!I0 z$QR~hA+$47%r)od!_R?+Oe>;P>?otfe!gtO-6^y1W9E3K5o`lLg7s+T5KCCMPmk3t zJdQF~^(gwra&A~xD!f?#7T*}{fym4TObCmCV%KCEqilvxR%)@@yGi1JB4-F*P{U7c zIDn4rU3gAlXuNNl!*=Rk06C9ke3-y-l@xlpX=@|+DR=6zecXDM7^K7=L`L9;YHPTy zJdbayX@d8|E<#TILbhXi58QCPfZaj!*jt%-Of{eya@P%DRXrMP^`046KGKgRQx+Sa zqQl$PP+vXsSYkn6CVCXX$L8fSsomm%Z@H~Nx?wh=il5*(k) zQkY4O3^U>laao!IrPW!(EqupS3wxMd0iWSeU@Pnh?S$KkPLOIX$%;C~eARbliVydN zke%)DD7Y8{v?RH2Ki$L{pE)vbh{wWoD|pcT6qP5-QNhv#4Ep*IWZx%YlW-=R-DJS` ze$Iq{f2`5FFpGSBMc^v!DDdnn;5+WbCOt4}rUMkT>r{AKWD>Grbe-M-6nVarbIJb5r-tXDUdkAhswfB93(A=N0Wo7z z3V2OcVrO1S(#Pjt@I^`l>#jPdO*F2=gKFoi)4{}_ z{7(5%@O7vdhxUfE_v=sd7NSI4yPz8n+M2?(s{7c|ugy+LbYtJuEfBVAAz7a`VPiED z;HA6=UjMQm+XRNghrdoRLUaNXyVb}=!-mcJV#y>5*0Wi!Zi_z7DP>jSFA&-8%x_x% zOb8&~#_J6yIY-||d~Sj?rM}((1%I4`?_?X!($uDa{#)I2h8CmY(1vsTdt)&-w;~0fW^9Ie=twvId2-txPGroY9zMI) z^UG$hWa@J2tmD&g>b+J3^8beOdDj)`Kj9v5VS~N6LU)H~&O-@mvJ%nt4Nt*H*avB@ zJc|!SI^=veogY%V9dw=cbH3{a!?W@>Y<#3Z4x(qGk`Id9uOZ&F|H3S|6*`j@acAI; z;5_WS=?Fc&Z*W4PF|*DXN9EU5K&Mfbe6Ktr)x3vve)~QA{K|zDM;?ZPC=DFd*Mrw* z4`l@|ds*oge|EpK2bWh5t+8|&OPMeKVzbnI7|(0M?Ipk9=erH8x~3YN%2v|oYAxp2 z`VKw}HinfarqcH5r*M6$54U^UYx_ch59noB0H;GnVnjeP_bqBC3sX>GzW3zVs?Pg3 z*K#o{F$xzqU9usu`aCvMK8ed5IR~Z-J+{7L2a`>`>@dtv-79WbH5F2 zv$_ZR?a*ZYF5_5+b~9>xvm)$l6nSOKvDQ2X3YfeXe;nw9Od-pCwf7(QW2-uab!DLY zhR0B)cZl_b9VesREguI!PI>?kT>Y9Ft%MYB4;-)=}J6;dn*QHoxSS?rL za}3Vhbq23Hmb7nR4Eqo>mKyS^NpV0TPTwKH2L?zmynC2#%{_%bFXuwb%5j)>Hjewy z6vq{vKaI;)#Igly^C(v7Dpq)QV|e~S5LfP{W)Deb92pGF*#`t3&L|M)uEZv=gr?`2 z>`f`hM9Tm1mCd(AyJKwG@s(EWV1x@CPFJLZCkL@2_a<1q^%K5SJ3txNH`22Cj_gd} zDtuKnn=V9-WXcZ~K>IXz+LCaU?b|<{UDlYxim%+q8TP}W)FmAc#@^$A@Zu3{lODo`IY@6L?505zV*4zNs}Ur&lWtTJC8zV zj?yHhpC{06$a+$Hd>LZ|Z+Drp1-rj!EUS>YL?hlk;I6h0WK$xO*=iXXnwpeAo1S)Y zYW1hUZ^Cs_>iLW2l9#!@1(EFG=QMWIdl}y%eHjOCabnJ%OPNlE6htRV!Fs(Sw(6Il zOP}sSbt^g`YxGv~E0Lhpv8Pcgr;8=@&!RW0&f&j)GiGo=lTMtwz{#Iogu&92s9DHR zzA9crx1|L>MWO;VJDfoG`8W5p<6^O8Y#Vw8%w-lSo9WIo z3GU8S3l?j?5>mewA(Jp;zn^NcmkMUA^3Qjuw^XL|&vMjWup2Hd{v%|TIFdhS0L4Dh zOgif$xX-eHB}0bM`TyLZzHN3qErx_yI_!;Xf_Uwi`E1MSRC-oh z%vGvN(%TCKkRBvrGXrn)3kE5|#AV9tMyMH0xmFFo=j+4g!!}esZ86(WFq&;NEyA6F z3~rol;Y#j1LEz!3%r!|DH1ge1TsR*bLY??w8nW!0{XBNont_zD6dwHw`*EncUbI3q4n>&vW`)a~|k7&SCLkRlQR*3dKI7v^^a-qW_l?C((J-@g@ z&POeRJxEL;wdRqm_0?E3D)HdfsoDuVrZCnw$ADcLl24}>X5!d9gxro6u1zUXY@C`z z(WQ-0_NQ0eWN5|vziNVtZ}Yh8zXs8d$C0Atht@&3ktEZZ_=xv2|G_O6CGv@C(?wsL zhvBy$Ml7Z^5*|2=LbpS^Sm@zME-F^=;5~JwYaxw%gmV*&SuAwjt_%})5A%7;LrFNK z--dP@I)bayB5~OJE-WAY7zYeAghNrsAW3l@UENRx!MklpdUXUnUnl0b_SD0pq=|Gm zW-lak@8)0be2$+Rt&tLjQ}KpId_O0ixBfU#*fFcIL&>v9r}hKCNMk)oj8Fo@^8fgw zI~DQ5fkkZInE-eI+VD@|DcHGYq1uh(7+?PpjD3V$pymorQ7>HVH|z>36v&Z&tS^dZ zq>{G$b*7%p3*6p%z=bOW?x6;a>9FIc=da=VJj7h3Y&A?h+KT65eb8vOz>rvPOfQpL z&?#jWtW4ZQrHMhj{e|iDH@E`Ke_M{1{Cq5jHben+SVDQQn42U{KJk#9xwJ!SObss!D+eFH;! z=P^;<31B@Vm23>h^jN3-|KWhX@~YXXObDZEzZNLX(@oQ0g^QQ`7N z9N_E89=ZFG*9##p?0J{FootT1yujn%dlrI{PGf2Ua~S9N)1Pwh!-sHzqH! zTEa!>B^%I*iHBhJa8Etdul)an;Q}`=*@mdyn3g63(pO&Lfb{b}$U5*)g;+lg|mh6VD5$@X6kChvD zVd~6%6q;9n3Fntk%?>Y0YCOkx>MPRQ`v*bFLZ7)9&qa0jCA6#JJ$||OjeBjYEgIgt zhFvhf2Y(l*bKe!7L7bT%3kjHjb55^>ACoQk#Ph}ckmQT7V?jKHu1=<-_p-4g_kuWB z!3k^9M$=oN)3{A?I{VMlh5pIEhnBK|oYmOpP@z1I4ZP36%R8Cy?1Kl4yyr?c3!dV> z%FlRJ$P$%L98WKU3#sY!bFeK{Vkf6)@ZJF(&^%KgbG9bH>nlT;>Ha-@UvxM3E@Tkg zix+nHqxR6!d{2zLbQpV2L8X*$5>(kZYzVt}os!%=6^9(wXt@O^%W#^ZtWSae@4j(a$e z{>9~he)=A`m-d3QSo;O;U(KPYAF4EVP7H5;qm#SawwrnB$YR^0*>qoQ#Aht*!#*tH zE`&^B<&h_<2cFTwPm-!|^280ip=gB)K^m!#oE>z{a9`54O{dlMejYoX?#uPo)P2dgy6 zh1GixFs;HYxLiDl4#b7?2YxCsV!``X#K`yJ z7J*x({lr>i{Ch9zoIe0#KJ3H4`wrkz$6QGLc9!3-wH>c5_NTY-2+J=pD%yGoldq4% z^>3Gv+=cLoKjTJ&&F;0l+@46$%EoK+zczw1edj=O`!z%Ozmp>n zvaeI*cToFg18Qj#=E!d!u;bhzw94Tzz0nMndM5M5j-gN+-+w;uloR;oPi8X*ZNaP- zCw416nEvPsIb5e+++`DQKkw8e+Vevj*!ETE{JR%*qUTVVlsVh2AIzk`UI1>wdrTeR zPKKA>qs$6_ruuQV_{|;}_Urdm7!jL<+5W{m0$b6ZR4J1?Qn zh~?NO@`Kf(M;X8AI4y`$r5%>h^ek~QNxBSTJ7YBXhaZyJg&}qDzBdo-w|;{OeR8y* z^Bt(YzRG(o^vC>6878h%W?8=!q2Zp;+rE{D(bM$WrjL%A*zWWQvjo>umF#N>wN+r5X@OAo)d{A##t1&RYW}Rocic8`8(F40 zf%_Q|jr;Nnw}jb~XXG}L=MJ-hgHE!Cs~C8=<+G6~BC1|EmTa&5hry>R;Lu!iE=O_+ zTby_WMopD&JED?;JOjczEd<&MR1klxP2eSBVQ*q}Oj0g&h$%aAjzvlR&Pk z4zb+GsqA&oFSL3f&xV`a!XHK@0*la%Eh;$AMN8jc$4kLN%(1b zKi+TD;h#_1NRm=Xq9Zela9R9cTy9*8ZId!t-4b2a{Cp*>W`wj=3GVGsV51$E3%U32 zymaGm){`}tCJ0l>T|X@8TIF~?;&%vWnEezwSc0cLZUF5WaaGhE6ob38CvopQ%-E~6 zd8~av9~#Vi2Di;k@ngXpX1Bfv_TCL<{}R>NyJ z>q&LVTNr)rx>$8p0@KP^%+0>4fxD%biX9RiNu^K+wzW!?pbQddQ3IBE%&^zAvq@$rwTxk!rsN~W?u#uvEni6yws zvVpQ*9-t{x2EopE7PQUImbuhg!t?*;V7##DT{Cw%D@|3VEU_yLjWoxB^MfGs!vt}u zLkGLkt-;1D2!%hr_t1r(!Jbd9q4?T!wDe@YSU<6l-M&%He{b@{i*pCjh?Bzn+D?HP zdw;@4*=*Lea29{FDGGn|Jj3ZGOKC-IhgkmRd?JM6gwrEQeVrbe z2$_S9SQ%#Cm&HOC8`4p)Z8-7Mt%+Oa6|w*;9cnuw!-Ay-(RVAM@0k7$f9E)}YvoIE zX3bgfE#@KbT7bY!8i~h+eeujM(j@*Jl_su@BJ`Gd4 z`*0ZeUw7pW)*Ykuze92U=e6wa1ZVO275iw9%|ndN%3!`@zvGR*IPUrMKDM;WLdcGs z6M3sU(TwhA;-B7kSa{_!{4JIj%iJH#^0!5XtB%TaK> ztrLYO&ZX7mR+L^U{J$s9qxmUW%yhzev`261?mx&f3vziS#U#2uWjUl<3H-z^J0T0~ z0E)}*q50f}{7Ij9TBB;fO}L>2R~5_fRN-%dK{|zGkPxShi^rP2Dnt42#3yWwH$` zP@5ojP&B4L$Ew(+-}eYF4lFoaA8uEYnS%UQXW0wrf& z2d^&S&fD}5TjTa($_H8gm%Klo>=}vUiZXH1yuaLPzrA?j!4NpR;S4*;*KkQAPrw1i z8dUu+0$dV~3bV6Mn6G&O#xFSs@22|G3XgGI{lqfV+iOB!g`Lh_-H|Z1(FDS6&T%Ey zDZFnO;_UKQ{E_2X{QS!@c;Q4Qx}Fox*=JM5Bl`>Cl%f$c@*6{o?M}f($tX6gb|EGo zut)J2DbY=tSlY3r09DU|$9DcyCw6uk9sRyrD$6FU4SE<9uqrGLYs@lV_GE zE^*Emhf}P1IUY0CA#KaapsXOlR(ibS4n9_bp>=UwX7FczN!vfzaQh_a2dhG(b&H+b zF&74kg)n+sCKHGEZ!Pj!P|#&8`bB6QMC+hyqkvO{m#Xm;81=OQ8rJS(owkplM_^f3IZCqO>4svR!htMaPnJb|dCYO!2hy8o zbD8AYJd}U6k2#%CL{;4rm~=M;FJ)`Oi0#qr*h5cdCA%E=+3DJ%a(-iW zwZXFW!C0?{$`SsNCW{Oh9~|KESP?lP4-AayCyrPlGco&d?waWI%i&KPLB;T zv1;jcNbi+pFG6Mcb;`DMxPKeFV!4*w^`-ISdtDs0Y9$^Y|CM{Q$N&_J$I#|kRiLgD z1J195>9NFSdi_!t4(JNcfz3RONsxi0wN((dlkj@)KUDeQKoV1qa<3|`adLh4KQFu>vbE4#lOM;5Nu~ zrfqRAP)X>M9Bxl#dee`Qa@n*?!-pEt_vvM@m$ylL&-D=9eo+h70k3eI!AuJA zt%U-;EWxQGMZNY)^!EFGuAe~mB_|kO4OxuF(kjS|EttG=1Wwh^rYHC6@IkE-%^7kB0&=6U{!%_vHXXyJ zfx0YclN!E%oxn}*(E_DgL8xdsn#rH@Am69{RC7KTEk)(R!nN8Ig>wp0*-|ogD(|_dCSj_*zvc9w8LD5ba!bnzmIvM3fEpf ze$r}o?g)=xtRA6{#ArIXrd`yfq0Y8=YvTw*eRw@oU=zI>%97Vd@`p}OprM{Tr0=m7 zn|xg%3cs&Fo_(v)eu+B$lozAj+1GgguoIk&J|{e*$8b@-9-Fz|jeiWspl;wfaCxhO zheFj^VD)U;TrnAsO|<^JP9e^ToSne}sFjb7;|h zX z`~;G;x#8IjoTs7CgK`|;hJ zLSe6P5RaF?hCL5GY0-*DTmrYA<$cV78<+E8`Gu2Qtn+3ps|X{{ErsYeSlHuMU%^8q z4cxIskNJmVttioR2o7R#aKUOR8=V&ket#TTk1Wq`Pm^VnZj4}KeW!qG%|2G*>q2hR zs$hq|l2Nl@5HmrAAxV zhlrN^RD<9UOZI()z_RVNWww!p{8c$ktQzwfdMb~jf8AxQay~>kGU<@A=NY`$J_~22 zXMpbvTlhJ1IFnRUM&EiX;&X#A-ZC2v-f7Srr#gOW>OAK4z?;(hBx*F`JHX@84ZM0q z;Py7f(&)|wRFo)%jb5klk6|j>dRw4NLnmB)s6&_csSDqlmWhAvgo3`NIz8aeux$Yw z*olB#2u_c{vNn5ej6@%QyI}x@J)KG>&c`4wyv&X&rC_BfkcPLlu&zBLX{VPw9&r83 z57HMrL!X{tZiF`Tn{ka3d=MCZuo3(pp24Q$HtgM^ne5BXZ?M^DHVxN!ZNE_>hL1Zo zkn%T&KY2|8Sj zMlD~G0s$;%V*&q|Nl5B2k(tn1#LC)bYBx<)}MAj(Q zaY*oQ{i_nU7XQFt&kVF3Fn|Uf%V4tJ8F=q%80*3_ykxBfr0oj9kga9N>&{>$ezMg5 zeK@Terc6EOWZCn+)%0kHKW!Pl7>}7N@;~FX*+-hkuC>|H1A`Y>8t#mxUk{*-`*Qrz zl7nJxb$b6ShC3Rx8PrMy$8)ZseYwEKkPK1fCJc|opRZGS|Aa+sgy$FW3V|cCb)gjb zFJ6uQ@AUY8UH4J+)1Tk?!HC9f`oP!3S7B&V0aktN#<}a8MIv%$Rrj92>1$s>v?p@4t6Hx2$Y>a+G`MfCNhG^?HL#h2DB;XcJ5;JkKQ zQ>gwVl3#e0bt=^0yGKFXxZ(y(8|zG|*)hyLDFs(+#8OY|2TpglDLtu>hUA||FzUHA z4O?i8UDYr7U|Dn=pF0{ZO-JI& zC`+*u!}2Yudx`AZ5laHfWKM z2QI3?o}+`I#$M7FC+;p&Ltds5)*iEqQsG9)|qEhmGy_d1WqxsMHjobI)>7g^|(J>K*pGu^wk^THdC1sj@;{krgf8;P(R$r;We~>9(Tyf8RiNnl|NX52ZQQA^7e~ zIKGv3rN632QO7(*a8FyZgcD|DVRwn^KfZ+ht&`!L++N_(UBl^$^Ggtq73O#c+-Uk{ z;q2<6!wx^)Pw^igz@i%?DMYy$V@9uM;|9IL`=5n6q@Cku3;*RSg{&Xr|rkTrVrs|hb)^Hc7V$2PtnEO{wUNf$Vhbr zMJ%-Brv-L`^cLaotLKj6T;wLz+LS_Ywk&_EUBoGDkYx+B8u^wBgUNWf15|F!z$p_d z_!p+na7$D)JL9|q(h3y0^D6 zMLZX#%t*wbXj8a!*OkrBF=aBo2gJp4`|zBmK3M160-vKxsrB3;Hpp=ZD}A2M_K3IQ zpuGb3>aYiQcfA5zlDh}$3{T(_6*-*R`IGZjOvN_iU%Y1a5%HF-7r7Y{54ow9ZLs>u z1TI?mz2qic0IS%+s5&-)%5Nv|A2ruN&;4I~@sA6_?*5I)$LSZ$d;VN}_{%<+AFM&` z=@QsFa~7!kJmJd^t^^t5et}g{g7zKrh0MDao$L#Dnpl4X)e3g87mls`R|#|aK6W}Ko>gPZ@7?6z zznsWg4PBgr|iHa<~;kp%n_@7I9IK9Z}=#m+OPrnn^x;fMP zTbXR+;yU~{Gn`3%dkmB2E5WU#6dHV(qwZgoU>$QBo2y=n+uZ8l-N!}LoM%av+70CO z%Ytoh$>kkgfn|Puge@NWc*|Yr5RACPf8E+C`ZAy!#`G+qib^B4$b4eWe)(j4Qclph zVw`=r%_bJ&Fpu0-N1(aEWVYwSSqMH?$mOlGq!`m3Sgmw~j*to4p&-RRE#J>PG{(_C zl%lYA={W3@GMYvwb59;xv+pe-OhsJE(#->DX7oII+^j+|-Fd`kUFA((h0Li=9xL+^ z&In6xV!uTLm_-g2e!f-IDw@Dtzcx|dLOpD{(g@RY`*8@j23u&>|M$G2dG&W;koq;2 z9n_7G0aUcYoW@wH39gS~vUUK0Bj8Vx{VJ?}nDG5-I!F_iUExxaW$BYt3p_O+g>rTm z$g~p0SLDm#nwBQak(diJHh7RiDB_$~GgxC&B0HyR#y-qU7lm)%is#}+u&nzL7&6b9 zCT^>ua;1Ij)!Qn#Za0Z8Pf&nUbEeVX>uIn`ZZd@%|Ao^I3uxw2A6(M=7Y|4sLD#1X z$*eJnzw)vcXLXs-^@o1E?IL+{x$i}a4QJ8#TP5G;pN~C}7W}-=s-)Q(3raf4oT`>3 zr{ZYEifigXZ=P`18Tgo6w>6p!q^r@)yc{&YJq7!jhNSiPD~2XG(zH2KY2mdRa1DBb z%d|J5?NC>kGTH({M!&=<1ILr1<`l~H=|M&3cvN+;MgPG8;8txZ>|O@2#b@m4d;3js zY|tA_RFY$V$4ar5Y00oF!3kD&rr^}3h3r{o78q7&vZTu+amctWR3PNjFUl{V52X|6 z^@+dOcB%^PZU(YRHrf2ggbYzyR1~{}DOj?vksm)l7H8g-q64PmXi(({n%Sws{tKQD zUyTNk!-{>__tSyfkfIK9`)7ey_69g0JDCjGN@3J3#k)xoU|hAmne(a)Y&Vxjnj>_}Nh49~OS$-9}y!{7nL*<3@ns zXF3Nvm*~-x=t5}Bk)n(9(9ZaUIEnJ_;JiO^m^nL_Hk^xO%f?Gmhy7d_Qndmj4L1h$J)XrVA9wi)T{hv z_pH1NbBiOUf?-bV%(`k z!hQN9zwgFK*7SZZDtA5Nnglnk-?s~*Wn$iV^ztPLYIdi0Pu-aNhR;|Zs7GA-UGDEY zMefe~Hk`Xdi)`acU|)403(U%;2iw2F-8sWBcd8LNI?K?1nl9vJ=9j0IKV{@LSY%UUk+t z+clHmv`KE*_Q-h859s z=)DdI*|YVu#WM$A%eO<)qe-kLrbMHf# z^2Lna_{OpIQhUg3&r67F7ILlT;bdn~f;F8*pno%v8Vq}Idv6&0x>hLkDZJS8hLs@e z>JD1QyTDgnIDgYj@XgQBm>Bwq$p^Twpn*c(K1_zb(|s7~0_c~M!A4z)r}Qxb3+&xk zzChjt-cGaU=6#-xhu2=uBGw=m%td+s(>N#fXlTIma-PLPPiGkj`2+GK_rn(#t*7)ZN zAJ!-E#m0OUT+sWu#ts#zuetcUYiNzq{oJo9jAX0#xzv(3#NKyVE)S}cJtaSnl))Z z)vDfS=C+z>ZWP6bq$=@Q`lhV$r5nG#Pm}IQO=ln5BKXG@=W%w?0XAXI9z1e%BS}iM z@B!h8tZBkoUTVx9=iK&sjyZ2(E1(B*8eE+?hm-O@-t+zL6#l0OyiB- zoWOzy8YmaOht5YXruW)<%)fmbxqQDwV;+718;$k6rol&i5vhdqMZ}+3DMzjU8PVP; zGHkZYOK^-m$#->j;+jY=TKX`J_8Uy+_Rn`BSQ~(+&)T1%n;KhvRe{vmZM)YM=AC{L} z)1cYk09UT3XVb=j_3$@PGrxczudxX(tT~3)JiH-T`zP=Hau49s2Ht$Z0VoI!MfGtB zIPS(~W-0uRHjgjlyUxh5UBh%(mts4-_$W>CZ+7yux*N8?kRtVqBjB^{c^rQD0<4)= zWcNk)7Z%v=66#lDS@G^pK6c!4dJShmQ?)GNUS>;ds2S6mfc z&;HIxXN4gjx%GwbK(TNSz1bbZ-XC@#?=?|E=c0xwot{UDj|7fE<|pW15yub2JVz@ za%>QDJLpZhi}hK#lo{2z#xex-;5MC`xJD5uWn_|G$N|9Bh22tfEIi3w$!CCh!Lqby>YJN$@#$HpluIw;A`J2UF z9MYh#+m^9>4&mfjDXKmq&5nEBgR@_Sd|H1jHzIBhWaVVh_GZC%rKd)7r2BD|!*~qW zm!hc;Q^Eeh7QEB3h?Tt10`W)U#CGJeiw%EpSHNhNP^^G;_r)klO9cd>0nKmmxoai?-l^Ipv(( z0sWSO6Vgqb2A<8NW%`M{ZTLcV@n1Hn_8f-9lf@+dY_HA!?fdxHQ?k?}^mZ-@9LCsg z7gAJhybDRQm-qC;a8V>Wh)r-V+!-dko3v zec>-XipL5`M;Lu@4BMq-2G14dvqw`FQmlqPMVSentWa07GI7Dg>zgQ5c;gIydYhAN z&7_u}!x^;?C)={Uq;Yf&eX{<>uQ27{ZYmYGVXxO6C6}-i8a?F_iU#lG+{z!p)n+ra?q82TJr|OF+Bj&u za~fvPbYxN?vaH4A5EJEgqjQT2tBDon3L4*GV*7mdq*aG4T-LyS53->P%KdOnxPz<- z9n6l1M(}q=x1d%=BA4~%95_ur0Es7tFq_X7TvzMryKY&d7*bZ-hhTj;?pY>)$#DR>LO=OlP|Ekmr8+kpqPF!TRg8SZ- zM>Zu5n6dRZyc=Z=iv^$G=k$Dd;GO}e^wv=YSFxsrq?cmoF?7AL(rEX%zH)|gqt&lA<)x@H9(T6qm;%l(5bCBD4uiez{{D;uP0t=OdI241FZ z7TvpB0|BE;@Nu{iS^gZ!4&G6>|1l*Sw(>|De;a?fbSo7aA#Udje`e8Cx7@>oIOmNfHP zfrIJnbw(X>G0bQ30XFq^Bz-cvh6;fq(YWD5YtB{H(0(aNur6z6pQc8T!_A-2yRRC% zFqe=tM&SUB5t5|?=!GtamO%=z47QSTo!HmiFL%GkZ26EQpK zig32ia?GUXPI+uYOcO0Rl*A@#ttQjMN;OT7?!wU-Qf$O&1Lol9$C_KuQ9<1Y(I%%1 z?!&xdxEb`Dg4)lqn5_??xIvK&HHVN{cOQGwsRQz}V}!ZjIQz5G;I1ga`)KCk#S6834_a~=?#EGOud4m{zA7?`bf|fCbQ9~SOeLrC z7gW1rHGTA5!8sgDW0K7)$xzN7ytX(~Ymu=3+@!%a?cRg?-)<)xZ6VL-coa4Wd%JsO z%`m6_D=&I*3mg81!fo$)?icDnb*RrIdW~ zC9M1-INc^n2&yBel54KHH zX#Yz&T3cEJ^Y%=oeUd6{^v%0=yRKC8{zhpmOGcIbU2+y9UKUqh@sAXkv1d55jZblj z;0yoYP)9aRvvJRV25g#Al-=~3KSX;4j>*f?IP8;1qGt!J>BbHP_;vU(w@sKkSlxJp z;oUnxh@s>^5D4&$e5?T2RcX6?kE@ABkNwV9vewAVyJ{8WX02{-()%K<81B%GAsJrj8`+ zHc(>+RDoWPTteifZ#Y&r1t2HQ@uA zU6x{tc1*=DP{8gTbLPf7Ph@ss!&qkV59kn_Kt9!9;Y(}{#@)UK#WQ+v+c-6PebfU@ zAE;2$zESkM)*qhzTZm(lzi@wo#`BLyRza7>AWF9eutS7jYI~!*~#zp^- z6$(BA3w`YOQ-LSv)R-y^X5lfq)M%Oy>l5_tlKS;2tvnKNSvUMlGGw$t0f}zYVbgR8mVZRVs}0}8zxOBv`^~3$=kzlITd^ARhHt^$wME!@{V>WDErsB5 z!dpx4B7XgnkD2fO@t;Etm`89qcCY+oH|@$SnBbv9M;4jFaaUhE!;E22m_C}Fo78}- z798XRpgC3DJOh8P=i?IBZRl`DoIKZ>;K6`4jQ3c=xeKiAhdIkY{CyBEbehK64EI6q z^DI!gVncJzWMXr@8f%)q3)Nr6Fc9uoPs{e=m+|-bnmlR3*%!G3YokTgnK~5TV$SqU z%RuAr2$np#7`Lmufu>3!SDvMB7wkO=$EHl6n4OC3zw#9N{V3D6Y3>uavO5?)6gP2E z@=9Fixhg1&GG@`uL+GgL3aS{H!w)x=WD7L?n9sllW-WZb6-tK8*Z(E=((nM<4hY}d zrr(^Su>0>ZT>-VvHc;uV2Y6uJJ}mzz!#Zc*0!If2RE=MY<_`4wqKa?a1`hIcNl06az)iw z;~~jbj9Eu6g|!2{Sg*Ssv+u^@N>`yfs5%wC-xN`N=uUi+XDB!vXHtGq4MZu$a=usk z;J8nV?MuJEcEPS_4VN`qUTkc9mUEnz8C z!=}x}m=OFALd0jl&`T{W?%pd@Y04mf_KsIM8OO{{)WgehGuSw-LuAQ!;@eS!xkKmQ z@#2BnEJ?bQRAe{6*k^hCn{;Cu^k@w#$t9DH@_L?aPUVh0D?n5$rfJ!Rc;7r4m&&WK zwuoHXp*sym$u6bmmE|%aXu}&>8tIsgSK^&1?f8A%D5jhLj^Ung0iI>T@i>o43`;H2o-ZYq8}jXB>m`lb3KO zkIO<+=yV8Nqjk~!rUJcfo6fH-cPBTcQ>gehmi=_eU`~5Gpv$2Y8WY+v6@{0II87r>XQH@wB+!Ms|KG!x(O5i?fg(z@9Xcu-Se zr>9II{JD>`{8o~8rx$i^*2mMupTJ?qDJ%~)!Ar6?uueyZ|Ed)PO3E|n_Nz$tW_>Cq zd7806S1nNg?-lRTehT(6mjp@g6u{$$1Do(Uk==N+TX2!PP-NgGusJkQ*d?lR;lICe zI#1o~!hBMM9IrMSre#8Hz#YCO*oOs{EyYu3m(o)U!H0Iy3XT|x(FM6+zB=?EpFq>u zx4p@j{LTxe9$QB-8ZqQ%IFxva3;d}Sjd*hY8Z6me2G7n67kcmqu+YGWP0!eaGq-r) zf>R32G0v6ji^ZweD+dp`i*ruZ3Y`BRR|t0!cqE6u^Q!ZP(ek&kym_EIY;3=Y7mr;7 zrQGRkZR}%s_}_IrIOr>s1P(#}O>V5g*B$$P) zmiv{F)HxZN$UbpIu}z-lUA7s2*T$tU}(h0ttm%RIJEV9{?&S-9OWVJ@SL4pOBo z@v$t)R)xbW^=(jQ*TU~t7{%7*TG5=dBk5+lFS~!Ffg8G4fzrgrAlGM&`d#TPN355h zV{6L~c#h>Xrd8tw%N6X~Yb%OXEuk@m``L%m9N01>6M{>4c)qcidp?kdn=TZy{paK< zGWP*$pEsxC`f4u1Bn*c2yOKFmpuZvQn03;QB&?3wMMY70oj#X~HUk(J zpGP;BUBhGhUgNjq)4cJ72rl^Elvs?wlNJmEeU9+`nTy%mAV)SqdKSqTzQdKL&*R>(@ zu@0H=bmv>p%RPWr;``var34vd%s}a$voJjpd$U{c4pjzFc=KGm{?(PmewSwf*GJ>m7Ym?@YY=ji_rYmb2luKkig#-SQN807 z7_Mi-T3p{@nP)nTo=}NHw=$+NXdG$3d&jw^Ugh$}{DVKs6Y<2A6rA}yAGfz(=itZS z>efDKd~-CF_Wp1q_sk5MbYUX@a^H9+AM_h{s?%(EpoBPjm+{AGxWlbk;aru>TKQjy!~J z5Bfk`cQ3HVJ5WQi05>Hb;@SQ)*z)`!cm3`Zrfl~X<1?ixCEXj#1mX0XVh7v$KLa}FsBo9;R zfBR57X%Hpd{sn;vJ6J};2X0luW}4~Jh)Z&A!+O=x@S)R@?;9e?#z*hKAx-b_-Hk60 z=~azoYA4a)!Y=0XdnSz;m5bNc<-=L!!!+#v42s>HgI?YZtZ(rE6eMSH87^<^HjW%g za}vX-=c@zH4 zgSCx3K<1bH`2t}Eo?4njwNn#?9rX?7P&}6VvFixU*dt&pEX53Sr2Q4`X zTxG@q_<8b%NH%RbW+w7*%%aZ5XGK4Eb*uvW#t{D{ZgNd`D{>=&3Q*(Wf!$KfXF z=OFppp9T*W_7G`lI7i@+Wu3VQd2##L{%<{Cb}&#Y;I1c>Vn$rJQ^@SUrw zm#3m_YV4xD9<9rC;^Vs~2>DpStD&@kZPs~-zl>K?RdECNtU?2;1~rPVN|dlik9p!> zzrf7ZA~s567<}1PO$An4?aB)DNh)+64xZ;snJ#LSxnB!&6J?m9+8vbFm4t2A--w!C z+p^-?)pYfUF15Da10ySS``VoSc%rAR+C_Cc1nq1>T{|Zl57xBz(-_i1!CSAZLJ3=D zW3jsmZ~`0XL!AmPd~yk`=DNbn|EAN{ffU&8--&acheCg#P-jebCY=}4aZKR^6l;IR z9kz_6G)`OTa!>ZZ;tuVe`Z<^0BvYm`{Y0tGw~c!rz$A`YO}3;ylMp=X>vL3$&6SGtThPYanM$-)VmbqFMk35QV~1*Yd-wB?E+u)r!w{IkwylKk`;`twQFem2Jq4;}AIE=I zw@`L#I6RstFbDU?Vv_$Q9A~qIGnxM!3q1B>(HjnuGOA$vOGk?Tu@d8bJ8_btHdzOb zr@7+~q4~mjBE#?M2d8aX zhCLs26OFn0evo-)6akebWb{f&!RR!%BMcean>N) z9gjG>(Ms%7b{ZE{F`Fv7Mv~!-W4Ld*2S%Hj!sxl4;QD1Sxp-LM)HyNm=ZGcI1#b{{ zmP?WG(-0*+#p z?jqiMw-!l+ZAa-`3Gi$aI&XU%u>MIZ`1ZVpPswiFHTycf+tIeKeocc?nKv zcc7`7KPNfw4DG&KgE&RVh7YXAz5iO_!**p_Jg1OlDGw#JM-}My*#yF*Qd$2eZQR4o z!xert6IFcSDsK5;w6H%6Eg#8(YvpOxL_PYKZw|?`I?%Hum3~V}l6mEGK9L;~1?QD= zT2EKQlhymsJX!}0WzONAs&-bVKZ(O|Emov66>Nt6;u1RCAk%?NBxD@d4Kqi1KasJ#~;G|XdmBZ^8nW*jj?-}m&Yen zgtEcBd5;)N`U za8Bmg-UF>OlbK&$ELW@fitBiP1x+uCvtLSsV8CcRZ9AvP4eh!OoxS(rQR4`9*J=f= z&3pjhC{WP57|ZJv+vc)qL9qdn3=2z3uNTc z^ZYJqw9nvHS*n2CAuTFd-D_uJAP-uOE=)W4FIcQ9=iK&K(4y8~=z2C2jh3&1!m1_s z%j62U?vUr5q7$$nFN62|^MIRr$N=;X29d#mAS!>O3O~nAWQRBIr@dpRu&!S!+|8Y` z?7ZbtoE#;FFV4rqWuas7X;?Z&)+$otfvmYy0^w@m%aNjN+y&O=l892YAj_36|@924%;1u$pG!_foVM zeuWQ0&C+JOLv07BujD6of9%DZa~H7|nR~eI_9}3VKa7L^c(P+Iv9P9gH5gXs!_=)m zxFcOMbn(Gse4w_I{8!r0>f|tZ|3jX_RJu`3N0FJ1{|iAra%_6~IUHTT5ng;!<9EqC z;nk8CLA<6Bj?_NLRZJeqw;8MlRS7vb|4E)1SG?jM8s>|hid49KTf~dTLhUWJ21~M@ z;;Q($_)`3=9aq+e30h-N^Uq80uiFVagDo-tO9j*0cM=kPf^htl^rvitChwhyzmGsp%U+>RS0egjT_R*`q;N%|g|L_E#=T=t;Oq8A^t9WJA)Gm0 z*!Z5`JV&5g=s1v3lLE%8T<1+mmE2V(GmoAq?6?*T?XnBF5Pm4@mzQNjQwsp!#<2MH zJMcz~EisFA6x392=bY2S*B#O(ZRZ%S`D!q(4vyyrT{q+Q-BjSs58JXb4{dJoo%wk5 zr@(f(kb&hfgXk=jq0O5oIBDu^p@%StZ;)8PHn?V?`Aoq_)$T%xrvxv0i@@~r7)7rq zHM84ZlJv{m71>KwmU>-q{vMKK`3F|wGlADCCANXr6RN$$Q%NuUbvmA|-W5o!iW> z*emQ`9F@^EEP%U_DBK;}d!SG7Z>*7x=3842VP0N1Y_<=<@0m+^e_w$Ix5$=$KbS$y z4}{&FW-Pubkf4`ee`0%7CL4Y0G=ABbW|#6Q7=AhlY_k6V&IS#Kr%9tB?Q9aH+;nBn z;xFP;ofXXGz*x3QRol+&$a22Bri>pL7>Nm|7P9mWk>IkV1Gg0pw>u*IUmjcO$~f~x z!5un)OP<=|?);G~&SWf&Zf=8ByV6m8k2kJ1islBUmZ7Y}Yi`y~5h`khc$Fpa=UgE_ZRZwm0{`baxkqam790=5nf&+ zf~l?(sORrxjJ{*aEK^Uzmuth>#jBH8p}_5T9Wj_&yjYsT{uXhE^*Z@k$*OFJn=DlN zpGL#0<^T$R`TVpOlU;iju|-Gi@%x5b{5ZXv+#{1$;3z^=S!RSOTP;Pc@lI^hn{N<& z!iv`1KPL*h^BoNL#NnKT1@LOLEc1S)LLUz;zE@#@*9p+16-x5-*Zv-DhTjL5DxY zYiLtK-9CIgwS#hlmXX%jt^8!?8B9%h!x)(U#%Is!Q0kT(%h@5pc253Am9v#uZRQ?! z>dXdQUUH1y3z_9>G2@{mNrLhFgXv*|168d;ig=g=H%6?3b*I%?^s(u*vfG~0=iXq; zSDm-px-p##H%)^zYv0o-A=h?n!xk76mPP|gIb@ms0$F7zGz=Dcx;^foSXY5z`je?B zsg|7Ws&Mss4KipEqyAJ6s*1XcoL4NYA3agXWlOSU(v=fcTMKOgZ z8cf?1$aCd0?D0yX1CHnE953_%pEWWu6UOR2?(+t-hSIxxcexbB_W+OPQ<9i8Sd28| zN^6=y_Wd9HqmhPkIM>;NU`jzVKeAY}iEO)D6xp{(QOcJ4sCg=iw#?T=Rqqt}ebJ@7F{TOv5gvL49 z>n_5n7IIAf+IH~whk0{TywD%w~NNw*ZxwGug06exjlWvzS|n;(spTxzT|z=bj?FaPa_t zOBqez<{?T#?-YxMiuY0wclRG0V^6a~YFKg>WCVlg0Ti;23K6}iocGlbN z_bdgE#CQ1gt|UntZKEIV_t0pFD>o@Vf)4#vp)2-?*>n$Q;5C)3Wt-*mXMzCHuGI%o8qjywwvn ze)dOev9&ZXbplJcD#<<{k*AM6Rb2Zofd##Rqq9!^oPl8}f9hlmD=a;X$x{mOtLji% zB)^D0yW7BhrF3%djiMC_y6jKS9Fo!3X4`UlxkXkNMG9wSF>dvE{!QpGc3`kE<;A4H zgQp|$_V*8b?amoo`qydjs(p|!=v;_#U%jaEh7GT$Sj3-j`zU0TqT!xM4;)ORtG^2T ziJIsqV0Wbi`wly?iK1{AROL-=?Jc-9(wSM`)}~crLVrYU3M_te8cwEn;Jo-nY)zI5 z!yN~pcz-JI9VEdI92PhmTK1?BSdZ&J9ptvpk;1))pTgRP4}5@`Gm|TpL(%KupfE#| z-L1Zk)Vz&SB%TTkR>3Kj9!*YiF}&iUC9F^05YM~JWADTKx&1Q6tTe<2Z|fECD@~5@ z?d}n{uEUhmWaW^1$=q%cM zshRsU$&((h+{|`Q`3@Sb+p#d+fQ_gW_Ov6Np>cx^Td**i&Vw$$rO1#|t{p+|m(OHI z3GbkH&v?AF#)&0#4a3zHlkuElg3iWWMumj6z2qc`YqD{jxP zHW}Xtocjyf^6(kdP5O_|J|xe6yLMwJm5M|^GcioMncaFA%hse7vP-4warrnM`dO&N zD$R!QrPq)1#~rT2v6a_g+g)MLGP_B*zDd3&8mtT}4F1iz7 zMh2nUFyi)pNbSwwbjHQNl-FJm^H-ZcAlU(n6xPCn(-~~@1rzo&_D^-!{q=bFc8aa3 z!gHv5zYa#q)o~lQZpHtmJmXSsJjMy?i>b>d1te-?N#bWNoPPaXbW`YM%>C5@8tKlY z6!;yLB`(1(fp>K^Bn&L)Dzm$nB-z`rw^*AP#ry4DN|k@=ggwALOf7C8KmAQMk%`vK z%=R_T4q8M`{?@oSrGVBhaAL7NRWR!LIJh1?PqZzy1)os`KRDuV^@7V)m?c_^JC#R3 z$7(G$eZ@3fmm7ymULBz{zlC<5yUn;IMzOq^?s%%`Hl>-ORqXFU14;}mA(;{V+_h7K zY0)`P5?9GV-I?P2ZsjQWcK;=0JKM8}x0A@5tH&7q?^qzMjzfgKpGU_bl9h`lm(PZ5 zrqw~1>m)eNy^y5({}o0k)I)!f61khc!%0`7`A4O%dB4dOWbynZo^+D1 z+x{-VR%<{B8f#aBBX}59V15H0<$4PUXpsVZcu~mbh!A@k}j%DMgQ>oI8dEM10R*i`?fGs-^Anm zm*c_VLqFW8H)6vD_N&L`Lum2Zhf7`V!!4MmN0RM_p?z!%PF@oR+q`_S$;+PI7seeg zjm|?%wz)7rRDy9MfOfo)hf&{)Q7$$IX1ARHjXe&Kt=-CHPg2E0Z8ErNb`=&(9R%9) z^V#53O}6#Vdi){0b=n3;Le}%U=&09&W^;$ozg|Pu+QQ+0ca~kv>H|>bHNcn6)Wd<0 zPA)3dgrdAxf=HfL}?mj+LH;wih>(Jk6(p0`rhd9qEG|w3E z`La=v)m_S+jTlPC{V%a9eIA=(k?cPH#1Av!u1Dll&pqMu!pIN7|CGtGJ6xcz{u{!LB-#89z zQb?!%8)(c0<~03*uy=fhdkT{9t4%We+?5H%rrTj{>`8byy#(E!ZsfJ6{eYqgoA5^J zXDpqpNM@Ei?P-6dST(G#En_T<>V`Hy?|Na8lEY-!$ zd8dwDt{*TiL4zsWngNMc+n}R)B%b+V#X_oQ)AG}XWW1)51L6mqP6p=?VUI*eU(7x z#ttQ$%xu>9xCu}1{E8;Z8C=~EBdWM|kREAH#(yg2P#+S@`82&k#F03$UWV!BWHR%G zrRc>Sf|Ig6+_?J^yxQJ0@E$w@r#QZ`yIedEs>;e)QpscN-8~eICz{j3ON)gax+cTF zdC+9HohpBc@K{G9NNyo+ww*f}XgudKOkd(HZ#^0o6UoBG{a{vY1}Gm#|?^CvO%P$4{)AB{FoC-I*_k5t=#f!F7JuEL@i8ak)h z?d=fG$Y3p2^H!Zk%b!5G!+<9itFza;XYdssrfjjzGk(i;394V|it=lg@i`tccxKs9 zT5;QmlQU4{7WfKzf}e6|?<|c)f?HwwFG;3Qzmu&iiiOeRQqV^d+2xNi3yvvSV?>sc?SH{H65ULW1AD^cwEiIF_xQ)Qmke8JfQ4GBqLZ@h^3(ki*^y zFD}ey1K~%xj?dFME2|2-%-628r(27~uB_#0b~GQQYQm+caon?Af+Jf!6OJk8K+Npx z5N-2^Tli-xI)(0m--WmNm2Fa_siDSNZ=Azbl~E{rLKm0)_9o4Sdbk_o&X$dyK+DIR z#q_%heCg#9Oop$5r*JnMsa0aPJ%Zs4v!L@gTlp%*S7^HF8`f-@PBZMi$oX@a-R{Rr z*rULkTkL=mU&5)q*#J zwb-u*m(ce^JlcwOKuV$}T$HuKw{kpuFkHzcy%|nrYL4Xe`5TlE9!Wu7(eSAyT@lsO34qvwtcXh=^jD5)sr}f^zFFt`Z{tk67n^{>-f!^1b*6F5%erb z$Hg_WbaJQ`;jHHnVy(sk&K&@zYmDL_ycsVS$PRn>Lf91_u1m$3DU6#=$vMrasa8O% zd(2qDjiV@c)*qIt`a@Y=i*0O{E?BJahP%zN%)3aEVyupVm6tK+cu!piTfs){ysy61xeb z;oa;aoMBjk3)xlCr&DE+;^xb%9gSwDep&eIat##Bc3~xhhOraEOe;t6IJePx7TZ}m z&aQao2xb+smHy@_ft^?`Q#d-5eTY58y?Q)_$&YxzAIk~gE&SrpapFC0?vp;0j@(S! z3U>3`+tT?(0Y6YyU`8C=J)D&f`G?P?hta0N>R|o24gzx-^tV*t1fAn-s$&qJSkwyo zcl2q;3Uz`VLhmwa5+vRlM^Ap*@lGM;bka5sU-u`1SJ*nHQ!YnmDu=LYxWbKj7f-$& z$1!b9G-+;9#+6&(~%AyWn&xbN>LAyC|jhdMw&6 zoVO>Z|Khzp51^rrIXCL$1Adz8Qfk-Uh_iZR@seXK88?4{gtBDhq}Ge19t~x8+6&2T zx(bUbxr(O`rUG7W!ByI(ICy6uZHi8!pD(V%meRqraGBsn{_H~2CeC0{+_ z<3TK2$lKWLM(f&#LRWkt+PzZZo!&2{V?Mux?=XceQ9K59vidCVuW*LqIIwLS!c9}n z!a<$?!J^T1n9#e0%{)4d)|73>v!4t=OX>){cvHZl-GWoK0hhi?u=F#naCh)CSQC-W>Y8q2PTW#*EYoD$)ZW39IxQAC zD}cGakHc5fg+HkH2rR%fh`jQ`4rOBT)|yo$Bm7&PWe4$1!&)%&`e)l{*3YJ$&Sari zfamRFNX6kd3ut$uuz<-JF<-JqpMQqzj1;Xh_#Z>( z8IWTehT(RKL{U+q(xibx?{nQHSq+qAq+w@|s1VvorI2W;PenySB)!jdRc1w2*|d~I zgb=Ctp8xq#-uGVDc^=1FcK&(`etzphRb2`!Lw6#VHu4?+?6DbBGZTD!FQ$`Li#wfh zTmzp!SkWP~KxSVZ2Y&mbSz+63&SRUvqr7zkbYgRHfF#G>K70quT%BP^XehgUp$0=_ zP1uL*3BnpVjoe*KapAz3?89t%IH&DNwdvb2?GMik%R=bioT;p7Vi(37JWs(_c0ukm zGrHw5k*WK|GwakK${n4HF7I7QLc)VgFB`JPCNo-7)6EA2UgEX(se-D^Pb}#C&aW}F zp;HDgxYu)Px%U?yH>NC>@=6xeESK~UU=d?#n-SS zZZG}p98T4)SGY2tL2R``F)Xi5qM=+Nc&(fR)7|~qsg<@Y;No}w@{DxxnyU3AIo}z^ z47VWlUB#TI^$ekpZbZ$q-KlR)JACxXBiX@8FvPA67v~d(J0BAdQ;SAHIkH-h5E zM&P;M-L;kZMpPa3{;reuzuHeolwO8Xgi|^vW zmQ}Pov=H|$I7W+_rU;%vJ1SAuWU}5C%*H9LWOH8#MSNa}7rtHw@2MVWlPtqh?G@Rq zq+=|>q6E4>KjRngkznkmfsiM-(Rlc!+9?jq>)K!a#r9q>N4)ea!_r#humftW;R|D zM(^E9b~dB1-Bq30OI2W^dnwwz&j+(XQ+e*rAo?sB$=}`4#Yesu;mr-akd^jle=>&B zdHqBjS#*qbUOtU0TP>NP`D7N+*oc>Ncc9bDFtEFSp1wFK@}bM#3VhNBAn#K|+wC1_ z(!Xb-waa3`LCD1g9F-*R!*f`Yod=tl?LdJom+`7q2%c-3gNMnKi;HGN#P&x zy^%5PSQ^eA{S(-Ng%<4a-47@zEI$ zxN#aNXqyWC-e{K8CETIQUJ4%gM!x-A6o}PN;CSOgh<|UutkV+V#O)a7dqf&1*2uH* z;Z9UikGTAL5$g{dfUQn8xLY?7J3WA0^5){Nwouw3e0IN-T;*R-#nskn8z5>*9XB>z zk9OJ|rTNt(DCX-qOx^K~+iii^CA>A}96ZKpDsMp3m|Y50+S zQZ&HmARPPn7Oq8IWCL{P(y8e|^wRY@xK-rCwj6;0+BF)7{W~HWzUURN<}l;MeC%z$AXIXl2_IZl{w1hUwMf+Qc|;|K}&VAn!&q&Y08O zYdp#OCE)7o@2x*-7{JNe*{tb$7D>khbfdqp>jZVG7l;hRzImL5}0IswIV7{*t|ayF}mSre}(;-w-hZ=*X$y1h znhGgu=|H-@x0jo*(gY2L<|Jb&a4Vl50IL&e{G?A#{PD$yd6`+aVcLyEQJAKX&F&3n z(MR>k!XOXLeblMjHjF!1+APlLkp_w5?R>h%1QvfTg#8+-%6>dO!f&5;9_|WK?*+NxkQ{!fK9y>llm1zVW^x(IaMRd5Pz+n~2^AZ_p+&q<6`VI~19 zaiZYS8thb#X2-Odrqmj`=@i1>UQmka$5z3-=q#vDTh70()1g?=DAGFC3>w{4XuP8h zpGbSd7RQOC@oxvTjuH0w$r9vLxe8oDjZtB;9BXdeic{o<(Hns|Ykz1JNs88!SFaqn zOD)HXwi`r`t7l`|G%<@fnS%SR$5Beg0ow6LN9Y$BQkqOJ_wV~kwsxTf`!;?q1X;}& zE6)=g>|YA8_-+|AMNNgiQU9>n!kJsPRbam!RHIn|0#on!Z@8?YMPsh#V%G0vSh!gk zS{0_iQpI0fe^oq^l_Ia5CBa-S1TdqG4Vb%R8B7)bg28t?xc4`zu(f?CUF|+WTjIZC z`43Yr$5;!;?)?hW3YtiXOHrs6_bU2%1^EKa{w%tpK0a61z6G544hYaY1_ zBhrO#q93tobENQ#w=PY5s7jSHnjk`7ldtZG<>qQ7VtTeB*as-lQOySK@tYR>^|K!K z`7OgG6B_Z!Vj*if{S()w7>*5(r1{0$$MFlFCb5Lmr7)-IBICNQu!o)lL5pRu5EEG} z*jLXhN~kfP8`|vXzVmoUZUZCteAJy)g9gvaC_4NY;m)zBHc*+4XRDI(FJBV1%xA|> z58@j#`*5y{I-RuHi~|+L+}{T_5ZU2PTLXua(#-Mr;>inG@vaj6e&zAo^TR>6Z#N|t zlne8dgY3dIeF{z$?zF3iQ^E^ln)7NS3w|BVR#_TT_IU+*Gv^LAPN}9<4vDl$=#v*( zZ9t=Onqb*#Lg%H0IctFoy?i;GQY}8RnMO-!`;yl%{r6~$zv0ZsJr(wWAp=?BoO$f~ zrs4GR9f@C8zvBXCG=ouVD7NZr(}q3r%-bqbU@^DwV=o?~M1{fR*KbBmf1^oN>HC)XtQpzu6vHBqJE z>jT;4omR{sJQlT@s#)n&J@R`OPm5P5p>kaf`0eW8LVO3)!TectJ#IC9y8T?NH*y~s zSv833D%x>1Ou$UPEG!(64OP#LS&EFj(1k{PZ@81`?00}BfxEf+;7S&DS&wveQ zf}zmq57yR=f!w=ca9Ws^?#la&zV!>ZxErJJu+WL0pLd(TSo$BFZ!v%o$_3;twH>pI zZ0X}fEmB!i#KM2c2{V*~pyPB5%|;tSuSyRd?*9$XQj+c?5%lu9 zGFki%z{BHQz+ur|oMAD6UD^>L@L)V(XoaNE-&4U0-a7Es`3=SjIoZ&A0bnpEl05}4 z*s#?D21qudQGpgKf6hT#XAeyIB1M1o${~2EEd8t%QHq6-y9zg=t+y4i@j(RhpEyZ$ zVb(qjIn%<4)C7jjh{Mcnxg(q8@E^S>w56k&?!3`a84SJkfzw=?LOBl~V(bJ}T>5SW znz@v6XQVEPw+RmH@?3LX>d6N*tGtH0=UTIco|1Ii>j`XnH4rL4+t9N|ySX(s9EOcB z!SY!jaKED!y*+40Ro&9;xq_eQef1%hc%u;;?~M_%ZB`(e{tjO+)I&*S6ZkB=Lx}zM z!l=8>BpUaf&-!wj+hH|S^p$~$zXIFMWXQ^2mHI|I(ho((@zPTlGaOvL%fh{wk8mDa%pEtzzt0u1;)wnP`&6 zN__EcG)w5~=A8{bAP$X%BMJ#@cd8|wIqSw&9Umm**@sZJkt#`#nvEK>gpU7{F|7M@ zB<`6X!SufiP7g1elCY5T++?>F=6~c1PFj}(rU_2eZra0MIL&3HO{VmreiWF`i(o&U z26F|o?un)EJL6+tb!a(~hik;byHwqMIQe!A8*qIj|JuAjRP-wauRRaJp5kf@(BDaJ zt75^~=MPwhPQ!PzW-ufFQ!K&Z4oo;F4bhi9g!$)kD!N)l(qosP|7k{BCPuJ-p~FPT#SLmXHBEtfWGxx5u&hVdwFTjUAme zt3uZ;iBPkBEw?*m59*{Az{l#rv{v1k74KGNVfFLa)|s=ZvQ!_}w3x6Rz9HN)Eq_>b zYC46VkRb2GZrm5q&wJXYqu1gjbiR8Hy@EE2y>4 zyH?Ye|1MxeOCb%LX-_{F1L?fE$WbI*3{Jx-}!L4zLR(I zxCd|UOXK^2X6!A@MXd|#*_Ns8{IUKnPU_)tK*?NI>adY%7(RpU7zy|$%3`oGHOT02>Zvd?BY67T3~?BRtRkUzjJU~hXY+ST@E*PJ+_{-EgIc> zC*ZEJTJ*YE7N(TMgGG}vTHdpPIJpvxDs9I>)$@d&3B&Vl)@b$MEo^%^n0;F+Nu?i# zaTC9`LcoS1?vk(%om0yMXODc|YDx$^`&-9p_de%lpB1>@DPsOltqxYKYC!!N55?Y+ z!=PcgJgK+DfYiJ(?48FX^vONM>~}m88NN*B1AZS7wLV$S?$4|TR(={nv=-3((G2$8 zAB+K}=IDAqS=@W33;w>)WZ7dHFw*A@-#i4xiHS}an7spAc0{1&@AI6FnKW76KLPvG z2cz=hEc87zm3Odfg2pM)Apal*livT~M7EKK(Q4rae*LD({$6Im>0YmN$8pAVX}Y-A?*b%)}= z%$58q%*2J8@1az55nc+^W_~f@EDOIoiyJ&7A3x zE^s31?i4}SWCd2HBTM~1levHSYx%n~(%|~qp;V%(#fPPw$D3=U$m`G@@RQR7*Z2o8 zuX7}O=A=b^9+9l7E(9-@UqtINHyU-lf}eAL8TEB;7Z=?TW=tQl;OSgjDzbZzXY{jJ zVOJfW6PV7|kJ^X!ddtcGVLToAdz{+KlxfeF9{6)7M{s-(fcmkPv_141l;|XJDyv7Z z#u`J^7|8IZejOTbdw~(=ub|5LBRpA_g=S4(xu37DvfRjS@$dXOxNpK0imDt2k$+}G za$!4mD|U(&*sQ@XpX_0I|0rs1+)PFS|L=@NI6N95!+bqtDB*$)B_FnhvhAzLe|a*y zEBzcL{3L0ERUc-n7NTz6dJK~mi>|*)pj8Y_LvVWS%G@KeigRoOEm`==0#ST#- zqp6$L zzi`j{VS;l=fi-m>ME`&L$zRrzY`6JBO=l|~nQw;+RxB2;Pc6l`=__GY{Ua#MPZJN- z9n4gEvrvEdeRy*CkKjoUMSHnd{Q2rAYmX_%`A4&_0h9_k$I?S^^>-+EhqS}Sb&9lf z=X=4Eq06~G>*pq=w1S0=G&A_E%im#(Kx$<)_sh~2)})Vs{K4Nil`Ab^7MzN^gRR)1 zsqyGztjD&DmWQ$_iePoe0(NM3;pMwUQ0HDOj{DOJQ4{OnZfqyt_1p<~U3+qR)Qne3 z^F)1KF1UKG0&9OR!4^n8hUHtV*^v`cxNE{Ga5hRr!yg)?dQAe}g}TtO5;ce=U2yIk zfu6QMP}k)oK03RN95*P}$uaY}-+}87V1Jf2!-VGL zu&?1LH}a1+J8pakTQ=2j`zn3V=vyDAHVoo+?>h|r>A7g-RLd9MOUDNrmk4vZV*X=^ z0oRij1qB-}^7&s?*ofZ6{QiHHa9hYQ{IOes2YahT$%3AndD1qW}2Ljz^QzwB1Muv3~1c6 zow&hT5*iBJ;k4TyQN!)G{GQ=$c+%<W8cL-K^2 zuc8KXyfcd3Rd*8=t8vg&xI|RY*8)vHVug&Kioo$J#^wG;_*m@ZxdR5YbM83yzD{7E zCay${>JMn?rHRd+pT#%!uf%kpN&HPyJ@UCf4*lcSliGp;K5$Yo=v3XuplBXX-w`;A zePK>Fb-3VQ6s%SDmhLn_ZNN$t``gr5Etiwa?Abs%(R~vcqsw`cFVHJ)z+;Q}xLyTawAR zPh|t#KB1w*ROmUwW5>T;;4HN3H<@*yOMMjg#-h_QOPBhO)ruA$)arCz(4@lv1K4cnXy0(rtD2pkW(Tc7#%@+&WzP`X2hN{RefU zO=-3Tf`6htMGAfH+sX%oJ8~t|*%qR0u`|;sH)2LDAH?IAzroeh2J@UnCb$Hzr>E;5 z!oe@UL~$}{ICI!uAy<~iSvaUNUSlOSh8xq1*Y0F^=_hm->fy?5g@V8H7|QFv7H_?! zf~xkz*mQ0$yEWJbRxa>l?9` zY*`t6?|ur>XU*x~g*&3zTMRJFjo@|YNTWg2(*5i4vI?)}|WoZWOi*6Vjdympn8*b#@5{6|gJ zQ#BD*%r@i)N7{g&wTSA)`{1TS1QlG`!{6R_8e$8~8TD#2gNi>G-m8c$zU`1dW(u4V zU8dw#3rwxP2U(wo(ub-_jJ>g*e4L9|Rnh~I(OnN{sqV#^P<8McV8o_Bj6m&)A24s| zJ$u8u|vaCS5V7q@(orS}6JM91XsavOA{sbI!VmhF2AGcx+nxSXRx=Nj<@EhqXUB7Xh1;dJ%G z3DV^C*bpOa-fvh2&Ul%^9(9FNNXZNg?;kv-4y8Mn4WnTkEO3B5`Sm`#G)NF|D{TlR7x0&8Q`CQq(~ zZ^qLTD`1xIMegxSe^T9lfK~6C#g>I^!Q5M`;Nuz@ZuwLx`n=g14|+TW^UT#;p4v-J zDQzQ_ES<_vP)SFd)W_WBhO20pTZkIJ9&sp zZ34T}wZV#wy>pLGOB}(?PLAayO;>{H4l@>>x|Di;8{lMp9Tw!emf2?Chy7it+=w0X z`P!d`boFK}OdNU+LrU&~>$>%9`29Ql+|j*YZ=X(|rDb_G-5dApTFAzP`m?6mRLr-j z#r)a;m_V+S8ms^ZG^&_p*HM^$rj5PHbmek`X0Q*9r|`T_BWLVY3J)(=iIentKiiARFKr_O8)Z=Xm`gj3FJSAQxpG;@m7%162piH^kJsKDpch+n;nG4& zq=BtyH(7!uJX=A_cfMdDkAKk7%3-9_x?0%plt}7H2tC{}kqsYeO~*8eA2(wtE0g>U zqn@9~PP3gN_rr2b`hq#r9WtHyrcPx}k0i+q_OK1t*J1VH7WA1hh+NM53Ue_LSy-#k zi!IC8$+po{kt4}g*M8+s`w1P{3gNyrFu*!JQRv0q?B!jT--Nsg1NevoTjy)ByqZXy=6?l>yxO5p+7=srHIb(IODZcri<9l7scX;{JZ?P- z1FFx`)V3LPWW!W2*Nwzp;e63e=TL6lNpa?u5*AT>80wDJLUz6lxVg_J%}qVf zYt-Vk^d<^hV{I456*f-jIqaj8f`9BST;~4Uwj5tsHzU>SLDTz0l6|8?rUDD(_wCDU;Z_wEIL?Sr z!+=RXImYgU+0lr>8|jQ_47ayY8}{FDWEwkOV4mV3=JzL(N8>NJIw=cPZ_Q+CQR+CT z=MpqF2ck~=dh-2U!_Rci06&%YT;hskTKU_GYo3MRwo%M$FPzHOHa9~n(`7#Ce|W3i zZA^3SbgF^Jc=U4#x6RZU`_7JLL0wa!bfP}a?K%L-JFj7h?ntcjiiEhK*39qXUF;Ly z+=>?aLHw#Pw2zcv0iVrTJTG*6c8#U#QMX}$<7A34xsLW@W9deQIWEqaj%urClFX?{ z_}!n4c?#{E>vSuU_LpVbJ7Vzf#ZdGSR$r?ff=j{Hlqxf`_&Oa8x_o5|mERlzulC#( z;ei+UC2|(xcff(6XTV&+9&b&_fn8f42>04#kk{KljV!0;PTq@emZqzc7l)hA+)TR1$$f~DQeOJFrWSgDm{{6!!s4uAu#%V z>K5ScH=&qd(2Rj&955acg^eX6;Ki2R*g0|_w>QxkyH+*vt4y}CGGj6K z%=9PJaH{Nri8l*7KbRdlxRA~0@x+3|xwz)?HI%S=%-6k}ik6=y(Q+6<@mnqN?@c`x zP`(C>Djwj+dj_n?q#ue+A42F$HB20`ltMEU@n*Iyh6WU4aYP1Q`W;L`G1EYEfGb7k z52ZQVjxdvkqda){<9*4&5I4>PD(-5rWk=#f2ZViO_`PN5{B;t)%ODy2Ixlbv20i%H z^eUIEmB@Dmenge+pTK^j5A51`3b@#toT0%ey7+ie>DAH@~JW^Poch-_~as zwRJp;4gQJh`{VIxOacE5LgDF}(QtEGvcOLY1bDTMetUeu!;N9=gGM4BJkA2mIv5p; z%~*}^TQ2T_FmoI8l^c5U3fRir1+`rgm}|3?J<8W0`5Rkd-O@*VuTdWqO>Qo|v9gt~ zb$*RgX0F6VZL+jr9ph|eKqcv^JTbs<1l~E@8{H-6ZVwU7lGT~&SxjKt!69d4?)TH5O!6n z7|qU(rCV|z#rM9+qeS6poS9?DQk_*nLcD@?yE`$B3~e;9-2&@(4`6c^Ig)YjdbIB) z$cT|;R>di>rZWns3-6|j=OhVyQVqdBbBe`{T*#T%4x%2XAMidnfj(>PqKd`mnY3pd zZAmZ|-OB33A&+I~`o!H zj*)yIY;61wSC*f|Ay)&Su1FQ13q94I+P8SzT!y6o?xMe&%J8(xA-3@K4;UEH3on;O z;rLsJxi6l#vBo7B->)bH>Fi)!o}A2LcdX?edozA})d6o-MZegEY|n(tpq_snPRI?lk%4Zs7qSGEl}ZA8SMVgAI>+6r_F`qyQLwaW zEM<)-M~BA0(CMSZUso6264it=Tk#7pIavl?8S>0$UNgKt5{|brwfXCVZBUd}g${ux zLS@^S%RA$Y)^DU(?st1g(p$`ILleaECym7Za@kBV`Uq|PPP~Uz3Y#`BfP>Q;=tQ70 zwQg_1$ZI0O4-&|1`3%sI{ZD*((JX3x=Yan{8L)FZqFB$bSJ? zs?QhxUh4x)__moA&X6YG{WD3feK;+fHw|rXc(PBy8T?UK6Y!l~3iQ%LtZL&V>}M8O zSk8FI@IY#4@`amQCSl*JeH1oHhk_SngHf(NlM;HyC;Nr`KK^OOfM13-%+_g8m3h)b|g&xk~eJinr1NU%T z_-l?+`-GQ9$dJT9EoSF(0eT+!v-$51V)Xeb@bc9iH20W>=J!3IpjU=ojkV?!?VVuA zyFkuu$pjYg?vdD3$j}Zooe6*S&vB6g&uig>1N`W#QCufy4;!sMqUlFjCRHebr@xHA z10%+;FEx(T)VGv#9iIeV{x;-p@(P@`yOCw2HNNhwfb_88EN}V--12=94IZk8?JEwW z!ec$W<)uMxSG?&;{D0z@6CNbdWCeBCZ^A(J#Y}o5W0lI56JTt3SWlmdlg+A<3^1Adyd^mrexaX`seH!LV<7yQI z_M;7bcp}5*f3m0TYQuzePQ<*rVz?RD4?)o<;7;&&+#9={m)w7epQyN+H_M!dJ8!lK z{j}@sd4zDji7^yAJbH@*s+Q65cS@9>=SZucpTj+UW61UAId0&Wc&736Bye-j(}XL7 zaHZdF+^ty6jpItd!?BnOlH%~Z{e0RKuMcxeawz=qAX?;BO6l(=(e*dYEJe2$pL6bP zNFdP8&p}wz=?pauf532=0{vQ(#yhNB0Y_FFvFuZEeA+e+e{2%EMvjI=BOQ?$MbM?o zZ}GfoEi;vhqS52Mn8y7z?8MS(*w}H70^Xd1%%)jT?zo8s?p9=R?JmsX+D!5u-;Qy! z3t3ET1U4t^qf$S8I<@y2?0j?!r#B^0MRgf=2A|^A4Do~^t-{`R!-)2-7u=9_2bt-e zV}cK=8d?O-@%qijxtozWyqlmbE%F*d4mSd6WNr<(FJ8`F>>f@5zmiy%%1qjFO++70 zeZg9pQR1b8I=M`>`8f69I4083KEBlU@fG3!^QlP1?mGWoaJw8%ioo}~!o;t~c~WAyIuj4;K)?6#qGRjhn4Mn0Mf#$QCqr*o9}>L-CsZ z3hw(Z8FV!?K{IJf8Wt;jwgzqx?Y(xCe&jdcN6vy9+nYgqUiR|_+Vgpn?I|#I=5%iJ z>o3sq&y{ADjb&^9HDP$E8FP13!tpQcFh=?pY?mKP6$(r7c%3TwXa)i57f@njFl5eM zgtD{8a{BED!D&e@7{A%gv(kfLUGpD27Thf_COt(fS4|qFV9(}HOhH@!Z{q%5OV-__ zOcFDWBHo({m;5Z~o+z7Jpx^+v#|5#lHwnV5Z7YVamZjvUpK(mJ9A4AYpmFYrNCA_% z5jHE)FDHbS$mde5U*SysJM~ry-YDW7pKLXs~iSi*Y>*SCyO~ zebI6lbo#8o%AE$MRxTu;(J@qJ@r!+~a)&SP1JPP-7P?vvVt))W&|+pj+pRg7G%wu4 z^N(8~YfBjHFdE7caKz_XoWrFI zaxFM2+E)J`+hBc=4E8kQ_APHY$tx+i`&x*wUq}OIZ%F3C*+1jV5Z<^;8j6l?qx%I{ z_#k7B2F)!(QAj!~?4E-z6EvW{$%EuByoT1}iD>*(k-cr}!2%^?I(e%MYK8lChQ2ly z@7v9`tgT`fvqj`lH;R3#wxnf`JHR8X8ZS`}?EY~O^_AjKX>vAZ_Wb5-$9#Z~&SPMM zQWSjZKZ+jFX1GaJmp(?TVVKoOrf69WcinfRO5-=qb+t43)tb=HJ{4rG2QXD{CaG2d zJC}8ozo0jU6rVS8V|P#FYa};NXNWYVJ~5_q=B~Kg*^ff*N)nea8~={A!^wq#Tx(_} z7QWHulQ)?_yUQ?^kekY}4XG57#iReHLNqDyW+9*FP_Kz8{QGBstCVkWpLe-36W2gC z>RcVH=VsH973bid$qmtA!=Ieh>Sf@RQ-@Ex{lOuS4{6kl>^RWVF+&_lZOU7}%=ZqoP$BhP^JBAyDbMhfu6_&emJ=^=-6ulLLY)@gD&m3HJG9L6Ra>Cx-#0&IT{Zn6J#H?|Tb9Iz-3UaB^=0^ag&SUp6ME}OWn}YHh1J~+WqRwKsd?uJ zcJa+#+C8pA;7%WbXYEJPu44xNb{Rx|$FyNk=y*=yyBht=a-!wVot%!!UaCsG2bHhR z!A-rp{7d&V9Nj;f9#|qIuPcO1n^Tx%wF}4Tw(~P|7$kg)fOh?>s4-?W-I-P^igeM% z;IwI&yi}6AF8?1kd)wk~8GU>*#F3q?$iY!U7dY`%83c{YgC%|f#!u9U1w+n*lf-2% zC+G(1sJsCcC2i6wGQd`cV*Ka4gPhluVc+~pZp=zwTJ$IoXN5fAoTfU1q>3zLpUa@g z(oD$OBYZA4x-z@!J~T*{z`epb($Cl!9yfJyP7|*3ULoc1@jqpFI7))~L??lLY6|RM zsKyUazQ!$X$iXLuKu-eCL6zG~KF4k-g)hI&0-?@#g95{rOugYP&z!MuzKgCLQ zGN7AV!)>mJ!4Sd6wDL+ZnqF&!!2Q|W&@Zdl(4nz(#O;Cjuz4vC4jD_<9c$R&x^NmO zJqSYPNl@@OWhQmQhc2|fg8SB&LFvsy(M?)MlI1Eidb1s^9d{7q$D7glOVX6qa)w=9 zs|(HXFCj=Jh7MdBLwoA9p#8oA+CA&SQDqtMw|fwT8W`}oH)pUZ;x>@?45SN{dr&DL z32*-$%$oT;yt!)+8}D3$@7Bg*()Qb&<~0eD68OxXJfb;Y15dmIwu`@kjh6Td0r4^(V0!VtZ= zv~R;yra!WscStV=jq?I?Z0lk6gXP2RBLX|Q?U(3LjRzGRdX9w>j9t5@PXEjok#*K8 zbd_Dga%7G%3!$@EFm)!YdFdveI9ZNF!BQx5HUhgly=l{+GSmvz!P%vCur6AeD!dE0 zo;@{K(KDA_ng0xRE*vI>-UM!bjSNLS_=&zO6$>Vn;Kxy)!SU#Spjq+=*M571_bo`o zX8Ev@>?D|~U&ZY~SMk-$cT;5dq5*S}c6M4jp6nKy)dY$Exh zf-xVlXfCYVQUz+a7r-CgV{A#|BzWDb4Wpi_3m)s$czakFyqF`)O`Um{-?9BWsP1Uv zd**16S@%?y5qcWZ#;+jr5z0(uz8(z{SVztmf8&ipIgD^<$7=a7wy|6$6Uu)@S`7j^9z-4!&lc?`2JlyI0^2- z`uHjE(R&)}dc7apnhe>Xp#Lvmr}fNWF&?0bztvd4m#NZOk%}4 z2*{SDIrU%gv$8iUj@cr*RD6(XYNxSTl7iLQ=Ng{Rk0(&G{#jbiS zz)-FTHas_FYsY^?hn5(AV6`7O3Yng{4GTqW^G32*wI8^Bg&w>ep+b*KM&Kd`9@VA@ z?2C(bfylG zQ=q$N8Sb!Dr8(c#`8y#`xds2`vjJ=<%T7HCU00uC#*>4z&*?S}X#337SstJR^M9j% z&T|}jOJD(~YlEc_(a8#~fNWu{oO$~X&bUQvUfTyQQ0f-UE?kYIH3N#DN;27wbC7g0 z2^2ij@!(=z`ZQ}H+w6xTpKfVU%MpQ#sGP?)7DZXV94hqcJuh-cT$)90cJ^RBa{(Wq zmBDIFi*ez{wJ_KD8xG|rvGg-nQCpm9-Dq8Foz*%Pm&=K0rOG63^e1b2JyrvvlHIrf zUY1FUD)^4hc;4t~78P|3W)ZK?z<*}y?EI5Qn5JjM{#z0TaIPQImndS&n17tiXj}I5 z!)lm(c@z0uK8QtbZ;%W0rpu>0VeM!$yfv{Ou2hAwls}1lf%$fRjr)A|NDy48z4yf; znLJojqswg5c9Plm1*~eQ8!w|AA@2DkaH@N4nbP|;7&~(u?XW(MfqOMUd@l^u=Vrjg z*+XgXzvOEx%MP(wH7fkr;28pw*PlMtcyj~gQ{heM0q*wQSr8QR2<<)P*x|Bu3^h%_ zp=UFxwbr1L^m49M+=pS#mU!aIP15iGj(rvqD0grTKIj+^1OI42hnXzjgBh6gDIH%g z6JzZkF^nOovj zZ>pJ$%QJZOc`4>L{6o)Rf;jaUx;sS*2HhD=-kT6&J?}uzj|h8(Fw(bQvbqMxzG z4;>iwvlpVj4uGDCf!L9+%B;)nsdQT;xA;;RO_f|n@m+>ApgV`J(K4r&(r{MlJ_)5F zJ24~T2gbArj-KdwxOUrYOw3N8hf{?2&ep9|v~LgBX^;wsOw^h25qY+K+hZ8%Vo$Zd z+AuUv1~Q@%%mW9pI}tg2hQQkGKSS{0XcB`m;XdL{%ye-*a_e>3=i!l5JK!Y#t{F~x zp&}?>vKZwaY#_^sHqJr*5a&DLGfvlDjHXXC+4>P0aOvxQ%Dx^076G^5%aSP|Av2jR zzod_9JyUSYY;VHB$5^gm2k-b)aIPxdhC3#DblU6;UXF61_p7!;QrsyjoxK>{IpJ?m zBKYn7?_n3ZyX?QBPF z$re&S_6{#M=fK*p3voyGLH1X3pzym5##Lq2aO%i5cEfEW8~;@f?9A^&T6HzKf(84y zP>!Nkn=ze`MKpD{DVzLd95oKiW{-UQts8{gs)T(g|Di#L&z)gFu|789tFVp52^^-y z3zf;CTZdl$o5T)%9!D}!spz0{9Oo>I#-!>qs50v#?;iOTtMeq`sF1tX<%C>qN(ahx z8^EEZPvJ@UUKq1=E^9A*fTM!~QM*WRhiAm$rLzyY=~WAH_mguhG3z)Pme`|JY$-&o zj3DVIebB2~1BQFXve#XvbjYiWKfL5MHb~T9pO-BTk8!|_R~*sYKNG872SBjde7fyy z!mL~6@JJ(vPSb<9J!2Novw*F*O=koo<_K)p@40-Zj0XlO$MY-lc8Hqc10Ufskkys! zW|hkWu;h+5{M@cgMkAzgaJ>vGFgwS$o<2q%a)&ANeG{HHGDB(USW5TNfe1$l3LPDb zQJw?nieC&_%t)R&lmn@fjg6(BW<&6Qyi>V^%2iiT*T+IjIRYRQQ-7D!Rb+VQO0Er-iHqKvYmthfmmd!U^^k@?3dMK zTG?AdvP~{zFYUpCStxp43!n{grlh}d2d>vo=GNIvfqx3`x!O^4S;0PEZnM{27;WQ; zh5}DvQ`#i@k|uCRuH-POm0KX*c_C{bjyOqpCs@Cjg%TlCXhU5lvR^yExPF@GurL=* z2U%+LIL_3!*W=OE$`rdT5c|J=XYKA&$=GrpRh&F1UZN04)g1xs=lm`{wIEb*-mS%U zb`TwQcEFDZdUQc&Hd}DG6zp}cz<}jx%(CMzYG&?+=5f~WvrcfVSsK7gcLw`s2jQ>a zC%EUXxA^3eVrq32?hJDeV9b(hSbhHy|2b_MOV^jCv7V2(5o2^&dG{n5l~Ks-C(eVu z^Qlj-|6_d}ko6@_)X;j~V799fzQPapJy*Xmr6QR7-zd43PCHLMvbn|h#|AIW}u zwX$0of{(pn1ZY1SOLH}!VW`d(lAWK($}dXc+V8j6Y(5C=@?L}fBw?qfSwj2@FW%bYD=_Cy zU`h8iabWmx_ITiaa_cUK1flzvu<{|c>NwD|Luy>!sw3c%?#z3=GsW-Xbz;#L2|h(r z=!44bhhrbEptbo6C@zg)pVS54Ywa4efjE9+>R5_)UkL7P!d!FRNa}rV$4cMqsMyg1Z%cYvPu?uHY|}UR_9hW)CTNS(3&+9u5(yNC zwWDr$5;XYy3sy!t+-?0U$1iSqeVok?tSk#%)xP#~1# zD&Say8b0aWEX)|F$W95~o+962%r{+?f0Da`BzlFJ4JC4#3#%|*rwl@e*MV_NCAV;% z9&EEZ40RVOMHTDc!b>+J+CIUIDz=%CTyid3VpWBCuTS8TPXl@53>(V#J&Y!IGdOgc zicx_9wD+MV?X(#NhvuC^hpy{zC757yUL?N1K87h>kYv_V6QSp1C7yZvSKtn`!nGa~ z`jl0N{L_(e!qgh)X^&^iI(E?Cf$OlqJdQ4THgl)u51=dUC7jibWcD-7RD34Rm~s6H z6nADO&8xqQDd&^OaN1Gc{nK^e-eie}&h%$TYYfQTZ3#{|{g{^-C4+MBav^uJCU%LZ zgXgdWrkymG%+$*Gb|VS4UH%X}aH&GK(iW7eO=gpg&2g&7JnGWYp$X#_QApln?75Q4 zzDnH_ck4gJVP3D;fz|b>Qyk6B&hp@r1de>@y+Mo&wJ<|37mhf$iG5!+;Lh5UxH)k; z%SjHVWflTgwQ?cmB)o(rFD9b4UnKsK9L+ZEi-N2uKX@=F8&-Eo^UxClmd14;`zs6& zHJ2c1gp_?bzesv8W2>jyuIiefK77A+PyxSubi#Z-v>KPUPBk zio33<$`=1p#EITg?8OylP=0<{$laDuWnmgi^&bF@Y1=r@!@2O)ZUh@>tBuMpuEVY@ zWfn5JPWbyrkkyvE(0P0gc)>PiA7Du z6UTmWGIeod2hSz2Ytf@{zrPyIoF~k!xifIt{TM_=m7_sR5T3CCu-({)XT#&T4P|?Ws9(d3^~d8F z$wp3bo)!CCJ)agou7>xbfsEg-OzGuUX}IHfSdj3T4;v6q9y_d=o5@sM5LwQq7ur*{ z_!=7Xu9#+gkdnGg*sa?~Ff9ElH`s6$#pf@>?3^$7#c%;Vn|}w3Ty*g#w+CK~HYSmN zI7=xpW2b%%paR%I$zPgbSLPvH6ZR9wUDqcEUY+`P-Qgigh8>T7%k}!{a<_+Dwt~Ci1w#ziUWC#pbm*o8usyc2t9f~mbTyRz~n`0nByhIR;J|A zym?yW-eJ$$;~vBDyc)P0n}+*Rd)e8Q>tRFtVc0K{WjEGpGr0pNus(h#O)6~UFCW~- z6!-UlpTnR#LbZ$kb1s61n6Clj0r& z!J9RT%$7-l#ScsBx1J9ZqjFjP*kyeFXlp2~+Rk3)#BwR2CiLZ^C0q374V>2;ODobn z=v;HMXv^BYs4;O6uKX*wJ%<-#tjT4%(0PW+%B4{u=PPa*^$uN3`Vnd)xEWOgImfj; zHW-@Xk=%aq+A2M^LvtZ;&-*bYBay7PucA4g7F>=nPqREB$z*&wYx98ZNo#gE;9S*Rj7<3=OU3%%RdB-fUQc)w~5(+>c?80`G~XlsbXk z*$o%wH{ySO&tRT&lz3iQ6Uc5?g{!3l*~JupoHI^}WMp%3%+h2i`F<0-q~kEaMG5*V zS3!(Y8NB99*fb*@@?MlJ@~+=ba=nLGPb|;Tm*em&N)I~&$BVa=?viDH9h8_|N+X}@^Z=W@O`hyzEgg7bJTDPOh5)t3DRO@Q@KKxMwa(X}-eZ_<9&!zZ>6;ng{i* zx%f<&=_nOF#Dc)7Y>=u4%Zt+?U;6>Le^wm~wmV7*DW&MyYK3;Ef}ro~UfdVF4Rk!_ zl4tRG^wMdAAO{`xXJmHuPvLo;=C6ho8@t&IA#dxpbs+J-YM@EruZ|o45*E1cpk*%; zuxaZhFc`1}TJP2iO!gEUEho>S(j}leOAp?f`*A0glDMXosc4nh0}g`Y_Od}Pu)swy zAbAd%yZEBYz%}^5;w|6W9Svy?3qc&wk5RJ)hUd4dc>Uf|@OD}UQ#%GzqKzyI3Co7* z8O~Ic7>n`SJ1&&f+tT}T9$iqCk0E*!0nC3EJtq}i(Y6;cL$eot7?S&?+!gaXol##UWvMpzk}kf3|D2vE(J( zHefs~YhD05%XRVc$>%u7qyqHjKEU}prYy*FG?(Xlf%INDvXr~R_jBHV;!3v+wr8y( zA1u34e4|F_fNXN1Bi=i~KwFi<1yAla>p5`AwG^fLF5m{aJdj?7*y?76rym=F?ZCzC z@)1QUG>pZ0tE||l-SYU56VB%T?I?aegDt$Zk~N+*B$r=(5MVAiSVEI|ceU~Chx|M! zFCB(oXKdiUZgR)t;S!t>n&F&JHeuuWx$NVBCTL|d=z*ycei4{f)uk0Y8`lR)2gBj? zC>x6CKZFO$24KkYPTphcD>VGq2L7)$pqo`1)IXoV8-yFt!ar~M_`LDSv9)FZ#zki0&(3<5vr$CnzwN{cf;U83$W*?q+l^zVKLy!) z1G&2KE8(8EEPb!mMQ7WUY^1pimKYNE=b8%pY^A`8FGj=ExLsJWE)$bwrMO9cZ@_f> zQt%72C)oqqu-!wAq#k6#+Kf9;Y|#a^?*`+yIhHsndm>zY(T7vR1Q*JROVA$Z$$ndY z!BzPQa6x#6AY7LMUoGb9Fs%BDWAkivoG-O-p8=!T@_zjF@#!vhQcR-a~Lkn$8FVD!BkIk zidi>`Y`Sx~kPjYYH+LWtZ!2eG{1WKP)(SZGcrc4SYfRP#Hf+E*1EwFHiH~E2bNA~A zFka^hn{H_{G|_|cHO;7LI-8yxlBA%jacJ1R8*lzuMAFfx;MdRqitxF^TdC!vtYal) zaw?+F^KIF`>*ML4V-UNN6;6we6hr#81?*zHIh#3bCQ524)6y3j^w7)-t!|tk&lwZ( za>*h}zY>@obADZ!^M45a0Hts;-)R_<%WL^jvA2L_Bar-$wjQL9FgH@`3+ zFGxP)O(SC9^2-GX;11~#uAq@@R(-@vNyz$Vf;fFEQwz+7wdTJ$NxyF1xn?v|oYjYJ zySuox>e0AMOYoP@2O=SA(!^-$cZOy|^mS>7&dni3nvnnIg-h2P(>A=C#h zmfz;I%=JOWqKb7^UVy#v!HB1R^4aCzV7tawP=0k7-@D~IRt>a=4X;`;PU;5wY0cmd zAAH3r*X*K^wL#qC+TCpUFHM{t@ma{^Ggbh*@zlo>9JG2Q)Vg?K*?=f)tq^l(R}1G( z*LAc`YCLUjA4uSO0y^h3ik;ep^US4LtY`BP?(F_@R6JiJ?lC-zwj;f8p>#aP%-#>D z??2^|6C*{9(p$LBf1&L7p(*gAv>3cQ&fy^ACA87T5B@E)rrf`7qAH6waA8U<7A|gu zycMyy#-3vac{QB1xgY!JK9=$xMdR!tduZYDer)ya<(@q%<_m`wE$QPwXG# z&LIcD*!MULKJUomo+Ehd{zblj-f7IR<#F}$8~o~hL($Skh2_SZQ~Wtyoa4R(Bc3`l zxiP-gO<{k5^AY@s6(MNy(~uAOF^)Uqu^Io|?dNc7Juf}22P;q3adKxi;PmYCe4e^J zEBtVi7v+`U>H)v;$Gqp_)ix5e?As9T@|tF-t5|{mEf=BeZid}Lm$yt#aF_3W%llnc z#+0}$d{U^zt#8giFQXqg{?RaW_zAc%uf2MuypRP6SimB2KZI`m$3HjS4N8xyA-PY_ zaa(97?DCz%XGV^txc4HaRVL)kt|&3Jk2CPs;ac?QZ5Pf&N?sA7-JBH0QsW4V~CR&@>kkOV{_*3%&|1KX2AA$uZ(*!wy zqJgw(qzfpBv@v(~8T5QOhJTW+CF)DFqVJk*Xg87PH}mpnbF6_kyB|(Bi&X{2^BPX$ zzwh`#T@MG#*<;(8m)L(|C9%(P%yNq{3*ZWf*FA%WJo0hSZ%%~ZGL9N^bbn$^E9W?2$Pd6Y-0=FN{_&p&7ZkApK`8P*jXOSlB0x!nfOuW zB_Ad*pbx4_(t3R%o4Ixc8z0_{d#+hR*r{&-nPwpMM4KIbv4Z5s`~#JwK#2EwgcB5J zv$AQQu=UdnW^&J;YA4&V13_OQ@W)NCE>{AL?DgEEcq8gb{E5nTLDXK-Cay0Z$(*K+ zW1D`=p~DqXRMgyoYC(-S@?ivS*tDD1PKbiT0)rU)vT%4@tr(Y=^K*4Qz#zR4-tQa4 z?mXOx;nGD|5xxb2SEr#^Sp@@Ke@oX?uKBfO~3g1r(%e37m;do5g((p0jlCpVrTFl%sLQ{{VO)Yzh|%D+@naG z;v3QXoqb#}+8jfI?B%*RX*W_d%6*%DqADjWw>E~2K=Zu}Nk$h!8=VG9J`(Pt}nHq1zoZ22Sb zum||^vrAdyuQWLGUXsmO;DR56royQHfBdIWO(-8Wl)Bfl>M@%#@%3*X7*x@VFN;sW z)2O!)VQq?PX$$bX^HDri^c~Y|#4z!m1M7D3VF5cd;ETdgzVX^zIvtS*DU!kL<5mHH z)ASH<%qs3pTY;1N<)JDXB?Itj)(R=5Xb85g06Ea^lu*0GnGA8)rZ|`8toUGw|=QUu! z(ud+13+6M?(UB~2_-=S^>W-IXc0trTF)Z1Zz(&wh2 zzS{~Kan*>PF8#$NG&SKiA8R}^#ej-CF9K_A<=%KJ!Q6jy1!wjE_NapAw|SbO=PbcD z6D{zybB5r}&4=;WtFgFcYAiPB|ADY~@w{b^16tJjb0*0`XK!pEck;I*>wh?s{`=;L z$*tX(l(!9AdUx?&Z&h*st5Ejrkux>VIl!!Clh9MxR~i%;Q0dYl@Odziio<`2)+tTm z()`k({oilQdDbQN=R@E|(Jn4NCySC#%d$P~D)1(Pi4O|dsqWxB>~%C_TMJ|%=Z!H4 z-aLxX&PBbV8_*Iknu3G!SZUAu>Yv*u;`BX9;%!O!Oc1GHsNsG{7_7p!k1|K80FL~X zBv@{%DO204M4JN7f@{V!=CxJ|KYzH-9Z}b!O~T&qOYL49cSM?5s7zsF)YRxs>qh=| z+(BFycnFqGvcc8&kFZrI6j|@{QS5vD7ZNyRyv@??ug{XZudT z!vI6}c^?VR5F0a8}-m$#*`Io(IEQ^E74=kJcv-2pu$!1T=w|K)SN102nY0G zO}Hid(-r@CouPt1Ws-9LKUmqtmZ`@pK5ZACYhOm z;i8wAzj|%;_t_iZU&Um+>uOFal~JrHp_|%9uM*Ezuz_X2ET}hA==4>{^Eb<@SmFE- zroJzVVj6<^7_|ZjxpW1GU@zePMa;B!Bio)^#V$WMN@GV{fmB{_=6wIcS-%Wo3I=n; zrZVzSGR_;EHxxtE&sH#c@BwukX2amZM4Y{0FdQw;h0P$#HZP1rZ6Oz~DDWhz{c>>V zlpCo(7MA7~8*r@X=EL@LDS z-={0zqG;e$Pc}(uGN-om2CmQAPbs_HDc&@P4=}huJMJ$LcFhI&OqfSk4tUFhw9pTE zCge~jzF<@StwdAbrR;Bj7EQ73<~CoifJ2v~$XY&{Gq^a8Tuz;1J2#a=T37^`83oWv z6**`czLjs>avG%0RSI10Xxt`g&d#XE@HbK#nB%zwTH+qfLe*0#bI(r3>&DYRf#dq~ zNDS&}SHr7+33OoYYVytMfT^pu@zvYf;Ch}s6$Z4S+6f67m-7j4D+JS~?^+a@V}seO zpUXV>0G(a$0Jq^8#P#Tcrsq@0&``res|B{xA!B&-_9R?rkYTpE-jq@}h}_f0Vacu@ zJdaao%iY`9>~@$}R#Aa_bJfY_NIzKn<*xM^bULyx{=zyUvPsTXbL{*d}cl=nDoCsWnExOXtVz9t@ms`$aGqTX;U^H|rIxemYcnim8Eyg}+Ii__`$dDVphqqsOzHI3h z@vFfF(8UFcx7eTL_U1>x5OsNS9^8wWk5@p}eLGZH6bV6=A^Z{7Vc7Y=3~iF)=+Snb zmyy_uT5)##ZiBICKd}klx(~uy$8~Tg>ODv;t%c<>bzH#Zp6buPC8;7=jFF85?HjD= zl1e<^m%Ci_MrJ6UcbG$uqYpsJU*Jb?H>dm&lhHZr5_i+ZnGKK@oE1y^c#Ug)eEG6` zag16VyEj9VI%keyK|zH$U&)$WoW?P;j1h>ct1+Z`Hp{B6uJ-O7$kK#6$KQa9c>au( zu%C9s!##o5qRa4dqbeL1T?OMF56r)ijz{j5;!Sder?Wz# zf9O>-YpUn+d^9L5C6-Tn_8E*LSrlgr$Zk%eF_KLC@J{6uAU67gG(F*tj0EYe81gduQz= zx3&~AJF<}OIgDqSv(~dbjWV!Yb4D~~)JCk7e~#1Q9O=hQ)=H7 zrXuk4944RRQs1m)2Gb2`fukpRzJ5W6&VGSUl@sZ2SO>ZYwP&}rC9rtH8VnHjWAo-m zi`&Z%iA_HbqDPM=vze_oaLOAE=Bu4+K|&-z< zUMq9NYPD$8%s23~V>$aW+JhQDbdossFN*iiXP@>;g529tSnF!UqBBGIeRj%N|1*t$ zT=WsY+}J`#$8N=4hdv3r$K!bAb`_T~QTVzg)YQ9`|TC?I9Iguc~tB=<^)ymy`ae-Sg?icKK|B2I9zlSlU z(xmn=n%zu|#}b23vN^Vj%{?H;WIp7Q>?A2FlsJkzF80CmX9D-FG6PZ#S7T{GKbJOm z6_IHyS&Vn$PY40Y-$y!7W`7z#;AIj_QmMkv6^3l6d;xFqt{R^vs<8TV`}nV}nZlW< z73ELfgzoi??Cn}(CJNp|!yZ3@G|izDd(nd(OV1(g^`lTd#2L4)_JAFh_H;E?P1rZx z!6>(Jyo7=Tyn1R(M>UN|T_O?w+gk(^eAfxNv$0gq9-&41Lm0j~j6Gj65d!*c*@P?8 zVRN+?{-+QCjly+s>$Ac1=%X=CJKD}A4El}6uG%#E$Pn0hagphWgJ>l?ibh^6gy{pDsZ;V57w_ukc%rF9I6rNIWeo{%X{iK@J88$tbj9$i zN1m1K_apP+63o^9H!2KOWoowexVWGh{tJpk&4IeiwkjPWKM*u+5*YGcWuVxk!&bCT zA}MCazd9c9+99%L~rdwak_}z1A_~oB@ zaK7~dRw`+*X?_~~n2pwG6mG&imTFSQ)EC?y3k9mmf6bkktIJ;zsXy&xm_d6T$&YeVMXK87u-b%*EgXR%|cx^O~EQ{bl!qPCb7 zY{>Oxv_V0Q7QScbQ>jDtIxAtZw+zibu!^dkxjJ$=8;M{gu3SWDc+wN_~?uRdCC00gs zR$Unt#s<<^iOZB{IDy8G9zvF)Oc|b0@yf52XmVwYH;>y=3uE&5Si(x~3ES~r`0i#7i57;A~=2HNjwe{IYe$U+-*DKr0rdIkI6B}pUzkDZkap;HEPfWjpFJ4Jw5ysBcW4l=sKu5q zIm)hCAI8;5L)e47KQQU241{(1(sRLQ(Ea`gF0j81+WrIR_RDwJKVOqg@e9TU1GCX< ziz?GNcMC4aUqPh@(vY1!ie`4#!LQjO{_TKG_zy%ZJUWpnUjeF$^khYK?>R@$F}#uU zcmCuwdtR>Y8qR-g$5uU_h;LrJaMGfZmn<1d8xNF%XQw@d7L~Ei^S~C4oQ6I{6WHuJ z2QdHE%6oOcrqA^%)by_lB3|vKC$W-rR9u4748Fsx&yMV@kZS+&U?H>8uAmH|hgEat z8Z@<@5xK6afu$NdS;(?bT6E_iTxeZP?V^boBa_6lisQWP_?u8YZVWSD`jB7pL594t zh1J91FWdyXXn3x+kDcsDf+qU_<|wkKAae<7{p2sIjF4stDUNjTnKU(bZoz5d2`K++ zEw5E5%MJ;CoCQ}6>FoV{@eh;TRB-{(v|E|GA>^%(on;U{Hk>UvTTUz99_9xY&47o( zS?O%L1zQ!+k8}H4A#mp&ip@15alSW>`JxZ2Ce3D&<1ElDv>w0r@#s-)&71c-vEalN z%)k2~@8Ft)G5Qw#@-fHxM@|drQiwU#o9Mux>WR!UZ64e3T8}z+6?51BIQ`#8f*&Gp zV}e=>@1~s1HaK2p%I^Ol*P(^$QursnS@Ds#s2_*gOZ_m@z6d`DsyoG~DMEWe8HV2* z4n|3b1Wx^4Fd3hLxx-yaY+DW+g-*vF!2wn8^07@xf0jAn#1tKC6Lr0BlP0`;eCBo(zE-8Pp)6& z(*)1;s;lqe%rk3tk-D(?=tIGCa0fIN2f~g?e>v|1q3~DEhD4_Vc%ik-o^P;Z8#_OV zZKVdXolADHg186xElHYf`dKJur`=e;K?K`3VHif{6=1jNc-X$-H=dt9hsBNv1H0Yj zP6s~b!*0(g_H=iwz_Z!_GBf8c^GdLc5YG0!Q)u5+DY)@Pg-QaB z{MYnY z9DQ~*$c?YV%8jGwfweof_8)~{i=o&pB}?hsZQ(*`DSW?J%0FNA8`6Id=3UaF*|$qM zurAvg7bGhPkh{O|TF8Jx-y)iQS(sg+G)jlN(9;$BSzqi)A#=SB#%u0_0-I2#bnm+0 zqngJqod^V(zDksQCP$~#v&4I=r?L9toy>n&6Lfrfj^Bqqf|bV`u%xp*194KeLJhRJJ zkdW=c>SuZ2ytpy6v80Oq?H()>7RG)w1Iw(ej}H;$6o6Dz*xZxsFKyBbe! zd5a6Zqgk(Z6v>ZY&NNAhA3<7P|UC zNp>;*VS8vq{~7M@Z9CzRD$hWjoovF4r`Yg4mZqZ7Ho4-^ZOZKGcx9SUdA{uA%65c#a#;t2tp2axZW7!LpTPh}g2 z?jec!(&T3>O+kkvvHDp%=6*}$LL1DTZ?7 zbFH1AGhC8}P5*)(4ufe{%L}eg)0K`@o&(v8(}Gte5F6%P=Jed$=*|Hb9AP<;RxX`H z7kMN0-|e+%a61h>o>%an;s;WYk2Gy+^<@tFY3LtOg`)kxaK$hqaM#(%h1x~pJ*nw1 z@}oD@^{29v!5g`((k^hY*+9DX_LSE5N$_C=@Yfd)U>PUeXx_FwT2qwA#q9UO;|~^GtqA0@JfifY3nUSwH8&{+&L;>h49eHr*l+ zZ$u|7ru$`Rm%XI`T4|&VU^)Rwo=xfcEZFY}w#wy42BHUOcQRb!0DSKS?%E)qOd+GT4%P5-WPkbi?8~*^f5Bb zS>T!YEp_3BC^|5MZ0IWEAuMmWe*Yx8e3YD?EJR?S=sf&v1voI%^0VLa$VXyx6<<`25@@ zbXzGa@OS=j-xr)CtFCzFY3e{<;+6PNH6i<5Cpb~6-a?1vX;`*Qoh}S;fEuAgGj)}a z&ohuEwZ496XzarL^%=Zg)?MgX8^=Jh6JH4D(Rn}Iar&_+l8#X%mjin2b7VX-Nw35D z6C5q`=%zcv|3cG{;S>;hMATn%8UKmYSsAe&U2B8q=s#+Fx(qprP6@qtqk_dDAY6P}jguSR29RB?bk zxpjrb?P$R!Wufu^OPxk_>azZIYnb)^bSjq9W(5~5sIe**q{ALC`TL(ad1+VL+}Ox( z6P0oqAH3+~k4rezH;0>b*pRw@rjSN;47M$7ps||AaDM$ds+0Z+!py@-E@-$g^EXC~ z(ZczC{33R!{48z4(R5kr7qm@yi_)&1?9rSe=34Xz6nuQx_VIC;64{AwP8iVqOC7Y* zx}1sY+yobU1jl*LVkH_oSoNwtID5|)(Mc5)kB%Uvzq5plNDI`tC*%BiPf^Jz1^(PI zAx{BBd~?iCZne!2n%u)dYD)lppZ9>9e0wZK`AmZBr}k_~+C%iQNWhR)`rOEu7g6QC zFQn-hqT=*8maZ%8EbUUA zSeo(29?Ksa)8dl>&@J_cYrR>yeE)!F*3q4fUIVczEd=dU(9>PQ!6p!Z*)hN~-`YqO7zh!8IMP+(TDlc>~MuYmU5E((vp=p^R6n&&x#jvJ~~v?upf`z?Z-%$ zERwUG#K?m5w zf^o2P`C~pw*b~3G*od$2jYwizH7fYb=NCHL@f-0ldTML2*HLbym2w+&EpMVlTPFS| zt4?wyu2}!Z9?wJ#;M!gOV(AiTkgt1#x34tfbH8Y+s<6a$9?PJiZ8pvy(2vIynsIsk zNmLd5AipMs@lDUl@Lp;*zHknr!A;U=qNPVuhn%NwtyW&G%LSZ-H@@X z@K9?gUHfyGNt(@OW6u?_kCG4JwcmHVqi#t#Rg917&|_W3zHI7fLr}GBfrKxc*-E2# zVCXpqc1)O$w?CUy+da!-nfuB>WvdHxs~lgC0 zo4(30v%IO?*wj|$Dzf64cmn)=)551{ALC3v_i^hZ6}WPvDl-2ENra0k$E(G%{(zGp%Y-k8LciDn&oCpzJgdZ;u-eNSB6&szq!*Ia&*+kpLXsGf@e81Db;Bw zYd%=Vs{5sIZsHYayfK*tIoETVw^Iezr9Ax^DzH2Cf?;Le2pXNXo^|I{@l)jsA@9Ki zusLMJg!BS@Q+khwX)A0A8;#$b<5@F5iF5^b^wgz;QTe&9z$5v9Ns9_--J7ps!^;A1 zqDqN=s#bIO`vH{1TcJX-6_!@*f|~2QuvO@LFB|I3zAh<)ePe8h-iz_~r~kNtzej<0 zS|yA+(*##eYKa~GUScEnDzU&(KVVRRG?}l=L**oEdaH2)?1{OMQ#B%-S47Lz6)^04 zF`l#YWMAhBnc&6$c%M4KTVRq*<6Ty~PNx;o zt(YKf%uF66;H413ZIPYG$(uglBodB6)#pqsah;9trnbPL20eCt?p)Y>K_oD3HP{Hn zxzz4ElFfW)4X2E=SkoS5?u>yHRs3Cx>7y1<)SrbUzPE__4#zTm1Axh2&(g$;U(u;y z1r$Bl1T9VP@YBj-Zr5iQmiw@X2H%balzxZ1JYul&>v9TO5YHwrTf+1UgDHKm6D)rm zLw*g1aMb0IypC@jKfKzNqHT`D-IMZIGJFpliO55r0WbL_z1sBnPa|v&6u1;GTu8^K z6P=Du!OFeHY{o$mU#%;+ZLk_@yyd_*dOkb|_=e|4<=~0vcep}j9Hk~6AjO-}xZ`RM z&bT!Yjz2OZs<{Aqa$n)<7diBDQJ`I;Qs`rv9Php<6Kr!&V$RiiIOV5LBei)v6TghT zU;GP2lh3D{D5tKwc__ts?3<(g__B(q&9pG+t475{g-RFl$xn5G5Ql1 zZkvKl>1p)nxfgA09K=#OwOHw#6!F*R{+wuZ0IoZ0E?S*s&IbSbi<6C=_~~umAi;A2 z`MfEC-T}7w$z>?L7VgW_ujp|1Y8tp(KR#p1X&#G{eb`ppBAoeaGn^EdRdrA8abf2( z&gbuKkwm%y#f*u=6H+$xvugq-*h;cBoAyJ};T|q9_Xw2CaVJGXKdN?Jf_-g2c*Pky zBzG%;`MglW*12Qpbn#p0GrPvE+~xq%aFh4e?MCUNo7oM8wYb!2BFp?x0Gb{hU~q3N z1wCp;gRV+(M#~U5&RwW}uCGJE|Kz#Kt9~@{+Eh}!e;oMVpRh3Eis;72Mu;-YL*Ew* z@L}IUe);ApxUf5k8aJ6kX6tpQKJGeeO#2Vq7JbM4y1}^WV;*vr_V9VZQFw7pcn{T% zgjsXtSoVf;?(oMgIIwaQyS79_Jj>%Tem#1cmmQpg;X28z_K69LwQ*tf5x`HEk6nL+}* z;|AsrLW2WWVNRqaiwWCu$q*(rcP8FcEt3=Y{(vG2e2 zFy>0OaPKjK@UNZdEq#XD{H_ci341}lFB&7C?C1MeB{Ij4TQPsJ7a2VUlwViKi8E(F zP1`aY=KctR|BWCW&zWrG<^r+zih*>m>nPek%0TV;GWfdQJfiim^NFJIdKHOD` z>ldkW>z6Ems{)H;{v09asFw&|K5gKN4!l6gf(NMOc$NRHa)8$^vw&GYGw{vt?YQSZ zNzlJn0yBl|>H2q*U|a7+m_K4Ext|=5AERDzIYxi*$Hyu@Kl3&O&*??gkj?zTm0RHG zH;$q<-v)cX7Ce?N1&Jg9_GMP)QJ+NkR*wj)ky&_fB$(cO|H&M4wjoK824>lZBp=yD+nT3@WeogMyhK zlXtuco2&$894kftO{pyDW;Nf~UO+>IXG2f#AHVxYX|3Co3!WXLU9czz&@AM}CHRqF#PHWb0vp$qBMt*a2BriAmuoIyKz4#Wjb z7kKxIvYYVvKaE-jAC-V2%MdwcMBPYi4MSi$FRG+}z$r||Wn3DA4vHyCHP zTXvi zo#XHL>rLm_@vNtC({CmF`Qk3lz2(n-*ZN{ZwFU+Jy@IncCz0WCFYNXN8oBr%{%GF; zi~Xc2?27@LF<~FHynKMQPfG>=i6T{%{enZ6MzYK`>1okDnSoNPXgs&H)3^05PwsX+$GP7*UlVIV~~$sz0Vi# z|8)*e2^{HJKO1qO-+$blIHQV9#;Pd0L+E)B09j?Mqty(rD0|5G=UkT38!C;BZDa#u;AoqJoPLO-sDYV zJ(i4?4_ymm17rDvIpbMJ#CRN1Bk&$pUB#jsrI4=}E%1;WV554U_|}5QP{U8B;*?N2 z{NV%^9JR)Mq{SN5g=@MHL0>lap!9gbA+g{r4%ur0W~b~(cm8Gm(cvVzcVG~B>{}1_ z6z-whz66jtwip^b6S(P?Arxn4z((DDgB#oAk;Y#`g*EfYXt9Dg_qI0|^jAdEiD}G# z!Do0gFb}MDj-~WUZ}=cpE@bU}@n)M2fA{we{QQm=rQJa)=X*40>XwP5zU?O3 zn|_0=)=a)_({a|HcNAT{$KdJp1~ljOKz3+|0h;8R(Z!#Qe5Sz!vJ6{IFGfGcUGDzy z$Xe)UlzY>ozo)VL)*1>(BCiW`#7jd5&_#Pmrn0$^ z{6Cwq5pS)Tcac0^9&;Kt7?!d!Gog?F-)y)u&m6WM+CX30P1xj_y%=`Hiln#y!*e<< z!W`C?qSlf2`M_QkcFSt4WTJ9Tj)y1UYKI|oy|RE z$71W7@t{hlNM1n!2c7oh6Yk|Q*Y--ZxLL$uVmhZ#l0%}GDyVZt4Vn_wsa4aI75>-- zXLaMqjXBW}??FN?If$x`3*Pq~cW@O+u#}`cbli3UFQ=H0Zu%1#D476Xa;kZ0hnEo4 zY|RH2s)5_Do4C45LYM=uAZ1w(Y!;r~AtjDfV=*4WgUiTnhdaHq0h+A22K@);P^jky z{J4ArHa0u3#|sy5`l&Y1BwU|+>=5y~Gt-!S@@g}iFY>&=F~S+eC-8i06X#l7h)W|o zar&1;DlmBj(^QOD!M|XFlY>e7tUGS7Hl>Fzym0f^^=R32f>Zk%iWY;V8Mt$#KjRs19eQS~`(!`q2kxpO?d7zK(nM z;3SK%>%gF?ODMTpjo$U|!k`>YR+n=K*L=BwGL2(sk4!nPU4EYb`!E%6pW2U-F-p`N zb)LTYuEmwHo7k7q0+ZP{&NmoAe<^B6uj;#x`vyY`f zr$nxEbvMp2w0ozu{_o(^0Ia%-^x5u@z~E8y49QYr$jIslSs8Q zwAl5ieqR6YaCBO{1cpb+T_%t7@%Jt$hb z8)m2qJeYy`bkD7eofB9hG&o*B+mlADljd6BWrlrf|sK! zuy<${I4udrsNwsev}!P$_tl7v7VeuLwdOFJq!8w?eiK}s;DV7AtD#un77TpjhC!D; z!sBW~TH~oqq45>`*uvYGZW={%d^{-U>mK}C=RpfE#ZY;ikbk=&FuOG$LgwZ5baek6 zI8&xifj$3l;Bg1|dV2tSmMicP?$3sR9V6MamB|oUX3Czl`cO{XGw^;)aP`#!u-1{K;FA-MUcC^*qA#5GgL%yKOfTm-b{MU_WlK+o{(*&! zhd?G)8BZuyqG7^jE?~MGG^#8m`HQxEsIeElJ9?9wEFq8XSIvq2Glr;RCowof5_HBY zF;BlhZi)1DUR2kFHhK~uS#HJ3mp{c(6OzF7-7CJQs2e_9mf}`$g8Si!85}c>#ShxcU^G%1*rz&jomyqzMG?7$vj+A^0da&sE+#>P%SX3Yiff2X~UlPANdA- z6|lc}8{3Xwg3NcDFu`moyc-$I+g=|D(b{L>xG>9hFU^Go9Vk}nIKZXYtzup^F6_dA ze16HNK;AL10))^$%)!i?VIqW8mj zy@}Vrd3HL|*KzFUlqm5?|0*16c?U<9nX_XP{@~ko7b;u-pOCjZ4iD}W)9Wrt_Uy_? ze&&N(*uS6W)+la-iFqMVo2rZ^`TkL^VmmQ4XUq=;f9Vo z$li?|fhi*^Yx>Sx(}v~AY`WxcQTv`SRB7ttuG<;WXTi0k>U)^oG2TzRJj2D6Z?s6w zY!rI-uYtQmg)G*VUb^{Z0rQzEL;t*E`6TyxthF@8OP=Xqt0l~dUt0@#fJIc0kqSAP zD_FF^Pg^hWE!w}9!+@v5&``$^hWmO_$FIlypu0a%eqJ=|dO8*Vb7;evg7^FG?_5X@ z>%#5L8p1g*Qao0@05jb4Inoo@k#HOI#U09nOE}VO;n}jw@(D;5{o&yF0t!6i z&E898qwnG6tRl054~RL{#BKNEIUxUE=Azv$&l5lCm1|OK>X4%;CT)0A$WMl4PsKmU+LWs+C(L4gqu$+mJTjyT#^s*@(U8;pyb(aY zYtOM&GR*48>ZuegU&hj{AA+d{iAKMg2cE5o{0eJFGD?W2u}HLLc0Bh}w?L#LZ?ZV{JX{lB z%9rC*34eGk?8j8J_R^E+2zFxO4Y1nxiR)By&X6 zQ@1KzQAnG&E2D<}1y&mG#xlN}vuU8fj>Qhf!;K1P(xyNLR=Y^fB2CCEp^!h(JuOQ zAeO(4<8jmMfwX_pZERWm2lKRNvz!rIK+1k4IP@N1TIJ3(tKEhH=ySHM{%?CL+(kGDGobR!e0VgT5s0@$J{RQb&I_5UxYNiY!>r-9Y>ST zo@V~-=|LD_zJl$PImVBw6nd*~zC+}*+t{HdeD`0~^AEd@!ud%+J+U%$YjOvaR?jBy z+2_!LW$?4?ve?3f+NiS>+rtWIRYWwokKD;goM`86Pf)~x*^&70 zh__xLyeDn};;ub9c)NNFglKP~JMGV4^bJ*})TF>BOfcaC3T5!u*hJ1L zT?sy}@Wji{HnP3?+01mOF{0)a*7Hr7wultC6|@KL?A`-^C)Mz-pX<38m3^?mTbaTK zPRGmt0k>$sIWORFM&nlyA2eze>(I}_?T4aBH~b$4&zz4M&mvf9i!bYQI0{#S z=AgMSW1Btby*ML)=Z(wv;0hfDl50N$-|k#Sqqpto`6`Spf1`@2o74H>68mvPcRzey zXh@#Gvbl8#~wxA&y!JRbA zVaIo>L4CO~G!DweP6JEm>sv(0laZf0257|J4-iwCMm>*XIVl}OoU{85m!%{ySR^93 zVY)Nfp8d1gDdBhd+NeUY!AlF+k;u_D$7mS!YA4@UHH&+esz{TC{LVU=xnQRi1Ftm; zM4#sc(<%=&veh`oa?Z%X$H6m5JtG^^b3A#ckc+S?N*QkLUBk>y6=QO%E-t!dOmtbE zJa@e3ADj$;qHp(kO9>ew_606itfFZvvS^@m1`e+Mi-9*&pyqNKcie9+H1xM&&WmY$ zQokL!+*;4(mfpZeWB)LInnZ1C|P_4*GnkVn%$2eW?6#e z@|WuvJNX+drdv`&{$_ThI1Q6)CLzDKpEppd#4W?_iT$3qf{{ch>yVG)U#s_W@8s4) zr}A%pm6!wTc2AhSsttF%%i%{Y$mT^RU-|yuPr0wTfc)D^)?RlJKQ0u}+K@|7IWnBd zLld`SZ#**M6e@uRm!wuTG61;yp&|RTZS@%L4{$_bY*0-Z<%!A9K%K4+X zN%;rRWcOWhRQ+N&w!o3D=JTN1aFYA#s*Z>D&rl^Mx9zznM*^!k&uSrM}^n z*;=eYQ3E#0JjJZ*e^7UA14_IRzKgpOcthl;M~tU`PEoi< z;U{bp=8p}x)_~5z)%36CgxFxqSN=lFUGV+k#1w1~@*<5UyeP0r_P9@Cf=vzer-?AW zq!Z@O3ub?Jjz$RS2MOgxlw_bs54Rb!PYYf`ewI4jk=+Jv=?Un%MGvIAk745zAM$*# z5!P#+LRTd{d^~y+4m~r8%XadlEn6m2|IA(RXstE)NzP<*>_$QiX8=9VZ-Ir~2E3;* zfI6M;(SOxf_-fS%EWU6YkCz0~(nFE#ik>=+yT6}1knTu#4=ITfGj6~#{VsG-J_3@H z<=CQSM}+*#JG341le5y%WB>im#n|Ce1iGb|uNlT)5SZL5r!{D9d=`d2&k!qy4S>KK z)A0GoX?XU5F|~eN41J4s!_V$_%+J7vLH82;XFQfIP1b^g_s7GH#Jjj!;Ll6(r(v*g z#%kP z8a2!xT+O=R%JnYh$o}pNDD>Kc!1qoQio z2n>x!HBsbb7YTC&e%)h<7?M+H;H_?FipIUq$BD;Yi@Ka!K)(76b=WRqLj(r%$Bzt7 zJ&>TB`7vD5xS2F!U?nY7Er4t1{pr7P>+x*oH)fMEo$ps%K^|Y{ko1LY?B10~-H!$C zz`#QOUga-N>rDVIyQN2tzB}+rULJjZAuz12n6QWsLXY;+C-`3S9*jM=Qcn0HG_^lK zW~TdLbtA+&fVZWrsPUyJMGS zz(ge)a#)x1iP}noh5M=bn=06Bcn{iVj7Og~d(!j1&Pflx0B^nD@b90lAb;Dx+#jtk z=+Ie7gBypkW8X%z;<Ig1svPldzzuTkdST(VC{vlLYf zXE$C)(Cf#kAW@(|lA{XXY{53HQ2c`i(^OcY&J+qeJP7nQ-Jrg?a?EZ|FhwUzV&Rxb z@@$Ub``w8<;aiPuMgLH%JBU`#`hu>8ov6B09X0-BVc3@_SaWg-dtB^*F`9^>Nv~nF z@m66bGKe2prh@0Me}q!L0kc-!$4QHJvy`45*eQHo{RVXqEzEk3Mb3bK#X_#RLk9-w z|3*K7g&`-f;9P@z(B^hJiY{8gqU#6vR>#$}`s**zYFkrQ890&6DBVhPbw;7S7DwJG zIR- z9yQM#Jw)dVH8Hqv2TL*0qazkl>{>d<-EeZ|+A2H2%(kDOJ3EYRb6x^-?|4(hIu(9c zV?4KKX$2c)vYmDco`9z^ZFs_A3jN+3%WuiP2Seng*^z{uXmCnO@W3PbX{2M}nxQQB zc>~1pvh-#7MSh}D9EMh|WAopP=5B8DWP9ewlU9i{>#n;eFmtRZv2Y_lEIg5lLTpKW z{Q~$He1m)c8Q5jBR*31#yRZ_fMRQ!W*gxH~sQC0CrF@8kf{*L*eWpAPxw99fOp@@~ zsB!Gyj9D-zV>%@_y9kUjO<_)G&u08gV5d`p$x~|%4pT8@!OvuA^sXmxJUW$)nA3z! zk4LhKick3X{W7*ezJOfCk2$NavSgum3RBG!=uCj{J&9K!QN?Ti^YvU-q3cY8DrLd# zjv;(==oLfd2=+ci7b2ac=u)^O7#^vlQ3d{F>2ZzUWTt@srY5qL_iwQYc8REVd>iQh zDkOTcjGUa_V(0!EzH&q%lOWT9)YSBfxbkr^A}oyn}5_woj7F4Mc4%5-C^ z;0XRD$5h7#v&<8bbatm6Y0X~1o^Msl zBBq6v^G8CLv+aq)@YJY%yyGurT6#m5orwK_=GhSxYcZFFN5nCWcM~ZoMU#bmB<$>a z%&CfHn3kt8M&~?(hhrvFcFa5+J5P?DDxlyY(4q@5C8#j;px9~I79L$Y(mM{W_U)v{o1<_+vLA*!o8m67Bdl=1LcYRcJ5`m} zZ_o0A2-vc3C-Y|;KPngDCK{q58;Y- zn83SD)%+jVXw=DO}oKGpA zl@JfPPu9WG6`LX8Rtx0ZeTkj7&e5o~)0odVcQ&O+=n>qJqV(Wl^fR&@U+jGa>z*#5 z&JJC2&b|vya@V2FSa{vmqi9(B9^Z~RMW-jN0j=AIVAms4zD;5o|F5cq>zOnOYcBoe zY=RV6^XoJ!Y&*vt^~z#(>+kVN`{MbIFGJWt&m{2#6(jC(1>*;;GACYf4h?pX#sm)! z)~;8Kd9YNpJT;1DBx^8@1MkqPxgM|Y8A#TO=Q|ePh zg$8O&ag;H8HDR&2(vVX4EBJ5zbQhtWav^?lj3J*!Vb+xyfV-S**xzw(^l@w{IDAfH zw_E4oh;2q}!Y2nRDb@n<9To67D~7Q~7x+0lvzh0s>+me@FivhLV&i9wh6;ZL{?7YC z)N~&}UE&!e@9`R)+Xi9#crE(&y@FhBUPI|w0MgWt8(!V#NB>wR@aoTijd%rYdKC<= z>SiRbJlmM!!HkcU;kc!W*lZ=ZB2OQq(boi5b9EaUNHX@eW(mHL ziQ}#u`pDl8HxROt!mj+aCVdD$g%5KQp=9O;R4-P9p#_&YFT+lLgVZH~gYQKdf``@h zL@?Vu;s!r_h5;Lx{|u)ad7x#;N>DiZ7$z=nlbzh6? zF7D*dPqt^$-ie5kgP4JyDZ3zVE%-&pveTJHB+k$yW3yuJsewIS+R@G(t5C&l`Gga^ zN3i(@FTlsigI3IoCBaw5z5I9?ALd_%H)Vr)W4$qKp}@PCudxlc+D`@Nz+Cp#c{FRO zI6)(qkAddD$8q*d4Sw0rrx3#{vb;4qY@OO$*f>8FZ+DF6Eo9q;yqFhT);xmxN5>N< zV+6_@4e05h41Uc}WqR%x1z!dBe_psDW=y#vnqQ#Bwg#u*)h+wD#<7DaVbe5z@$f0E zdPbJu;`zztzj)6ry?B@F?ij|>y$vYBZ4P(bvPRr=UGQbqF2c=wALE4o7Fvc4uA_8; zU3BIeAMbt$J3CjzZK3+k=DSKCpm7)LwEeL%n~MtHsRTisocu7xfnCf zh(@@z@|~~JFk{JQcsG1MI;&)$MPnZJ+mB;6hlH}QM?X>0staGl?iW0QULef;)QA*_Yuk-)ReNOw}ai*~|IK^YcJynXGturV@>e8ZXGaj&r_u zeQEB2Pn=PH1Y@0^H1}3Mj=7}E)J_dzlhqr+=ux$3UW){KJFNz_m-3u?y*8y@G=oRM zFZos7HE6y$4}NTw!n-+xp~s;JTa8udhvX($wbSfERGSnH3O^5TZbX3ZsU)~in~%2Z zgSp*jJ0bYwY&r`GoZCDRThZOXhn4ToD~Y4>d1~hOv_XPY26&r@gt}3lm803TcpRjzmI~zSyPz&ot2n*OrJKm z7V$ARbhs7zI@GauKkK?Umi^mMh*oL?plM_ec{vf`5Re*~wY(SI8(Y$Bh23YE_n;r1FfHSL8;C-JzyW?O7lh=E2`Kzy^ zR+bTcammIb**Cz}!ve>(STOlO3r_xiAAdq~5G|TG0Vm5|;vdI$Vn|j2@93kBk|}Gs z65XpXyZTs*QmV?M z4E>IsJ(38z(=u`KRC%kR8tS0b(FAw8#D+d&&tNd@dcP2YD!LhaX4yM0b5Ij5GY&7by>+Xj?JVuQ9}Rgh(7o5=tCI# z^A{v}IKo2LnULS_2kgU6y6adC4dX3P?y~|_Tn*r(u64kfnnD~q=M-)!x`wIT046&L zAV@Qu8d~}x^TJp#YYr#N|K^BVFMWsI1+)0uZbSJyPyJ!I{0y#fog^Fnp9oJWEn_kd zcd|ki51jPI9q%6ciTTE57_I&o#E*us$4@j^)8JfqZ6?KQEqn@Kt;VytvGo1Q7rt|9d?lxWxi(v!v5vw-8ThNt0#U+W<_Z7Rxb z`G40T73)?DbJO28EH%>}uKt}&?~m-jw3B+QKy7}fIHyLvINk6Wldx1SpeN@V{ zwqC`3Xv<3CWvQHV!87qIxXVQ{ENJ&@@uw~w_CjFV%#$jIae`aR=iN&ociF~uS;$lN zumNmB?pPMSY&f?jbQ(^bd<}OiMX6EK_E?sv1%sUq(%ZQEc@y25SBRk=G==*$ubJ8;wo;MG$ z85XjWZ?_416c5lpV9wP_cjGqg+uXW2B6v`_3On}aaO-A%;Od5sW51^Na1EnN&@M2Z z>lxrqjlp@~rZbGDNKIu1`k`<`KcFToW}9FL1hd1O|3Xv(aOH zp!SgyTW43rJ>Zf+G-?lTbN`mmB^iiSO2Z&!jvy%7bPN|%M6sRylJwB%DIcm6kF#TZ zxPasPnCof-GW+faVS{GFsYT1dI%^okm$tFPciMQPm$7tdK_IFBNN2%|i&*)ZAv9!S z4or8uDW2n{PVa=he3hLOempC1mU3Rf#mO#sWvvVCHJprLE8|$noO70)Lt@#Ssq=*A zQ6)Om8-V*0Z_(%Nr@4K$#$-|Z5o3y~F;@FBI_jCzYJ){IXyzUqeqkOL@{D7?QO;al z*AVvM{Z9Vk-NW?3eLQphnTAqR!1B;KdG6kB6Kef=u4dBjGvL@GAut-M*!l}2Xl?6r zJii9$`pB_V|04>7?kT_LZmn2aDg%^$JwxT|x3M+#w~&o(=e=6~@w1+1f$ySn5hrCs z-&>9|zhAJWv>sgI>0-jiL50X_aalpzBtTK>b-H}JR zygL@?D5b$x^>$*!sVs4wi#d62`G(w+2JZe*Ijj+U7K`7GfbIID*pH54-q>58Hg_Fk zcg+6q2kNHcZqpbl?6qNPd3*TBNeQ^3;shox7*5|dOET@J=fGOmhH?c)@lR=OI?!Sd zMsnL>e(FT<4DsO7<~q~2HMep8@RsK?hl&uc7HgIUgDV?L;_6wa49!3{}A_-q&szcX$^ zoR1$j^v49qiWH%nSrJqnYX|*T8@cJ7huPUWD<&`JM5-h1;nM}HMav_Xg3$mqSfx9W z4N-`u0GrEbrISJhQ^HAYQx_~{A~w%+E`|SGfQc(JaoFFr;9)kAG#Z2XA1ks!5_Yp> z$9&-&DzF54Eiu4CU=jM9=s_aVT$UkSl*o_ipIg1({8ln ziwzA+(<8rCdtp+s4{VvZnI#XEU`e^t;c;ODE-{@b>|IW9|13Gm?N_I3&$ckpP${zh zVgWWrDy;GRRn)yC#Wo7r2DU36Q;VNq;lu!1E8|PUcL7~Ku@M{ZEEOEWVN6E;aYe+r$il4DcR!2{|1otNUQG7ps3??%Zo3pRv|VaRn4dX##by#G~!%hW1Db)g0zo;!)HiQ03|Ui6e>^K`fSEc?c`}%6cU98n zG*f2cJCk{sML>hrJ~;PwAyp4n^~g*c;%M+&f11Di zFMsxR5jp=?!=mTAlML;nGM%fiM96x`luu$YZpXo?YCd@0IVzsgQ3j5(BdpFy%Fwc= zm;4x9M+kpP!w{HYaXjNn;P9KOj>zj~34L16fGOC#-sE zOE*-GP+N{7YwvBubBF5C3!>0}&j@z7(uCGkR+E|AUDWuhf(mOdlCwhrW|hBVy^jmY zX-EJYefBW5{?%uPTr=3UQ@U)}t)V!$X#yz+mvh0+q2%oE#~RGPfLq^NHrd&XWXtbz z-*m&6OHdC#=FvT{EZk1rhTXz>_dO~!Cxe^&SseH40HqAG!2{fTxY;wCeXlVUX6ciu zF0u|RGM19F-Rhc`wvW)xWi4NNBb`lIwp=g-?xRyh4(!%KA#-QthV=$(Y3DK*Ec;J| zjU3Fwg4kpz)I1?%Qn%qOyHvjQW(9ZnZ7#`4snEC=tzxa4c9b=ABE_FpX0J9(rqswB zbgz_TA49sBXqpR?uIz^E(y#bqYfnM>;?FeFaSSsuiK4CF0Zvzq&qf8)vJ3qno~X(n)*S}R_iksa@i3&EJPOmg%Yc98jSiuL_vB8B=(5*P zu4_v)H>+QP4RKC}Eg<~PpEDANe7qts^R-#^M=i!XjbQdwz}#XEi(H>{!)&7xT$Jt# z?J;rGJaGU_xgN=-?eeGli!`yyR*C)k{Z+`CmO_~L6Fklo_InHOfQQv2{*>iG_&TVK z-_`Mk8!E8GqUJK@a_tm39JXT}4c{4Cw2NeynqtD<8q&=aW5(V{D$R6dS*A0wV`B!p z@$HZ(eZ*SOOL@la*4JX4>g{a$-Fq-^`bp||Scffg609jH8;AdkAc=&%G+J)}Z0yR# z^Yz& zy{Id`zqcQUA9Jqhds~geHV($HtmXVdFJRG6La4fGDGO~Cn6Bqy_&?#lMOPzC*_3`2 zwn?0iZ5so~?&1Jk8LY{SO*Y}9H%VNSr5Hw^8Orh-2C}QC7U7t{%`k3vAC9%Sh$g|K zpe%GB8fq;UhonswW)(A_FA)U4$Y5G%YDI0^AL90Gp<7t_7`hH0N3&1A`A^!~)Ok{x znVk4fV5^u=Lx9lJGFRuvd5>eWfBnMI2VG%^!FGP^vgOt_b^Dg&+9oRWB$f>#|S_cL>Vc zk3olD@a8U~s6EFC4?kOv$_HX$;Ads%*moOu?=0nZbc})BKMcwG z1g`irWj1u-UM{m=i}E*^vysq}pN&K+Jl=qtKMBo5ojqk)A)-9Z6`yzh3>3cL7yo?=s zHj_@i8UqsLLDYG91-tfjGkbd~5cJAQ;M9d!(hg0j*^$h1i$b(m-!d)sOHrE6e->fA zNQ&ldwjiy+Cuk`%LI;^`tn`TBi2qkFlH6H{U-~j(<4zgMw$H);G9Qzy;!)V2sfcTT z?!Z=5;|E%4k%O=|Toy3~^)@K8o%cF~jM6eRd0s-k%ZAgeU*l2TP?1-%9LE`lcP$Fl5!(#nY;vSUW782 zjkeTrY%cVMoYTadEjpV&6E3^J>?)5!RhxFL5i1SG%%} z5!$@r!MDJD7dU;E`^i!8rOaP<)N+bhEic`B6-N2~?$|ZY>rugx;my@=Q>BS zWrN69doEo*GfUWiPGhEGUTol|PA~rqqnp=ln8DpZxOuD&%hbBLiik<%C8NSJf_8zV zO_jj(UqGrt-_mdHbC48&7ntyOA?i#Fx;g~ortPOm@tLqEpMQ{)YR2HBAPX3u5f7&f z&f~DCZqeJxdECRIqvEZiCAjC779TO{5dQk5%C-q?jhz?QLVEjIq|sUwJoG%T`|Bf& z_!)&B&y3h_`3Tn3u~pbr+vDn_Uf!18aEoOEaJaqTdbPO$Q}X0VGBg6khCjgZiaCrL zBy>{zGQ?8ldVKVVsVrio6b0r6L6pvH$O!A>4IS!W+58L~G+YMd<04Te&Kqrqueh&A1Hki$%b9aV`0@XsQlp}f93op)IaP)@dKN2ck*{WNbJiZB63hZ zO%{&o{o$`)+Cbf-m(ke=Y23~>IqqEjVpgA<0GWOze6p7p6xVi%Eta0fh1zoDeb0r9 zI&cPG_>6?!Z(jWFvI;2t`46{>p9^OZ15EQiBQ`$Dk!nbx_;|=tc6#T0b~Wh&KRQIl z>Pk?6rQNP+Z28>9HP`ZHv4oEbRARrK^##^(FUL;Crt4#wqTC=%(zpg=mOqArQ-_k; zqVbe)u^Yy;)uZJu2fC1yO!~rX(j`<1XU5k-bz=m+Zxg&Vf41ZEAq7nRl@c9L`-3%u zYWZgy2Q$kv$#~i}N$}XHao{RXb~<`+I4ObOzH~LsPaKXvCnFcoWWmx-?qV%dd2!Um z9w?tZlw`M*i{g`1X_8_K=7p5ty4)_2eQi2uNI27vOLHLl!*$Fs%x4xtUrBsb3HrzP zz@Uzw{DX0!7@pb$znmomR-^)CB&(8KKR}pUA@mY={e1p_wkN9{NGGiUJ<_fDSN=8>`YIHhhD?MgHDP~#qo0py4~u;s4jFgz{ z8ZqztavtkBa0xYJI5xdw8oRY*IeTc(4Dz9jZ)@0vo(|`6c`foUgwF6-t7zO_BINKl z{Sf6F>vC3Gd-(xv>iDebK0JPT9hZL7Vfw36SedU3+po6@RD`^p@z;wG{9_>KSg4C7 z^5nSb?G11{`7AA5=uhiTJ5ZvQHXHv+0nCq%A@QO&TqQkYvU5z}KuQYjUDL(!f79t| zWD_P#jo~)0FlVpiHJFHsad^oEdZjO1i(5GPl(q94JvXtVyQ9GByB#cxe8u1DjN>;8 zpKGvqHe2iJNZMbPP?W+fZnp9y<~_O)3i(U8BjgC1f3g>h!ykf%oB@n*{>}evF~#2o zPcZ)2R=#S3FV!23X5Cu__rseH*fM`Ei^ej+|@*S(8Qv`!PwIZhHBX@BUSI z(BcbDS-%HPuS%!Vg7K{Etqm2a8{wDner#6e8LS@Pz!JA^B6}YfT=B?;YDEofeQq?J z9e5fWNR7#~s=3%4w_Vkc@EcQ^(};va@E8i@=$7+Lk9a3`KVP`Yh@e z90B)F9mBk;NE&-S1m`Us#`Z3>r7@c((){8BZ2Q&OrG(KfshMPZrho+mwDUy| zC$dF1_hH!1Nl+wYDtt#(L%L5nn0DE)t+lFT;~_~K2T5FfZ7`W`ulSBWTVx^sa3b5e zMT$iZc7feH=dkEVJ-j=#4g2F|FwQ#@b&efCj|bII?WE2=Tzw^Um?Jn=xf1ZEpn$v~ zcz#ygfzV^hG)}$|Zr#sAKRL#BJt?K>9>(l}r989WHx*y+YvnEcyKsM*6zla?fY!^N z^y=wcIwsn~0=;JP;{=}1-3?DMP&g}px^zTf$+>XnCJ7lIUt6@vN@iEJwz1C_KBJ7{ zPCWa!hx?-_$!x|Iv4sy7b1GIN>Eh<2eEg96+|APeJ1FNvTF5g#>f8jhDQkn?M^&OP zZ4dCUbs^p?yT{efXynq0#MrR)6I9noGCKn!N*txjW#t8m{fx5ltyr4|%zGy~Hf}bz zs!v*&4+2vb3v=gpIy6$?-&zSX=cUDQ;HX{CDYFQ&k=_hLh9ogAqK>cWQ74g+0~zRa z!px7lbZ<%$y!3w!e6S1U4{)XHZd)*9Q3Tz1w}_qnJdE-$O=8Dq1yVu!M3K_IX3KEv z8fw|o&iAZNrb%bn@sBq4Aegx0vC9wOWO_8awJ)*8=<8eD-s^#>f_HKCHc5&IxWKp%X{;56ab)kyw`=bN$`B(Yc-}dS2=b53Q9o0RbLpyT2Vf)aYnrFY=>G059ICOUku0AlgW|8dC z^jH=%R@jx@9LIcOUAXsu1vbu<(Ig=wu+=J+NiIN=Cg~R8XAdj7Gfb1HFN%GzJ<75Z zw?mN8H1^=_KvG$G5Thfcgbv+l80-8$iq69!r~ixN?L|vdrId!E%u3Ha9}N+u2t~*Y ziDZ+JwkBzB$u3b^dhR(2Q6z+vkv%h`?7n{Y_b1$*?)aSZe!pJEc;!VZ?c5PX=T|7u zjTu|8L2?{*t=e2k3Iqkn^ z#w;|8;eOac2-2NG9;2+NzH=Du>DmpW-%Y^T-?T|T=dsxTTD-uI1uzn3{QIo?`Ntvi z*?N&5f8ZGpmUDG!$MG^&a#@}JME@3>Xl&uHhn%N51Mcy;pA>0E?lpmZY9onRx4ZfuwsP)~N)f&5DQTIyv zl6;kYiyng!X1!>?Vh|g#Xe3?Ll4A0Ld)oZ=V_f;SgpF05$?$#`O`^3Yxy%EKY`3r+z9Ynh) z2bkMMfvNp!0A=1b0yBd=?054f8MRLA*{M#$cWAOf&I?8B2F--7@1fB4Fc$*yb9m$S zjjXWQpL94G_F&dFu4cjw&L{5&*BE>nta{rZGT#UWE>L5Qsd7xLKM!g=my?oLC_X)8 zMS3<7;9W5ZoaPQ@4tJtqK2(dA^$%zNqNC`B_i|94qDP$374SC*CgowrcnMv7=Az)s z?@ZssPi)g>eWr8i$Xg{GJV=5ib>CqQF>9FBHv@L~RW*cp>(k~RT^M`VpAy$s<07|E z2&uY_F9VVQ_Rzzyaql$trZItwdGLuFGH4n#M2>P+asvsjq-%b2^e z#RG2XYLLPAdt%FNy|5u&pMP@sEvAf)hT2GTQGVz%Twk%3#h*}`IIiazyw@tPOBAw^ zo85#yxlg36uJUbo^EHwUaxF%K-D>Qq{7v|JBp#G^G^5D^eby&Gh+YXyI`M6He6;@& z`1E#x+PdBRjwd!4=yL+?p9aFk?3b*?%aRW7alqgwx31EpLuvMNrHm9MWj@}l>rEbT?HitI$V*OZ=$W zoISd>nEG$XP^z>Yu1|W3(!--TyX(Dpy{}B%WOtUEadIdY^uESQf&KaYwJeF6UD>3C zk|bRe3k&O&1@2if%Q?~rM|?lQ({DLBt5j5-TW=auQbwE|OVQvsF2JP4>!qc~oI zZ`tf1ez)tFsBp+3uFN(Y6N=BUvpa|%+hNI0>75j3?-uwq>oYgUpMP}Et?Y98UJEKsl)t{vAg;U6tZr){u3%j-W zI@9^E33lv!!b&S-sbo_$WOR!`R#F|0t^G|k*S9f6%|rO&jt`p}7Q?#?`^0Xq{0)5S zM0RbV78@J=5*%JXfdC6-HsQi^EL--SN|+s0FHI7zXRMGDDuX5Zo2VwuSm5*)vxFX? ztxL194=eD8=F=p>+kAW9bvUNO*sNJSv|jc(o}VUg3O)!xZVrTHLbSI(`S6pu^#u0VbC1yS<)9eh_C!N&Rf_@FRVrgHrmt}O`1%8d@R zMJk%SatOm`*MoTAXwLgaEr0RxQr=C>sME}MTB*fUkJ3GOxF}0ReW|xW+l?>SU zigTh0QyWU{AH`>NS@BW7!os8|49tM$mnYgQ|4%CHSb8Wsp%V~**;2F70*=>vXoA+*JHTpSsbYBO| zwOU4-mTHrEp9LOl9u7JO6Uly*8ktMF)4;{Ke4$4ZO1JF6keNbWMLCUEJRHSdnf?Nm zT_$Xo?HF=f9?7yJQ?X3LjE$MTP3W!P;(T*1@c&H5bCxZqaHOrkt4dx)H-5Tc!uRDA zD4&UcLY{!<8y-ezSTYKg#X6aA?#{BSC@=7zTW%i3`R9_T)p!SYG@%}Q*Sv>7cNb1dbb9qe)#;!1{yFMifH04y-nk;!%6rPN^e+=N?c7pv< z$#pqS1K28$oBY6GJ>1En>Fkt2zbLWJj;)t|1Yu`6R%RE@Tx`2J`=xUkcn!ig-WF8e z>&0wSDtN7JZ(w4}LoV>27X$=9V!KXfq2APK(A01eAJ^wXyN@C{-VG=3Q-@iZz&Ta% zu7jrq_0VD}K?9wt(92~QdhGa#ZIw+Tqu1HEz(9&l7^Z-1L_SK{K7pINHrmh2u|n0T z;rKSNfKC4@!LGmUgG5^`QZ06%kUJ%;p!POQeBq8SEL~{#ygGVj7a?jCdd?r?HEG)C z!5F_#n%RFZ!O^b`9Avb&6Z_PGvK|`jY0SgghSUb`gM>F0dddi0_k%2J(`A0vZ-H_4 zYAE$sr=z0B6k44Z52*=f@!f7OtTYY7^4Wu!D4Mv<|C-S9>{BeQs}h65{M`IXIVW&Jlk^y543(`kWEJYgHHOceNqzdL!UgR`0I zmHQ}N6AGsKikwaNV0LO8@J$msaBFcI7pjP`v6N%-zN7GXT`~=(PVVsY(YRdC0(2C1 z;o4*J(6s0?FR?q0`{KP3W;F-F0c&17tDv7d@aHN{^^;>uWF6W1x~a_V%O8knTtMGF z^x2t{(%?V;Ak>b%0T+{=g4cp>m>aCh=xjWwmF0k09zd&CG%263XSTruX!hZsD5?Gc zXD!m^3MR*i>i>FCyGcDJS!qz9Y$mQ(XP=ELX-E@uwE= zp%|_Zx2SmXt^YL8K7S-`Gak!TxLktC`|fdtRw~AQKt`K zjc{mA30mCwCVD3s1jch-L+IM|qEz{QZpIgDQADM{FtT|hKDl5os0e#gkI$RM4hjEp zt>cn$TG$;FY;}09S28kF|_DjF8e#I>K|DdWEta3o|uE{dtaCN+-j_n*&H zA1kuDyaEi|RY>-4Ghkr8BAauh2#>AQXHmL_LS{0a-Lm?B=5inlKKYL;sNEvIJVuJ; z9Q2~L+}`XkR@+ABbxj177o083(>Y+*bmge%2W4Y*x)?&XQ(z?@0>*UlD?o+ zNC7S?&St*?^=M>_98}E*8CS$7RfbZ? zr*qt=ia_{V5laDGE5J8>J~MR*;hGb^L$pFOH+0)(cyIL@CXAK@g|}AhyiYCYD_YU5 zrCGRm_frhe_yDt}HlS<&AU101T;?407(g8auV{+S-9tH5JfyMXBFCU+{ej?QVpY^J5LSob}Yr@+}vr<%{B@tDAbFD^In#iwR=uUb>{tCI@ zgKYn@7IYG3q(_%Ufo1n)fvve7tMk{g)9>`zw7d=6!<8;@J}?C}7hS;NVareaomDaL=vXW)eRmh%-rENGSrgcn zh+EvXu^FO-&Fg8-Tt}AqB#Bc@*vlAdLt z#F2|^^R75(7-dO=-{nBbE(LfwU3l-O5&g3Snx^UjmbJ4W{O}Ie|rF6 zm5G04bW!Kde`u)S52NCYX~}@?bR+g1SL|y;xgiZ)Ku8`wTaiMNv$sQl(|VF*V=?zC z&&Rn5JK|rt6#FV0c2_PSza1lag@h!s|L+*OJw3A!}D}JeI5=V7Ufj7D!c6`1ao43nR=)GY=|L`JzR9y$E=7?y)rd(W>+r#Ph zGp69a7d0!c!_|mOOLY!rO^n|>I=R(D09P-KA zpi}w}jugBzS0e2i(=s!1BVM(a)PY){V=b?<%Ky=({%JfvC*z<%!sGl5<-AYrj>{2mKNQuK6 zmDvt&2lS$|kHG2;y^l?CH~CGuH$>O{Uqf!^RV*Aonx^JwaaGk~kwM*XxOQ|X>lH`w zH7Lg5H^J`G(snRVJ`p>o9srCYl9hat%=nxMjVgxQd^l)ZX|Iwyx`fH0Q&( zvhNi#Pa|H{-w7{Nl!^Z+3K_)ndHB@8fu&rRXKnWKu**0G#Th~eSwew}sy&P1t!^N_ zXBn>ER)RWr9Vn;47Q4s0GAC`p^UxYj_6Jw8v0nz#>7mDAx^6N~h#v{@u+MK6Lgp)cD>d{Ivd@vHUL_2 zpe(o+WyhB77)NCXylINmD%g4_0#%=kV|gJvDRZ}hvyP^dB6Ay&k{{j=D#zpJ?=uZ0=N z)@)Gh*A#rg!c0(jub6xn(a-&R$*#|Z0`to`>q2c7vi~s2$VV z3jKnsa~<_)Bs0fIWjggzl|S;sP{bJyO>JmMj{}YAz1B0F96X6m`nuxj>o2)a&I2$@Pl-i% zSK-~j-U*9x&4bQCQx z;mc3n<&}`@Jt1@#*JYx;&m?wzjVlJtD}*AON#uXUnpJI>%Dy{PR`*(%u;3x~fy6%QY`iW?C!i%bh{d%o-e;yaw_w-Qr3Ud*R`y!R&IPEL)qL zf~{W#hrlsCu*}!yb4Fg~W`sY7kQItnh2^Ah>q+lU7Zj$>7P2%Qct;x*Jak)2K@jCs7? zp=rG$u{;U-v~V69ofk<1Y#EMQ(84*&mg2!Cj^yfPX1NOJPwNw*`SwS4M_xl5!`W8XrSOn@KE)@ zjlWIU{Q5EC!KD>!l5ove$0$(s4i&OqUW!oxwahGiCR?4c9_IYm3$*GpayPEy@BGKO zmMdgA6@%c!nn5JEN2zv)5li$=hL~~0U#@8YL94+&*p8)PCokf>a-j0VLzu$+EIPHN z2!ERiPM`*0T3hB)fB-08rpspF#?pD6f}v;< zn#oI?UV|r}ad@HQEWr6ncvGNEcXO`tPxh{0PYhRKm%zgL-2VgrdLCr9*Iwb^*{4u` z%v0=7yDt8nAw|PX+)(aU7k=M9lTI{cVt>G7Ncj}S`!Ab925Oh##=0JXLD`2BhqmFj z*oDmMbs5?$?}FgJyJ2!e8BPv6=`hIm1wQ0b02kO1-BM;wDUDpiZ57@f1|kJA!kt~ zQ-wK8Y`|aB14RFwm1DL}32-vyF}L^R02;3-Fzi=N!R2@7qpaQ*rdv=9JvT}*DeF3x zX9R%1o;vB34Pd>X#IE&BV3#5{QP89NxPImc%AZq%D?O9gw-ZO8L4Ppa6UT^WF8U7w zKds@9o=_yi!3I?H<``ah*~(`R5<}dWp}0S_9i-I$VzyrtsMwC9rIiPm=l7{-EVr4z zRbWKi0^zK(B2{E;^NQbWl7h|$)0l$Sa`tdb1sz_qhx_PmgO>+|vf+7sIOx@Nd@JV# z3Y{vjecVX)ltp#rQsG{*R1Fp8<5DbiQ#zevA`eE}- zikd7-xo?6obLuv<&X7`N^DJZA#WbgjS(hkoOYl; z)x3^kx|fddcUR36IOAV==W}D&=D3Z#vb8k5-gr{z0^DOhg-dYJ6DxM1`V{==no5f{ z-xL{te#Eb2&G_!B(9s^l3od(Mhi(6}u54usUij^dekyiwZc8!Oe0c;kEWZn`Uq+!+ zPy(6n4lgJ%L!YD}+y~@er6#^Vn=nUYuO7L5JsUMHVm1 z-fgqO2Os+&qH`hmP$Oh`JVmojVYEte38{8mz|DyR*%*9@Y9poDUxTlFN4o`tIeO4w z+3%RpdJ9fg;jd6^_4G zwPR680NwoQ&b&KEiECfG^MC)A;v>`Ff?#hICF(}Nra3XRR^YX6?a9O`YWA>U!f6a2 zGK`IyFb(_9Xwgp(Pxhn8)8XKQGFtGw7~Y-R1pUY2@xF%z)y!(;8kRU`=;iAB) zNM%C&(J}j2)g)D+R8-HsN%i1uC+cVFeeUN-6 z+A1T5P9Q;pC3o|x(l7B_!VY@ys}B_u3?alw#3KIsgWHFFnB^wS_`8PC))~&!H@i=a zKi<~0=$=LATA{~!tedk^T+7Nso0-bR6Odl=2AV6{_+OS^p&-u>qj+@&%o!&O&uoji zZbB!*fE~Zd=tqb&n=BKH9~1vMY_lli(*?7!tL{xcS8(clxTJ%Fecp3lSG#hT-i#*4 zTdyHRxR>1@np4^NXgHyzO~by#;X}g{7^AdZv_<79YMGb|Zk8)tMXZU#!{j{ZT+@ki zj>}ls5HtGIUyMNt1K6mJT|!T!fKs$s_pX7s@>I+j z+2ZiZRf=axehxXEx|tmYeVi+I<29?vkm$PN8MB~?8Hx8 zwCpGbrUrtk&lo!3U`n~(rnpgIGM8_sOm#wkA$@oR|1#H@Jh%GdmFK!_;)ew^)G-<+ zO1u-E<0hc9B2VyX$>O&n!sl!XJKee&)BQ$Zh3{E*NAQk`_PUYonn752`Vlv`w;5kv zajEMcGL2W^OUVE<*Z@l*bMd1A#S26f_}~{`5xJTY8ZuEL>>QuE{3Q3nZ$CcI{es)g zo#2Y)C6bmEn43zzxTAU$9y&R2;^AW=IuZVxuN`4X&r1tI@4m9=)V)}2n;^o#j4B*z zkOX1Uyf43m9oO_e1yPZyCVl0r{~h!Ju!UW+b~u!yNV`e%z=?NU*VXF zI!?>pm-t7zc>lOGtErlb-_E7bX4~IlXO9~8+EEh>rj1}PZRO7oOr6D?dv@{>@5i8H zps=_0i2~=gv5**@ND+%BF}u%xyqe&H{_3j8f_-{;uauR%Sfu*IbFbW?`K=bTjJCa z+tAQ#Ee`);#kz+TL*wQ1{P0_;RATW)TvOx6K1AuV*5l7H`N2jZ z>h5uzydj0TEtP@e(Lv0m=KvQyeUGr`cVzX2IV>(G4bF^si2bhBaOQL+gf*H=9MuvCOptI}{_LnSV5;Nt= z{ZTNt?rsV*k8+^tTUUc>h7I%&6&Sx8qu2w@29c-E52URrptNm2wJ$HnC1+&OVB{mP z=omsOnSHqPY&tIASOYJuv$>wi)9|pY4)ync!{(;z+#q=~YELK!>61=0u^@6p>3ePqt_3yBKc&EWYB=PnRop8%7q1=thc@LY{MJiXMEeG9#(E*2 zsPoN{%I}Y3xoj~#R;d&%2%UtN`~z^*OA-I%*;QCSa47jdNQblK%kl82)zsOyf|j_w z0hd9K@b%py@gevPd%c4}Q?m`#q%860mYop%x(BRBwc{;cc|5YQ4Y$1>2;8r&6y_2s z4wu>u1DkYMXmBjF3w^vrWs^yBWgG8s`X5T2R)+eJ0g%_C&uZ2b;{|4g_FYB1XZbSn zOSEPqzJzk!LVjq;@sqe_1xH*_3I4o0nB7SlgxO8}VVBkf_74WL-HR9VF~5f3@wG4UN9=8QcJ!a<*xVDG zM5+SD?JtA(t3H5aULmw-{Nuj_&87Flc;wm+!JgEI+|qsp?9lzhZ%90hV`*?AgVkq|{h>pACZF zKOP9Ph!d>l*%5f5;wd;z1&4jC9Lo}%ed{j8@@v1=fRs}|a53kg@#r+Dld~7*@w;#? z>XPoP#oV(3p5Id{!OkDv54x_dyu`*BHt3@!MaV>g*)Us?`J~JI+*uh+VX7IOSY6BP zZW*!Pk(%(<*;P9gI$nykMkt6FDdvt(3JKk zKZCVHA7J;5)38=9n?6Jd!1r~>`SQC7AiXwSVC|ICx(AnWs+|Na|E*5qq700AG=`m4 z@}cBQwIZ3$T>ORtqe*KC_-)N%Qwu#=q|;(LeYghxi~P%#jNHYWJvYJh_pjib|4uwA zx(G9lNP&%B5B&ZmFyQmYvXnPR`BkaX==>-ghgUZ8a=HhoICv^KSbAVy&{gb^m_u7rc2B z2kyRyxNT0m*!t3sJeMAevyS`nLl0Pj|B4*(QST=Hh(;J-z+wJ^; z_(n|KtMBk+P7@~89R}A8GFba_mY^TKiJAvK!MeSRxfF+?6uA8|SSD^c_3H&0(g8BQrwcEOUl zXDTw8kIA@2emn-&j|UqY8+!PC43%m7GAZ>^kZE2+BZad|Wu7G*pHYXQj(70!F@a%l zBNum%ypF3CH{iQXmSnLu9@F+{0Q|m=zVnY`<{VwJczh6efwkcyWd0p2Oqg0r3L9@V z0%Ia}qUDAi?7M^>le;mAwBoPv7Z3f0U7|QlDe2|oRu|%u_m?1gjbQa?eTRJsdK4T483VOs?j z=7LjUxHIJdyZq>fc#*Fmqpj-Xo#jJS@umFtY0=!prk_=qL&@?)c`>HdH?jQdn zlKGs+4CX1Yn$!N2@LosA(5$1!U4!Vk5JK6+4`kXJy2L+A!evt~@Wn!}^5G0;PzsJG z_u23Gb@LXo+?6Y6`bJe|^3ofpuTtUl54S_vyWg-W>@PeR?u@B!Z!n;B8h3QMAD{02 z6TWY-hav4Mup`Zir5=)l55iu$#6*%Bnl}MWI*LW|v-t};LG)!+)171|{c}qem=u9}jxT+clZ<$XQ@~oJ}xDNh^nHKfz@hrTY1(!-HuP{tHgsh0{GaCC-_tC zU&N8wUtqh>T+Uon!ZxScvE`HhajP|kVQ1(#kWEPd-P?>=4t8Opzjx6nEC~DAX*l32S0B3f`c}vP|+%32V@$J2lNR4+o=NC;lk!8Y6myadML;(SxB1;6_|y7 zB3Xp{ap`J?6sh_Uwe>VfttJok{fudMwH~tiMpWIrk%FbJLC?Tmc$s^aU17_};(jYA z%$?1>yxj{C2|L+}BWlo^eid|^T}4_2a`aoR78|>RDbw^M4jZY@_J$czJbdP(t40yZ zJ;vtDCjJ}lg;t$YIA@r^277MG{}g6n*CdT0%Blg<&e_tCUE0uls}k4N=i!o()9_u& zR~ThEMVJMqp!t{O+~JO6c+AEX9mD;p>FEhtW$R3>yQahUmSg;k<~IJVWGi^N>rzw` zV<#zJ_z> zx0n6MJ9#J*H%%Wir)1*=nFLIt3G`-vH{5I-1)49$3g=`6rhTUyjURsn-2qj&sWy-l z$CSV!{va&aBoC3@6)=0uQY^aXg+>{jsQ-&WOlA;WPgFz~*Cp_)^MnbrioX{)k zf=ORbuu`et{LK*#+#A!!?8;yzb~pB%xHlr6*bOU|cE^|n53@&v1CS{j%5|O_`K-A3i(2 zi#<2j;Tpf(=JhIi_=NEj*fv!l+2`h9GW{41eXvIGW^2>C7k9azaE5C?(LqqEI>R83F9nK8;-Nkj;`zBHioN!r4GW(Ks)4QE$(IkK;2(ky)G zJj&iS1dLKwN6NL3anqM2^`-J7Tq%LC z3~Syv&7rf(o2k`D^Oo_dG`LZ4)`ZW*)g5|dJtB&&TVl(4N@H+9n-={(G8B$_b%3mp zYuLRknlCgqX07#$K_}gnjnJ4!=?b~vG_@U7E*&KQprc&pKP`Hz+>2Jj!*ON62(lZy z8c^dYE?(UMfg3DHT|p1IVT$ZUT`^wqX~aKwGzAXbd;WB|E`8efnX6OUgdsHh+@v3a znahbreDTqbjum{so>`BeZBGH_Uu)s*rj@Xcs>^Wo?*-~%6Ij`O8M4yV1vX?fCCYw4 zjV?QI>hs3@g*sq%APdb)V<9?Fh7>bK3LXt5u$L5An_eDh9)Ffxrd8v?b55vx@+};C z^9SRmHK4THYF4>49(1on!0ivm>LTVw^1)}$qiCWF>##97XS7eqbuUln2Obx8uwSN; z&C(-Ob)*AF@7Rz1hB+iJ%!jtf*P_NdHJF;Q0%rWNrLrJl|Gy(14)w=i=tOBk16{^f zKH|N$+{1qSjw_xu@Nah|!8UJ6khD;SSt+&@TDjM0eH$jPe<%09%7rt}nNOM{Sdf!L_mr!Mz zE0RXJ>vOnmwjwyAvsUO;7NeH!LNps(jRy{gU}Mv9`W&0VHQEoLt-B|Q>fTRf=VYxR z>6J2jXg`AXZm?!QLhmzu=O-xnmGKQ3KHLnU<5oSo7&i=)q8obH=?)rn9zFRbmV4Q_%R;7$SEKXKl*Y_-)Rr0`pH5KEALA z#>T*q4fi1Bf-n=>c>|};kKvERAHd{#O`0z-E-h`gvA~JSB(p@4{g`|lVr_;%diM#4 zh|EC8SSh^I&QVOeDOpdw&njp8^C3Q-+~V|RxNAHR_PGV}HHqGAa{6rcJm(F}9kz+v zEIy8M(H9^{;5vCuQe^Xo?u8K@2{_1SA*=sui`EOu#G4wzh26kMG|4=Iy#sGR_Nqwo zbQETwVS=w|jwP&_T!W8ROo!ArXTjGylkMGUT)Fa0xY?)z5! z^5YpdRi_8#1;+pRq1(YIYCKIdD}e5qce%4&8YJHQ0w3)56m1%?i+@$!!1+s5Ganaq z)^%UVuty$a759a+OQ4d#D{{wo-J>8##(?HFpMW>qA@KV862(GKs$^_B7`(UxL#`RJ z4eTJ(xRi#~U8l)!r8~54Fv1Nh1m5TzQ<~aw6h8j!gUEfh+`Nq2s1rDif@}uR-F9zw z{#6zC^4x5SjZxy}cSsWd_7pCZUrgPm7y0Vz4cyMtGOTsaKL{RM2_~QH@UyBDB%koY zn60xYaAqXFtoVoDgH+-B7gx6bjXlY}vLj1%Pxho+kNmw=LD0ftPs?;xtf$B1GgWBP zBu$c=E=doorJ2JdSvL6fc&5L)m%sYDkWHH*=D(hs%T2lMM6dt!ik76CGxlUA(|g*< zcXsT?;J4k_aBwuvpWz`2&Q_;2-Kj9uvku1w9p@UVIBL}@6WH{1(01hu^hln9>>&bs z`@&09oe3DeRiAY%*Jo>igQr>1pOu|qB%jxn-*KKx$*Dty@V;#IU7LI zjvOg>J;t-{`B*#f8r+j_1?j#Ny0z^amvB3SY`$91&}Uh~b+5vgN%5Su&OJ!4E2fA@ z#)ehIfJ1E~JU49R&Z}O=u=z&dH7|qgZAOEm)_XLVU5S>5r(*4>74-Pybk;KW5x>ek z8MnImbAv~G5*@zQ1uK@xGb<-Q3Yv9>IWBPGI-hQ4b!+$Xh3%7>l;Fc%U$+XW|uo2tTXlEve({!8A z^-(U1&>AN&RFbJCDTg-M|A*x#^jOQaIwR_PEL5E9N_ z76{J=r+SPIT*(d98;!+#H7BmSv6@A35u&K_w_J&k+1j#5M0Izg@xk_LT)%V_)7@;z zy4GBycJuw@BXoeY6|2$X%~Lvmz=#x=Dw9XuQg$F1(3X z0iC(9 z!T+QvqxTY|w9bGYMuPeCYYY}}6$>oMBVR=9B_bhPXIbV8r=M4^sOXXC75IsCCU1#{oTP)1P;d@xg}t5gtp91U%vi05Odr{0IVwQ36cl5}@;9DbiOnHe?Bp|4}?*!8>sI9<;OWp$Wd+HlZLD8k$rftewD z7y7T>M>Ns|&tfIE|J+p0dtxXJjWS@NiHihIy*tckzQq zU~8n)`3;S~aPKX38rEOHdVV_5(#{?h`^*Zzo{VSR-z4ClpALL)OQfNe5p^S~zT(CE z7SQ$f3&%-)#LIn8Q0N!4c?micrg9k9%^FTmc6i~sOnLf#S76g6&tqlko5|&!92jIp zQ{72z5-A1}tH;v?Lp^TKfJVMoHy{24C&SuRe=u{;1#B(2j~=e4`D@cQ zq0u@o_WMH&8c40UN|!U-68*@@~Sd@1Y28s_)lG_(jgm7n?3Aa&gg z@vV{>Fts(3(rPv6vqT>Fyr|%GGopCO=?A&;Z)V*61$u1chrN7Oc?hT)+M`|X47Pl# z9S(dPOc7eD>`6rc+gY(0Qxdht=4iV93Q-L4+BaW8Moy8S)uS5U0$*`+24)!fS z#N;dVXhfU>>-_c!P48ylsGcrVO-%ra5&k%1+&ymoq=D>CKr1*n*mFwXeu6pa&s9+K@Zv#CFUmmRRr(ndUQQZnNng;!xTlK6E1ld zi;q6WLsEW}olc*cKk!!8>4M9!QuOxnY|Q^^+>Ov53-6(%F>92oQF<-7ws6oi$e7Nz=Uhr zD7Dj&`Riw5_3Q;Wp?(b-WZKY+ksmNd#hE!z$wTK!H_zQlv*M$V2z=Xpb$s+LFY>!7 zOEJs6Y0u0GjCklr@28EW3*$yn`S}evy4{(&EIr|e);o~se}=IaQ|Uvi74wXB7V^h8 z@zw%WR>azIu5t#`JFE$&Pyg{Ubs1Qgy%;shTkz?bgItcNjQ^~B6043RVo2sG44yB% zJ5K-O*BmzE$~WwTxu*xw^wq)mU;jV6DHdkaPp^oq0}e95GS7}>T|@PK!F16709D&m zvelWNp=aw+3|~D|=$Dl8M?JgX;UB^0DJteW;-sOubqusnG}yPrKv&^p^qew}tr{kD zH8QW_`ybkrUNDM%GRXt8zLhl1)0mzP9}Z8psWF8P53Whrr~TthXvdRuk=1omSpT<% zbNOll--JET^w6JJ_rQP-bF0}Ln<2QDd&T@a_rrq4JDJRriwG4>Ad-#+`D(^HDjVW@ zAvC@8EYJa=(D=-RJhHIlRG-=0G-dr=qm-(5p;hXOd?6>?1J zj~8qSGl2byCD_(Fk*z#FljXRW;?&&55V7+R9Jt*Bwb@ztUz^~%o$&nJSb^QLu<{Jt z)n|0YTJXSaS_ijXiy=WzB+hyoM}OLTAW}M>F8nOzqyCz*^4c_Jrn{45i{sg&q5W|6 z*AOy%rN;7xr@-QUNqoQxU~cOzY11qliZ_jA%Q{tXNK_E!8@RHz%mbWu{6ui=(}8a3 zanw3Ojz*l5!?*s&AX*#v`yUkeM~(>;6fg_i0u$J(?~?Q;!kBb69pcxXO@O+oMuJyZ zgIom-K%v|M2pl?=C3Pi`@n~y0e1Rj{pofe5=P{oy5x$>o#iD-w$LR#5;a9)aAgSIc z-f>13UW`-1fSnte$$BN0y7n-9{ri+Zty6=CPo+@(xnzv8GNlL0Ga)1`f;D-Kr<4?b z*z$Ngch9~E@=ff7Zhbko|I!~+sIU?oKqh3vpM%=wt-N0&hx^}mf~wFHANaf;6;y@p zbzB?lnA6PPpWsffgQoN68xFw3n-^fj9icB2x)4uhm*LC92@wC{5XLM$4?AHWHAgMQ z0}q;b-ydygGvy^NGd3ji`O$2%Wgv4GvLI^T(wX>v1}bMZW1nUV6sU!f`ISmEjku1s zmHDVU`31h{^1uh}-e}}KfX^H!bam!QlWd^_-FaY3M*;=5aNk&-#x9@+>m}54QJX84 zJxm5=_1ykBLSAzIXxKd@jqR1Whq1>8qUEV7*egAg{%$?Nf{!t3)#$?ANs*v;T!vKL z+Tq)}MDY&q@$_&Mg1s!_lA`^5V_PRaUi?3b&chL_?~mhUl$9NlA`%rD5uW=wMpBe0 zDuifi*ew}lWE3(Z<4cMZkyOTWKSzn8Qi@8YqG(W>l4$(y??2$V_nv$1=e*yqR}#!$ zCrXZ-v(W^H139kBxGFksy-Lo6tC2?O3mngH zFSsT^Z{L$JDcQXZX$}mT&X~kA!=zgbDoVd z=AP$koG3qnBV*QFzqEw@!|hNr5JsQcPo>gLI;82%Y^uJiAKULnB6E|6$roQSAsIa= zq_vg&Z5w4G=5K}d7)Pcr+y-UkX+&U;H_`hNfG_U#K-RA$l48h^Pd0tfaaS5vrK^*3 z$!hfDyEV9Q^*xMzS;afB{V)y`tfvMd`Ka}36dv?E=h*$TX`Av8jCzjZX_d>Mv`7SJ zwYOo!(?_`c#t=AN;Q9{9I$*JMB3(OcF1_$`h@JRc1_YJ0$=IpK`13|GJHh%TOzq6Y z4$~;IYP~P-VS^`Q9(b2?OZu=kUMYgS3CGa*{sTRBeqr=99Kl!6i9Aag#=|YAAttZ| z)$KhP_xtmx@quOJx8o+xSF8pF+zhKK^fU8W=oNeTt2-QUdCEvUav;%PGjack5VH2i zRNB!pnYM>0kw}A4?9v&;TN>PYwf+Lxe(or~98JSt6)iYCEKGR3|3KhxJdUUrl6%QE zaMLpeuU)q#KYM)X$@0~7Z}Cs&{q2kRx%Cf|Z*aVwb40r+qCr}Nc&alVi~>AoL@ znR#bvhUEvGvGWxEsWG5EzEWhjj}2s&yuw!>9qFU{eAqJiHEU3|nx2$ZCO-vU;nsv_ zaOTr4diLZyzP#EIY)a!;ZF^U-8RO3|R%#M>rA?+%qDBy6r;qEp6PSwFgE;t8lq`@q z3UTQ}>}^HvI`D;wPuN^s(QHM085g?qlreFORiqyc3c=iR8vP-dPqhUv@+L2ThKFP0 zG1BHAfA2OA{OKsn>KA4(8H>%p;nF^|D>%pwtgD2F(;SF)tTeP=>Blb{H_+hKA8~9I z#m?DsBtB>&%>0{5FBK#+Io-zidvXHp96(Nq5@fzh} z!6r>=lNfK7>Gh?)NPjMyGS!TvuhS$?w$CINTa-y-4@JF}&+NnaVP?~_el}Sx8S}Hx zqn%zen`1GZ_+*>~5&XJTo`IDbrxtRWtodmpZ|6qU06zI|9!P}@_h;i%! z?@iXwe^Zd$6zAAo2aiLL;yLK4YR0k?fMj?S8^Q@xtrvy7=c7#9^H;oVrj%W5WqYk}3j zOmgIiG@V@1fLdZJQJc%hEED0_0bLom+SP}=7W;+2zFovR-wOyMt$2Q>I=#$g>TWr4 z{)FN#kmwL2t)aCTy!Iz5ET{tUiFWX)_6u5HOax7TWJT;glksqS+}}Eby4G>;t;@NP zY5S)p&wT{kNA2h~VHaNS?|4vOH<>8g-)8+~XHfSvbr|p7!tvfBaqG+9ptU-f65V7j zD^m|uV|!S^qng;l@$pT(IR|{zKJstOABW%m$1mP=9f!`ZW#vRS@)*jo60T1qzeO%F z)2+-%u;?N*3!Fd~nT(;6LOd)upTxNAYJ`tdlUZ1_2rfswf*a3!*eCje(DP|Aoxsh) z)Y|u8-u9CusJ9h9<>f(MXb9eHwg3y!)n@JOQJ7$Z^wz_tn3J~$%eH-iiE;AOqZILl z$~z=U0o3e|1y#)C?%@}mDB{1G7s_&OlzvC5_Ld^by#%c_9$a4K2;YxAh4|1D&EU=EcR`ph;nFY(vpODLAL7*%g@4DL4z_~Ap|^w!4` zIQnlMl}s6eF5VC3f)5MY`D6Sy$C4o8!z0+o@P`jfzRqp-wv1dS(C@sv2;?;J&5>yg6jtCW16={lP@2% zsmRDLMuyuP-MAt_2e0bl$ygC8Q*#{->Yie@OJuPR+Kk|A=DYgkGnHYEb1vG@6d1A< zB0~ZnVfn{+Br^`feU~7r@?<)VxpET>xihUPYl?Ut!9Z;{ZiXL|XOQ;JB1YSh4|m>L z(A=Z5>7sL$jQvg?&0CTQPg1|KBe}Z7-lLV(*|3ZpO7(|HC!g`OC3iw9ac8GrET)q* zEO5taVOp;+kzT)O%o5Jiu(nN^8oQt5+h7b1oxQ>@%0CNo(gKWKRWvK$pi3<_bA7k< zZ$NRqE>3-{N!#tq;jvg8&Zt~KNYJE_|bF3-GxHkCc7@^|sf@bNUS#CK>FP*Oj=}R}l|w38xQtzhsV^<-rVd zKQz6bik&%IsW|^SnB_DO(kMee9e)Dc)`cGFzYk&+8Q2k#MTI+^m<@Kebf4@L;#Mn6 zwhkVL#KfN;JVd~rq_MtX(l`)ujT59i&rG)+}jBsXIIb(S|4Cd)izT;(PIbvSHQfIXkJXt zT3G9?g-Zux(Bt$Zdg)yz+TTfLzAHwN<_*souO+`x)#^XiT;NA(H%3m`YvyK^{EKfQ>76&{fAg=*F--tnzru1`q2};*`cW z4VAz->~3PX>I@V#Sdq0sWz2n?Pi;jQ+AMa1$>tb;iTo-EmRdv?aJ&HT%B48N_cWf| zFuB3_a36fXV?)$4&vAfo!~oGY{BZaWlSg0S4I!559@Ihg^)0OV)F|9s;Xxf8cyPyS zj9q$6kev2ur@j};(fUF>W0>Ykaz#$!w^?VI8}G}h+){Buli;Ts&K}~ zB$>tvdXiebue_OQ-5|MlA&#!yi<`DfKv&~jykm3?mHQTuJ*CpL-Qzku@e_dXL}_?> z(}DgzX$LtYPuY}{&T#c0*X`VO1%8~KLqoZ95ZA8Mv)43)Hft=%GMqx^;IZEdH>8v@agRRY#WK%<>qTwRZ(084fh( za3_3BKoAvHuCvpo z3(+fa0`$lBNmQ)(73N;LL)^vpvz?Uy^+|5z+})*YyW}7<7WxYhKc0dI`eJb74MRNd zIGH{P6(#;XIW$}04fsv-qMb%@aO<)yRq=}=#e3!v!kx?CJ`h6<-`J5qR~C?mazW(p z;yTE@eIHY1YSG+~Vb*r8EyxMXrhA0uz}1rFM02?aOm_+*ZXCa0>Xk^k;jRB^5gw=hA^V1M2N5iCNj^)ceg!ayT~{S3WAm){;CLhdGfi_s zyS5tAOXicYkn7b?;c|hlPVt0l)!{h_eR9Pxi*>X^fFvvW$U1?WF}`7aZW^$T#YuQd zNszjVAFccCy{O(|m<7wWU_5Mm0eq~KsiMV7EN6GtZ#EOgk;GA^;h!ZPu9BcBTfcDK zLvuF#whC3Bevqu0;e!`+4};K#Za5I(3Cd!gH2q37&igrvho>zgPtCr=Bp+|q^#cnj z0ruq03==#*D9&j1QqE24$Sme&YQ0kl_#{U`p79PYe;P-_*9F$|w`t)aK@6ftKlT8-nRmzypMYq6@~EIJtN`ey>|A;Pl@O=rR8<^VRJ(s+7voy^`M4H7X7dA5`SnImTGedBN88 zgrHGbGk=R*2`iUrLmQu6$KtEUiQcOUA{or(p*-v0jU9`H_KLJYMuqI;f5r)Alj(7} zas0ji12W20lf^vh;Pteq9Z+*$8NgDS6p6UX>+?s@_OT=s9A+Y9+>yP~POBAz>7 zkKOaO0$g9uS9jS@WBo$WwA+T>dz}Yyc9qy6UjnrTe&k?CI$P403lptHsmCq~C#J^Y zcPqq_J|(i-^e+5~>cX<^-&nQPsbD-jhzA73@DS9p5(|^qmHo2`tf9O`a1zhb)!UmXz-vV~gzO_f0X$}Td!pWO#*xCfnM>Aow#V5R0P{!Z( z>^RxvnKm8gR>G%d_-fnwxW3d;zmsw8FufNMN%$k^E z;x1h7@h_Y{YDITA&mfQYT;=UsqYVEghhngSIb2+Cjv3-Dn14|f4Cl2#@iDIBAlhd3 zubAOH_8k)mdouOk0#3qMV^0O;(MwDhbnS$kTZ#(%e? zTa~OR?sy8uR<)d$$b^Q7je*7sWweuc%5f)BiDlIt=GDUAyy3)nX3~W|+|c|NS6zrf zR`(W!KQ{((k<~D7z9F3^5zWqN-c61D6H)4_9t~SMhAZ_}QmNp@5H>gozg4dW)n+d& zw-lrk;`-r6)GyXtg%HzJJ-Y0(91%P+iTpgD&IH^UhQ5YE*jjW33VU=&O2`04L^iS1 zJQO8g>JfUr4zGzQ(0gxl>ng3S@WCEAD)gtFzby@MWsfA-M@!Xvi$wCCZCXLk@6#gr zsbh>+D>ujNe~DKz07+TeImbX4F6kJfUXTi*t7ILoNd1d!4u}um+h)_Ra*+&Z#JfPoKqpt z$r|4uuLk`Mr$J=nLUdoLN4IE?L^bu?>^g@dJUH~J^`1-1?67yB ztwpFANHAM_V{nNkVe5B&U|+VVp$d#Z$>(02nVLuaRr4s>#Nw&NOX%}oCxO0gg`WYr zRQp#Rm_0LsX=NN=t9U&apI$)IW>v73?UBe2B`8&7OAb7mM&}Lrq31{wcb4VIO9?0e zd76T|5@VUp5FPG5dII({WNDq>F_ib(4BCD*Saxmzy$%V}F3K@F!j0*K^-=UneGFZa zFqhW;J%AsJ#A%E{3mZ`P7S$t;U|ie)QU9DVv8gYX>8Et{Lhk=rPXKl8) zfZaAzf#~@q(}GPK$OIt)I$g*I9gBWIY3>O|#d0T9h1K4GOf_S20kyI9S)VN@^6 zhq&4FgZfK8tgIPe&bVvC&-F`a^S0+8AMgp1uP=k1bZz*gww}DUGa!H71>&4(KX9z# z6j&a~XWu-vFj?{^o<_WIgFMf6_O+S?aa%hJ|H#-tk>^9^w{QjmXeBDEpvO9YE+hMI?Lr-W7EOzI zP|>DKyj?^{tBVTNc_~Hq%+f?(9PA34cYx3!{>d4 z4X1J-N8&V>F=^y@dc#bhG?-m^mBTDJXvOu!^~vbPVCL3sb>c2~irgD7V@KNVAa4s`iD$UM+U`c=6NyO8?<3Kv+K6Y1*BNx%au4+wq5hYI< zpF~*eDMM6NWCJYf;zjm7hv1pXShUXz9fqUGV8~ifDxFUYq$@D|QU;RX307cdTwGjOTJYgTiWB;8`I z&(!*s;?34Abh~*E6be^@c7FpqS4kNTUM=BYKNd{pELlMM7dpay{TSRozXC;L1n9%~ zR+OLC$dilHwv+NS!LOS)Xk3a$2e&YF{aW~D zts2pZIz(pt5+m<&yh)j0Bz#;ZO|Go}1c{xW;X^-{Up0-zKReFS;ZNbvH?I+ElnYV$ zdJ4Rdm_QyySKwgR5{_wB#|Y^eQDH7m8Ma4?w>0x5+N}^H<67OkCH@+W-8vo@zKH@R zo>mil_I~mc~_t^LNbUdh*{WzpG6iqU&`qvhoFP3dv?pCx);`tS#uy z48X9Xuh{;_13bg~s_0&l38BK0w4-4TtCg%q)(>u=c4x&P#3mNf?;4=TT_x%|$&_AP z69Ueh?=gPMGWNgG5+c+-!n<}U5mL6iF&paUV_>Tzak)R25v<(-3Mn4sZ_^)Cb1x%y zW=HCUvW-aj1rPS++;n(ZlZ#EK7K0MM5g%nm5Tzw&*dvcyVMAgHo5763k3W@Yp*4e2 zWi7HVw;H>*=fUcoS0TM86O1Cy^Jp;V%NlJ$kEcO2rD8WZnOcVpNoP?(e=@F~*~&Z- zjb_Bt>&zD0&w{_^ttgdv1s>J3!<9%~qB^#f&T=;+)%)6^=ejhBx^#-Ury31bBlEd$ zr(I;xlEdV7K@jOpxrosTB2;*}G8Jb=g&Xa= zxF5En2uXaW1F`=l@u!yrvuY`KI_-=k z>|7NJ?_1j0RiAWuiZ(MyQtBdz`l?3#XWT_2x|yEjvL>}xmC2_+5!iRWfi;_8L<&!O zQ_G*COiS+$DreagPE`AG!o5gZwaQlOxuBTLZt^Ucv#3a=f3fLmymC<+=|sXn0cw z;_VbMYGxP8cy7kE>Mcy^DlH=Gy%+I<5ZPyDM9nOHS(nHN=2}}j&RjT~9&Ios8B8JT zbVCKqXYC~)WJO3^l^NKF1W@zp^NeBzA@<&FaIt9|rq3&4XRHw<6BAgFRo%_pj`pS3 zA`PhJiF|Ad(betKB>kspYaLrnhJMA`eWneb-Ytf_v zWBQoj;YeYo9`kj}PK1?L*n2nfd9Sk`!?S%V^mTqY{ukH849rf1Y~5D0R7$6kp^8NM zx(T~zoiSbiEf){v)neDHNkn3?96rhW&L}xu!gKf3sX(_ZF@_c7S=brWeXorpnRzH5 zJqX*krjd@jKjDhqIIr)N4jk^!;@NQXG7`AQ5rtuWV*2tFJ9eK6M=r?3F>Q>T2@r;2IROZDsGdi9%R{P(y675{xSxhRIxh z_nP7hbew+=z8>1azMno0N+6k$z#Cas`v3crETTOItqU!Cz--2r{NX>ez01lcQCjxPEp zba`AhwnfRXI(EM?y-*9bZj*sYy#r`VAHsY8IQGqeCaG$+C+^3O(p&HM(!p*c)Q{Bz zarsRCiH}M&>*aGu7OjN7AzkXGb^|6R%*NA+T&AjHHq+H5MDBAw1kZ~esQCKE zpyFZH!8nFoFPu+%HmGsl869&xVUC^lw&-kUM7&Km;F|(-Kr=<^@==6V_ueOQ3-!s9 z<(tSJH7DBFs?FB(N4QR`Ew+DYAr~_2z~K7|(7fnQ_w%PyueOh-xssmL|Ck|-Q&$0_ zhXri$^mAC0YRSa?T?$K|so>_ZZSej21ga6#%PXBOjf)SQBnwlP!n71=`gc(>D`PQ$ zBg$T=%r~Z=L(6ziJfdk+X*Bho?M{>5im)N6Etb8|h`mB2Zc|2#c2dWLI&$vAGXs z5dYa9ap~0rQe8U_t9XHEdF?L0I?#`-x&y>brXFfU$ z)5&u#GdEYyXFJAUvt6qf)7c#Nrr^vz`oL}+&sARL`|GWt#&uKCSi_&JyQPO)zHcP{ zVp-&d-%>iE<1~M5u`3j{^}#?&8-DpRkz~y-qSnV|kTsFv||JqY-ZTU$(x(5oOEZP)(AMz3>_()5w_cbPy- zx{E<)%?P8ByNZ_aJDI*ZJ(zMpg+v{_2RvVExtxiP*6NH@W~ zvr|dk)j8-NrVlC_$H=qWXZfdN&)|)Lb!19kFb&@(Lj?BA(!Wa+=*Nv;V97KO8XFiz z)IZTpze;at%|R^0<9H@~#hF#pjO|K$e|J0B1cXx===#tXee#<_cbC#xBR0h#y%)Z~v78&lE$r z7${EuSN2~ags}7-TS%8UO^G9CQusS)lGKJo6!Phs-T`v(nANw4iDx z8MK;DEy-3|S+fz>ypIF3!`+P2uJuH1p9lN>Q91dT-HG3xoP_BX8u+kW%53eE!?a_l z1ZVn)lGTC5n0P&qJl=5*PrUDg9G_#TGtrNKY_B|fEAkw_t8WD!zNrj`tr=kXIStCZ zS3{Gk0L*`N4;{AN;uyfn)V5xe^u^tRUSAzB*uw|ukYaZ4mu`+lx*A-ESJEpp|H0cx zJ@Wjz2#KEL!^TFgBuZ-!Q6*Km_5E?}(T|2DU`HF2%y2HNOzJdnHXQEd8H5giV28&Dk z*?z9e?$#5sI^;E2hK_As-c?c6i(Sjqad39+v~h>`@8 z8{p8^1m|bZAX|gA(c@Ms(ftIV|lkiz%PFd8Z4YlI{%wZJa?5s@9}ta%o#!7FW>O_zO$(DF9Q~A zxR1YMtMPA@8hz{CjmCB97%dZpdkrb`twWA>PO5?Xvlh`TF0ZY@bq$VBoQ*Q0Hz9Ib z3t#xC4V?2V#hLTkafO;1t@aIrPFDjw{$K&vt7?+vx0Kn=PpXh4DM>?9?!Y3B-=oX% zXIp(IVfHgwn$U5DXL-qpR9zC}xt`c!tX(mUR5nSHOK-bCH)}Vwv2nno=MbM8Md3(> zFU~$Vz+8Sih1qsci~6}4VS7Uwb<0*DpZ9Nuoq=nJvr#%Pv5DjRZg!*luPtY*RHl%n zXROGN4@UIjpNf%Q zj8CZED z0}B2Ll6%Hu%s}=M6#Gy>x*pe%*Y5`z0mG@JaZnoKCro6^|4EVHr_W(-_$qeIJYNu2 zYDAIt|8Pm|ZYWshN-}&vcj9Z?wy5K+bh|vDoV7zdl7Ey;C^>Y z8%Dd9n_c~vhi(5v*+&KnWZi;T8n2WCc^s>4m0mjbyN|%JpeT6rOrCT}Cd2DV70`9| zI4i&W0E#e<+%~6M?|i z*Z7h1l;5dXLB}<7;pClcG~Lk41noR)x%gd-^tqEN>IfQj;&qKZ3 zF?jM&m}V(0r+&)rbh0&{-C-?B^)AhTjHFw&kKc8&6ZTA`wjKFwpiM6OygdbvwFV(c zbp@Y(Nu�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 z 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

h~h@ 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%0DQ<|MygQkDmIP^NlzF+YB^lUTZaKgq`z_ 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 z∋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

>)2b zR*ssK`tjXD9<1)}S6=D;49tvrV0rv=0o{`odNrFu+1Aetr%1nJd*yg4j+3QV2YZCi zzaPJIyozMomvA;e#a8G|hf>aH5jOk{<-+2}LQb0^FI6!LqI=(CH}Yf18MLJ#fOP3G6g!`H97;mwj^P~fb@wn){n`M-0i zN`4h{uTO&GE}b}MTn6J0Z(;KW%hCOskF?PQ$m(+iRu0hu4exG@Y&r_-JX|4OCzkbd zA5Q&_%%ME9Os4)z{6CLhNX5T|>g)Z^}H)}b#4Ri&f|io z#Fr8k3h-WB&P_>QHJ%)(0n>X!aKo{0%1<|lK84<8j^GqmZNuu^MDZbOdHShR$N$Z=r3J&QQIv8B z+$Sc|)k$yB<5xE}Oo+!%qB1W3QV%Dmc#0ftJYlMry>Lf(&-Z;Q#?L1@nB4>&_@_32 zX8O({qk-yl<$NR`Q!)YEukT_9_a|dbcmuv2b_X4TwCM}9Sh~9Bk!`aLX$MThIYnZm zE2Z>pKoM6nMTw3dSVh)XiALL$Se&;o1FxSd*g9w;U7Ws@jS!fxcHL3DZ`Uo17r5fv zg=}`Y7GsZxmD5fQZAf}7%tSM%v%AxVux~1=5d9J;^HVN9+FZv?74D`6qYjD3Hy(oz z^VDhWV12rF_Bv-3V1YIQdoBHi0vD?_j-*!YByNlnJnR1-w7d4eo;GQ)Z9B$A

?L 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%0AJI6;o!%e#!#WLb!9%(=5J>BohUbOw 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

ue!f0P*Q2*w6d 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

@7(X3*_?ZkJc)d-V%gH~ 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°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

-GQ(cwNG3Fk#jB3-WS~l)vC6yL<;(lw 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 z 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%0A&RYg1 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%0DmR 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

$HO?%xJHW(W!DNFXBX1Zzl(rW$iR%L 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%0DUcK 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�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�{Z3 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